Research: Write-Side Seam: Matrix & Tracer Writers
Phase 0 output. Most unknowns were resolved by two profile-loaded grounding squads (see pre-planning-ledger.md); this file records the decisions that shape the design.
D-1 — This is an adoption mission, not a construction mission
- Decision: Extend the existing write seam (
PlacementSeam.write_target(kind)→resolve_placement_only) at bypassing call sites; do not build a new resolver. - Rationale: The seam predates #3060 (ADR
2026-06-24-1); its C-006 explicitly rejects a parallel write-only resolver. Metric: ~80 seam-routed reads vs ~3 seam-routed writes — the gap is adoption. - Alternatives rejected: A new write resolver (ADR-forbidden, re-leaks the read-side defect three times).
D-2 — Matrix storage format = JSON, single canonical artifact (Decision plan.matrix.storage-format)
- Decision: Both matrices are JSON.
issue-matrix.jsonbecomes the single canonical artifact; noissue-matrix.mdrender — the dashboard parses JSON directly. - Rationale: Consistency with the existing
acceptance-matrix.jsonand the JSON-parsing merge drivers; a duplicate markdown render only confuses operators/agents. - Alternatives rejected: YAML (diverges from acceptance-matrix, second format for drivers/readers); dual JSON+markdown (duplicate source of truth).
D-3 — Back-compat = migrate-on-write + failover-read + bulk command (Decision plan.matrix.issue-backcompat)
- Decision: A shared migration sub-module: (a) failover-read the legacy
issue-matrix.mdwhenissue-matrix.jsonis absent; (b) migrate-on-write — the first structured write converts a mission to JSON; (c) a dedicated bulk-migration command for one-shot swap-over, using the same sub-module. - Rationale: No in-flight consumer mission breaks; the migration logic is authored once and reused (FR-013).
- Alternatives rejected: Forward-only (in-flight missions lose the new tooling); a permanent dual-format reader (drift risk).
D-4 — Row-aware matrix merge driver on structured JSON (FR-008)
- Decision: Replace the whole-file
_write_more_filled_sideacceptance/issue-matrix drivers with row-aware drivers that union disjoint rows keyed by a stable row identity. - Rationale: Grounding refuted the "already row-aware" assumption — the current drivers clobber the lower-scoring side when two lanes fill disjoint rows. Structured JSON (D-2) makes row-level merge tractable and testable in isolation.
- Alternatives rejected: Keep "more-filled-side" (satisfies #2482 stale-residue only, not the disjoint-row gap); markdown row-merge (fragile).
D-5 — FR-009 lane base = recorded planning-artifact SHA (new ADR)
- Decision: Branch execution lanes from the recorded finalize-tasks tip (captured in
lanes.json/meta.json), not the pre-planning coordination tip nor a movingtarget_branchtip. A new ADR (amending2026-04-03-1) governs this and MUST resolve whether the base also carries coord-status lineage. - Rationale: The coord branch is minted before planning artifacts exist, so lanes lack a common ancestor with the consolidation base (#2993). Pinning to a recorded SHA avoids the moving-tip guard trap; a moving tip would re-introduce base-strand bugs.
- Alternatives rejected: Branch from current
target_branchtip (moves; guard-strand); keep coord tip (the defect itself). - Constraint: No consolidation-time abort path (ADR
2026-07-23-2);merge/ordering.pyis a pure frontmatter topo-sort and is untouched.
D-6 — FR-010 kept to "Move A" by design
- Decision: Design the new writers to route COORD dirs purely through
write_target/commit_for_mission. The coord-authority gate scans onlyresolve_feature_dir_for_mission, so seam-routed writers are invisible to it — FR-010 reduces to Move A (routedecisions/emit.pyoff the allowlist; re-pin census floor 4→3). Move B (widening the gate predicate) is only authored if a writer must resolve via the kind-blind resolver. - Rationale: Move A strengthens the gate (one fewer sanctioned bypass); avoiding Move B avoids predicate-widen risk. If Move B is unavoidable, it must be def-use gated with an alias-bite non-vacuity test.
- Alternatives rejected: Widen the gate by module/name proxy (weakens it; ADR
2026-06-26-1confirmation criterion forbids a vacuous gate).
D-7 — FR-011 = zero-write refusal on unroutable writes
- Decision: On a deleted
target_branch/ missing coord surface, the write refuses with a structured, recoverable result that discloses #3033 as the deferred real fix — never a fallback write, never a consolidation abort. - Rationale: The existing degrade path falls back to writing the configured primary (
main), resurrecting a closed defect and foreclosing #3033'sCONSOLIDATED-surface decision (ADR2026-07-23-2: refuse rather than fabricate a surface). - Alternatives rejected: Reuse the fallback-write degrade (regression); implement the post-merge mode here (#3033 out of scope, C-006).
D-8 — One-seam discipline (enforced across the writer concerns)
- Decision: One write-surface resolution + one materialization authority + parameterized scanner/writer cores with thin per-kind wrappers.
- Rationale: FR-001 confirms the pattern is clean (computed verdict property, no re-authoring). Giving FR-001/003/006 independent compute-and-commit paths reproduces the pre-#3060 read-side leak three times.
- Alternatives rejected: Per-writer bespoke compute+commit (whack-a-field regression).
Out-of-scope confirmations (C-006)
- Post-merge write mode #3033 (FR-011 guards only); finalize-tasks cluster; status-writer behavioural unification (only #3027's mark-status-roster campsite is in-core); review-verdict integrity P0s (#3044); mission-card-as-alternative-source #1742/#1740 (
at_tension_with; this mission commits to the scanner + structured-artifact path).