Plan · grammar · consumer: imas-codex S18

One definition per concept

The grammar says how a name is spelled. Nothing says how the shared ideas inside a name are defined. So the catalog writes the flux-surface average five ways and glosses the plasma boundary as the separatrix. This plan adds that missing layer beside the vocabularies it is keyed by, and releases it with them.

§1 — Why here, and why now

The imas-codex consistency census of 2026-10-12 (imas-codex:sn-catalog-consistency-census) measured 72 accepted entries re-deriving the flux-surface average, in five notations and with one wrong. 24 boundary entries call the plasma boundary the separatrix, and the WEST batch opens its documentation in four styles. The consumer plan imas-codex:sn-house-style authors a single house style to fix this. On 2026-10-12 the lead ruled that the house style lives in ISN now, released before the WEST re-cut, rather than in imas-codex first. A definition belongs with the grammar that names the thing defined, and every consumer of the standard should see it, not only the generator.

Existing guidance is the base, not a competitor. docs/guidelines.md states naming rules and the flux-surface-average tag. The shipped symbol definition policy requires every symbol to be defined by identity and name link. The locus registry already carries a definition per locus. The new layer adds what none of them hold: one canonical equation per concept, one symbol per quantity, and one opening template per name pattern.

Four existing owners are extended or referenced rather than restated. Per-token definitions live on the vocabulary entries (LocusEntry.definition, PhysicalBaseDef.definition, GeometryCarrierDef.definition in imas_standard_names/grammar/vocab_loaders.py). Alternate spellings live on their aliases and abbreviations. The writer's rubric (section order, the generic sign-convention form, equation and symbol rules) is entry_schema.fields.documentation.guidance in imas_standard_names/grammar/specification.yml, generated into field_schemas.py. The governed-term accessor is terms.py. imas-codex's cluster vocabulary (imas_codex/definitions/clusters/concepts.yaml) carries symbols for cluster labels; it is a consumer of this layer, recorded there rather than changed here.

§2 — The registry and its loader

Three files under imas_standard_names/grammar/vocabularies/conventions/:

The models and loaders go into imas_standard_names/grammar/vocab_loaders.py beside the existing ones, reusing _load_yaml and the registries it already loads. For concepts.yml and notation.yml, which are keyed by tokens, the loader refuses any key that is not a real token in the current vocabularies, so the registry cannot drift from the grammar. templates.yml is keyed by patterns, so its rule is that every token and segment kind a pattern names exists in the current grammar. The public accessor goes into imas_standard_names/grammar/terms.py beside fetch_standard_terms: it takes a parsed name and returns exactly the entries that apply to it. No new loader module is added. Surface: one accessor and one refusal family (an unknown token key, or a forbidden spelling that equals a registered alias) are added. Nothing is retired, because no per-token equation, per-quantity symbol or per-pattern opening exists to merge with.

Done when: the loader validates all three files and refuses one deliberately malformed entry per file, plus one entry keyed by a token that does not exist, each failing by name. For flux_surface_averaged_argon_density_at_plasma_boundary, the accessor returns the flux-surface-average concept, the plasma-boundary entry, the density notation and the species-density template, and nothing else.

§3 — The entries the WEST batch needs

Content is authored by the coordinator under imas-codex:sn-house-style §3 and lands here. The lead's rulings of 2026-10-12 fix three entries before any other is written:

Done when: every concept, symbol and pattern used by the 220 names of the frozen WEST roster has an entry. The worklist is produced by running the §2 accessor over that roster and listing the tokens it finds with no entry, so the list is measured, not guessed. The run is shown able to report a gap: with one entry removed from a scratch copy of the registry, it lists that token as missing. The lead has read concepts.yml. This section is the landing of imas-codex:sn-house-style §3, where the coordinator authors the entries; it closes when that section does, and is not built separately.

§4 — Released before the WEST re-cut

imas-codex already consumes this repository as an editable path source, so the registry is usable there the moment it lands on main. The release is what makes it part of the published standard. Cut it with standard-names release before the WEST candidate is cut. In imas-codex, both imas-standard-names pin occurrences move together, and the graph's grammar snapshot is verified to carry the release rather than assumed, since a scoped run does not resync it.

Done when: the tag is published and installable from the package index. Both imas-codex pin lines name it. A read of the graph's grammar snapshot reports the released version.

§5 — Population, zone and aggregation tokens carry definitions

Three near-duplicate rulings carry a separating sentence (§7) that must render only on the names it describes. The registry cannot do that today. _vocabulary_definitions (imas_standard_names/grammar/vocab_loaders.py ~715) returns definitions only for locus, physical-base and geometry-carrier tokens. The population (populations.yml), zone (zones.yml) and aggregation (aggregations.yml) vocabularies are plain token lists, with any meaning in comments. The lead ruled on 2026-10-15 that the registry gains both mechanisms: definitions on these tokens (this section), and token conditions on templates (§6).

Each token in those three vocabularies may carry a definition, held in _vocabulary_definitions. Holding it is not enough. select_conventions (grammar/terms.py ~280) emits an applied definition only for a token keyed in concepts.yml, and uses the vocabulary text merely as fallback for such a key. So it must also emit an applied definition for a population, zone or aggregation token that carries one. AppliedConcept (terms.py ~116) requires phrase, equation and restates_equation, which a token definition does not have. Either make those fields optional for a definition-only entry, or add a sibling definition-only shape that renders beside concepts. Never invent a phrase or an equation to fill a required field. Say which you chose in the fragment. Change the files from lists to entries in the shape the locus registry and physical bases already use, so a token without a definition still loads. load_populations and load_aggregations return exactly the token sets they return today. load_zones returns exactly the same ordered tuple, because its order is the canonical intra-order rendering and validation rely on (vocab_loaders.py ~380). No consumer changes. Move the meanings now held in comments into definitions where a comment states one. Do not invent definitions for tokens whose meaning no comment records.

Done when:

§6 — A template may require or exclude tokens

select_conventions (imas_standard_names/grammar/terms.py ~297) selects a template from conventions/templates.yml by the name's base and the segment kinds present, through a subset test. So a template reaches every name of its pattern. A sentence about cold neutrals reaches electron_temperature, and a sentence about the unqualified triangularity reaches upper_triangularity_of_plasma_boundary.

A template entry may carry optional conditions:

select_conventions applies the conditions after its subset test. An entry with no conditions selects exactly as it does today. A template entry may also carry an optional note: one sentence rendered after the documentation opening of every name that selects the entry. TemplateEntry (vocab_loaders.py ~662) has no field for such a sentence today, because its description and documentation are the pattern's openings. §7 places the separating sentences in notes. No precedence among templates exists today: they are an unordered list returned in file order (vocab_loaders.py ~678). Define how a conditioned entry and an unconditioned sibling combine or take precedence when both match, state the rule in the fragment, and test it.

Done when:

§7 — The sentences that keep near-duplicates apart

The coordinator ruled every near-duplicate overlap that touches the WEST roster as distinct (imas-codex docs/evidence/fragments/sn-catalog-grouping/scg-near-duplicate-rulings.json, 2026-10-13). Three of those rulings carry a template_sentence that separates two names which otherwise read alike. Use each sentence verbatim from that field:

After §5 and §6, place each sentence with the mechanisms those sections built: token definitions and conditioned template notes. The placement is the worker's to choose, and the done-when below is the contract. Two constraints are known. A token definition carries only what the token means in every name it fills, so a neutral-temperature sentence cannot go on cold, which also fills cold_electron_density. And a name can fill several segment kinds at once, as total_thermal_electron_density does, so a sentence placed in more than one entry must still render once per name. Say in the fragment where each sentence went and why.

Done when: a test renders the documentation of every name in each family that the graph-free registry can name:

The test asserts that each sentence appears exactly once on every name it describes, and on no other name in any of the three families, including names that fill more than one segment kind. It fails with any sentence removed, and fails when any sentence is duplicated so that some described name renders it twice. Both are recorded with EXIT=. For each sentence, a further control moves it to a placement that reaches a name it does not describe, and the test must then fail. Where no such placement exists for a sentence, say so in the fragment. The registry and template tests pass at head, judged by delta against base.

Render through one owner, not a test helper. Nothing in production yet reads AppliedTemplate.note. The only renderer is imas-codex, which inserts template.documentation alone (imas_codex/standard_names/workers.py ~9661 and imas_codex/standard_names/docs_gates.py ~983). Add one accessor beside select_conventions in imas_standard_names/grammar/terms.py. It returns, in order, the sentences that a name's selected templates contribute: each template's opening, then its note. The test asserts through that accessor. Switching the imas-codex writer and gate to it is a separate node in that repository. In tests/grammar/test_template_conditions.py, rename _legacy_selection and its docstring by what the oracle computes, a selection by the subset test alone with no conditions.

§8 — A base for a distance from the separatrix

A harmonize run in imas-codex (2026-10-18) exposed two registry defects through one WEST name, gap_at_outboard_midplane, and the lead ruled on both the same day. This section is the first; §9 is the second.

Three DD quantities are a measurement position's radial distance from the separatrix, mapped along flux surfaces to the outboard midplane, positive in the scrape-off layer: langmuir_probes/embedded/distance_separatrix_midplane, langmuir_probes/reciprocating/plunge/distance_separatrix_midplane and thomson_scattering/channel/distance_separatrix_midplane. The grammar cannot say "distance from the separatrix". Relational spellings (distance_from_separatrix_…) fail as unknown bases, and radial_separatrix_distance_at_outboard_midplane parses today only as a distance in the separatrix zone (zone=[separatrix], base distance), which says where the quantity sits, not what it is measured from. Add one physical base, separatrix_distance, beside decay_length and connection_length: the distance of a position from the magnetic separatrix, positive outside it. That spelling, an existing identity in imas-codex, then decomposes as what it means and can be revived there.

Done when: radial_separatrix_distance_at_outboard_midplane parses and round-trips with component radial, base separatrix_distance and position outboard_midplane, and a test fails with the base removed, recorded with EXIT=. Every other name in the grammar's fixtures keeps its parse; names that use separatrix as a zone or locus are tested explicitly. The grammar suite passes at head, judged by delta against base. The release in §4 carries this section with §7 and §9.

§9 — Locus definitions say what the concept registry says, and name no DD field

locus_registry.yml defines outboard_midplane as "follows the DD midplane_identifier (default option 'dr_dz_zero_sep': the outboard separatrix point where dr/dz = 0)". The imas-codex documentation gate copies a locus definition into every documentation that uses the locus, and its reviewer docks the DD field and option names as implementation leakage. So every outboard-midplane name loses points whichever way it is written. The gate requires whatever text the registry carries, so rewriting the registry changes what it requires; the two are not in conflict.

The physics is already settled in this repository. Commit 0e43cde (2026-10-14) removed the dR/dZ = 0 definition, which is undefined for a limited plasma with no separatrix and disagreed with poloidal_angle. conventions/concepts.yml now defines the outboard midplane as Z = Zmid, R > Raxis, with Zmid the midplane height the data's midplane identifier selects, or the magnetic-axis height when none is given. The locus definitions never followed.

Rewrite each locus_registry.yml definition that names a DD field, an IDS path or an option value so it states, in words, what its concepts.yml entry states. Do not reinstate dR/dZ = 0 or any definition a recorded decision removed. At least these carry DD references: outboard_midplane, inboard_midplane, outboard_midplane_separatrix, pedestal, pedestal_maximum, pedestal_top, separatrix and an at-limiter entry. A locus with no concepts.yml entry keeps its physics and loses only the DD reference, unless that physics is the dR/dZ = 0 point. outboard_midplane_separatrix is such a locus: today it is "the outboard separatrix point where dr/dz = 0". Redefine it from the midplane, as the point where the separatrix crosses the midplane height on the low-field side (R > Raxis), with no dR/dZ wording. Where the default midplane height is the one the data selects at the separatrix's outermost point, that is the same point, so no consumer's meaning moves. The one locus whose meaning is that point, dr_dz_zero_point, keeps its geometric definition (the outboard separatrix point where dR/dZ = 0) and loses every DD reference it carries: its IDS path, the midplane_identifier field and the option value; it and outboard_midplane_separatrix coincide under the default midplane height, which the fragment notes as a question for a later vocabulary ruling, not this section. Keep each pointer from one locus to a sibling, such as outboard_midplane to outboard_midplane_separatrix for a value at the intersection. List every definition changed, before and after, in the fragment.

Done when: a test asserts that no locus definition names a DD field, an IDS path or an option value, and that none of the midplane loci (outboard_midplane, inboard_midplane, outboard_midplane_separatrix) contains dR/dZ or dr/dz in any case. It fails on the old outboard_midplane text and on the old outboard_midplane_separatrix text, recorded with EXIT=. A second test asserts that the outboard_midplane and inboard_midplane definitions state both parts of their concepts.yml relation: the midplane height, with its magnetic-axis default, and the side of the magnetic axis (R greater or less than Raxis). It fails on a planted definition that drops either part. The grammar suite passes at head, judged by delta against base.

§10 — One outboard-midplane definition

Lead ruling, 2026-10-22. The catalog records one definition of the midplane loci and uses it in every name. The outboard midplane is the point on the low-field side where the flux surface in question reaches its maximum major radius. On the separatrix, that is its outboard maximum-R point. The inboard midplane is the corresponding point of minimum major radius on the high-field side.

This replaces the per-dataset wording of 0e43cde, where the data's midplane identifier selected the height, falling back to the magnetic-axis height. That wording is not one definition. It made the generic locus sentence contradict any name whose quantity is taken at a stated height: gap_at_outboard_midplane scored 0.50 to 0.56 in three reviews, each reviewer reading two heights. The ruling keeps both concerns 0e43cde answered:

Change. In imas_standard_names/grammar/vocabularies/conventions/concepts.yml, change outboard_midplane and inboard_midplane, their equations and symbols, and the poloidal_angle sentence. In imas_standard_names/grammar/vocabularies/locus_registry.yml, change the definitions of outboard_midplane, inboard_midplane and outboard_midplane_separatrix, and any other entry that restates the midplane height. Every definition stays physics-only: no DD field, IDS path or option value. The existing physics-only test keeps passing. Its relation test, which encodes the old midplane-height-with-magnetic-axis-default relation, is updated to the new relation and fails on the old text.

Done when, all of these:

The release and the downstream pin bump are separate nodes under grammar-release-and-downstream-pin.

§ Followups

Land the loader and accessor first; content follows from the WEST worklist

§2 is self-contained code in this repository. §3's worklist comes from running the §2 accessor over the WEST roster, so §3 cannot start before §2. §4 is a coordinator act from the main checkout.

/reckon-build concept-and-notation-registry §2

Registry, loaders and accessor landed (commit 1e12625); 481 passed vs 469 base, negative control red, review 102/120. Section stays open for the template-scope follow-up. evidence

Added the conventions registry (vocabularies/conventions/concepts.yml, notation.yml, templates.yml) with its token-validating loaders in grammar/vocab_loaders.py and the parse-selecting select_conventions accessor in grammar/terms.py; for flux_surface_averaged_argon_density_at_plasma_boundary the accessor returns exactly 2 concepts (flux_surface_averaged, plasma_boundary), 1 notation (density) and 1 template (density), and the loader refuses a malformed entry per file, an unknown token key and a forbidden spelling equal to a registered alias, each by name.

§2 landed: registry, loaders and select_conventions (commit 1e12625), narrowed to openings-only templates read through _load_yaml (commit 0a977ee); reviews 102/120 and 118/120, no added failures. evidence

cnr-template-scope: removed the template sign_convention field from the model, templates.yml and the select_conventions output and folded _load_conventions_yaml into _load_yaml; rg finds neither name in the registry code, the gate files run 44 passed 5 xfailed vs 42 passed 5 xfailed at base (no added failures, EXIT=0), and re-adding sign_convention to TemplateEntry makes the refusal test fail (EXIT=1).

Independent review of run r-20261012T145518269054-cnr-registry-loader at head 1e12625 (base 264aa2e) is stored as a parsed record scoring all six dimensions (goal_fidelity 20, evidence 20, scope_discipline 18, durability 17, fit 17, reuse 10; total 102) with added_failure_count 0 and two follow-on findings, both non-blocking: _load_conventions_yaml duplicating _load_yaml, and a non-discriminating templates.yml refusal match.

review-of-cnr-template-scope: reviewed run r-20261012T153955809358-cnr-template-scope at base 6a9a943 head 0a977ee; the openings-only template narrowing and the _load_conventions_yaml fold both landed and are guarded; read all six checklist items and scored 6 dimensions 118/120 (goal_fidelity 20, evidence 20, scope_discipline 20, durability 19, fit 19, reuse 20) with no findings; the previously recorded follow-ons (_load_conventions_yaml duplicate, filename-only templates refusal match) are both repaired.

Rewrote the three registry tests around entry presence, density spelling policy and parse-selected notation; the four-file gate moved from 3 failed and 79 passed at base to 82 passed at final head, and three targeted scratch mutations each failed (EXIT=1); [landing anchor](/imas-standard-names/evidence/fragments/concept-and-notation-registry/cnr-registry-test-invariants.html#cnr-registry-test-invariants-landing).

The three registry tests now check the registry's invariants rather than pinned entries (merge 448d2b9); the gate went from 3 failed to 82 passed. Section stays open for the accessor operator keys and the binary-operator templates. evidence

review of run r-20261013T081300178088-cnr-registry-test-invariants at head 23597051: all six checklist items read and all six dimensions scored (goal_fidelity 20, evidence 20, scope_discipline 20, durability 19, fit 19, reuse 20; total 118); added_failure_count 0; one follow-on finding (landing fragment is an empty anchor); record stored at reviews/imas-standard-names/r-20261013T081300178088-cnr-registry-test-invariants.at-23597051f6d7a37adad4f66dcbeb1a0ec2031ca8.json.

review-of-cnr-accessor-operator-keys-64b51002225a: stored a parsed six-dimension review of cnr-accessor-operator-keys at head 64b51002 (base 18b78cd), total 97 (goal_fidelity 18, evidence 17, scope_discipline 20, durability 14, fit 18, reuse 10), zero added failures against the reviewed run's own baseline, two follow-on findings — the ratio-concept test is green at base so it does not guard this change, and _operator_token prefix-strips a fused indexed token instead of reusing model.py:_split_fused_indexed_operator.

cnr-accessor-operator-keys: indexed derivatives now select derivative_with_respect_to; ratio names select the ratio concept and ratio-keyed templates, and placeholder is excluded; the five-file gate ran 3 failed, 63 passed, 5 xfailed against 3 failed, 59 passed, 5 xfailed at base (zero added failure ids); removing all four selection mechanisms makes all four new tests fail (EXIT=1).

Convention selection keys indexed derivatives and ratio names by their registry tokens (merge 757e2f5). Next in this section: the binary-operator templates (ratio, difference, product), which also replace the copied fused-operator split with the model's owner and make the ratio test one that can fail. evidence

review-of-cnr-operator-key-reuse-e9a47864c352: independent review of r-20261013T120542044271-cnr-operator-key-reuse at base 9813991 head e9a4786 scores goal_fidelity 19 evidence 18 scope_discipline 20 durability 17 fit 19 reuse 20 (total 113), zero added failures, no blocking findings.

cnr-operator-key-reuse: the fused-operator split is routed through model._split_fused_indexed_operator (prefix loop and _operator_keys cache deleted) and the operator tests can fail; five-file gate 67 passed, 5 xfailed, EXIT=0 against 66 passed at base, and three mutations (raw _operator_token, binary ops excluded from _ir_tokens, binary keying dropped from template_bases) each fail EXIT=1 — fragment [cnr-operator-key-reuse](/imas-standard-names/evidence/fragments/concept-and-notation-registry/cnr-operator-key-reuse.html#cnr-operator-key-reuse-landing)

Binary-operator templates landed (commit 9813991), and the selector uses the model's one fused-operator splitter (merge 440942e). §3 closes with the registry census re-run on the WEST roster in imas-codex. That run must select entries through select_conventions, not a copied segment or template lookup. evidence

review-of-cnr-plasma-boundary-definition: independent review of r-20261014T194406258201-cnr-plasma-boundary-definition at base d0b7eaf head f9965fd scores goal_fidelity 20 evidence 17 scope_discipline 20 durability 5 fit 19 reuse 20 (total 101), zero added failures, no blocking findings; record stored at reviews/imas-standard-names/r-20261014T194406258201-cnr-plasma-boundary-definition.at-f9965fd4aef6a9f9dd139f23dbf32a033243a2f2.json

plasma_boundary now defined as the last closed magnetic flux surface in locus_registry.yml; the five-file gate ran 39 passed (EXIT=0) at head against 39 passed (EXIT=0) at base, zero added failures; landing record docs/evidence/fragments/concept-and-notation-registry/cnr-plasma-boundary-definition.html

Independent review of r-20261014T194710866779-cnr-midplane-and-inductance at base d0b7eafb head 0e43cde1 scores goal_fidelity 20 evidence 17 scope_discipline 20 durability 5 fit 20 reuse 20 (total 102), zero added failures, no blocking findings; the two midplane equations and the l_i(3) definition match the coordinator-authored text verbatim and the diff stays inside the two-path fence, but no test asserts the reworded text so a rollback reddens nothing; record stored at reviews/imas-standard-names/r-20261014T194710866779-cnr-midplane-and-inductance.at-0e43cde1a7918313fe2585175e665bde74e17260.json

§3 closed, together with imas-codex:sn-house-style §3. The registry worklist over the 220-name WEST roster is closed (every pattern selects a template). The coordinator read all 46 concept entries under the lead's delegation, and the three corrections landed: plasma boundary as the last closed magnetic flux surface (f9965fd, review 101/120), and the midplanes at the data's midplane height plus internal inductance as li(3) (0e43cde, review 102/120). evidence

The midplane entries now take the height the data midplane identifier selects (the magnetic-axis height when none is given) instead of the point where dR/dZ = 0 on the separatrix contour, which is undefined for a limited plasma; the internal-inductance definition names the l_i(3) form explicitly. Gate: 20 passed EXIT=0 at base d0b7eafb and 20 passed EXIT=0 at head 0e43cde, 0 added failures. [cnr-midplane-and-inductance]

Lead ruling, 2026-10-15. The registry gains both mechanisms: definitions on population, zone and aggregation tokens (§5), and token conditions on templates (§6). The near-duplicate sentences (§7) then render only on the names they describe.

review of r-20261016T052029421979-isn-token-definitions at base 7161a3b head ffd17ca stored as a parsed six-dimension record (101/120) with four follow-on findings and zero added failures.

docs/evidence/fragments/concept-and-notation-registry/isn-token-definitions.html

§5 closed. Population, zone and aggregation tokens carry definitions that render (merge 903e8e4, review 101/120). evidence

independent review of r-20261016T083852210600-isn-template-conditions at f01dd7cf0b3ef40d808084bc468a9118179285a6 scored goal_fidelity 18, evidence 17, scope_discipline 20, durability 16, fit 18, reuse 20 (total 109 of 120), zero added failures, three follow-on findings and no blocking finding; the landed change implements §6 conditioned template entries and template notes.

§6 closed. Template entries carry conditions and a note, and a conditioned entry wins over its unconditioned sibling (commit f01dd7c, review 109/120). §7 must render the note through the production documentation path, not a test helper, and rename _legacy_selection by what it computes. evidence

docs/evidence/fragments/concept-and-notation-registry/isn-template-conditions.html — a template entry may require tokens or exclude segment kinds and carry a note; selection applies the conditions after the subset test, a conditioned entry superseding its unconditioned sibling when both match; tests/grammar/test_template_conditions.py (8 tests) exercises the required token, the excluded kind, the note, the precedence rule and the shipped-registry no-op

/home/ITER/mcintos/.config/reckon/crew/reviews/imas-standard-names/r-20261016T102003154342-isn-near-duplicate-sentences.at-729c94deda18e631190c0c91284797917b382f51.json — parsed review of a5ced68975780bd2a2834d366bbe58fc336ed452..729c94deda18e631190c0c91284797917b382f51 with six scores and zero added failures

§7 closed. The three near-duplicate sentences render exactly once on the names they describe, through template_sentences (commit 729c94d, review 118/120). imas-codex sn-house-style §14 switches the writer and the gate to the accessor. evidence

docs/evidence/fragments/concept-and-notation-registry/isn-near-duplicate-sentences.html#isn-near-duplicate-sentences-landing — 62 family names checked, five red controls EXIT=1, full grammar 1275 passed versus 1212 base with zero added failures

Independent review of the separatrix_distance base node scored goal_fidelity 20, evidence 18, scope_discipline 20, durability 17, fit 19, reuse 20 against the diff 1e9d01f..fffa20c, with one follow-on finding on the red-control log header; the landing fragment is docs/evidence/fragments/concept-and-notation-registry/isn-separatrix-distance.html and the node is promote-ready.

The separatrix_distance physical base landed in physical_bases.yml; radial_separatrix_distance_at_outboard_midplane now decomposes as component radial with base separatrix_distance and position outboard_midplane and round-trips, while the separatrix zone and locus readings are unchanged.

§8 closed. separatrix_distance is a base, and radial_separatrix_distance_at_outboard_midplane now decomposes as what it measures (merge 089f55e, review 114). evidence

docs/evidence/fragments/concept-and-notation-registry/isn-locus-definitions-physics.html#isn-locus-definitions-physics-landing — 10 definitions revised; grammar 1275 passed at base and 1278 passed at head, zero added failures, both red controls EXIT=1

reviewed run r-20261018T111026811632-isn-locus-definitions-physics at head 6f5782aa63ab688a5e212e4d60e1bd6c0a8e6da1 — approve; six dimensions scored total 117, zero blocking findings, one follow-on

§9 closed. Locus definitions state the concept registry and name no DD field, IDS path or option; the midplane loci carry no gradient wording (merge 785e858, review 117). The release in §4 now carries §7, §8 and §9. evidence

Independent review of run r-20261022T093735018238-isn-one-midplane at base 2451ab4 head 88d7af7: all six checklist items read (goal, done_when, write_paths, manifest, diff 4c044f1+88d7af7, call sites terms.py standard_terms and select_conventions, grammar/context.py, catalog/dataset.py, grammar/parser.py, validation/semantic.py, models.py), six dimensions scored (goal_fidelity 20, evidence 19, scope_discipline 19, durability 15, fit 19, reuse 20; total 112 of 120), added_failure_count 0 from the reviewed run's own baseline_suite and after_suite logs (both completed, EXIT=0, 1282 and 1285 passed); one follow-on finding: the reworded poloidal_angle definition and its new up-down-symmetry sentence are unguarded.

§10 closed: the midplane loci carry one maximum-major-radius definition, as the lead ruled on 2026-10-22. The ISN release and the imas-codex pin bump follow under grammar-release-and-downstream-pin. Then gap_at_outboard_midplane's documentation is reviewed once more. evidence

Midplane loci are defined once by the major-radius extremum of the flux surface (outboard_midplane at maximum R on the low-field side, inboard_midplane at minimum R on the high-field side, outboard_midplane_separatrix at the separatrix's maximum R); the poloidal_angle zero stays on the horizontal plane through the magnetic axis with its coincidence with the outboard midplane restricted to up-down-symmetric equilibria; the relation test asserts R = max_S R and R = min_S R and fails on the previous per-dataset height wording. tests/grammar/: 1282 passed 32 skipped at base 2451ab4, 1285 passed 32 skipped at head 4c044f1, zero added failures. Record at docs/evidence/fragments/concept-and-notation-registry/isn-one-midplane.html.