Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions crates/ogar-class-view/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ use ogar_vocab::{
unit_of_measure,
visit,
vital_sign,
weather_cell,
weather_static_cell,
};

/// All promoted canonical concepts: `(canonical_concept_name, Class)`.
Expand Down Expand Up @@ -207,6 +209,12 @@ fn all_canonical_classes() -> Vec<(&'static str, Class)> {
("pricelist", pricelist()),
("pricelist_rule", pricelist_rule()),
("unit_of_measure", unit_of_measure()),
// ── 0x04XX — Weather / Atmosphere ──
// These canonical views intentionally carry no W1 payload fields:
// field/level/unit slots are selected by WeatherNext's ClassView
// manifest, not promoted into the shared OGAR schema.
("weather_cell", weather_cell()),
("weather_static_cell", weather_static_cell()),
// ── 0x08XX — OCR (container kinds; content stays in content stores) ──
("unicharset", unicharset()),
("recoder", recoder()),
Expand Down
2 changes: 1 addition & 1 deletion crates/ogar-vocab/src/capability_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ fn resolve_concept_row(id: u16) -> Option<(&'static str, u16)> {
mod the_canon_carries_no_palette_rows {
#[test]
fn no_0x17xx_row_reached_the_globally_mirrored_codebook() {
assert_eq!(crate::class_ids::ALL.len(), 91);
assert_eq!(crate::class_ids::ALL.len(), 93);
for (_, id) in crate::class_ids::ALL {
assert_ne!(*id >> 8, 0x17, "a 0x17XX row reached the codebook");
}
Expand Down
88 changes: 83 additions & 5 deletions crates/ogar-vocab/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ impl Class {
/// 0x01XX project-mgmt (OP ↔ Redmine fork lineage)
/// 0x02XX commerce / ERP (OSB ↔ Odoo cross-curator)
/// 0x03XX Ontology (OBO biomedical reference: MONDO/HPO/Uberon/PATO/RO — zero rows here; concepts in ogar-obo)
/// 0x04XX unassigned
/// 0x04XX Weather / Atmosphere (forecast + atmospheric reference cells)
/// 0x05XX unassigned
/// 0x06XX unassigned
/// 0x07XX reserved: OSINT
Expand Down Expand Up @@ -1222,6 +1222,12 @@ const CODEBOOK: &[(&str, u16)] = &[
// consumers (odoo-rs, openproject-nexgen-rs, …) never pull them into their
// concept space. Public reference, firewall-separated from `0x09` Health
// PHI — same reference≠PHI split as Anatomy (0x0A). Do NOT mint rows here.
// ── 0x04XX — Weather / Atmosphere domain ──
// Canonical atmospheric/grid concepts consumed by WeatherNext and the
// lance-graph weather SoA bake. These are shared meanings; renderer /
// ClassView selection remains in the low u16 of the full classid.
("weather_cell", 0x0401),
("weather_static_cell", 0x0402),
// ── 0x07XX — OSINT domain: ZERO vocabulary rows BY DESIGN (operator
// ruling 2026-07-02, corrects PR #145's two hallucinated concept mints
// `osint_system@0x0700` / `osint_person@0x0701`). Within the OSINT domain
Expand Down Expand Up @@ -1417,6 +1423,9 @@ pub enum ConceptDomain {
/// never pulls into ERP / project consumers. Public reference, NOT PHI —
/// same reference≠PHI split as [`Anatomy`](Self::Anatomy).
Ontology,
/// `0x04XX` — Weather / Atmosphere. Shared atmospheric and forecast-grid
/// concepts; public environmental reference data, not an OSM extension.
Weather,
Comment thread
AdaWorldAPI marked this conversation as resolved.
/// `0x07XX` — OSINT (open-source intelligence).
Osint,
/// `0x08XX` — OCR (optical character recognition / document
Expand Down Expand Up @@ -1490,7 +1499,7 @@ pub enum ConceptDomain {
/// transcribing a GPL/AGPL implementation, so this public codebook stays
/// unencumbered while GPL consumers link it freely.
Blocks,
/// Any high-byte slot not yet assigned a domain (`0x04XX`–`0x06XX`,
/// Any high-byte slot not yet assigned a domain (`0x05XX`–`0x06XX`,
/// `0x10XX`–`0x16XX`, `0x18XX`+).
Unassigned,
}
Expand All @@ -1504,6 +1513,7 @@ pub fn canonical_concept_domain(id: u16) -> ConceptDomain {
0x01 => ConceptDomain::ProjectMgmt,
0x02 => ConceptDomain::Commerce,
0x03 => ConceptDomain::Ontology,
0x04 => ConceptDomain::Weather,
0x07 => ConceptDomain::Osint,
0x08 => ConceptDomain::Ocr,
0x09 => ConceptDomain::Health,
Expand Down Expand Up @@ -1763,6 +1773,15 @@ pub mod class_ids {
/// `uom.uom` (`qudt:Unit`).
pub const UNIT_OF_MEASURE: u16 = 0x020B;

// ── 0x04XX — Weather / Atmosphere domain ──

/// `weather_cell` (`0x0401`) — one dynamic atmospheric/forecast grid
/// cell. Time is a dataset/version axis, not a new concept id.
pub const WEATHER_CELL: u16 = 0x0401;
/// `weather_static_cell` (`0x0402`) — static support cell for terrain /
/// geography-derived weather context, distinct from dynamic fields.
pub const WEATHER_STATIC_CELL: u16 = 0x0402;

// ── 0x08XX — OCR domain (document extraction; the Tesseract-rs arc) ──
// Class-level container KINDS only: the concept slots name the container
// types the Core resolves — never their content. The 112 unichars of a
Expand Down Expand Up @@ -2054,6 +2073,9 @@ pub mod class_ids {
("pricelist", PRICELIST),
("pricelist_rule", PRICELIST_RULE),
("unit_of_measure", UNIT_OF_MEASURE),
// 0x04XX — Weather / Atmosphere
("weather_cell", WEATHER_CELL),
("weather_static_cell", WEATHER_STATIC_CELL),
// 0x07XX — OSINT: ZERO vocabulary rows BY DESIGN (operator ruling
// 2026-07-02; see the CODEBOOK 0x07XX section note). No entries
// follow — OGAR vocabulary carries no OSINT concept names.
Expand Down Expand Up @@ -2182,7 +2204,7 @@ pub mod class_ids {
// lance-graph mirror is rebuilt against it.
assert_eq!(
ALL.len(),
91,
93,
"class_ids::ALL count changed — update this pin AND the \
lance-graph mirror COUNT_FUSE (crates/lance-graph-ogar/src/lib.rs) \
in the same PR",
Expand Down Expand Up @@ -3005,6 +3027,8 @@ pub fn all_promoted_classes() -> Vec<Class> {
// vocabulary carries no OSINT concept names, see the CODEBOOK
// 0x07XX section note.
// 0x08XX — OCR arm (9 container kinds), in class_ids::ALL order.
weather_cell(),
weather_static_cell(),
unicharset(),
recoder(),
charset(),
Expand Down Expand Up @@ -4653,6 +4677,30 @@ pub fn joint() -> Class {
c
}

// ─────────────────────────────────────────────────────────────────────
// 0x04XX — Weather / Atmosphere canonical builders.
// Field/level/unit slot semantics live in the consumer ClassView manifest;
// the canonical class carries identity, never the weather payload layout.
// ─────────────────────────────────────────────────────────────────────

/// `weather_cell` (`0x0401`) — one dynamic atmospheric / forecast-grid cell.
#[must_use]
pub fn weather_cell() -> Class {
let mut c = Class::new("WeatherCell");
c.language = Language::Unknown;
c.canonical_concept = Some("weather_cell".to_string());
c
}

/// `weather_static_cell` (`0x0402`) — static geography-derived support cell.
#[must_use]
pub fn weather_static_cell() -> Class {
let mut c = Class::new("WeatherStaticCell");
c.language = Language::Unknown;
c.canonical_concept = Some("weather_static_cell".to_string());
c
}

// ─────────────────────────────────────────────────────────────────────
// 0x0FXX — Geo domain builders (OpenStreetMap geodata reference ontology).
// The canonical reference shape of the OSM element model harvested from
Expand Down Expand Up @@ -5570,8 +5618,10 @@ mod tests {
// lives in ogar-obo; plug-and-play, never pulls into ERP consumers).
assert_eq!(canonical_concept_domain(0x0300), ConceptDomain::Ontology);
assert_eq!(canonical_concept_domain(0x03AB), ConceptDomain::Ontology);
// Unassigned blocks (4-6).
assert_eq!(canonical_concept_domain(0x0400), ConceptDomain::Unassigned);
// Weather / Atmosphere block (0x04), then still-unassigned 0x05-0x06.
assert_eq!(canonical_concept_domain(0x0400), ConceptDomain::Weather);
assert_eq!(canonical_concept_domain(0x0401), ConceptDomain::Weather);
assert_eq!(canonical_concept_domain(0x0500), ConceptDomain::Unassigned);
assert_eq!(canonical_concept_domain(0x0600), ConceptDomain::Unassigned);
// HR block (0x0D).
assert_eq!(canonical_concept_domain(0x0D00), ConceptDomain::HR);
Expand Down Expand Up @@ -6680,3 +6730,31 @@ mod tests {
}
}
}

#[cfg(test)]
mod weather_classid_mint_tests {
use super::*;

#[test]
fn weather_domain_and_codebook_are_append_only_and_not_geo() {
assert_eq!(
canonical_concept_domain(class_ids::WEATHER_CELL),
ConceptDomain::Weather
);
assert_eq!(
canonical_concept_domain(class_ids::WEATHER_STATIC_CELL),
ConceptDomain::Weather
);
assert_ne!(
canonical_concept_domain(class_ids::WEATHER_CELL),
ConceptDomain::Geo
);
assert_eq!(canonical_concept_id("weather_cell"), Some(0x0401));
assert_eq!(canonical_concept_id("weather_static_cell"), Some(0x0402));
assert_eq!(weather_cell().canonical_id(), Some(class_ids::WEATHER_CELL));
assert_eq!(
weather_static_cell().canonical_id(),
Some(class_ids::WEATHER_STATIC_CELL)
);
}
}
37 changes: 37 additions & 0 deletions crates/ogar-vocab/src/ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,9 +617,46 @@ pub const OSM_ALIASES: &[(&str, u16)] = &[
("User", class_ids::OSM_USER),
];

// ── WeatherNext / weathernext-rs port ───────────────────────────────

/// WeatherNext's `PortSpec` over the shared Weather / Atmosphere (`0x04XX`)
/// canonical concepts. `0x0009` is the reserved WeatherNext ClassView skin;
/// the canonical meaning remains in the high u16.
pub struct WeatherNextPort;

impl PortSpec for WeatherNextPort {
const NAMESPACE: &'static str = "WeatherNext";
const BRIDGE_ID: &'static str = "weathernext";
const APP_PREFIX: u16 = 0x0009;
fn aliases() -> &'static [(&'static str, u16)] {
WEATHERNEXT_ALIASES
}
}

/// WeatherNext public names mapped onto shared canonical weather concepts.
pub const WEATHERNEXT_ALIASES: &[(&str, u16)] = &[
("WeatherCell", class_ids::WEATHER_CELL),
("WeatherStaticCell", class_ids::WEATHER_STATIC_CELL),
];

#[cfg(test)]
mod tests {
use super::*;
use crate::app::{app_of, concept_of, render_classid};

#[test]
fn weathernext_classview_composes_canon_high_custom_low() {
assert_eq!(WeatherNextPort::APP_PREFIX, 0x0009);
assert_eq!(WeatherNextPort::classview(), 0x0009);
assert_eq!(WeatherNextPort::class_id("WeatherCell"), Some(0x0401));
assert_eq!(WeatherNextPort::class_id("WeatherStaticCell"), Some(0x0402));
let dynamic = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_CELL);
let statics = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_STATIC_CELL);
assert_eq!(dynamic, 0x0401_0009);
assert_eq!(statics, 0x0402_0009);
assert_eq!(concept_of(dynamic), 0x0401);
assert_eq!(app_of(dynamic), 0x0009);
}

#[test]
fn openproject_namespace_and_bridge_id_match_canonical_strings() {
Expand Down
3 changes: 2 additions & 1 deletion docs/APP-CLASS-CODEBOOK-LAYOUT.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ materialised until the app mints its first private class).

| `lo u16` | App / namespace | Core domain(s) it consumes | Private codebook today? |
|---|---|---|---|
| `0x0000` | **Shared canonical core** | all (`0x01/02/07/08/09` + `0x0A` anatomy + `0x0B` auth + `0x0C` automation) | n/a (this *is* core) |
| `0x0000` | **Shared canonical core** | all (`0x01/02/04/07/08/09` + `0x0A` anatomy + `0x0B` auth + `0x0C` automation) | n/a (this *is* core) |
| `0x0001` | OpenProject (openproject-nexgen-rs) | `0x01` project-mgmt | **no** — maps onto core |
| `0x0002` | Odoo | `0x02` commerce | **no** — maps onto core (converge `od-ontology`) |
| `0x0003` | WoA / woa-rs | `0x02` commerce (work orders) | **no** — maps onto core |
Expand All @@ -146,6 +146,7 @@ materialised until the app mints its first private class).
| `0x0006` | q2 (Gotham / aiwar / neo4j) | `0x07` osint (+ TBD) | **TBD** — port not yet authored |
| `0x0007` | Redmine | `0x01` project-mgmt | **no** — same concepts as OpenProject, own templates |
| `0x0008` | OpenStreetMap (openstreetmap-website-rs) | `0x0F` geo | **no** — maps entirely onto core |
| `0x0009` | WeatherNext / weathernext-rs | `0x04` weather / atmosphere | **no** — maps onto core |
| `0x00A0` | (reserved) future app block | — | — |

> **OpenProject (`0x0001`) and Redmine (`0x0007`) are the showcase:**
Expand Down
Loading