Implementation Plan: Placement-Port Residuals Closure
Branch: placement-port-residuals | Date: 2026-07-25 | Spec: spec.md Input: Feature specification from kitty-specs/placement-port-residuals-closure-01KYDEF0/spec.md
Summary
Close the placement-port residuals PR #2920 deferred (Parts A/B, issues #2923+#2924) and green the six gate/contract reds the PR merged red into upstream/main (Part C, incl. #2926). The work is a brownfield hardening pass over the birth-cutover / legacy runtime cutover, the coordination write-target degrade idiom, a best-effort tracer read, and four architectural/contract gates. Every fix is red-first through a pre-existing entry point; A1/A3 are validated across the whole FR-007 dogfood corpus. The engineering approach is fixed by the squad-hardened spec — no open design questions remain.
Technical Context
Language/Version: Python 3.11+ Primary Dependencies: typer, rich, ruamel.yaml (runtime); spec_kitty_events / spec_kitty_tracker (external contract pkgs); mission_runtime placement port (in-repo) Storage: Git-backed mission artifacts on disk (kitty-specs/<mission>/), append-only status.events.jsonl; meta.json metadata Testing: pytest (PWHEADLESS=1 pytest tests/), parallel -n auto --dist loadfile; red-first per DIRECTIVE_041; tests/architectural/ gate suite; mypy --strict; ruff (complexity ceiling 15) Target Platform: Cross-platform CLI (Linux/macOS/Windows), Python 3.11+ Project Type: single (Python CLI package specify_cli + shared mission_runtime) Performance Goals: N/A (correctness/gate mission, not a perf change) Constraints: No new lint/type debt (ruff+mypy clean, complexity ≤15); no legacy terminology; canonical sources only; no version/patch number assigned (C-005); no direct push to origin/main (PR workflow) Scale/Scope: 12 FRs / 4 NFRs / 7 constraints across ~8 product files + 5 test files; corpus-wide validation over the dogfood kitty-specs/ missions
Charter Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
Charter mode: compact (software-dev-default). Binding gates relevant here:
- Red-first / ATDD-first — each fix ships a failing test through the pre-existing entry point BEFORE the fix (NFR-001). Part C reds are already-red and satisfy this inherently; judged per the failing-test remediation framework (fix PRODUCT vs re-pin TEST), never retry-to-green.
- Canonical sources — use
mission_runtimeport surfaces + doctrine templates; no improvised path reconstruction (FR-001/FR-005 route through the port). - Terminology canon —
Missionnotfeature; PRIMARY-partition ≠ Primary-Branch (Domain Language table). Terminology guard run each spec commit (green). - Quality gates — ruff + mypy
--strictclean, complexity ≤15, no blanket suppressions (NFR-003). - Git workflow — mission merges to local
placement-port-residuals; PR tomainseparately; nogit push origin main. - No version prescription — C-005 (PO superimposes at release).
No charter violations anticipated. Complexity Tracking: N/A (no gate justifications required).
Project Structure
Documentation (this mission)
kitty-specs/placement-port-residuals-closure-01KYDEF0/
├── plan.md # This file
├── research.md # Phase 0 output — decisions already resolved by the post-spec squad
├── data-model.md # Phase 1 output — partitions / gates / capabilities (no new persisted entities)
├── quickstart.md # Phase 1 output — how to run each red-first repro
├── contracts/ # Phase 1 output — the invariant contracts each FR must satisfy
└── tasks.md # Phase 2 output (/spec-kitty.tasks — NOT created here)
Source Code (repository root)
src/
├── mission_runtime/
│ ├── resolution.py # resolve_artifact_surface / resolve_placement_only / placement_seam (FR-001, FR-005 home)
│ └── artifacts.py # MissionArtifactKind (PRIMARY_METADATA / STATUS_STATE / TRACER_FILE partitions)
├── specify_cli/
│ ├── migration/
│ │ ├── runtime_state_cutover.py # _flip_phase (FR-001), cutover_mission seed/verify (FR-002)
│ │ └── backfill_runtime_state.py # read-dir vs write-dir decoupling + has_evictable_state (FR-002)
│ ├── merge/executor.py # coord-seed safe_commit @1053-1060 (FR-008+FR-012), committed-set (FR-011)
│ ├── events/decision_log.py # _mission_meta_exists clone + _resolve_commit_target (FR-005)
│ ├── git/bookkeeping_commit.py # _mission_meta_exists clone + _resolve_bookkeeping_commit_target (FR-005)
│ ├── coordination/status_transition.py# _resolve_write_target divergent degrade (FR-005)
│ ├── retrospective/generator.py # _load_traces best-effort read (FR-006)
│ └── cli/commands/agent/mission_repair.py # raw KITTY_SPECS_DIR/mission path (FR-009)
tests/
├── architectural/
│ ├── test_no_write_side_rederivation.py # FR-008 allow-list (+ context for FR-003)
│ ├── _placement_whole_tree_scan.py # BOUNDARY_SANCTIONED_PREFIXES→MODULES (FR-003)
│ ├── test_no_raw_mission_spec_paths.py # FR-009 constructor allow-list
│ └── test_guard_capability_call_sites.py # FR-012 MERGE_BOOKKEEPING allow-list (#2926)
├── specify_cli/cli/commands/agent/test_mission_cli_golden_contract.py # FR-010 _EXPECTED_COMMANDS/_FLAGS
├── cli/commands/test_merge_status_commit.py # FR-011
└── integration/test_merge_lane_planning_data_loss.py # FR-011
Structure Decision: Single Python package; brownfield edits confined to the surfaces above. No new packages, no new top-level directories. New helper for FR-005 lands under src/mission_runtime/ (the placement-port package that owns resolve_placement_only).
Complexity Tracking
N/A — no Charter Check violations to justify.
Implementation Concern Map
> Concerns are architectural areas, NOT work packages. /spec-kitty.tasks translates > these into executable WPs (one IC may become several WPs; small ICs may merge). > Lane hints below reflect C-007 (shared-file cohesion), not final sequencing.
IC-01 — Sole status_phase writer routed through the port (fail-closed)
- Purpose: Make
_flip_phase's PRIMARY-correctness enforced by a runtime home-equality assert through the placement port, not by caller discipline. - Relevant requirements: FR-001; NFR-001, NFR-002.
- Affected surfaces:
migration/runtime_state_cutover.py(_flip_phase),mission_runtime/resolution.py(resolve_artifact_surface). - Sequencing/depends-on: none (first in Lane A).
- Risks:
repo_rootmust be the CWD-invariant main-repo root derived fromfeature_dir(neverPath.cwd()); a resolver raise on a well-formed legacy corpus mission must NOT abort the flip — only an equality mismatch fail-closes;write_metais invisible to the write-side gate so this is runtime-enforced (see [[reference-write-side-rederivation-gate-grammar]]); corpus regression risk.
IC-02 — Cutover read/write partition decoupling (no silent PRIMARY-runtime loss)
- Purpose: Read the legacy
tasks/frontmatter from the PRIMARY leg so a pre-IC-07 cold-upgrade coord mission is not silently evicted, while the seed-event write stays on its canonical COORD leg. - Relevant requirements: FR-002; NFR-002.
- Affected surfaces:
migration/runtime_state_cutover.py(cutover_missionline 202,_seed_phase:205,_verify_phase:214 — split read-leg=PRIMARYfeature_dirfrom write-leg=COORDstatus_dirinternally). Public signature ofcutover_missionstays stable — the split is internal. - No-change verification anchors (post-squad): the only COORD-reader is the two-leg
executor.py:996birth-cutover caller. The three single-leg callers (m_zz_runtime_state_backfill.py:204,cli/commands/migrate_cmd.py:868,cutover_repo:281) already read PRIMARY and MUST be byte-unchanged — do NOT spawn a caller-fanout WP. NFR-002's corpus run asserts they are unchanged. - Sequencing/depends-on: IC-01 (same file; sequence after).
- Risks: NOT a leg swap — the event log (STATUS_STATE) must still land on COORD; the read/write split is internal to
cutover_mission+_seed_phase/_verify_phase(signature stable); red-first test drives the two-leg shape (evictable PRIMARYtasks/+ stale/absent COORDtasks/) and asserts bothseeded_count > 0AND events on the COORD leg.
IC-03 — Birth-cutover coord-seed commit: reconcile both arch gates at one call site
- Purpose: Green
test_no_write_side_rederivation(FR-008) andtest_guard_capability_call_sites[MERGE_BOOKKEEPING](FR-012, #2926) — both flag the SAMEsafe_commitatexecutor.py:1053-1060. - Relevant requirements: FR-008, FR-012; NFR-004, SC-008.
- Affected surfaces:
merge/executor.py(coord-seed call site),tests/architectural/test_no_write_side_rederivation.py(allow-list),tests/architectural/test_guard_capability_call_sites.py(_PROTECTED_FLOW_ALLOWLISTS["MERGE_BOOKKEEPING"]). - Sequencing/depends-on: none (Lane A; shares
executor.pywith IC-04). - Risks: resolve BOTH gates with one coherent dated rationale (best-effort coord-seed writes
status.events.jsonlto the protected coord ref during merge); do NOT downgrade to STANDARD (would refuse the protected destination) and do NOT seam-route (adds merge-window resolvability coupling).
IC-04 — Merge status-event durability
- Purpose: Ensure merges durably commit
status.events.jsonlalongsidemeta.json/status.json(product regression, not a stale test). - Relevant requirements: FR-011; NFR-004, SC-008.
- Affected surfaces:
merge/executor.py(committed-file set),tests/cli/commands/test_merge_status_commit.py,tests/integration/test_merge_lane_planning_data_loss.py. - Sequencing/depends-on: none (Lane A; shares
executor.pywith IC-03). - Risks: the tests encode the real FR-019/FR-020 durability invariant → fix the PRODUCT; verify across planning-only and mark-done merge paths.
IC-05 — Whole-tree gate carve-out narrowing + guarantee wording
- Purpose: Convert the
src/specify_cli/migration/whole-subtree prefix to per-fileBOUNDARY_SANCTIONED_MODULESentries with individual rationales, and reconcile SC-002/NFR-001 wording precisely (migration/-subtree-scoped, not falsely un-qualified). - Relevant requirements: FR-003, FR-004; SC-002.
- Affected surfaces:
tests/architectural/_placement_whole_tree_scan.py(BOUNDARY_SANCTIONED_PREFIXES) ANDtests/architectural/test_no_write_side_rederivation.py(_PINNED_BOUNDARY_SANCTIONED_PREFIXES:511 — LOCKSTEP edit; the meta-test at :916 hard-asserts equality, so both must change together or it reds); the mergedcoord-write-placement-closure-01KYCF83/spec.mddeferral note (by anchor). - Sequencing/depends-on:
{IC-03 for suite-green verification, IC-01 defensive}. Corrected C-001 (adjudicated from source): dropping the prefix reds nothing on_flip_phase(the write-side gate scans onlyCommitTarget/safe_commit;migration/has none) — so no mechanical IC-01 dependency; keep IC-01 ordering as defensive insurance. Last in Lane A. - Verification (3 shared-scan consumers):
BOUNDARY_SANCTIONED_PREFIXESis imported bytest_no_write_side_rederivation,test_safe_commit_import_boundary, andtest_read_surface_placement_guard— verify all three green after the widen. C-003 refutation (recorded): the read-surface guard has no whole-scope offender scan and the AST consumers flag onlyCommitTarget/safe_commit(absent frommigration/), so wideningscan_scope()overmigration/provably engages NO read-side offender grammar — no #2922 collision. - Empirical red-first (closes C-001): with the prefix dropped and IC-01 NOT yet applied, observe whether the gate reds on
_flip_phase— empirically confirms the mechanism either way. - Risks: keep
mission_runtime/(port can't scan itself) ANDupgrade/migrations/(C-002); every retained per-file entry needs a rationale; do not overclaim closure forupgrade/migrations/; the C-004_MIGRATION_WALKER_DIR_PREFIXESblanket intest_mission_resolver_walker_gate.pyis a SEPARATE, intentional, permanent carve-out — out of scope, do NOT convert (SC-002 is scoped to the placement-enforcement scan only).
IC-06 — Write-target degrade unification (kind-parameterized) — SPLIT into 6a/6b
- Purpose: One shared
resolve_write_target_or_degrade(repo_root, mission_slug, kind, , degrade_ref)inmission_runtimeunifying port-resolution + the_mission_meta_existspre-gate — NOT the degrade policy*. The three sites keep three legitimately-distinct null-degrade_refpolicies (decision_log = fail-openreturn ref; bookkeeping = fail-closedraise ActionContextError; status_transition = secondary-resolverget_feature_target_branch), sodegrade_refis caller-computed. SC-004 "exactly 1 implementation" = one resolution+pre-gate helper, not one degrade action. - Relevant requirements: FR-005; NFR-003, SC-004.
- IC-06a (mechanical, low-risk): extract the helper; migrate the two verbatim clones (
events/decision_log.py,git/bookkeeping_commit.py) through it with caller-computeddegrade_ref, each keeping its fail-open/fail-closed contract. Satisfies SC-004 "0 verbatim clones." - IC-06b (behavior change, C-004, dedicated tests): adopt
coordination/status_transition.py::_resolve_write_targetonto the helper — this ADDS the_mission_meta_existspre-gate it lacks today (real behavior change) while preserving theget_feature_target_branchdegrade. Separable so 6a lands even if 6b iterates. - Affected surfaces: new helper in
src/mission_runtime/;events/decision_log.py+git/bookkeeping_commit.py(6a);coordination/status_transition.py(6b). - Sequencing/depends-on: none (Lane B); 6b after 6a.
- Risks: kind-parameterized —
STATUS_STATE/coord kinds degrade to the COORD ref, never PRIMARY (C-004); do NOT flatten the three degrade policies into the helper.
IC-07 — Best-effort tracer read guard
- Purpose: Wrap
_load_traces'read_dir(TRACER_FILE)so a deleted coordination branch degrades to[]instead of crashing. - Relevant requirements: FR-006; SC-005.
- Affected surfaces:
retrospective/generator.py(_load_traces). - Sequencing/depends-on: none (Lane C — split-candidate).
- Risks:
except (CoordinationBranchDeleted, StatusReadPathNotFound)only — do NOT widen to bareException; single call site (C-003), do not touch #2922's read-side set.
IC-08 — CLI path + golden-contract hygiene
- Purpose: Green
test_no_raw_mission_spec_paths(FR-009) and reconcile the mission-CLI golden contract for the sanctionedrepaircommand (FR-010). - Relevant requirements: FR-009, FR-010; SC-008.
- Affected surfaces:
cli/commands/agent/mission_repair.py,tests/architectural/test_no_raw_mission_spec_paths.py,tests/specify_cli/cli/commands/agent/test_mission_cli_golden_contract.py(_EXPECTED_COMMANDS/_EXPECTED_FLAGS/_EXPECTED_POSITIONALS),cli-surface-contract.md. - Sequencing/depends-on: none (Lane C — split-candidate).
- Risks: FR-010 must pin repair's flag/positional surface (not just the name) and rename the "exactly_eight" test/docstring 8→9 — else it green-washes the count while leaving the flag surface unverified.
IC-09 — Tracker / issue-matrix shape
- Purpose: Parent the orphaned issues and give the Part C reds a tracked home with a 1:1 issue-matrix.
- Relevant requirements: FR-007.
- Affected surfaces: GitHub issues + the mission issue-matrix. Terminal check = per-FR → exactly one issue (12 FR rows across 4 child issues under a new parent epic):
- #2923 → FR-001, FR-002, FR-003, FR-004 (IC-01, IC-02, IC-05)
- #2924 → FR-005, FR-006 (IC-06, IC-07)
- #2926 → FR-008 + FR-012 (same
executor.py:1053-1060call site; IC-03) — FR-008 rides under #2926, do NOT mint a separate FR-008 issue - new Part-C issue → FR-009, FR-010, FR-011 (IC-04, IC-08)
- FR-007 maps to IC-09 itself.
- Sequencing/depends-on: none (planning-time; seeds the terminal matrix).
- Risks: #2923/#2924/#2926 are all
parent: nulltoday → native-link all four children under the new epic; do not ride the FR-009/010/011 reds under #2923 (whose body covers A1/A2/A3 only).
Lane grouping (input to /tasks, per C-007):
- Lane A (serial): IC-01 → IC-02 (runtime_state_cutover.py) and IC-03 + IC-04 (executor.py, same file) and IC-05 last (gate; depends-on
{IC-03 suite-green, IC-01 defensive}) — one lane for file-ownership safety. - Lane B (parallel): IC-06a → IC-06b.
- Lane C (parallel, split-candidate for a fast PR if Lane A slips): IC-07, IC-08.
- Planning: IC-09.
Post-plan squad note: paula-patterns + architect-alphonso + planner-priti (profile-loaded, read-only) hardened this IC-map. Key adjudications folded above: C-003 collision REFUTED (widening scan_scope() over migration/ engages no read-side offender grammar); IC-05 acquires a lockstep pinned-tuple edit + 3-consumer verification, not an IC-01 correctness dep; paula's IC-02 premise was INVERTED (corpus callers already read PRIMARY; only the two-leg executor.py:996 reads COORD — fix is internal, signature stable); IC-06 split 6a/6b to avoid over-folding three distinct degrade policies; SC-002 scoped to the placement-enforcement scan (the C-004 walker-gate blanket is a separate permanent carve-out).