One Definition Per Concept, Published With The Grammar — landed record

Closure synthesis for One Definition Per Concept, Published With The Grammar: 0 committed run(s), 0 section-anchored comment(s), and 0 landed commit(s).

§2 — registry, loaders and accessor landed

Commit 1e12625 adds vocabularies/conventions/concepts.yml, notation.yml and templates.yml, their token-validating loaders in grammar/vocab_loaders.py, and select_conventions in grammar/terms.py. For flux_surface_averaged_argon_density_at_plasma_boundary the accessor returns exactly two concepts (flux-surface average, plasma boundary), one notation (density) and one template (density with subject). The loader refuses a malformed entry per file, an unknown token key and a forbidden spelling equal to a registered alias, each by name. Gate: 481 passed against 469 at base; removing the flux-surface-average entry from a scratch copy turns the accessor test red. Independent review 102/120, no added failures. Open in this section: the templates still carry a sign_convention field the plan removed, the conventions YAML reader copies _load_yaml, and one refusal test matches too loosely; a follow-up node narrows all three.

§2 — registry narrowed to openings and its existing YAML owner

Commit 0a977ee removes the template sign_convention field from the model, templates.yml and the select_conventions output, folds _load_conventions_yaml into _load_yaml, and makes each refusal test assert its own message. rg finds neither name in the registry code. Gate: 44 passed, 5 xfailed against 42 passed, 5 xfailed at base; re-adding sign_convention to the template model turns the refusal test red. Independent review 118/120, no added failures. With the loader landing (s2-registry-loader), the section's deliverable is in the tree.

§3 — the registry tests check the registry's own invariants

Run r-20261013T081300178088-cnr-registry-test-invariants, merged at 448d2b9. Authoring the conventions registry had broken three tests in tests/grammar/test_conventions.py, because they pinned entries and spellings the authored registry no longer had. The rewrite tests what the registry promises instead: every declared entry is present, the density spelling follows the notation policy, and notation is selected from the parse. The four-file gate went from 3 failed and 79 passed at base to 82 passed at head. Three targeted mutations of a scratch registry each fail a test (exit 1). The independent review scored every dimension 19 or 20 with no added failures. Its one note: the node's fragment is an empty anchor, so this record carries the account.

§3 — convention selection keys operators by their registry token

Run r-20261013T081403384041-cnr-accessor-operator-keys, merged at 757e2f5. select_conventions in imas_standard_names/grammar/terms.py now handles operators by their registry token. An indexed derivative such as derivative_of_X_with_respect_to_Y selects the derivative_with_respect_to concept. A binary ratio name selects the ratio concept and the ratio-keyed templates. The placeholder token is excluded. Four new tests in tests/grammar/test_conventions_operator_keys.py each fail when the selection mechanisms are removed. The five-file gate adds no failures against its base. Its three base failures are the registry-test breakages the test-invariants node fixed.

The review scored 10 to 20 with no added failures and left two notes for the templates node. First, _operator_token splits a fused indexed operator by prefix stripping, duplicating model._split_fused_indexed_operator, which also validates the bound index. Second, test_ratio_selects_its_operator_concept already passes at base, so it guards nothing this change added.

§3 — binary-operator templates, and one fused-operator splitter

The registry's template set gained an {operand} placeholder and three binary-operator templates (commit 9813991):

The conventions selector now splits a fused indexed operator through model._split_fused_indexed_operator. It drops its own prefix loop and the _operator_keys cache, and binary operators are keyed to those templates. Three mutations each turn the operator tests red: a raw operator token, binary operators excluded from the IR tokens, and binary keying dropped from the template bases. The five-file gate went from 66 passed at base to 67 passed at head (merge 440942e; review 113/120).

§3 — The coordinator's read of concepts.yml, and its three corrections

The lead delegated the read of conventions/concepts.yml to the coordinator on 2026-10-14. All 46 entries were read. They are correct and consistent with the catalog's convention, and none names a COCOS. Three corrections landed.

Both reviews asked for a test pinning the new wording. That is declined: a test pinning approved text is a change detector, and the accessor tests already show the registry is what renders. The midplane fragment says a before-capture of the accessor is on disk. Only the after-capture exists; the before text was checked against the base blob instead.

§5 — population, zone and aggregation tokens carry definitions

The population, zone and aggregation vocabularies now carry a definition per token, moved from the files' comments, with nothing invented. select_conventions emits each through a definition-only shape. The loaders return the same token sets, and load_zones the same ordered tuple (merge 903e8e4, 5 tests; review 101/120). Follow-ons for §6: the vocabularies use a token-keyed nested shape rather than the locus registry's entry shape, and a second YAML reader sits beside _load_yaml.

§6 — A template may require or exclude tokens

A template entry may now require tokens, exclude segment kinds and carry a note. Selection applies the conditions after the subset test, and a conditioned entry supersedes an unconditioned sibling (same base, same segment kinds) when both match. The shipped registry carries no conditions, so selection over it is unchanged. tests/grammar/test_template_conditions.py adds 8 tests, covering the required token, the excluded kind, the note, the precedence rule and the shipped-registry no-op. tests/grammar passes at base d2713d4 and at head. Commits ea6ea2c and f01dd7c. The review scored 109 with three follow-ons. Nothing in production renders AppliedTemplate.note yet, so the test proves the note only through its own helper. The test oracle _legacy_selection is named by revision rather than mechanism. And one negative-control log header names the base revision. The first two go to §7.

fragment

§7 — The sentences that keep near-duplicates apart

The three ruled sentences are notes on conditioned template entries in templates.yml:

A new accessor, template_sentences beside select_conventions, returns each selected template's opening and then its note. It emits each distinct note once, so total_thermal_electron_density, which selects both density entries, renders the sentence once. select_conventions is unchanged. tests/grammar/test_near_duplicate_sentences.py checks all three sentences on 62 family names: 10 temperature, 28 triangularity and all 24 electron-density combinations. Five red controls each fail (EXIT=1): a sentence removed, deduplication removed, and each sentence moved to a broad entry. tests/grammar has 1,275 passed against 1,212 at base, with no added failures. _legacy_selection is renamed by what it computes. Review 118/120. Commits 29dc668 and 729c94d.

fragment

§8 — a base for a distance from the separatrix

separatrix_distance is a physical base: the distance of a position from the magnetic separatrix, positive outside it (merge 089f55e, review 114/120, zero added failures). radial_separatrix_distance_at_outboard_midplane now decomposes as component radial, base separatrix_distance, position outboard_midplane and round-trips. Before, it parsed as a distance in the separatrix zone. Names that use separatrix as a zone or a locus keep their parse, and the decomposition test fails with the base removed. The grammar suite passes at head. Record: docs/evidence/fragments/concept-and-notation-registry/isn-separatrix-distance.html.

§9 — locus definitions in physics terms

Every locus definition that named a DD field, an IDS path or an option value now states what concepts.yml states (merge 785e858, review 117/120, zero added failures). outboard_midplane reads: the low-field-side equatorial midplane, points at the midplane height with major radius greater than the magnetic-axis radius; the data's midplane identifier selects that height, or it is the magnetic-axis height when none is given. outboard_midplane_separatrix is the crossing of the separatrix with that height on the low-field side, with no gradient wording. dr_dz_zero_point keeps its geometric definition and loses its DD references. One test fails on the old midplane texts. A second fails when a midplane definition drops either its height or its side of the axis. Record: docs/evidence/fragments/concept-and-notation-registry/isn-locus-definitions-physics.html.