§1 — Verdict
This review examined the full standard-names system across its three repositories: imas-standard-names (ISN — the grammar library and read-only catalog server), imas-codex (the LLM-augmented name-minting pipelines), and imas-standard-names-catalog (ISNC — the published data repository). The architecture is sound and the separation of concerns (ISN defines what a valid name is; codex decides what names to create; ISNC carries the data) is respected in practice. The system's weaknesses are concentrated at well-defined seams, and most of what this review found was fixed in-session (§9). The headline numbers:
| Axis | State | Evidence |
|---|---|---|
| Grammar ↔ catalog consistency | Perfect | 2124/2124 published names parse strictly and round-trip; only 1 name carries a multi-token qualifier segment |
| Grammar engine | Strong, 2 high-severity defects found & fixed | LLM contract taught the retired long form; parser silently dropped operators over binary expressions |
| Vocabulary structure | Excellent | 113/113 qualifiers categorized exactly once; zero irreducibility violations; all 13 cross-set overlaps intentional and ratcheted |
| Vocabulary curation | Decayed in LLM-fed sets | physical_bases at 154 tokens with ~16 ungated catch-alls; processes.yml at 89 tokens with synonym accretion |
| Codex grammar integration | Clean core, drifted edges (fixed) | Single integration point (build_compose_context) correct; 37 unparseable prompt examples, stale counts, and a dead kind-derivation path found at the edges |
| Catalog documentation quality | High | 63/68 stratified sample entries clean; no boilerplate, no missing sign conventions or ranges |
| Catalog referential integrity | Weakest axis | 388 dangling structured links touching 314/2124 entries (14.8%), plus 74 dangling inline references |
| Lifecycle governance | Vestigial | All 2124 entries status=draft; zero deprecates/superseded_by anywhere; renames leave no trail for consumers |
§2 — Scope, method, and the system under review
Method: parallel specialist reviews (grammar design, vocabulary audit, codex prompt audit, codex pipeline debug scan, export/import deep-dive, stratified catalog sampling), with every load-bearing claim re-verified by direct execution against the live code and data before any fix was applied. Confirmed defects were fixed in-session and pushed; design-level faults that require physics or governance judgment are ranked as recommendations in §10 rather than changed unilaterally.
sn import.§3 — Grammar design review (ISN)
The grammar is a two-layer system: a structural intermediate representation (operator stack,
projection, ordered qualifiers, base, locus, mechanism) with a strict pure renderer and a liberal
staged parser, bridged to a flat Pydantic StandardName model.
parse_standard_name recomposes every parse and requires byte-equality, so the grammar
admits exactly one spelling per name — a strong and well-enforced invariant. Dual-role tokens are
governed by an explicitly ratcheting allowlist rather than convention, which is the right mechanism.
The design earns a positive verdict overall; the defects found were in the details, not the architecture.
| # | Sev. | Finding | Status |
|---|---|---|---|
| F1 | High | get_grammar_context() — the single ISN→codex LLM contract — advertised the retired {axis}_component_of_{base} long form as correct, plus three further non-parsing examples (temperature, power_due_to_ohmic, major_radius_of_plasma_boundary), actively training the composer toward invalid names. The MCP tool surface carried the same stale examples independently (hand-maintained duplication that had already half-drifted). | Fixed: all advertised examples now parse; a guard test walks the context so examples and parser cannot drift again |
| F2 | High | The IR parser silently discarded prefix operators peeled before a binary terminator: gradient_of_ratio_of_electron_pressure_to_magnetic_pressure recomposed without gradient, zero diagnostics — silent token loss in a layer whose whole contract is lossless round-tripping. | Fixed: full operator stack carried over the binary; flat model raises an honest "not representable" error instead of a misleading token-loss message; regression tests added |
| F3 | Med | Round-trip is a tested property, not a structural guarantee: the flat model is a lossy projection of the IR held together by fold/reject special cases. F2 was one instance; others may exist outside the tested corpus. | Recommendation (§10.9) |
| F4 | Med | No canonical intra-order on multi-token qualifier segments — both incident_fluctuating_… and fluctuating_incident_… are accepted as canonical, violating the one-spelling invariant. Zone order is enforced, so the mechanism exists. | Recommendation (§10.6) — verified safe: only 1 published name has a multi-token qualifier segment |
| F5 | Med | The two parse entry points disagree on unregistered loci: IR-level validate_round_trip accepts electron_temperature_at_foobar (vocab-gap diagnostic) while parse_standard_name rejects it — opposite validity oracles. | Recommendation (§10.10) |
| F6–F7 | Med | AGENTS.md documented disambiguation rules for a parser that no longer exists, claimed pre-commit hooks that were never configured, and the codegen drift gate ran only in CI — which is exactly how a vocabulary change landed without its regenerated enums (the incident that opened this session, breaking the reaction-channel tokens for the pinned codex consumer). | Fixed: rules rewritten to match the actual peel order; check-only pre-commit config added with the drift gate wired in |
| F8 | Low | Reaction-channel routing is purely syntactic: deuterium_tritium_electron_temperature parses. Governance controls which tokens are dual-role but not which combinations are meaningful. | Recommendation (§10.11), contained |
| F9–F10 | Low | Stale generated-file annotations (obsolete enum-removal notes, wrong output filename in the spec header); Transformation/Decomposition enums are byte-identical duplicates. | Headers fixed; enum dedup is a recommendation |
§4 — Vocabulary audit (22 sets)
Structural discipline is excellent: every qualifier maps to exactly one category (113/113, test-enforced),
exhaustive decomposition finds zero real irreducibility violations in
physical_bases.yml, and all 13 cross-set token overlaps are intentional, documented, and
allowlisted with a shrink-toward-empty ratchet. The eponym rule is coherent (multi-base eponyms are
qualifiers; single-base eponyms are atomic bases). Two stale allowlist entries were pruned and a
contradictory file header corrected in-session.
The weakness is curation quality in the two LLM-fed sets. physical_bases.yml has grown to
154 tokens, including ~16 semantically empty catch-alls (coefficient, factor,
parameter, index, flag, weight, …) that are not
gated as generic and therefore validate almost anything — while current, power
and temperature are gated: the gating policy is inconsistent.
processes.yml (89 tokens) shows clear per-rotation synonym accretion:
three tokens for thermalization, collisions beside coulomb_collisions,
a seven-token radiation family, disruption/disruption_event,
viscous/viscosity. Smaller issues: non-species tokens filed as subjects
(state, gyrokinetic, hard_xray, pfirsch_schlueter,
bare halo — which holds an unphysical triple role); regions.yml fully duplicated
inside the locus registry with one typing conflict (halo_boundary: region vs position);
15 of 18 directional tokens duplicated between components.yml and
coordinate_axes.yml; a handful of baked-in operator compounds
(maximum_over_flux_surface) against the compositional style. Remedies ranked in §10.
§5 — imas-codex: prompts and LLM pipelines
The core integration is exactly right: one function
(build_compose_context()) pulls ISN's get_grammar_context() plus the full
closed-vocabulary token map at runtime, and every prompt receives grammar knowledge through it.
Renaming logic imports ISN's real parser; the vocabulary tooling pulls token maps at call time.
A prompt-hash clear-gate exists so silent prompt drift trips a barrier. The exceptions sat at the
edges, and the worst three were live defects rather than future risks:
- Dead vector classification (fixed).
derive_kind()reimplemented ISN's scalar/vector taxonomy with stale hand lists and had no code path returning"vector"— while the graph writer unconditionally overrides the LLM's kind with it. Consequence: no node could ever persist as a vector, soMAGNITUDE_OFedge creation (WHERE v.kind = 'vector') could never match. Kind now comes from parsing the name and reading the base's declared kind in ISN. - 37 unparseable "good" examples injected into live compose prompts (fixed).
The naming-consistency rules YAML feeds examples straight into the generate/refine system prompts; 37 of
its 72
examples_goodnames failed ISN round-trip — including a family the adjacent system prompt explicitly says does not parse (the pipeline told the model two contradictory things on the same request), and one rule that instructed the model to avoid the exact operator the grammar registers. The guarding round-trip test read the unrendered Jinja template, extracted zero examples, and so never saw the YAML. The test now loads the YAML directly (144 guard cases) and every example and rule text was rewritten against the current grammar. Several rule texts had drifted to prescribe retired forms (rate_of_change_of_, the component long form, suffix-form operators) — a periodic reconciliation of rule prose against the live parser is recommended (§10.7). - Stale hand-typed counts and mislabeled segment taxonomy in the core grammar prompt (fixed) — "80 registered tokens"/"108 tokens" vs the real 154/113, and a summary table that labeled the qualifier segment with subject/population example tokens. The counts now come from the same Jinja rendering the file already used for its token registry, and the row teaches real qualifier semantics.
The pipeline debug scan (19 confirmed findings) rated the claim/lease machinery, LLM-response retry
handling, score typing, and the fail-closed validation gate as sound. The bugs that mattered:
the sn edit --rename cascade hardcodes override_edits=True, include_accepted=True,
silently bypassing both human-edit and accepted-name protections with no CLI opt-in and a dry-run that
previews the clobbers as ordinary renames (High); name-hint edits strand edit_status='open'
forever because the recomposed successor never inherits the edit fields; --only's
skip-generate flag is computed and then dropped, so scoped runs still burn compose budget; an empty
{"reviews": []} LLM response persists as a canonical 0.0/"poor" review, driving good names
toward exhaustion; scoped clears wipe the whole LLM-cost ledger; and an explicitly-empty path allowlist
widens to the entire graph — the exact shape of the historical 1863-name reset incident, still unguarded
one layer below the CLI. All eight are fixed with the protections defaulting closed: rename cascades now
block on protected/accepted descendants unless the operator passes explicit
--override-edits/--include-accepted flags (recorded on the edited node and honoured
at acceptance time), hint edits propagate their open-edit state to the recomposed successor and reconcile the
predecessor, and empty path allowlists fail closed. Findings that need operational design (claim TTL vs batch
runtime, cascade atomicity with acceptance, family-scope semantics) are ranked in §10.
A full-suite integration pass after the fix wave surfaced six pre-existing test failures
(unrelated to the fixes — verified against commit dates): the geometry-enumeration-collapse and
shape-parameter tests still target line_of_sight as a bare geometric base, which ISN migrated
to an along-relation locus (toroidal_angle_along_line_of_sight) before the previous dependency
pin; and two benchmark-runner tests use fixture names whose residues (divertor) no longer parse.
These document an incomplete codex-side migration to the along-locus grammar surface and are queued in §10.
§6 — Export, import, and release integrity
The export/import deep-dive found two high-severity data-integrity defects and a cluster of
accounting/determinism faults. High: (1) the export query projected the unit exclusively from the
HAS_UNIT edge, so any node whose unit lives only on the property exported with an
empty unit into the published catalog (fixed — coalesce, matching the codebase's canonical
read); (2) curator-only catalog names import without validation_status, are therefore
ineligible for the next export, and a full-scope publish then deletes them from ISNC — the
round-trip that is supposed to preserve human edits silently destroys them (fixed: import defaults the
status with a coalesce that preserves an existing quarantine).
Medium, all fixed: import force-flipped every entry to accepted — superseded nodes are now
excluded from the write set entirely and genuine no-ops no longer masquerade as writes; four ordering
queries treated the scalar physics_domain as a list, silently degrading the advertised
topological file ordering to alphabetical; wall-clock timestamps and an embedded HEAD SHA made every
export churn all 18 domain files and dead-end the no-change fast path (stamps now derive from the source
commit — identical content produces identical bytes); the manifest's exclusion buckets did not close
against the published count (new accounting lives in .export_report.json because the
manifest schema is closed and validated by the release gate; one semantic correction:
excluded_below_score_count is now purely score-based). The 388 dangling links in the
published catalog (§7) are pruned by a new export gate with counted, logged accounting. The watermark
CAS, import locking, and sn.id-keyed merge idempotency were verified sound.
§7 — Catalog quality (2124 published names)
The strongest single result of the review: every one of the 2124 published names parses strictly and round-trips through the ISN grammar — the grammar and the catalog are fully consistent. Documentation quality is high: in a 68-entry stratified sample, 63 scored clean, with dimensionally consistent equations, explicit sign conventions, plausible ranges, and relevant cross-links throughout; no boilerplate patterns were found. Two suspected faults dissolved on inspection as principled design: the K-vs-eV temperature split is exactly hardware-vs-plasma (0 violations in 63 entries), and the s⁻¹-vs-m⁻³·s⁻¹ source-rate split is exactly plant-injection-vs-plasma-continuity (52/52 correct).
The real faults cluster in a small number of families:
| # | Fault | Breadth | Remedy |
|---|---|---|---|
| 1 | Dangling cross-references: structured links: to names absent from the published set, plus dangling inline references in documentation prose | 388/5783 link edges, 314 entries (14.8%); +74 inline | Export-side pruning gate with manifest count (in flight); ISN-side validator resolving both structured and inline references (§10.3) |
| 2 | Z-axis generator gap: empty or missing documentation exclusively on the third member of x/y/z coordinate and unit-vector triples | 6/6 instances on z | Fix the batch generator; targeted docs regen for the affected names |
| 3 | Bare "momentum" means momentum source density and collides dimensionally with the differently-defined *_momentum_flux family | ~30 entries | Rename family to *_momentum_source; add validator rule for source/flux families sharing units under near-identical names |
| 4 | "energy_flux" names carrying particle-flux units (m⁻²·s⁻¹) with docs that admit the mismatch ("despite the energy-flux label…") | 4 entries vs 24 correct siblings | Fold into the particle-flux family; reserve energy_flux for W·m⁻² |
| 5 | "power_density" used for both W·m⁻³ (volumetric) and W·m⁻² (surface flux); one near-duplicate concept pair (power_density_at_wall ≈ energy_flux_at_wall) with no linking | 6/69 entries + 1 pair | Rename the six to *_power_flux_*; deprecate/alias one of the pair |
| 6 | _at_plasma_boundary momentum entries are surface integrals of a density-like integrand — no standard physical referent; corroborates the already-tracked composer separatrix→plasma_boundary locus issue with a concrete example | momentum family | Raise the priority of the tracked locus fix |
| 7 | One-line self-contradictions: electron_source_rate (unit s⁻¹, text says "per unit volume"), toroidal_angle_of_active_limiter_point (unit 1, text says radians), one Hz-vs-s⁻¹ outlier; plus one self-referential broken link (height_of_optical_element) | 4 entries | Fix in the codex graph via sn edit so the next export carries them (ISNC YAML is generated — not hand-edited) |
A meta-finding on validation: the official validate_catalog run passes with 0 errors but
emits ~600 advisory notes, the dominant class being a "may indicate measurement location — consider
using subject (electron, ion)" nudge fired at obviously intrinsic hardware properties
(width_of_poloidal_field_coil). Since the specification itself declares the
of_<entity> postfix locus to be the authoring convention for instrument
properties, this advisory contradicts the spec and buries the one real warning in the stream
(an energy with unit 1). The advisory should be suppressed for hardware/geometry bases.
§8 — Lifecycle rules and import robustness
Two disconnected state machines govern a name's life. Operationally, codex runs a seven-stage
pipeline (pending → drafted → refining → reviewed → accepted, with
exhausted and superseded exits) keyed on graph properties, with claim
tokens, TTL leases, and a fail-closed validation gate — this machine works and is well-tested.
Governance-side, ISN's models define draft / active / deprecated / superseded with a
validator requiring every deprecated entry to name its successor — and this machine is
entirely vestigial: every one of the 2124 published entries is draft, no entry
anywhere uses deprecates/superseded_by, and nothing in the export path can
ever promote, deprecate, or supersede a published name. When a name is renamed in the codex graph, the
old name simply vanishes from the next export: catalog consumers who pinned it get silent breakage
with no deprecation stub, no successor pointer, and no trail. The graph knows the supersession
chain (it maintains supersede edges internally) — the information is simply dropped at the boundary.
Import robustness ("what happens to a catalog after a successful review") had the two genuine holes
described in §6 — curator-name deletion on round-trip and unconditional stage-flipping — both now
guarded. The locking, watermark compare-and-set, and id-keyed idempotent merge were verified correct.
The ISNC release chain is sound: validation gates the release workflow, and the tag carries both the
data version and the resolved ISN SHA. Recommendations: (1) emit deprecated stubs with
superseded_by for renamed/superseded accepted names at export, activating ISN's designed
governance path and giving consumers a migration trail; (2) decide what status: active
means for this catalog (e.g. survives N releases, or curator-promoted) and implement the promotion —
or delete the status field rather than publish a field that never varies; (3) the ISNC validate
workflow should not rely on --summary text alone (known to hide error detail).
§9 — Fixes landed during this review
All commits pushed to main on their respective repositories; both test suites green (ISN: 1648 passed; codex: targeted suites for every touched module).
| Repo | Commit | What |
|---|---|---|
| ISN | ddf7fa9 | Regenerate model types for the reaction-channel qualifiers (closes the vocab-vs-generated-enum drift that opened the session) |
| ISN | 81c1416 | Unit-restatement documentation check: token-boundary matching (the draft's substring test false-positived every single-letter unit) + 7 tests |
| ISN | dae87b8 | LLM grammar context: every advertised example now parses; retired long form flipped to an anti-pattern; guard test walks the whole context (F1) |
| ISN | d9c4e80 | Generated-file headers no longer claim live enums face removal; spec header names the real outputs (F9) |
| ISN | 4ee656b | normalizing_qualifiers header corrected; two satisfied overlap-allowlist entries pruned (ratchet) |
| ISN | aff701a | AGENTS.md disambiguation rules rewritten to the real parser; check-only pre-commit with the codegen drift gate (F6/F7) |
| ISN | 515d83c | Parser keeps prefix operators over a binary terminator; flat model raises an honest error for unrepresentable nesting (F2) |
| ISN | e83e5c0 | Tests and comments named by capability instead of plan/release labels (five test modules renamed) |
| codex | 09acc9fb | ISN pin bumped past the drift incident; reaction-channel qualifiers verified visible downstream |
| codex | d8708d24 | Kind derivation reads the ISN base registry; vector kind reachable again, un-breaking MAGNITUDE_OF edges (+12 tests) |
| codex | 1c491a9b | Export unit coalesce — no more empty units when the HAS_UNIT edge is missing (+ query-contract tests) |
| codex | 57808564 e3d8c72e f4d1419b | Import integrity: curator-only names stay export-eligible (validation_status coalesce); superseded nodes excluded from the write set; genuine no-ops honest in the report (+ full content-field change detection including non-protected unit/physics_domain) |
| codex | 15ca50ef a7b443f8 c2fc7021 a56bb71e 31fffcd1 | Export integrity: scalar physics_domain equality restores topological ordering; deterministic commit-derived stamps and no per-file SHA churn; Gate B fails loudly without ISN; exclusion accounting closes (in .export_report.json); dangling internal links pruned and counted |
| codex | 5ef1efbf c9d0c07b 0021367e 4ec8ec97 4530f03f | Prompt repair: all 72 naming-consistency examples round-trip under a guard that reads the real YAML; rule prose reconciled with the live parser; token counts rendered not hand-typed; qualifier-row semantics corrected; VALID_SEGMENTS derived from ISN; DT dual-role wording |
| codex | 8a3ce10f 3f4c316d ef2678fb 10d16a5d 91cb77e5 c8894436 201b5f07 24a33482 | Edit/pipeline protections: rename cascades default-closed with explicit operator opt-ins honoured at acceptance; hint edits propagate open state and block source-less targets; --only phases stop composing; empty LLM reviews fail the cycle instead of scoring 0.0; scoped clears spare the cost ledger; empty allowlists fail closed; prune never injects stages; last pipeline_status straggler gone |
§10 — Ranked recommendations
These recommendations are now planned and decision-locked in Systematic Review Remediation — a six-phase plan (deprecation architecture for accepted names only, sn edit validation parity, referential integrity, unit-family repairs, vocabulary curation, pipeline hardening) with the governing decisions recorded there. The list below is retained as the review's original ranking by leverage per unit effort; items 1–5 close whole fault clusters.
- Referential-integrity validation on both sides of the boundary. Export prunes and counts dangling links (in flight); add an ISN semantic check that resolves every structured and inline name reference, failing the ISNC build on misses. Closes the 14.8%-of-entries defect surface permanently.
- Deprecation trail at export. Emit deprecated stubs with
superseded_byfor renamed/superseded accepted names, activating ISN's dormant governance model. Without it every rename is a silent breaking change for consumers. - Fix the z-axis batch generator and regenerate documentation for the six affected coordinate/unit-vector names.
- Curate the two LLM-fed vocabularies. Dedup processes.yml (synonym families listed in §4) and gate or retire the ~16 physical_bases catch-alls; add a curation gate so rotation harvests cannot reintroduce synonyms. These sets otherwise erode the closed-vocabulary guarantee release by release.
- Catalog unit-family repairs via
sn edit: momentum→momentum_source family rename, the four energy-flux dimension flips, the six power-density flux outliers, and the four one-line self-contradictions. Each closes a cluster, and all must go through the graph so exports carry them. - Enforce canonical qualifier intra-order (F4) using the category ranks, mirroring the zone mechanism — verified to affect at most one published name, so the change is cheap now and only gets more expensive.
- Suppress the "measurement location" advisory for hardware/geometry bases — it contradicts the of_<entity> authoring convention and buries real warnings (600-line noise floor on a clean catalog). Periodically reconcile the naming-consistency rule prose against the live parser too: the example guard now catches drifted examples, but rule text prescribing retired forms is what produced the 37-example hole.
- Derive the MCP grammar-tool payloads from
get_grammar_context()instead of hand-maintaining a parallel copy — the two surfaces had already half-drifted apart when found. - Operational pipeline hardening (design-level): claim-TTL heartbeat vs batch runtime; cascade atomicity with acceptance (or constraint-collision handling); family-scope semantics (currently a parent-subtree, documented as siblings); docs-edit claim preconditions and protection filtering; single-transaction reset/clear; declare the new
edit_override_edits/edit_include_acceptednode properties in the LinkML graph schema (persisted raw today — verified safe, but the schema should own them); enrich_parents claim verify-guard (the one pool without it). - Finish the codex migration to the along-locus grammar surface: six pre-existing test failures (geometry-enumeration collapse, shape-parameter surface, benchmark fixtures) still target the retired bare
line_of_sightcarrier and non-parsing fixture names — update the collapse feature and fixtures to the along-relation forms. - Reconcile the two parse contracts (F5): decide whether unregistered
_at_loci are valid, then makevalidate_round_tripandparse_standard_nameagree — or document the IR entry point as diagnostics-only. - Semantic gating for dual-role reaction-channel tokens (F8) once a second dual-role family appears; today the exposure is contained.
- Vocabulary hygiene tail: resolve the halo triple-role and the regions/locus
halo_boundarytyping conflict; derive regions.yml from the region-typed loci; retire binary_operators.yml if truly superseded; dedupe the Transformation/Decomposition enums; sweep the remaining RC-tagged provenance banners in vocabulary YAML comments.