ogar-from-schema follow-up: 9-domain test + XSD transcode + framings#106
Merged
Conversation
Extend the lift-surface verification from MARS-only to 10 domains: MARS + Transport + Accounting + SalesDistribution + Credit + Cost + ServiceManagement + WorkOrder + Compliance + Audit. Coverage: * 210 TTL files across 9 new domains (in addition to MARS's 29) — all parse, all round-trip via the generic `assert_domain_roundtrip` helper. Zero unparseable shapes; zero round-trip failures. * `ttl_emit::tests::nine_domains_lift_surface_round_trip` is the permanent regression gate. Pins each domain's expected TTL count so an upstream re-vendor that drifts the inventory fires the test. Authorship verification (per the operator's suggestion to check `dcterms:creator`): * WorkOrder is FULLY OURS — sole authors are internal agent names (`bus-compiler`, `family-codec-smith`). The unusual `rdfs:Class`-as-verb convention is ours to revise toward `owl:ObjectProperty` without external coordination. * Accounting is MIXED-AUTHORSHIP — Viktor Voss (23 files, original arago) + a prior session's Claude extension (11 files, our local additions). * All other 7 domains are pure-upstream (single external human authors: chris.boos@almato.com, Marek Meyer, Peter Larem, Ola Irgens Kylling, Aymen Ayoub, …). This makes WorkOrder the natural prototyping ground for new TTL predicates OGAR wants to ship before pitching them to OGIT upstream. Doc updates: * `docs/OGIT-DOMAIN-LIFT-CATALOGUE.md` — 10 rows promoted to Lift-tested with per-row authorship provenance. Adds a verification recipe (`§ Verifying domain authorship`) so future sessions can re-run the `dcterms:creator` scan in one Python heredoc. * `.claude/board/EPIPHANIES.md` — new FINDING on author-provenance as a who-can-change-what discriminator. Test footprint: 16/16 in ogar-from-schema (was 15/15; the new test adds one). Workspace-wide: nothing else touched.
…haped action template, not a quirk
WorkOrder's 12 verbs/*.ttl are declared as `a rdfs:Class`, not
`owl:ObjectProperty`. The prior commit framed this as "an unusual
convention we're free to revise" — wrong framing.
The encoding is load-bearing. A `rdfs:Class` verb carries a typed
slot list (`ogit:mandatory-attributes`), an inheritance chain
(`rdfs:subClassOf`), and policy metadata (`ogit:requires-perm`,
`ogit:emits-audit`). That makes each verb a compile-time-validated
action template — the ontological counterpart to askama (Rust) and
jinja (Python) HTML templating.
Structural correspondence is exact:
* TTL file = template (.html.j2 equivalent)
* mandatory-attributes = struct field list (askama context shape)
* per-call binding = struct instance
* render = SPO triple emit + declared side effects (audit, ACL gate)
* rdfs:subClassOf = template inheritance ({% extends %})
* lift-time slot validation = askama's compile-time {{ field }} check
The existing ogar-render-askama crate is the natural landing — it
already renders Class views (noun-shaped); the verb-as-class encoding
is the parallel render path for Class actions (verb-shaped). Same
engine, different output medium.
Foundry-parity sharpens: Foundry's "action types" carry typed
parameters + slot validation + declared side effects + inheritance —
sold as a paid platform feature. Verb-as-class TTL + ogar-render-askama
gives the same four from open-source schemas and Rust templates.
Adds:
* docs/VERB-AS-CLASS-TEMPLATE.md (FRAMING v0) — analogy table, worked
example on WorkOrder/verbs/AccessesPortal.ttl, render flow,
cross-references to the existing render-askama crate.
* docs/OGIT-DOMAIN-LIFT-CATALOGUE.md (WorkOrder row): walks back the
"we can re-author to owl:ObjectProperty" framing — the convention
is deliberate and load-bearing for the action-render path.
* .claude/board/EPIPHANIES.md: FINDING entry with the correction
citing the prior commit, the analogy table, and the implications
for the ogar-render-askama actions submodule.
No code changes. Lift-tested round-trip count unchanged (16/16);
verb-as-class TTLs already parse cleanly via ttl::parse_file as
entities and round-trip via ttl_emit::emit_entity.
…oundry-parity collapse
The operator's framing — "digest Odoo and store it in TTL Jinja
Templates in OGIT and relive it agnostically for any verb/entity as
a class" — crystallizes the four pieces shipped across this PR (TTL
mirror, schema lift, verb-as-class template, dcterms:creator
provenance) into one coherent pipeline:
Odoo source → ogar-from-python (AST schema filter) → Class IR
→ ttl_emit → OGIT TTL templates at
vocab/imports/ogit/NTO/<Domain>/ with
dcterms:creator = bus-compiler
→ ogar-render-askama → any consumer instantiates any
entity-or-verb-as-class with a fresh binding;
Python runtime touched only at digest time.
Why store digests in OGIT NTO (not a parallel vocab/imports/odoo/):
the dcterms:creator author-scan from this same session gives clean
provenance — internal-agent authors (bus-compiler, family-codec-smith)
signal "ours to revise"; external-human authors signal "upstream-arago,
coordinate". The precedent exists today: Accounting/ already has 11
Claude-digested files alongside 23 Viktor Voss originals.
The Foundry-parity collapse (the punchline) — Foundry's four-layer
platform pitch maps to four pieces in this repo:
Foundry ingest → ogar-from-python digest (~1500 LOC, queued)
Foundry storage → vocab/imports/ogit/NTO/ TTL (exists)
Foundry render → ogar-render-askama::{views, actions} (~200 LOC for actions)
Foundry IAM+audit → verb-as-class requires-perm slot + Lance-version-as-audit (exists)
Foundry change mgmt → diff -r of digest re-runs (exists)
Total marginal code: <2000 LOC for what Foundry charges $$$ for.
Adds:
* docs/ODOO-DIGEST-TO-OGIT.md (FRAMING v0, 8 sections):
pipeline diagram; why-store-in-OGIT-NTO; the four shapes the
digester produces (entity-as-class, datatype attribute, association,
verb-as-class); v0 mapping table from the 6 already-minted commerce
concepts + 9 queued for codebook mint; drift-detector recipe;
blockers; Foundry-parity collapse table; cross-references.
* .claude/board/EPIPHANIES.md FRAMING entry: the pipeline, the
storage-location rationale, the parity-collapse table, and the
two concrete next-step deliverables (ogar-from-python +
ogar-render-askama::actions) that ship independently in
follow-up PRs.
No code changes. The architecture has been latent the whole time;
this commit makes it visible as one shape.
…es XSD↔TTL bijection, drops the Python oracle dep
The MARS XSD classification extractor (arago/MARS-Schema/tools/extract_classes.py,
~360 lines: ~140 extraction logic + ~150 table formatting) is now a
faithful Rust transcode at crates/ogar-from-schema/src/xsd.rs, behind
an optional `xsd` feature (pulls roxmltree, pure-Rust read-only XML
DOM; the default TTL path stays zero-parser-deps).
Not huge — the transcode is ~350 LOC Rust including tests. And it
doubles as the seed of the broader XSD → Class front-end: the same
walk that extracts classifications is the structural-arm lift for any
XSD schema.
What it lands:
* BYTE-FOR-BYTE transcode proof. xsd::to_asciidoc() reproduces the
Python `-F asciidoc` output exactly — 628 lines, including verbatim
XSD-documentation whitespace and the printAsciiDocFooter trailing
newline. Test xsd::tests::asciidoc_matches_python_oracle diffs
against the cached _oracle/classifications.adoc.
* XSD↔TTL BIJECTION CLOSED (was "queued" in MARS-TRANSCODING.md §2).
xsd::tests::xsd_classes_match_ttl_enum asserts full bidirectional
set-equality between the XSD-extracted Application value set and the
TTL validation-parameter enum — not just one-directional membership.
Two independent encodings of one taxonomy, provably equal both ways.
* PYTHON DEPENDENCY REMOVED from the calibration path. `cargo test
--features xsd` is the whole oracle now; no python3 interpreter
needed. extract_classes.py stays vendored in _oracle/ as the
provenance witness (what the transcode was proven against), not a
runtime dep.
Transcode discipline (faithful to the Python semantics):
* getAttribute("xml:lang") returns "" for absent (not None); lang
filter is "absent OR en". roxmltree resolves xml: to the xml
namespace, matched on attribute.name() == "lang".
* getXMLText concatenates DIRECT text-node children only (not
recursive); the documentation's internal whitespace is load-bearing
for the byte-match.
* :revdate: is datetime.now() in Python (non-deterministic); the Rust
to_asciidoc(c, revdate) takes it as a parameter so output is
reproducible and testable.
* The two-level extension chain (master complexType carries NodeType,
intermediate complexType carries Class, leaf element carries
SubClass) + the post-process phase that stitches base→element is
reproduced exactly, including the master_types gate.
Tests: 20/20 with --features xsd (16 default + 4 new xsd); 16/16 on
default (xsd code fully feature-gated). Clippy-clean (--no-deps),
fmt-clean.
Docs:
* docs/MARS-TRANSCODING.md §2 — bijection marked closed; Python-dep
removal noted; the Rust extractor added to the oracle-direction table.
* .claude/board/EPIPHANIES.md — FINDING with the transcode-discipline
notes for the next source→Rust port.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this is
Follow-up to #105 (
OGIT 1:1 import + ogar-from-schema producer). Fourcommits that were added to the branch after #105 merged. All additive,
no conflicts. Merge-base with
mainis the merged commitcce8420.f44f712dcterms:creatorauthorship provenanceb5984607d680428945b7fextract_classes.py— byte-faithful, closes XSD↔TTL bijection, drops Python from the oracleHighlights
9-domain round-trip verification (
f44f712)Extends the lift-surface check from MARS-only to 10 domains: MARS +
Transport + Accounting + SalesDistribution + Credit + Cost +
ServiceManagement + WorkOrder + Compliance + Audit. 210 TTL files
across the nine new domains; all parse via one of the two existing
parsers, all round-trip. New permanent regression test
ttl_emit::tests::nine_domains_lift_surface_round_trippins eachdomain's expected TTL count so any future upstream re-vendor that
drifts the inventory fires.
Authorship verification via
dcterms:creatorfield scan:(
bus-compiler,family-codec-smith). Natural prototyping groundfor new TTL predicates before pitching them to OGIT upstream.
Viktor Voss(23 files,original arago) + a prior session's
Claudeextension (11 files,ours).
authors).
Verb-as-class is an askama template, not a quirk (
b598460)In #105's commit message I framed WorkOrder's
rdfs:Class-as-verbconvention as "an unusual choice we're free to revise to
owl:ObjectProperty." That framing was wrong; re-encoding wouldstrip the very property that makes WorkOrder useful — the four
template surfaces (slots, inheritance, policy, side-effect spec)
only exist on
rdfs:Class.The structural correspondence with askama / jinja is exact:
template.html.j2verbs/<Verb>.ttlwitha rdfs:Classstruct Context { name: String }ogit:mandatory-attributes (subject object timestamp){% extends "base.html.j2" %}rdfs:subClassOf ogit:AuditableAction{{ field }}checkrender() → HTML stringrender() → (SPO triple, audit, ACL gate)New doc:
docs/VERB-AS-CLASS-TEMPLATE.md(FRAMING v0).Odoo digest → OGIT TTL templates → relive agnostically (
7d68042)Architecture doc for the producer↔storage↔render pipeline. Digest
(
ogar-from-python, queued) → store as TTL templates in OGIT(
vocab/imports/ogit/NTO/<Domain>/withdcterms:creatorprovenance) →relive agnostically via
ogar-render-askama. Python runtime istouched only at digest time; consumers never depend on Odoo Python,
only on TTL + the askama renderer.
The Foundry-parity collapse fits in one table:
ogar-from-pythondigestvocab/imports/ogit/NTO/<Domain>/TTL +dcterms:creatorogar-render-askama::{views, actions}requires-perm+ Lance-version-as-auditdiff -rof digest re-runsNew doc:
docs/ODOO-DIGEST-TO-OGIT.md(FRAMING v0). Includes the v0mapping table for the six already-minted Odoo concepts +
~nine queued for codebook mint.
XSD transcode of
extract_classes.py(8945b7f)The MARS XSD classification extractor from
arago/MARS-Schema/tools/(~360 lines: ~140 extraction logic + ~150 table formatting) is now a
faithful Rust transcode at
crates/ogar-from-schema/src/xsd.rs,behind an optional
xsdfeature (pullsroxmltree, pure-Rustread-only XML DOM; the default TTL path stays zero-parser-deps).
Three things this lands:
xsd::to_asciidoc()reproducesthe Python
-F asciidocoutput exactly — 628 lines, includingverbatim XSD-documentation whitespace and the
printAsciiDocFootertrailing newline.xsd::tests::asciidoc_matches_python_oraclediffs against thecached
_oracle/classifications.adoc.MARS-TRANSCODING.md §2).xsd::tests::xsd_classes_match_ttl_enumasserts full bidirectional set-equality between the
XSD-extracted Application value set and the TTL
validation-parameterenum.cargo test --features xsdis the whole oracle now; nopython3interpreter needed.
extract_classes.pystays vendored in_oracle/as the provenance witness, not a runtime dep.Test footprint
cargo test -p ogar-from-schema)--features xsd(16 default + 4 XSD)--no-deps), fmt-clean for the new codeDocs touched
docs/MARS-TRANSCODING.md— bijection marked closed; Python-depremoval noted; Rust extractor added to the oracle direction table
docs/OGIT-DOMAIN-LIFT-CATALOGUE.md— 10 rows promoted toLift-tested with per-row authorship provenance; verification recipe
added (the
dcterms:creatorscan)docs/VERB-AS-CLASS-TEMPLATE.md— new (FRAMING v0)docs/ODOO-DIGEST-TO-OGIT.md— new (FRAMING v0).claude/board/EPIPHANIES.md— four new FINDING / FRAMING entries(newest first)
Generated by Claude Code