LearnNewsExamplesServices
Frontmatter
id16226
titleRetire the transient 'parity' plane name from durable substrate
stateClosed
labels
enhancementairefactoringarchitecture
assigneesneo-opus-grace
createdAtJul 31, 2026, 3:59 PM
updatedAtJul 31, 2026, 5:26 PM
githubUrlhttps://github.com/neomjs/neo/issues/16226
authorneo-opus-grace
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 31, 2026, 5:26 PM

Retire the transient 'parity' plane name from durable substrate

Closed Backlog/active-chunk-11 enhancementairefactoringarchitecture
neo-opus-grace
neo-opus-grace commented on Jul 31, 2026, 3:59 PM

Reframed 2026-07-31 by the author, per operator direction, before any implementation. The original body treated this as a duplication defect — the parity plane root restated 33 times — and prescribed Compose interpolation. That prescription was right about the mechanism and wrong about the defect: projecting one value would have entrenched a transient migration name in one authoritative place instead of 33 sloppy ones. Better hygiene, identical debt. The original framing is preserved at the end under Superseded framing so the correction stays auditable.

Context

parity names a migration state, not a thing. It meant "the containerized stack running in parity with the native local Agent OS" — a condition that existed only while both stacks coexisted during the #16167 cutover. That cutover has happened. The name now describes a relationship to something that no longer runs, and a future reader has no way to recover what it was parity with.

Operator framing, 2026-07-31: "parity was a transient migration state, which name was never supposed to stay inside substrate, since it has no meaning for future us."

The duplication makes it worse but is not the defect. The defect is that a temporary condition became a durable identifier.

Scope, measured and deliberately narrow (git grep, excluding the generated resources/content/** mirror, 2026-07-31):

token occurrences files
.neo-ai-data-parity 52 9
integration-parity 21 8
NEO_PARITY* / PARITY_ROOT 24 5
neo-local-parity 18 3
parity-plane 4 1

parity also has a legitimate, ongoing meaning in this repo — equivalence between two artifacts — and that sense is explicitly OUT of scope. config-leaf-parity.json, configTemplateParityProof.spec.mjs, GuideToolParity.spec.mjs, and list_pull_requests field parity all use the word correctly and permanently. A naive grep -il parity returns 1034 tracked files; that number is meaningless here and must not be used to size this work. Only the plane-identity family above is in scope.

Live latest-open sweep: latest 20 open issues read 2026-07-31T13:56:32Z; no equivalent. A2A claim sweep at the same time: no competing claim. #16206 (ai/deploy composable layering) is the nearest neighbour and does not cover naming.

The Problem

A name that encodes a transition cannot survive the transition. Three costs, in increasing severity:

  1. It is unreadable forward. "Parity with what?" has no answer available to a future maintainer from the substrate alone. The referent — a native host stack that the cutover deleted — is gone. The name is a dangling pointer in prose.
  2. It misdescribes what the profile now is. The profile is a second, isolated, disposable plane that runs beside the canonical one under its own Compose project, plane id, and relocated root. That is a durable and useful thing. Nothing about it is parity; it is isolation.
  3. The duplication makes the debt expensive rather than free to fix. Because the root literal is hand-copied 33 times in docker-compose.dev.yml alone, renaming today is a 33-line edit with no mechanical check that the edits agree. This is why the two problems are one ticket: the naming debt is the defect, and the duplication is what makes it costly.

And the sharpest instance of (3): --expected-plane-data-root "/app/.neo-ai-data-parity" exists to prove the served plane root (ADR 0019 §10.6, "resolvable is not observable"). Its expected value is a third hand-copy of the thing under test, so the desired-vs-observed comparison has two hand-maintained columns — the shape §10.6 names as passing trivially and detecting nothing.

The Architectural Reality

  • ai/deploy/docker-compose.dev.ymlx-plane-env: &plane-env is a YAML map consumed via merge keys. YAML anchors alias whole nodes, not string prefixes, so *root/sqlite/... does not parse. That is why the file's existing anchor mechanism was not applied to the root; a real constraint, not an oversight.
  • The file's own header states the principle it violates: "ONE VALUE, PROJECTED — … divergence is not prevented here, it is inexpressible." True of plane-id; false of the plane root.
  • ADR 0019 §10.3 / §10.7 — plane.id is opaque and "never derives a filesystem path or port." So the root cannot be derived from the plane id, and any rename needs its own declared value. Verified before proposing, because deriving from the id is the obvious-looking move that the ADR forbids.
  • ADR 0019 §10.5 requires per-member placement and forbids implicit cascade: "relocation is per-member placement work … never an implicit cascade." Any remedy must keep a per-member line.
  • The canonical profile already uses ${VAR:-default} for this class of problem (${NEO_HOST_BACKUP_ROOT:-${HOME}/.neo-ai/backups}, #16201). The idiom is established in the sibling file.
  • ADR 0019 §10.7's matrix row is titled "Dev parity" and carries the name in decision authority, so the ADR moves with the rename.

The Fix

One rename, projected through one value. The two halves are inseparable: the projection is what makes the rename a one-line operation now and forever after.

  1. Choose a durable name describing what the plane IS. Recommendation: dev/app/.neo-ai-data-dev, project neo-local-dev, volume dev-plane, test dir integration-dev. It is accurate today, survives the next migration, and needs no referent. Alternatives considered: sandbox (accurate on disposability, but implies untrusted rather than non-canonical); isolated (accurate but describes a property every non-canonical plane shares, so it does not distinguish); keeping parity (rejected — it is the defect).
  2. Introduce one interpolated root with a default preserving the new value, and project it into all 27 env bindings, 3 mount targets, and 3 healthcheck args in docker-compose.dev.yml.
  3. Rename the plane-identity family across the measured set: compose files, project name, volume, integration-parity test config and its CI job, ParityPlaneVolumeScoping.spec.mjs, the latency-pair diagnostics, and ADR 0019 §10.7's row.
  4. Add a static guard asserting the file contains at most one literal spelling of the plane root, so a future hand-copy fails rather than merely being ugly.

Verified empirically before proposing (Compose on the canonical machine, 2026-07-31): interpolation resolves inside a merge-keyed x- extension field, and an override moves every member together:

default:                 NEO_AI_DB_PATH: /app/.neo-ai-data-parity/sqlite/memory-core-graph.sqlite
PARITY_ROOT=…-teamB:     NEO_AI_DB_PATH: /app/.neo-ai-data-teamB/sqlite/memory-core-graph.sqlite

This is not the implicit cascade §10.5 forbids: every member keeps its own line, and a member that must not move simply does not consume the variable — which is how NEO_TENANT_REPO_MIRROR_ROOT's pinning stays expressible. Only the shared prefix literal is deduplicated.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
plane root name ai/deploy/docker-compose.dev.yml one interpolated root carrying a durable name, projected into every member binding absent env resolves the new default; no per-deployment action required parity→dev profile comments docker compose config render shows one root spelling across all members
plane-identity family compose files, volume, project, test config, CI job renamed off the migration term in one coordinated change none — a half-rename leaves two names for one plane, worse than either ADR 0019 §10.7 row git grep for the retired token returns only the generated mirror
equivalence-parity surfaces config-leaf-parity.json, GuideToolParity.spec.mjs, configTemplateParityProof.spec.mjs unchanged — different, legitimate meaning none those files appear in no diff
healthcheck expected root ADR 0019 §10.6 consumes the same value as the binding it proves absent env resolves the same default render shows arg and NEO_PLANE_DATA_ROOT equal under default and override
literal-count guard this ticket static spec asserts at most one literal spelling of the plane root none — a second literal is the defect red-proof: reintroducing a second literal fails the spec

Decision Record impact

amends ADR 0019 §10.7 — the per-profile placement matrix names this profile "Dev parity" and carries its root literal, so the row changes with the rename. §10.3's opacity rule is not challenged: the root gets its own declared value precisely because the plane id may not derive one. §10.5's per-member placement is preserved by construction.

Acceptance Criteria

  • git grep for the retired plane-identity tokens returns zero hits outside resources/content/**, and the equivalence-parity files appear in no diff. Both halves asserted — a rename that also renames the legitimate sense is a failure, not an over-delivery.
  • docker compose -f docker-compose.dev.yml config renders one root spelling across every member binding, mount target, and healthcheck arg.
  • Overriding the root variable moves every member together, verified on a render.
  • A profile-pinned member that must not follow the root is still expressible, proven by a render under override.
  • The file contains at most one literal spelling of the plane root, asserted by a static spec, with a recorded red-proof.
  • The renamed stack boots; assertPlaneCoherence and assertPlaneMemberCoherence pass unchanged.
  • The CI job and integration test config resolve under the new name, with a green run.
  • ADR 0019 §10.7's row carries the new name and no stale referent.

Out of Scope

  • parity as equivalenceconfig-leaf-parity.json, GuideToolParity.spec.mjs, configTemplateParityProof.spec.mjs, list_pull_requests field parity. Correct, permanent usage.
  • The canonical, parity-CI-successor, and local-agent-os placement decisions — only names and the projection change; no plane moves, no member set changes, no port band changes.
  • ai/deploy composable layering — #16206 owns that.
  • Migrating existing dev-plane volume data. The plane is disposable by design; a renamed volume is a fresh volume, and that must be stated in the profile comments rather than silently absorbed.

Avoided Traps

  • Deduplicating without renaming. The original prescription. It would have made the transient name more authoritative by giving it a single canonical home — the debt entrenched rather than repaid.
  • Renaming without deduplicating. A 33-line hand edit with no mechanical check that the edits agree, leaving the next rename exactly as expensive and the healthcheck still asserting against a hand-copy.
  • Deriving the root from plane.id. The obvious-looking move, and ADR 0019 §10.3/§10.7 explicitly forbid it — the id is opaque and never derives a path or port.
  • Sizing this from grep -il parity. Returns 1034 tracked files by conflating the equivalence sense and the generated mirror. Using it would inflate the work by an order of magnitude and put legitimate files at risk of a careless rename.
  • Treating it as cosmetic. The healthcheck consequence is why it is not: a desired-vs-observed check with two hand-copied columns degrades to desired-vs-desired.
  • A plain YAML anchor. Anchors alias nodes, not prefixes; recorded so the next reader does not re-derive it.

Related

  • #16206ai/deploy composable layering; nearest neighbour, natural merge target if its owner prefers one change over two
  • #16201 / PR #16221 — established the ${VAR:-default} idiom for a plane-adjacent path in the canonical profile
  • #16167 — the cutover that ended the parity condition this name records
  • ADR 0019 §10.3 (opaque id), §10.5 (per-member placement), §10.6 (observed identity), §10.7 (profile matrix)

Superseded framing (original body, 2026-07-31)

Filed as "Dev parity profile restates its plane root 33 times" — a duplication defect with Compose interpolation as the remedy. The counts and the empirical interpolation proof carry forward unchanged; the framing does not. Recorded rather than deleted because the correction is the useful part: a fix that removes duplication of a wrong name makes the wrong name canonical. Deduplication is a multiplier on whatever it deduplicates, so the name has to be right first.

Origin Session ID: 59fd6dbb-fc01-482b-a778-bed01f16e699

Retrieval Hint: parity transient migration state name retired from substrate plane root dev rename compose interpolation one value projected