A base for a distance from the separatrix

grammar/vocabularies/physical_bases.yml gains one base, separatrix_distance, beside decay_length and connection_length; the entry is kind: scalar with no aliases, and its comment states what it measures: a measurement position's distance from the magnetic separatrix, positive outside it in the scrape-off layer. It is the quantity the DD stores at langmuir_probes/embedded/distance_separatrix_midplane, langmuir.../reciprocating/plunge/distance_separatrix_midplane and thomson_scattering/channel/distance_separatrix_midplane. It names what a distance is measured from, which is a different statement from the separatrix zone, which says where a quantity sits.

The parse before and after. Before, the residue of radial_separatrix_distance_at_outboard_midplane resolved through the zone segment: component radial, base distance, zone [separatrix], position outboard_midplane, round trip true. After, it resolves as the base itself: component radial, base separatrix_distance, no zone, position outboard_midplane, round trip true.

No parser change was needed. In grammar/parser.py:_match_base_with_qualifiers the residue is tested against the closed base set (s in v.bases) before the split loop that strips a zone or qualifier prefix. For the target name the projection stage recurses on the residue separatrix_distance, which now returns the base directly, so the longer base match wins over the zone reading separatrix + base distance. The parser file is unchanged.

Fixture parse comparison: the 41 names in imas_standard_names/resources/standard_name_examples parse identically at the base vocabulary and at the head vocabulary — the two dumps diff with no line differing. Positive control: the instrument is shown to see a known difference, because the same probe trees parse the target name as base distance (zone [separatrix]) at base and base separatrix_distance (no zone) at head, so the empty fixture diff is a genuine absence and not a blind instrument.

Names that use separatrix as a zone or a locus keep their parse and are tested explicitly: separatrix_density stays base density with zone [separatrix], and temperature_at_separatrix stays base temperature with position separatrix. Both round-trip.

Negative control. With the separatrix_distance base removed from the vocabulary, the decomposition test (test_radial_separatrix_distance_decomposes_to_component_base_and_position) and the round-trip test (test_radial_separatrix_distance_round_trips) both fail, while the separatrix zone and locus tests still pass: 2 failed, 2 passed, EXIT=1. The log is negative-control.log in the run directory.

Gate: the whole tests/grammar/ suite, run twice, each arm in its own scratch copy of the tree with its own basetemp, so neither arm reads a file the other writes. The base arm (base vocabulary, head tests) ran 2 failed, 1277 passed, 32 skipped (EXIT=1); the head arm ran 0 failed, 1279 passed, 32 skipped (EXIT=0). Failure ids added at head: none. The base arm's only two failures are this node's own new tests — test_radial_separatrix_distance_decomposes_to_component_base_and_position and test_radial_separatrix_distance_round_trips — which is the red control reproduced at suite scope, and both pass at head. The logs are full-base-grammar.log and full-head-grammar.log in the run directory, each naming its own module.__file__, working directory and vocabulary digest (sha256 3374bc40… base, 93b066b3… head).