From 080514b2172c11bad697e36b7f0cdaadefde61b8 Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:07:15 +0200 Subject: [PATCH 01/18] ci: bootstrap weather classid mint --- .../weather-classid-mint-bootstrap.yml | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 .github/workflows/weather-classid-mint-bootstrap.yml diff --git a/.github/workflows/weather-classid-mint-bootstrap.yml b/.github/workflows/weather-classid-mint-bootstrap.yml new file mode 100644 index 00000000..5dace910 --- /dev/null +++ b/.github/workflows/weather-classid-mint-bootstrap.yml @@ -0,0 +1,133 @@ +name: Weather classid mint bootstrap + +on: + push: + branches: + - codex/weather-classid-mint-271 + +permissions: + contents: write + +jobs: + mint: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + with: + ref: codex/weather-classid-mint-271 + fetch-depth: 0 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt,clippy + - name: Apply append-only weather authority + shell: python + run: | + from pathlib import Path + + def once(text: str, old: str, new: str, label: str) -> str: + n = text.count(old) + if n != 1: + raise SystemExit(f"{label}: expected exactly one anchor, found {n}") + return text.replace(old, new, 1) + + libp = Path('crates/ogar-vocab/src/lib.rs') + s = libp.read_text() + s = once(s, '/// 0x04XX unassigned\n', '/// 0x04XX Weather / Atmosphere (forecast + atmospheric reference cells)\n', 'domain map doc') + s = once(s, + ' // ── 0x07XX — OSINT domain: ZERO vocabulary rows BY DESIGN (operator\n', + ' // ── 0x04XX — Weather / Atmosphere domain ──\n' + ' // Canonical atmospheric/grid concepts consumed by WeatherNext and the\n' + ' // lance-graph weather SoA bake. These are shared meanings; renderer /\n' + ' // ClassView selection remains in the low u16 of the full classid.\n' + ' ("weather_cell", 0x0401),\n' + ' ("weather_static_cell", 0x0402),\n' + ' // ── 0x07XX — OSINT domain: ZERO vocabulary rows BY DESIGN (operator\n', + 'CODEBOOK weather rows') + s = once(s, + ' Ontology,\n /// `0x07XX` — OSINT (open-source intelligence).\n', + ' Ontology,\n /// `0x04XX` — Weather / Atmosphere. Shared atmospheric and forecast-grid\n' + ' /// concepts; public environmental reference data, not an OSM extension.\n' + ' Weather,\n /// `0x07XX` — OSINT (open-source intelligence).\n', + 'ConceptDomain Weather variant') + s = once(s, + ' 0x03 => ConceptDomain::Ontology,\n 0x07 => ConceptDomain::Osint,\n', + ' 0x03 => ConceptDomain::Ontology,\n 0x04 => ConceptDomain::Weather,\n 0x07 => ConceptDomain::Osint,\n', + 'Weather domain routing') + s = once(s, + ' // ── 0x08XX — OCR domain (document extraction; the Tesseract-rs arc) ──\n', + ' // ── 0x04XX — Weather / Atmosphere domain ──\n\n' + ' /// `weather_cell` (`0x0401`) — one dynamic atmospheric/forecast grid\n' + ' /// cell. Time is a dataset/version axis, not a new concept id.\n' + ' pub const WEATHER_CELL: u16 = 0x0401;\n' + ' /// `weather_static_cell` (`0x0402`) — static support cell for terrain /\n' + ' /// geography-derived weather context, distinct from dynamic fields.\n' + ' pub const WEATHER_STATIC_CELL: u16 = 0x0402;\n\n' + ' // ── 0x08XX — OCR domain (document extraction; the Tesseract-rs arc) ──\n', + 'class_ids constants') + s = once(s, + ' ("unit_of_measure", UNIT_OF_MEASURE),\n // 0x07XX — OSINT: ZERO vocabulary rows BY DESIGN', + ' ("unit_of_measure", UNIT_OF_MEASURE),\n // 0x04XX — Weather / Atmosphere\n' + ' ("weather_cell", WEATHER_CELL),\n' + ' ("weather_static_cell", WEATHER_STATIC_CELL),\n' + ' // 0x07XX — OSINT: ZERO vocabulary rows BY DESIGN', + 'class_ids::ALL weather rows') + s = once(s, + ' 91,\n "class_ids::ALL count changed', + ' 93,\n "class_ids::ALL count changed', + 'class_ids count fuse') + # Two minimal canonical Class builders. Keep the row payload schema in ClassView; + # these builders identify the concepts only, per the classid-is-address doctrine. + geo_builder_anchor = '// ─────────────────────────────────────────────────────────────────────\n// 0x0FXX — Geo domain builders (OpenStreetMap geodata reference ontology).\n' + weather_builders = '''// ─────────────────────────────────────────────────────────────────────\n// 0x04XX — Weather / Atmosphere canonical builders.\n// Field/level/unit slot semantics live in the consumer ClassView manifest;\n// the canonical class carries identity, never the weather payload layout.\n// ─────────────────────────────────────────────────────────────────────\n\n/// `weather_cell` (`0x0401`) — one dynamic atmospheric / forecast-grid cell.\n#[must_use]\npub fn weather_cell() -> Class {\n let mut c = Class::new("WeatherCell");\n c.language = Language::Unknown;\n c.canonical_concept = Some("weather_cell".to_string());\n c\n}\n\n/// `weather_static_cell` (`0x0402`) — static geography-derived support cell.\n#[must_use]\npub fn weather_static_cell() -> Class {\n let mut c = Class::new("WeatherStaticCell");\n c.language = Language::Unknown;\n c.canonical_concept = Some("weather_static_cell".to_string());\n c\n}\n\n''' + s = once(s, geo_builder_anchor, weather_builders + geo_builder_anchor, 'weather builders') + # Independent mint falsifiers, deliberately outside the huge legacy test module. + s += '''\n#[cfg(test)]\nmod weather_classid_mint_tests {\n use super::*;\n\n #[test]\n fn weather_domain_and_codebook_are_append_only_and_not_geo() {\n assert_eq!(canonical_concept_domain(class_ids::WEATHER_CELL), ConceptDomain::Weather);\n assert_eq!(canonical_concept_domain(class_ids::WEATHER_STATIC_CELL), ConceptDomain::Weather);\n assert_ne!(canonical_concept_domain(class_ids::WEATHER_CELL), ConceptDomain::Geo);\n assert_eq!(canonical_concept_id("weather_cell"), Some(0x0401));\n assert_eq!(canonical_concept_id("weather_static_cell"), Some(0x0402));\n assert_eq!(weather_cell().canonical_id(), Some(class_ids::WEATHER_CELL));\n assert_eq!(weather_static_cell().canonical_id(), Some(class_ids::WEATHER_STATIC_CELL));\n }\n}\n''' + libp.write_text(s) + + pp = Path('crates/ogar-vocab/src/ports.rs') + p = pp.read_text() + anchor = '#[cfg(test)]\nmod tests {' + weather_port = '''// ── WeatherNext / weathernext-rs port ───────────────────────────────\n\n/// WeatherNext's `PortSpec` over the shared Weather / Atmosphere (`0x04XX`)\n/// canonical concepts. `0x0009` is the reserved WeatherNext ClassView skin;\n/// the canonical meaning remains in the high u16.\npub struct WeatherNextPort;\n\nimpl PortSpec for WeatherNextPort {\n const NAMESPACE: &'static str = "WeatherNext";\n const BRIDGE_ID: &'static str = "weathernext";\n const APP_PREFIX: u16 = 0x0009;\n fn aliases() -> &'static [(&'static str, u16)] {\n WEATHERNEXT_ALIASES\n }\n}\n\n/// WeatherNext public names mapped onto shared canonical weather concepts.\npub const WEATHERNEXT_ALIASES: &[(&str, u16)] = &[\n ("WeatherCell", class_ids::WEATHER_CELL),\n ("WeatherStaticCell", class_ids::WEATHER_STATIC_CELL),\n];\n\n''' + p = once(p, anchor, weather_port + anchor, 'WeatherNext PortSpec') + p = once(p, + ' use super::*;\n', + ' use super::*;\n use crate::app::{app_of, concept_of, render_classid};\n\n' + ' #[test]\n' + ' fn weathernext_classview_composes_canon_high_custom_low() {\n' + ' assert_eq!(WeatherNextPort::APP_PREFIX, 0x0009);\n' + ' assert_eq!(WeatherNextPort::classview(), 0x0009);\n' + ' assert_eq!(WeatherNextPort::class_id("WeatherCell"), Some(0x0401));\n' + ' assert_eq!(WeatherNextPort::class_id("WeatherStaticCell"), Some(0x0402));\n' + ' let dynamic = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_CELL);\n' + ' let statics = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_STATIC_CELL);\n' + ' assert_eq!(dynamic, 0x0401_0009);\n' + ' assert_eq!(statics, 0x0402_0009);\n' + ' assert_eq!(concept_of(dynamic), 0x0401);\n' + ' assert_eq!(app_of(dynamic), 0x0009);\n' + ' }\n', + 'WeatherNext tests') + pp.write_text(p) + + dp = Path('docs/APP-CLASS-CODEBOOK-LAYOUT.md') + d = dp.read_text() + d = once(d, + '| `0x0008` | OpenStreetMap (openstreetmap-website-rs) | `0x0F` geo | **no** — maps entirely onto core |\n', + '| `0x0008` | OpenStreetMap (openstreetmap-website-rs) | `0x0F` geo | **no** — maps entirely onto core |\n' + '| `0x0009` | WeatherNext / weathernext-rs | `0x04` weather / atmosphere | **no** — maps onto core |\n', + 'ClassView allocation table') + dp.write_text(d) + - name: Format and test the mint + run: | + cargo fmt --all -- --check || cargo fmt --all + cargo test -p ogar-vocab + cargo clippy -p ogar-vocab --all-targets -- -D warnings + - name: Commit tested mint and remove bootstrap + run: | + git rm .github/workflows/weather-classid-mint-bootstrap.yml + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add crates/ogar-vocab/src/lib.rs crates/ogar-vocab/src/ports.rs docs/APP-CLASS-CODEBOOK-LAYOUT.md + git commit -m "feat(vocab): mint Weather/Atmosphere classids (#271)" + git push origin HEAD:codex/weather-classid-mint-271 From a472e551b358c2e70b77db3629e06a0ed11a5cb9 Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:07:47 +0200 Subject: [PATCH 02/18] chore: trigger weather mint bootstrap --- .claude/weather-mint-trigger | 1 + 1 file changed, 1 insertion(+) create mode 100644 .claude/weather-mint-trigger diff --git a/.claude/weather-mint-trigger b/.claude/weather-mint-trigger new file mode 100644 index 00000000..405d0b63 --- /dev/null +++ b/.claude/weather-mint-trigger @@ -0,0 +1 @@ +issue=271 From b207c2a6ae71b961dc3582e16d43597cf8b9793e Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:08:17 +0200 Subject: [PATCH 03/18] ci: replace weather mint bootstrap --- .../weather-classid-mint-bootstrap.yml | 133 ------------------ 1 file changed, 133 deletions(-) delete mode 100644 .github/workflows/weather-classid-mint-bootstrap.yml diff --git a/.github/workflows/weather-classid-mint-bootstrap.yml b/.github/workflows/weather-classid-mint-bootstrap.yml deleted file mode 100644 index 5dace910..00000000 --- a/.github/workflows/weather-classid-mint-bootstrap.yml +++ /dev/null @@ -1,133 +0,0 @@ -name: Weather classid mint bootstrap - -on: - push: - branches: - - codex/weather-classid-mint-271 - -permissions: - contents: write - -jobs: - mint: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-24.04 - timeout-minutes: 15 - steps: - - uses: actions/checkout@v4 - with: - ref: codex/weather-classid-mint-271 - fetch-depth: 0 - - uses: dtolnay/rust-toolchain@stable - with: - components: rustfmt,clippy - - name: Apply append-only weather authority - shell: python - run: | - from pathlib import Path - - def once(text: str, old: str, new: str, label: str) -> str: - n = text.count(old) - if n != 1: - raise SystemExit(f"{label}: expected exactly one anchor, found {n}") - return text.replace(old, new, 1) - - libp = Path('crates/ogar-vocab/src/lib.rs') - s = libp.read_text() - s = once(s, '/// 0x04XX unassigned\n', '/// 0x04XX Weather / Atmosphere (forecast + atmospheric reference cells)\n', 'domain map doc') - s = once(s, - ' // ── 0x07XX — OSINT domain: ZERO vocabulary rows BY DESIGN (operator\n', - ' // ── 0x04XX — Weather / Atmosphere domain ──\n' - ' // Canonical atmospheric/grid concepts consumed by WeatherNext and the\n' - ' // lance-graph weather SoA bake. These are shared meanings; renderer /\n' - ' // ClassView selection remains in the low u16 of the full classid.\n' - ' ("weather_cell", 0x0401),\n' - ' ("weather_static_cell", 0x0402),\n' - ' // ── 0x07XX — OSINT domain: ZERO vocabulary rows BY DESIGN (operator\n', - 'CODEBOOK weather rows') - s = once(s, - ' Ontology,\n /// `0x07XX` — OSINT (open-source intelligence).\n', - ' Ontology,\n /// `0x04XX` — Weather / Atmosphere. Shared atmospheric and forecast-grid\n' - ' /// concepts; public environmental reference data, not an OSM extension.\n' - ' Weather,\n /// `0x07XX` — OSINT (open-source intelligence).\n', - 'ConceptDomain Weather variant') - s = once(s, - ' 0x03 => ConceptDomain::Ontology,\n 0x07 => ConceptDomain::Osint,\n', - ' 0x03 => ConceptDomain::Ontology,\n 0x04 => ConceptDomain::Weather,\n 0x07 => ConceptDomain::Osint,\n', - 'Weather domain routing') - s = once(s, - ' // ── 0x08XX — OCR domain (document extraction; the Tesseract-rs arc) ──\n', - ' // ── 0x04XX — Weather / Atmosphere domain ──\n\n' - ' /// `weather_cell` (`0x0401`) — one dynamic atmospheric/forecast grid\n' - ' /// cell. Time is a dataset/version axis, not a new concept id.\n' - ' pub const WEATHER_CELL: u16 = 0x0401;\n' - ' /// `weather_static_cell` (`0x0402`) — static support cell for terrain /\n' - ' /// geography-derived weather context, distinct from dynamic fields.\n' - ' pub const WEATHER_STATIC_CELL: u16 = 0x0402;\n\n' - ' // ── 0x08XX — OCR domain (document extraction; the Tesseract-rs arc) ──\n', - 'class_ids constants') - s = once(s, - ' ("unit_of_measure", UNIT_OF_MEASURE),\n // 0x07XX — OSINT: ZERO vocabulary rows BY DESIGN', - ' ("unit_of_measure", UNIT_OF_MEASURE),\n // 0x04XX — Weather / Atmosphere\n' - ' ("weather_cell", WEATHER_CELL),\n' - ' ("weather_static_cell", WEATHER_STATIC_CELL),\n' - ' // 0x07XX — OSINT: ZERO vocabulary rows BY DESIGN', - 'class_ids::ALL weather rows') - s = once(s, - ' 91,\n "class_ids::ALL count changed', - ' 93,\n "class_ids::ALL count changed', - 'class_ids count fuse') - # Two minimal canonical Class builders. Keep the row payload schema in ClassView; - # these builders identify the concepts only, per the classid-is-address doctrine. - geo_builder_anchor = '// ─────────────────────────────────────────────────────────────────────\n// 0x0FXX — Geo domain builders (OpenStreetMap geodata reference ontology).\n' - weather_builders = '''// ─────────────────────────────────────────────────────────────────────\n// 0x04XX — Weather / Atmosphere canonical builders.\n// Field/level/unit slot semantics live in the consumer ClassView manifest;\n// the canonical class carries identity, never the weather payload layout.\n// ─────────────────────────────────────────────────────────────────────\n\n/// `weather_cell` (`0x0401`) — one dynamic atmospheric / forecast-grid cell.\n#[must_use]\npub fn weather_cell() -> Class {\n let mut c = Class::new("WeatherCell");\n c.language = Language::Unknown;\n c.canonical_concept = Some("weather_cell".to_string());\n c\n}\n\n/// `weather_static_cell` (`0x0402`) — static geography-derived support cell.\n#[must_use]\npub fn weather_static_cell() -> Class {\n let mut c = Class::new("WeatherStaticCell");\n c.language = Language::Unknown;\n c.canonical_concept = Some("weather_static_cell".to_string());\n c\n}\n\n''' - s = once(s, geo_builder_anchor, weather_builders + geo_builder_anchor, 'weather builders') - # Independent mint falsifiers, deliberately outside the huge legacy test module. - s += '''\n#[cfg(test)]\nmod weather_classid_mint_tests {\n use super::*;\n\n #[test]\n fn weather_domain_and_codebook_are_append_only_and_not_geo() {\n assert_eq!(canonical_concept_domain(class_ids::WEATHER_CELL), ConceptDomain::Weather);\n assert_eq!(canonical_concept_domain(class_ids::WEATHER_STATIC_CELL), ConceptDomain::Weather);\n assert_ne!(canonical_concept_domain(class_ids::WEATHER_CELL), ConceptDomain::Geo);\n assert_eq!(canonical_concept_id("weather_cell"), Some(0x0401));\n assert_eq!(canonical_concept_id("weather_static_cell"), Some(0x0402));\n assert_eq!(weather_cell().canonical_id(), Some(class_ids::WEATHER_CELL));\n assert_eq!(weather_static_cell().canonical_id(), Some(class_ids::WEATHER_STATIC_CELL));\n }\n}\n''' - libp.write_text(s) - - pp = Path('crates/ogar-vocab/src/ports.rs') - p = pp.read_text() - anchor = '#[cfg(test)]\nmod tests {' - weather_port = '''// ── WeatherNext / weathernext-rs port ───────────────────────────────\n\n/// WeatherNext's `PortSpec` over the shared Weather / Atmosphere (`0x04XX`)\n/// canonical concepts. `0x0009` is the reserved WeatherNext ClassView skin;\n/// the canonical meaning remains in the high u16.\npub struct WeatherNextPort;\n\nimpl PortSpec for WeatherNextPort {\n const NAMESPACE: &'static str = "WeatherNext";\n const BRIDGE_ID: &'static str = "weathernext";\n const APP_PREFIX: u16 = 0x0009;\n fn aliases() -> &'static [(&'static str, u16)] {\n WEATHERNEXT_ALIASES\n }\n}\n\n/// WeatherNext public names mapped onto shared canonical weather concepts.\npub const WEATHERNEXT_ALIASES: &[(&str, u16)] = &[\n ("WeatherCell", class_ids::WEATHER_CELL),\n ("WeatherStaticCell", class_ids::WEATHER_STATIC_CELL),\n];\n\n''' - p = once(p, anchor, weather_port + anchor, 'WeatherNext PortSpec') - p = once(p, - ' use super::*;\n', - ' use super::*;\n use crate::app::{app_of, concept_of, render_classid};\n\n' - ' #[test]\n' - ' fn weathernext_classview_composes_canon_high_custom_low() {\n' - ' assert_eq!(WeatherNextPort::APP_PREFIX, 0x0009);\n' - ' assert_eq!(WeatherNextPort::classview(), 0x0009);\n' - ' assert_eq!(WeatherNextPort::class_id("WeatherCell"), Some(0x0401));\n' - ' assert_eq!(WeatherNextPort::class_id("WeatherStaticCell"), Some(0x0402));\n' - ' let dynamic = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_CELL);\n' - ' let statics = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_STATIC_CELL);\n' - ' assert_eq!(dynamic, 0x0401_0009);\n' - ' assert_eq!(statics, 0x0402_0009);\n' - ' assert_eq!(concept_of(dynamic), 0x0401);\n' - ' assert_eq!(app_of(dynamic), 0x0009);\n' - ' }\n', - 'WeatherNext tests') - pp.write_text(p) - - dp = Path('docs/APP-CLASS-CODEBOOK-LAYOUT.md') - d = dp.read_text() - d = once(d, - '| `0x0008` | OpenStreetMap (openstreetmap-website-rs) | `0x0F` geo | **no** — maps entirely onto core |\n', - '| `0x0008` | OpenStreetMap (openstreetmap-website-rs) | `0x0F` geo | **no** — maps entirely onto core |\n' - '| `0x0009` | WeatherNext / weathernext-rs | `0x04` weather / atmosphere | **no** — maps onto core |\n', - 'ClassView allocation table') - dp.write_text(d) - - name: Format and test the mint - run: | - cargo fmt --all -- --check || cargo fmt --all - cargo test -p ogar-vocab - cargo clippy -p ogar-vocab --all-targets -- -D warnings - - name: Commit tested mint and remove bootstrap - run: | - git rm .github/workflows/weather-classid-mint-bootstrap.yml - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add crates/ogar-vocab/src/lib.rs crates/ogar-vocab/src/ports.rs docs/APP-CLASS-CODEBOOK-LAYOUT.md - git commit -m "feat(vocab): mint Weather/Atmosphere classids (#271)" - git push origin HEAD:codex/weather-classid-mint-271 From 244dabc10aa469936639aecc77b6971f01bdac5e Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:08:40 +0200 Subject: [PATCH 04/18] ci: add weather mint patcher --- .github/scripts/weather_classid_mint.py | 192 ++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 .github/scripts/weather_classid_mint.py diff --git a/.github/scripts/weather_classid_mint.py b/.github/scripts/weather_classid_mint.py new file mode 100644 index 00000000..617b0285 --- /dev/null +++ b/.github/scripts/weather_classid_mint.py @@ -0,0 +1,192 @@ +from pathlib import Path + + +def once(text: str, old: str, new: str, label: str) -> str: + n = text.count(old) + if n != 1: + raise SystemExit(f"{label}: expected exactly one anchor, found {n}") + return text.replace(old, new, 1) + + +libp = Path("crates/ogar-vocab/src/lib.rs") +s = libp.read_text() +s = once( + s, + "/// 0x04XX unassigned\n", + "/// 0x04XX Weather / Atmosphere (forecast + atmospheric reference cells)\n", + "domain map doc", +) +s = once( + s, + " // ── 0x07XX — OSINT domain: ZERO vocabulary rows BY DESIGN (operator\n", + " // ── 0x04XX — Weather / Atmosphere domain ──\n" + " // Canonical atmospheric/grid concepts consumed by WeatherNext and the\n" + " // lance-graph weather SoA bake. These are shared meanings; renderer /\n" + " // ClassView selection remains in the low u16 of the full classid.\n" + " (\"weather_cell\", 0x0401),\n" + " (\"weather_static_cell\", 0x0402),\n" + " // ── 0x07XX — OSINT domain: ZERO vocabulary rows BY DESIGN (operator\n", + "CODEBOOK weather rows", +) +s = once( + s, + " Ontology,\n /// `0x07XX` — OSINT (open-source intelligence).\n", + " Ontology,\n" + " /// `0x04XX` — Weather / Atmosphere. Shared atmospheric and forecast-grid\n" + " /// concepts; public environmental reference data, not an OSM extension.\n" + " Weather,\n" + " /// `0x07XX` — OSINT (open-source intelligence).\n", + "ConceptDomain Weather variant", +) +s = once( + s, + " 0x03 => ConceptDomain::Ontology,\n 0x07 => ConceptDomain::Osint,\n", + " 0x03 => ConceptDomain::Ontology,\n" + " 0x04 => ConceptDomain::Weather,\n" + " 0x07 => ConceptDomain::Osint,\n", + "Weather domain routing", +) + +# Scope the constants insertion to class_ids so the identically-worded CODEBOOK +# OCR marker cannot be selected accidentally. +class_ids_at = s.index("pub mod class_ids {") +head, class_ids_tail = s[:class_ids_at], s[class_ids_at:] +class_ids_tail = once( + class_ids_tail, + " // ── 0x08XX — OCR domain (document extraction; the Tesseract-rs arc) ──\n", + " // ── 0x04XX — Weather / Atmosphere domain ──\n\n" + " /// `weather_cell` (`0x0401`) — one dynamic atmospheric/forecast grid\n" + " /// cell. Time is a dataset/version axis, not a new concept id.\n" + " pub const WEATHER_CELL: u16 = 0x0401;\n" + " /// `weather_static_cell` (`0x0402`) — static support cell for terrain /\n" + " /// geography-derived weather context, distinct from dynamic fields.\n" + " pub const WEATHER_STATIC_CELL: u16 = 0x0402;\n\n" + " // ── 0x08XX — OCR domain (document extraction; the Tesseract-rs arc) ──\n", + "class_ids constants", +) +s = head + class_ids_tail +s = once( + s, + " (\"unit_of_measure\", UNIT_OF_MEASURE),\n // 0x07XX — OSINT: ZERO vocabulary rows BY DESIGN", + " (\"unit_of_measure\", UNIT_OF_MEASURE),\n" + " // 0x04XX — Weather / Atmosphere\n" + " (\"weather_cell\", WEATHER_CELL),\n" + " (\"weather_static_cell\", WEATHER_STATIC_CELL),\n" + " // 0x07XX — OSINT: ZERO vocabulary rows BY DESIGN", + "class_ids::ALL weather rows", +) +s = once( + s, + " 91,\n \"class_ids::ALL count changed", + " 93,\n \"class_ids::ALL count changed", + "class_ids count fuse", +) + +geo_builder_anchor = ( + "// ─────────────────────────────────────────────────────────────────────\n" + "// 0x0FXX — Geo domain builders (OpenStreetMap geodata reference ontology).\n" +) +weather_builders = '''// ───────────────────────────────────────────────────────────────────── +// 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 +} + +''' +s = once(s, geo_builder_anchor, weather_builders + geo_builder_anchor, "weather builders") +s += ''' +#[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)); + } +} +''' +libp.write_text(s) + +pp = Path("crates/ogar-vocab/src/ports.rs") +p = pp.read_text() +anchor = "#[cfg(test)]\nmod tests {" +weather_port = '''// ── 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), +]; + +''' +p = once(p, anchor, weather_port + anchor, "WeatherNext PortSpec") +p = once( + p, + " use super::*;\n", + " use super::*;\n" + " use crate::app::{app_of, concept_of, render_classid};\n\n" + " #[test]\n" + " fn weathernext_classview_composes_canon_high_custom_low() {\n" + " assert_eq!(WeatherNextPort::APP_PREFIX, 0x0009);\n" + " assert_eq!(WeatherNextPort::classview(), 0x0009);\n" + " assert_eq!(WeatherNextPort::class_id(\"WeatherCell\"), Some(0x0401));\n" + " assert_eq!(WeatherNextPort::class_id(\"WeatherStaticCell\"), Some(0x0402));\n" + " let dynamic = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_CELL);\n" + " let statics = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_STATIC_CELL);\n" + " assert_eq!(dynamic, 0x0401_0009);\n" + " assert_eq!(statics, 0x0402_0009);\n" + " assert_eq!(concept_of(dynamic), 0x0401);\n" + " assert_eq!(app_of(dynamic), 0x0009);\n" + " }\n", + "WeatherNext tests", +) +pp.write_text(p) + +dp = Path("docs/APP-CLASS-CODEBOOK-LAYOUT.md") +d = dp.read_text() +d = once( + d, + "| `0x0008` | OpenStreetMap (openstreetmap-website-rs) | `0x0F` geo | **no** — maps entirely onto core |\n", + "| `0x0008` | OpenStreetMap (openstreetmap-website-rs) | `0x0F` geo | **no** — maps entirely onto core |\n" + "| `0x0009` | WeatherNext / weathernext-rs | `0x04` weather / atmosphere | **no** — maps onto core |\n", + "ClassView allocation table", +) +dp.write_text(d) From 8aec7c6bc6dcb2a0f9243b31e56962bac6f9fdd9 Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:08:48 +0200 Subject: [PATCH 05/18] ci: run weather mint bootstrap --- .../weather-classid-mint-bootstrap.yml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/weather-classid-mint-bootstrap.yml diff --git a/.github/workflows/weather-classid-mint-bootstrap.yml b/.github/workflows/weather-classid-mint-bootstrap.yml new file mode 100644 index 00000000..5ba370e3 --- /dev/null +++ b/.github/workflows/weather-classid-mint-bootstrap.yml @@ -0,0 +1,38 @@ +name: Weather classid mint bootstrap + +on: + push: + branches: + - codex/weather-classid-mint-271 + +permissions: + contents: write + +jobs: + mint: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-24.04 + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + with: + ref: codex/weather-classid-mint-271 + fetch-depth: 0 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt,clippy + - name: Apply append-only weather authority + run: python .github/scripts/weather_classid_mint.py + - name: Format and test the mint + run: | + cargo fmt --all + cargo test -p ogar-vocab + cargo clippy -p ogar-vocab --all-targets -- -D warnings + - name: Commit tested mint and remove bootstrap + run: | + git rm .github/workflows/weather-classid-mint-bootstrap.yml .github/scripts/weather_classid_mint.py .claude/weather-mint-trigger + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add crates/ogar-vocab/src/lib.rs crates/ogar-vocab/src/ports.rs docs/APP-CLASS-CODEBOOK-LAYOUT.md + git commit -m "feat(vocab): mint Weather/Atmosphere classids (#271)" + git push origin HEAD:codex/weather-classid-mint-271 From c8fd977816ee312ce8ac011679315909e09eafe0 Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:11:49 +0200 Subject: [PATCH 06/18] ci: cover weather mint drift mirrors --- .github/scripts/weather_classid_followup.py | 50 +++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/scripts/weather_classid_followup.py diff --git a/.github/scripts/weather_classid_followup.py b/.github/scripts/weather_classid_followup.py new file mode 100644 index 00000000..cd60345c --- /dev/null +++ b/.github/scripts/weather_classid_followup.py @@ -0,0 +1,50 @@ +from pathlib import Path + + +def once(text: str, old: str, new: str, label: str) -> str: + n = text.count(old) + if n != 1: + raise SystemExit(f"{label}: expected exactly one anchor, found {n}") + return text.replace(old, new, 1) + + +libp = Path("crates/ogar-vocab/src/lib.rs") +s = libp.read_text() + +# all_promoted_classes() is an ordered structural mirror of class_ids::ALL. +# Weather occupies 0x04XX, immediately after 0x02XX commerce and before OCR. +s = once( + s, + " unicharset(),\n", + " weather_cell(),\n weather_static_cell(),\n unicharset(),\n", + "all_promoted_classes weather builders", +) + +# The domain routing test intentionally enumerates reserved/unassigned blocks. +# 0x04 has now been authoritatively allocated; only 0x05-0x06 remain unassigned. +s = once( + s, + " // Unassigned blocks (4-6).\n" + " assert_eq!(canonical_concept_domain(0x0400), ConceptDomain::Unassigned);\n" + " assert_eq!(canonical_concept_domain(0x0600), ConceptDomain::Unassigned);\n", + " // Weather / Atmosphere block (0x04), then still-unassigned 0x05-0x06.\n" + " assert_eq!(canonical_concept_domain(0x0400), ConceptDomain::Weather);\n" + " assert_eq!(canonical_concept_domain(0x0401), ConceptDomain::Weather);\n" + " assert_eq!(canonical_concept_domain(0x0500), ConceptDomain::Unassigned);\n" + " assert_eq!(canonical_concept_domain(0x0600), ConceptDomain::Unassigned);\n", + "domain allocation test", +) +libp.write_text(s) + +# This is a count fuse for the global codebook, not a palette-only count. The +# two canonical weather rows legitimately move it from 91 to 93; the 0x17XX +# exclusion assertion remains unchanged and continues to prove the actual rule. +cp = Path("crates/ogar-vocab/src/capability_registry.rs") +c = cp.read_text() +c = once( + c, + " assert_eq!(crate::class_ids::ALL.len(), 91);\n", + " assert_eq!(crate::class_ids::ALL.len(), 93);\n", + "global codebook count fuse", +) +cp.write_text(c) From dc1ce6379fe5e0c674a24d132c4f5da840d5d31f Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:12:04 +0200 Subject: [PATCH 07/18] ci: apply weather mint drift mirrors --- .github/workflows/weather-classid-mint-bootstrap.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/weather-classid-mint-bootstrap.yml b/.github/workflows/weather-classid-mint-bootstrap.yml index 5ba370e3..5def70f3 100644 --- a/.github/workflows/weather-classid-mint-bootstrap.yml +++ b/.github/workflows/weather-classid-mint-bootstrap.yml @@ -22,7 +22,9 @@ jobs: with: components: rustfmt,clippy - name: Apply append-only weather authority - run: python .github/scripts/weather_classid_mint.py + run: | + python .github/scripts/weather_classid_mint.py + python .github/scripts/weather_classid_followup.py - name: Format and test the mint run: | cargo fmt --all @@ -30,9 +32,9 @@ jobs: cargo clippy -p ogar-vocab --all-targets -- -D warnings - name: Commit tested mint and remove bootstrap run: | - git rm .github/workflows/weather-classid-mint-bootstrap.yml .github/scripts/weather_classid_mint.py .claude/weather-mint-trigger + git rm .github/workflows/weather-classid-mint-bootstrap.yml .github/scripts/weather_classid_mint.py .github/scripts/weather_classid_followup.py .claude/weather-mint-trigger git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add crates/ogar-vocab/src/lib.rs crates/ogar-vocab/src/ports.rs docs/APP-CLASS-CODEBOOK-LAYOUT.md + git add crates/ogar-vocab/src/lib.rs crates/ogar-vocab/src/ports.rs crates/ogar-vocab/src/capability_registry.rs docs/APP-CLASS-CODEBOOK-LAYOUT.md git commit -m "feat(vocab): mint Weather/Atmosphere classids (#271)" git push origin HEAD:codex/weather-classid-mint-271 From d1953d20dc0305a18bcf31ee1552f6f434e3a2fd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 14:13:20 +0000 Subject: [PATCH 08/18] feat(vocab): mint Weather/Atmosphere classids (#271) --- .claude/weather-mint-trigger | 1 - .github/scripts/weather_classid_followup.py | 50 ----- .github/scripts/weather_classid_mint.py | 192 ------------------ .../weather-classid-mint-bootstrap.yml | 40 ---- crates/ogar-vocab/src/capability_registry.rs | 2 +- crates/ogar-vocab/src/lib.rs | 86 +++++++- crates/ogar-vocab/src/ports.rs | 37 ++++ docs/APP-CLASS-CODEBOOK-LAYOUT.md | 1 + 8 files changed, 121 insertions(+), 288 deletions(-) delete mode 100644 .claude/weather-mint-trigger delete mode 100644 .github/scripts/weather_classid_followup.py delete mode 100644 .github/scripts/weather_classid_mint.py delete mode 100644 .github/workflows/weather-classid-mint-bootstrap.yml diff --git a/.claude/weather-mint-trigger b/.claude/weather-mint-trigger deleted file mode 100644 index 405d0b63..00000000 --- a/.claude/weather-mint-trigger +++ /dev/null @@ -1 +0,0 @@ -issue=271 diff --git a/.github/scripts/weather_classid_followup.py b/.github/scripts/weather_classid_followup.py deleted file mode 100644 index cd60345c..00000000 --- a/.github/scripts/weather_classid_followup.py +++ /dev/null @@ -1,50 +0,0 @@ -from pathlib import Path - - -def once(text: str, old: str, new: str, label: str) -> str: - n = text.count(old) - if n != 1: - raise SystemExit(f"{label}: expected exactly one anchor, found {n}") - return text.replace(old, new, 1) - - -libp = Path("crates/ogar-vocab/src/lib.rs") -s = libp.read_text() - -# all_promoted_classes() is an ordered structural mirror of class_ids::ALL. -# Weather occupies 0x04XX, immediately after 0x02XX commerce and before OCR. -s = once( - s, - " unicharset(),\n", - " weather_cell(),\n weather_static_cell(),\n unicharset(),\n", - "all_promoted_classes weather builders", -) - -# The domain routing test intentionally enumerates reserved/unassigned blocks. -# 0x04 has now been authoritatively allocated; only 0x05-0x06 remain unassigned. -s = once( - s, - " // Unassigned blocks (4-6).\n" - " assert_eq!(canonical_concept_domain(0x0400), ConceptDomain::Unassigned);\n" - " assert_eq!(canonical_concept_domain(0x0600), ConceptDomain::Unassigned);\n", - " // Weather / Atmosphere block (0x04), then still-unassigned 0x05-0x06.\n" - " assert_eq!(canonical_concept_domain(0x0400), ConceptDomain::Weather);\n" - " assert_eq!(canonical_concept_domain(0x0401), ConceptDomain::Weather);\n" - " assert_eq!(canonical_concept_domain(0x0500), ConceptDomain::Unassigned);\n" - " assert_eq!(canonical_concept_domain(0x0600), ConceptDomain::Unassigned);\n", - "domain allocation test", -) -libp.write_text(s) - -# This is a count fuse for the global codebook, not a palette-only count. The -# two canonical weather rows legitimately move it from 91 to 93; the 0x17XX -# exclusion assertion remains unchanged and continues to prove the actual rule. -cp = Path("crates/ogar-vocab/src/capability_registry.rs") -c = cp.read_text() -c = once( - c, - " assert_eq!(crate::class_ids::ALL.len(), 91);\n", - " assert_eq!(crate::class_ids::ALL.len(), 93);\n", - "global codebook count fuse", -) -cp.write_text(c) diff --git a/.github/scripts/weather_classid_mint.py b/.github/scripts/weather_classid_mint.py deleted file mode 100644 index 617b0285..00000000 --- a/.github/scripts/weather_classid_mint.py +++ /dev/null @@ -1,192 +0,0 @@ -from pathlib import Path - - -def once(text: str, old: str, new: str, label: str) -> str: - n = text.count(old) - if n != 1: - raise SystemExit(f"{label}: expected exactly one anchor, found {n}") - return text.replace(old, new, 1) - - -libp = Path("crates/ogar-vocab/src/lib.rs") -s = libp.read_text() -s = once( - s, - "/// 0x04XX unassigned\n", - "/// 0x04XX Weather / Atmosphere (forecast + atmospheric reference cells)\n", - "domain map doc", -) -s = once( - s, - " // ── 0x07XX — OSINT domain: ZERO vocabulary rows BY DESIGN (operator\n", - " // ── 0x04XX — Weather / Atmosphere domain ──\n" - " // Canonical atmospheric/grid concepts consumed by WeatherNext and the\n" - " // lance-graph weather SoA bake. These are shared meanings; renderer /\n" - " // ClassView selection remains in the low u16 of the full classid.\n" - " (\"weather_cell\", 0x0401),\n" - " (\"weather_static_cell\", 0x0402),\n" - " // ── 0x07XX — OSINT domain: ZERO vocabulary rows BY DESIGN (operator\n", - "CODEBOOK weather rows", -) -s = once( - s, - " Ontology,\n /// `0x07XX` — OSINT (open-source intelligence).\n", - " Ontology,\n" - " /// `0x04XX` — Weather / Atmosphere. Shared atmospheric and forecast-grid\n" - " /// concepts; public environmental reference data, not an OSM extension.\n" - " Weather,\n" - " /// `0x07XX` — OSINT (open-source intelligence).\n", - "ConceptDomain Weather variant", -) -s = once( - s, - " 0x03 => ConceptDomain::Ontology,\n 0x07 => ConceptDomain::Osint,\n", - " 0x03 => ConceptDomain::Ontology,\n" - " 0x04 => ConceptDomain::Weather,\n" - " 0x07 => ConceptDomain::Osint,\n", - "Weather domain routing", -) - -# Scope the constants insertion to class_ids so the identically-worded CODEBOOK -# OCR marker cannot be selected accidentally. -class_ids_at = s.index("pub mod class_ids {") -head, class_ids_tail = s[:class_ids_at], s[class_ids_at:] -class_ids_tail = once( - class_ids_tail, - " // ── 0x08XX — OCR domain (document extraction; the Tesseract-rs arc) ──\n", - " // ── 0x04XX — Weather / Atmosphere domain ──\n\n" - " /// `weather_cell` (`0x0401`) — one dynamic atmospheric/forecast grid\n" - " /// cell. Time is a dataset/version axis, not a new concept id.\n" - " pub const WEATHER_CELL: u16 = 0x0401;\n" - " /// `weather_static_cell` (`0x0402`) — static support cell for terrain /\n" - " /// geography-derived weather context, distinct from dynamic fields.\n" - " pub const WEATHER_STATIC_CELL: u16 = 0x0402;\n\n" - " // ── 0x08XX — OCR domain (document extraction; the Tesseract-rs arc) ──\n", - "class_ids constants", -) -s = head + class_ids_tail -s = once( - s, - " (\"unit_of_measure\", UNIT_OF_MEASURE),\n // 0x07XX — OSINT: ZERO vocabulary rows BY DESIGN", - " (\"unit_of_measure\", UNIT_OF_MEASURE),\n" - " // 0x04XX — Weather / Atmosphere\n" - " (\"weather_cell\", WEATHER_CELL),\n" - " (\"weather_static_cell\", WEATHER_STATIC_CELL),\n" - " // 0x07XX — OSINT: ZERO vocabulary rows BY DESIGN", - "class_ids::ALL weather rows", -) -s = once( - s, - " 91,\n \"class_ids::ALL count changed", - " 93,\n \"class_ids::ALL count changed", - "class_ids count fuse", -) - -geo_builder_anchor = ( - "// ─────────────────────────────────────────────────────────────────────\n" - "// 0x0FXX — Geo domain builders (OpenStreetMap geodata reference ontology).\n" -) -weather_builders = '''// ───────────────────────────────────────────────────────────────────── -// 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 -} - -''' -s = once(s, geo_builder_anchor, weather_builders + geo_builder_anchor, "weather builders") -s += ''' -#[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)); - } -} -''' -libp.write_text(s) - -pp = Path("crates/ogar-vocab/src/ports.rs") -p = pp.read_text() -anchor = "#[cfg(test)]\nmod tests {" -weather_port = '''// ── 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), -]; - -''' -p = once(p, anchor, weather_port + anchor, "WeatherNext PortSpec") -p = once( - p, - " use super::*;\n", - " use super::*;\n" - " use crate::app::{app_of, concept_of, render_classid};\n\n" - " #[test]\n" - " fn weathernext_classview_composes_canon_high_custom_low() {\n" - " assert_eq!(WeatherNextPort::APP_PREFIX, 0x0009);\n" - " assert_eq!(WeatherNextPort::classview(), 0x0009);\n" - " assert_eq!(WeatherNextPort::class_id(\"WeatherCell\"), Some(0x0401));\n" - " assert_eq!(WeatherNextPort::class_id(\"WeatherStaticCell\"), Some(0x0402));\n" - " let dynamic = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_CELL);\n" - " let statics = render_classid(WeatherNextPort::APP_PREFIX, class_ids::WEATHER_STATIC_CELL);\n" - " assert_eq!(dynamic, 0x0401_0009);\n" - " assert_eq!(statics, 0x0402_0009);\n" - " assert_eq!(concept_of(dynamic), 0x0401);\n" - " assert_eq!(app_of(dynamic), 0x0009);\n" - " }\n", - "WeatherNext tests", -) -pp.write_text(p) - -dp = Path("docs/APP-CLASS-CODEBOOK-LAYOUT.md") -d = dp.read_text() -d = once( - d, - "| `0x0008` | OpenStreetMap (openstreetmap-website-rs) | `0x0F` geo | **no** — maps entirely onto core |\n", - "| `0x0008` | OpenStreetMap (openstreetmap-website-rs) | `0x0F` geo | **no** — maps entirely onto core |\n" - "| `0x0009` | WeatherNext / weathernext-rs | `0x04` weather / atmosphere | **no** — maps onto core |\n", - "ClassView allocation table", -) -dp.write_text(d) diff --git a/.github/workflows/weather-classid-mint-bootstrap.yml b/.github/workflows/weather-classid-mint-bootstrap.yml deleted file mode 100644 index 5def70f3..00000000 --- a/.github/workflows/weather-classid-mint-bootstrap.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Weather classid mint bootstrap - -on: - push: - branches: - - codex/weather-classid-mint-271 - -permissions: - contents: write - -jobs: - mint: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-24.04 - timeout-minutes: 15 - steps: - - uses: actions/checkout@v4 - with: - ref: codex/weather-classid-mint-271 - fetch-depth: 0 - - uses: dtolnay/rust-toolchain@stable - with: - components: rustfmt,clippy - - name: Apply append-only weather authority - run: | - python .github/scripts/weather_classid_mint.py - python .github/scripts/weather_classid_followup.py - - name: Format and test the mint - run: | - cargo fmt --all - cargo test -p ogar-vocab - cargo clippy -p ogar-vocab --all-targets -- -D warnings - - name: Commit tested mint and remove bootstrap - run: | - git rm .github/workflows/weather-classid-mint-bootstrap.yml .github/scripts/weather_classid_mint.py .github/scripts/weather_classid_followup.py .claude/weather-mint-trigger - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add crates/ogar-vocab/src/lib.rs crates/ogar-vocab/src/ports.rs crates/ogar-vocab/src/capability_registry.rs docs/APP-CLASS-CODEBOOK-LAYOUT.md - git commit -m "feat(vocab): mint Weather/Atmosphere classids (#271)" - git push origin HEAD:codex/weather-classid-mint-271 diff --git a/crates/ogar-vocab/src/capability_registry.rs b/crates/ogar-vocab/src/capability_registry.rs index 3dff13fa..44bf1a0b 100644 --- a/crates/ogar-vocab/src/capability_registry.rs +++ b/crates/ogar-vocab/src/capability_registry.rs @@ -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"); } diff --git a/crates/ogar-vocab/src/lib.rs b/crates/ogar-vocab/src/lib.rs index cdc8f54f..affe854e 100644 --- a/crates/ogar-vocab/src/lib.rs +++ b/crates/ogar-vocab/src/lib.rs @@ -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 @@ -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 @@ -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, /// `0x07XX` — OSINT (open-source intelligence). Osint, /// `0x08XX` — OCR (optical character recognition / document @@ -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, @@ -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 @@ -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. @@ -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", @@ -3005,6 +3027,8 @@ pub fn all_promoted_classes() -> Vec { // 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(), @@ -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 @@ -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); @@ -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) + ); + } +} diff --git a/crates/ogar-vocab/src/ports.rs b/crates/ogar-vocab/src/ports.rs index f0217340..6947a721 100644 --- a/crates/ogar-vocab/src/ports.rs +++ b/crates/ogar-vocab/src/ports.rs @@ -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() { diff --git a/docs/APP-CLASS-CODEBOOK-LAYOUT.md b/docs/APP-CLASS-CODEBOOK-LAYOUT.md index 9b2fc700..f015f234 100644 --- a/docs/APP-CLASS-CODEBOOK-LAYOUT.md +++ b/docs/APP-CLASS-CODEBOOK-LAYOUT.md @@ -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:** From 70c286ac62b51fcf0a748318a907553f786d732a Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:16:14 +0200 Subject: [PATCH 09/18] ci: patch Weather ClassView mirror --- .../scripts/weather_class_view_followup.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/scripts/weather_class_view_followup.py diff --git a/.github/scripts/weather_class_view_followup.py b/.github/scripts/weather_class_view_followup.py new file mode 100644 index 00000000..fd286b69 --- /dev/null +++ b/.github/scripts/weather_class_view_followup.py @@ -0,0 +1,36 @@ +from pathlib import Path + + +def once(text: str, old: str, new: str, label: str) -> str: + n = text.count(old) + if n != 1: + raise SystemExit(f"{label}: expected exactly one anchor, found {n}") + return text.replace(old, new, 1) + + +p = Path("crates/ogar-class-view/src/lib.rs") +s = p.read_text() + +s = once( + s, + " visit,\n vital_sign,\n};\n", + " visit,\n vital_sign,\n weather_cell,\n weather_static_cell,\n};\n", + "weather builder imports", +) + +s = once( + s, + " (\"unit_of_measure\", unit_of_measure()),\n" + " // ── 0x08XX — OCR (container kinds; content stays in content stores) ──\n", + " (\"unit_of_measure\", unit_of_measure()),\n" + " // ── 0x04XX — Weather / Atmosphere ──\n" + " // These canonical views intentionally carry no W1 payload fields:\n" + " // field/level/unit slots are selected by WeatherNext's ClassView\n" + " // manifest, not promoted into the shared OGAR schema.\n" + " (\"weather_cell\", weather_cell()),\n" + " (\"weather_static_cell\", weather_static_cell()),\n" + " // ── 0x08XX — OCR (container kinds; content stays in content stores) ──\n", + "all_canonical_classes weather rows", +) + +p.write_text(s) From a6731a7ad55b0ff6bc67997acd99408711f20e57 Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:16:22 +0200 Subject: [PATCH 10/18] ci: run Weather ClassView follow-up --- .../workflows/weather-class-view-followup.yml | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/weather-class-view-followup.yml diff --git a/.github/workflows/weather-class-view-followup.yml b/.github/workflows/weather-class-view-followup.yml new file mode 100644 index 00000000..f3e3686b --- /dev/null +++ b/.github/workflows/weather-class-view-followup.yml @@ -0,0 +1,37 @@ +name: Weather ClassView follow-up + +on: + push: + branches: + - codex/weather-classid-mint-271 + +permissions: + contents: write + +jobs: + patch: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + ref: codex/weather-classid-mint-271 + fetch-depth: 0 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - name: Apply ClassView mirror + run: python .github/scripts/weather_class_view_followup.py + - name: Prove the affected package + run: | + cargo fmt --all + cargo test -p ogar-class-view + - name: Commit tested follow-up and remove bootstrap + run: | + git rm .github/workflows/weather-class-view-followup.yml .github/scripts/weather_class_view_followup.py + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add crates/ogar-class-view/src/lib.rs + git commit -m "fix(class-view): mirror Weather canonical concepts" + git push origin HEAD:codex/weather-classid-mint-271 From ecbea129682ca51c324ad94a693891cd1fa3df15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 14:17:48 +0000 Subject: [PATCH 11/18] fix(class-view): mirror Weather canonical concepts --- .../scripts/weather_class_view_followup.py | 36 ------------------ .../workflows/weather-class-view-followup.yml | 37 ------------------- crates/ogar-class-view/src/lib.rs | 8 ++++ 3 files changed, 8 insertions(+), 73 deletions(-) delete mode 100644 .github/scripts/weather_class_view_followup.py delete mode 100644 .github/workflows/weather-class-view-followup.yml diff --git a/.github/scripts/weather_class_view_followup.py b/.github/scripts/weather_class_view_followup.py deleted file mode 100644 index fd286b69..00000000 --- a/.github/scripts/weather_class_view_followup.py +++ /dev/null @@ -1,36 +0,0 @@ -from pathlib import Path - - -def once(text: str, old: str, new: str, label: str) -> str: - n = text.count(old) - if n != 1: - raise SystemExit(f"{label}: expected exactly one anchor, found {n}") - return text.replace(old, new, 1) - - -p = Path("crates/ogar-class-view/src/lib.rs") -s = p.read_text() - -s = once( - s, - " visit,\n vital_sign,\n};\n", - " visit,\n vital_sign,\n weather_cell,\n weather_static_cell,\n};\n", - "weather builder imports", -) - -s = once( - s, - " (\"unit_of_measure\", unit_of_measure()),\n" - " // ── 0x08XX — OCR (container kinds; content stays in content stores) ──\n", - " (\"unit_of_measure\", unit_of_measure()),\n" - " // ── 0x04XX — Weather / Atmosphere ──\n" - " // These canonical views intentionally carry no W1 payload fields:\n" - " // field/level/unit slots are selected by WeatherNext's ClassView\n" - " // manifest, not promoted into the shared OGAR schema.\n" - " (\"weather_cell\", weather_cell()),\n" - " (\"weather_static_cell\", weather_static_cell()),\n" - " // ── 0x08XX — OCR (container kinds; content stays in content stores) ──\n", - "all_canonical_classes weather rows", -) - -p.write_text(s) diff --git a/.github/workflows/weather-class-view-followup.yml b/.github/workflows/weather-class-view-followup.yml deleted file mode 100644 index f3e3686b..00000000 --- a/.github/workflows/weather-class-view-followup.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Weather ClassView follow-up - -on: - push: - branches: - - codex/weather-classid-mint-271 - -permissions: - contents: write - -jobs: - patch: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-24.04 - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - with: - ref: codex/weather-classid-mint-271 - fetch-depth: 0 - - uses: dtolnay/rust-toolchain@stable - with: - components: rustfmt - - name: Apply ClassView mirror - run: python .github/scripts/weather_class_view_followup.py - - name: Prove the affected package - run: | - cargo fmt --all - cargo test -p ogar-class-view - - name: Commit tested follow-up and remove bootstrap - run: | - git rm .github/workflows/weather-class-view-followup.yml .github/scripts/weather_class_view_followup.py - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add crates/ogar-class-view/src/lib.rs - git commit -m "fix(class-view): mirror Weather canonical concepts" - git push origin HEAD:codex/weather-classid-mint-271 diff --git a/crates/ogar-class-view/src/lib.rs b/crates/ogar-class-view/src/lib.rs index 20061af7..327fd8ea 100644 --- a/crates/ogar-class-view/src/lib.rs +++ b/crates/ogar-class-view/src/lib.rs @@ -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)`. @@ -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()), From 6837a7548dcd7a531d1ed4d59f0da73ad2da642f Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:18:18 +0200 Subject: [PATCH 12/18] chore: trigger final Weather mint CI --- .claude/weather-final-ci-trigger | 1 + 1 file changed, 1 insertion(+) create mode 100644 .claude/weather-final-ci-trigger diff --git a/.claude/weather-final-ci-trigger b/.claude/weather-final-ci-trigger new file mode 100644 index 00000000..6be6f331 --- /dev/null +++ b/.claude/weather-final-ci-trigger @@ -0,0 +1 @@ +pr=272 From f8c409076c2f04098a60d384af83a6cc74e58fdc Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:18:30 +0200 Subject: [PATCH 13/18] chore: remove final Weather mint CI trigger --- .claude/weather-final-ci-trigger | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .claude/weather-final-ci-trigger diff --git a/.claude/weather-final-ci-trigger b/.claude/weather-final-ci-trigger deleted file mode 100644 index 6be6f331..00000000 --- a/.claude/weather-final-ci-trigger +++ /dev/null @@ -1 +0,0 @@ -pr=272 From a9261f74ea4836a5dfdd6d2f7f3d1875fe5aadc8 Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:21:19 +0200 Subject: [PATCH 14/18] ci: stage Weather review-doc fixes --- .github/scripts/weather_review_docs.py | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/scripts/weather_review_docs.py diff --git a/.github/scripts/weather_review_docs.py b/.github/scripts/weather_review_docs.py new file mode 100644 index 00000000..6fed880a --- /dev/null +++ b/.github/scripts/weather_review_docs.py @@ -0,0 +1,30 @@ +from pathlib import Path + + +def once(text: str, old: str, new: str, label: str) -> str: + n = text.count(old) + if n != 1: + raise SystemExit(f"{label}: expected one anchor, found {n}") + return text.replace(old, new, 1) + +p = Path('crates/ogar-vocab/src/lib.rs') +s = p.read_text() +s = once( + s, + ' /// Any high-byte slot not yet assigned a domain (`0x04XX`–`0x06XX`,\n' + ' /// `0x10XX`–`0x16XX`, `0x18XX`+).\n', + ' /// Any high-byte slot not yet assigned a domain (`0x05XX`–`0x06XX`,\n' + ' /// `0x10XX`–`0x16XX`, `0x18XX`+).\n', + 'Unassigned domain documentation', +) +p.write_text(s) + +dp = Path('docs/APP-CLASS-CODEBOOK-LAYOUT.md') +d = dp.read_text() +d = once( + d, + '| `0x0000` | **Shared canonical core** | all (`0x01/02/07/08/09` + `0x0A` anatomy + `0x0B` auth + `0x0C` automation) | n/a (this *is* core) |\n', + '| `0x0000` | **Shared canonical core** | all (`0x01/02/04/07/08/09` + `0x0A` anatomy + `0x0B` auth + `0x0C` automation) | n/a (this *is* core) |\n', + 'Shared core allocation documentation', +) +dp.write_text(d) From 3fd487456be2b39a95320ae013d6277dff7030f3 Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:21:30 +0200 Subject: [PATCH 15/18] ci: apply Weather review-doc fixes --- .github/workflows/weather-review-docs.yml | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/weather-review-docs.yml diff --git a/.github/workflows/weather-review-docs.yml b/.github/workflows/weather-review-docs.yml new file mode 100644 index 00000000..e16d88a2 --- /dev/null +++ b/.github/workflows/weather-review-docs.yml @@ -0,0 +1,30 @@ +name: Weather review docs + +on: + push: + branches: + - codex/weather-classid-mint-271 + +permissions: + contents: write + +jobs: + patch: + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-24.04 + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + with: + ref: codex/weather-classid-mint-271 + fetch-depth: 0 + - name: Apply review fixes + run: python .github/scripts/weather_review_docs.py + - name: Commit review fixes and remove bootstrap + run: | + git rm .github/workflows/weather-review-docs.yml .github/scripts/weather_review_docs.py + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add crates/ogar-vocab/src/lib.rs docs/APP-CLASS-CODEBOOK-LAYOUT.md + git commit -m "docs(vocab): align Weather domain allocation" + git push origin HEAD:codex/weather-classid-mint-271 From 68fd3a4e9fa0689d5a0cfbf45e24a55f48e8f30f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 14:21:39 +0000 Subject: [PATCH 16/18] docs(vocab): align Weather domain allocation --- .github/scripts/weather_review_docs.py | 30 ----------------------- .github/workflows/weather-review-docs.yml | 30 ----------------------- crates/ogar-vocab/src/lib.rs | 2 +- docs/APP-CLASS-CODEBOOK-LAYOUT.md | 2 +- 4 files changed, 2 insertions(+), 62 deletions(-) delete mode 100644 .github/scripts/weather_review_docs.py delete mode 100644 .github/workflows/weather-review-docs.yml diff --git a/.github/scripts/weather_review_docs.py b/.github/scripts/weather_review_docs.py deleted file mode 100644 index 6fed880a..00000000 --- a/.github/scripts/weather_review_docs.py +++ /dev/null @@ -1,30 +0,0 @@ -from pathlib import Path - - -def once(text: str, old: str, new: str, label: str) -> str: - n = text.count(old) - if n != 1: - raise SystemExit(f"{label}: expected one anchor, found {n}") - return text.replace(old, new, 1) - -p = Path('crates/ogar-vocab/src/lib.rs') -s = p.read_text() -s = once( - s, - ' /// Any high-byte slot not yet assigned a domain (`0x04XX`–`0x06XX`,\n' - ' /// `0x10XX`–`0x16XX`, `0x18XX`+).\n', - ' /// Any high-byte slot not yet assigned a domain (`0x05XX`–`0x06XX`,\n' - ' /// `0x10XX`–`0x16XX`, `0x18XX`+).\n', - 'Unassigned domain documentation', -) -p.write_text(s) - -dp = Path('docs/APP-CLASS-CODEBOOK-LAYOUT.md') -d = dp.read_text() -d = once( - d, - '| `0x0000` | **Shared canonical core** | all (`0x01/02/07/08/09` + `0x0A` anatomy + `0x0B` auth + `0x0C` automation) | n/a (this *is* core) |\n', - '| `0x0000` | **Shared canonical core** | all (`0x01/02/04/07/08/09` + `0x0A` anatomy + `0x0B` auth + `0x0C` automation) | n/a (this *is* core) |\n', - 'Shared core allocation documentation', -) -dp.write_text(d) diff --git a/.github/workflows/weather-review-docs.yml b/.github/workflows/weather-review-docs.yml deleted file mode 100644 index e16d88a2..00000000 --- a/.github/workflows/weather-review-docs.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Weather review docs - -on: - push: - branches: - - codex/weather-classid-mint-271 - -permissions: - contents: write - -jobs: - patch: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-24.04 - timeout-minutes: 5 - steps: - - uses: actions/checkout@v4 - with: - ref: codex/weather-classid-mint-271 - fetch-depth: 0 - - name: Apply review fixes - run: python .github/scripts/weather_review_docs.py - - name: Commit review fixes and remove bootstrap - run: | - git rm .github/workflows/weather-review-docs.yml .github/scripts/weather_review_docs.py - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add crates/ogar-vocab/src/lib.rs docs/APP-CLASS-CODEBOOK-LAYOUT.md - git commit -m "docs(vocab): align Weather domain allocation" - git push origin HEAD:codex/weather-classid-mint-271 diff --git a/crates/ogar-vocab/src/lib.rs b/crates/ogar-vocab/src/lib.rs index affe854e..053386cd 100644 --- a/crates/ogar-vocab/src/lib.rs +++ b/crates/ogar-vocab/src/lib.rs @@ -1499,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, } diff --git a/docs/APP-CLASS-CODEBOOK-LAYOUT.md b/docs/APP-CLASS-CODEBOOK-LAYOUT.md index f015f234..23453a68 100644 --- a/docs/APP-CLASS-CODEBOOK-LAYOUT.md +++ b/docs/APP-CLASS-CODEBOOK-LAYOUT.md @@ -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 | From 471438b7207c9cc3d600132379ca46b72fcccf1c Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:22:14 +0200 Subject: [PATCH 17/18] chore: trigger reviewed Weather mint CI --- .claude/weather-final-reviewed-ci | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .claude/weather-final-reviewed-ci diff --git a/.claude/weather-final-reviewed-ci b/.claude/weather-final-reviewed-ci new file mode 100644 index 00000000..9aaa4769 --- /dev/null +++ b/.claude/weather-final-reviewed-ci @@ -0,0 +1,2 @@ +pr=272 +review=resolved From f7a305ec549b619ce4c50af8f17744ee0b06ff8d Mon Sep 17 00:00:00 2001 From: AdaWorldAPI Date: Sat, 15 Aug 2026 16:22:26 +0200 Subject: [PATCH 18/18] chore: remove reviewed Weather mint CI trigger --- .claude/weather-final-reviewed-ci | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .claude/weather-final-reviewed-ci diff --git a/.claude/weather-final-reviewed-ci b/.claude/weather-final-reviewed-ci deleted file mode 100644 index 9aaa4769..00000000 --- a/.claude/weather-final-reviewed-ci +++ /dev/null @@ -1,2 +0,0 @@ -pr=272 -review=resolved