Tasks: Landing-Pass Campsite Follow-ups

Mission: landing-pass-campsite-followups-01KXKWD7 Branch: feat/landing-pass-campsite-followups | Plan: plan.md | Spec: spec.md

Every WP is red-first (C-005): reproduce the failure through the pre-existing entry point, commit the RED test first, then go green. Coord topology with lanes; owned_files are disjoint across WPs (the real parallel-collision guard).

Subtask Index

IDDescriptionWPParallel
T001RED: unregistered arch test file double-reds GC-1 + orphan gatesWP01
T002Add default_fallback field to ShardGroupWP01
T003Root-gated hash-bucket fallback branch in shard_for()WP01
T004Opt-in on the arch row; rewrite the doctrine header (FR-011)WP01
T005Verify GC-1 union + orphan gates green; explicit entries still winWP01
T010RED: structural — real mission_creation.py mutated mid-scan under -n autoWP02[D]
T011Isolate _SourceMutation to a tmp copy + process-local audit.SRC_ROOT monkeypatchWP02
T012Confirm the second scanner (test_surface_resolution_audit) is immune (#2638)WP02
T013Preserve what the bite-battery proves (real detector path); parallel smoke ≥5×WP02
T020RED: test_dry_run_evidence_on_spec_kitty_repo ANSI break + real synthesis-manifest mutationWP03[D]
T021Deterministic no-color output via CliConsole; strip/avoid ANSI in the assertionWP03
T022Isolate the synthesis-manifest write to a tmp fixture (no real-file mutation)WP03
T030RED: _build_remediation_lines inline command escapes the guardWP04[D]
T031Hoist all remedy prose to constants; expose ALL_REMEDIATION_TEXTS registryWP04
T032Both the dict and the inline builder reference the constants (byte-identical output)WP04
T033Repoint the command-name guard at the full registry; verify inline typo now failsWP04
T040RED: get_wp_lane returns `Lanestr; assert pure-Lane` + import safetyWP05
T041Add Lane.UNINITIALIZED member (non-display, non-transitionable)WP05
T042Add its _STATE_MAP/_FACTORY_ALIASES entry (wp_state.py) — no import crashWP05
T043Canonical non-display-lane authority; update filters to exclude UNINITIALIZEDWP05
T044get_wp_lane returns Lane.UNINITIALIZED; get_all_wp_lanesdict[str, Lane]WP05
T045Update ~12 pre-existing lane-roster tests to exclude/extend for UNINITIALIZEDWP05
T046Exempt UNINITIALIZED from CANONICAL_LANES parity like genesisWP05
T050RED: behavior — unseeded path (worktree-topology "planned"; done "not done")WP06
T051done_bookkeeping: treat Lane.UNINITIALIZED explicitly as not-doneWP06
T052worktree_topology + aggregate + coordination/status_transition consumersWP06
T053workspace/context annotation ripple from dict[str, Lane]WP06
T054workflow_executor: str→Lane ×4 (now cleared) + typed _locate_wp ×2 + Optional 668/873WP06
T055coordination/status_transition `StatusEventNone` narrowingWP06
T060RED: duplicated decision_id interview block; `strNone→str` mypy errorWP07
T061Create widen/interview_helpers.py; route both interviews through the narrow-once seamWP07
T062Drop the 3 config-verified redundant casts + delete stale follow_imports=skip commentsWP07

Work Packages

WP01 — Shard-registry default fallback + doctrine header (#2671)

  • Goal: unregistered tests/architectural/*.py auto-covers via a deterministic root-gated hash-bucket fallback; explicit entries win; union invariant retained; doctrine header rewritten.
  • Requirements: FR-001, FR-002, FR-003, FR-004, FR-011, NFR-001, NFR-006, C-002, C-008.
  • Independent test: add a throwaway arch test file → GC-1 completeness + orphan gates stay green with no shard-table edit.
  • Depends on: none (land first — soft enabler).
  • Subtasks: T001–T005. Est. ~300 lines.

WP02 — Bite-battery mutation isolation (#2673 + #2638)

  • Goal: remove the shared-mutable-real-file hazard so concurrent scanners never read a half-mutated mission_creation.py; both scanner victims fixed by one change; battery still proves detection.
  • Requirements: FR-005, FR-006, NFR-002, C-003, C-006.
  • Independent test: -n auto --dist loadfile across the three files, ≥5× green; git status --porcelain src/specify_cli/core/mission_creation.py empty after the run.
  • Depends on: none. ⚠️ SHARP cross-mission contention on test_single_mission_surface_resolver.py — land in a quiescent window (C-006).
  • Subtasks: T010–T013. Est. ~280 lines.

WP03 — Color/synthesis hygiene via CliConsole (#2672)

  • Goal: test_dry_run_evidence_on_spec_kitty_repo deterministic without ANSI-sensitivity or real synthesis-manifest mutation, via the CliConsole seam + tmp fixture.
  • Requirements: FR-007, C-004.
  • Independent test: the test passes in a color-enabled local shell; git status --porcelain .kittify/charter/synthesis-manifest.yaml empty after the run.
  • Depends on: none.
  • Subtasks: T020–T022. Est. ~220 lines.

WP04 — Sync remediation registry + guard (#2674)

  • Goal: single-source every remediation sentence; the command-name guard scans the full registry so inline commands are validated; no duplicated literal; byte-identical output.
  • Requirements: FR-008, FR-009.
  • Independent test: a deliberately mistyped inline command fails test_no_unknown_commands_in_hints; rendered lines unchanged.
  • Depends on: none.
  • Subtasks: T030–T033. Est. ~260 lines.

WP05 — Lane.UNINITIALIZED member + loader + FSM + display unification (#2675 cluster-1 core)

  • Goal: introduce the new canonical Lane.UNINITIALIZED member cleanly — FSM state-map entry (no import crash), a canonical non-display-lane authority, and the loader returning pure Lane.
  • Requirements: FR-010, NFR-003, NFR-004, NFR-005, C-001.
  • Independent test: mypy on lane_reader.py clean; import specify_cli.status.transitions succeeds; display summaries exclude UNINITIALIZED.
  • Depends on: none (foundation for WP06).
  • Subtasks: T040–T044. Est. ~360 lines.

WP06 — Lane consumer behavior + workflow_executor type-clears (#2675 clusters 1-downstream, 2, 4)

  • Goal: update the sentinel's behavioral consumers with tests on the unseeded path, and clear the workflow_executor.py errors (all three clusters in one lane).
  • Requirements: FR-010, NFR-003, NFR-004, NFR-005, C-001.
  • Independent test: behavior tests pin unseeded→"planned"/"not done"; mypy clean on all WP06 surfaces; no new suppressions.
  • Depends on WP05
  • Note: WP06 needs Lane.UNINITIALIZED from WP05 before its consumers/type-clears compile.
  • Subtasks: T050–T055. Est. ~420 lines.

WP07 — Interview-helper de-dup + config-verified casts (#2675 cluster-3 + casts)

  • Goal: de-duplicate the byte-identical decision_id interview block into a shared narrow-once helper; drop the three in-scope redundant casts (config-verified) with their stale rationale comments.
  • Requirements: FR-010, NFR-003, NFR-005, C-001.
  • Independent test: mypy clean on the interview + cast surfaces; both interviews exercise the shared helper.
  • Depends on: none (disjoint from WP05/WP06).
  • Subtasks: T060–T062. Est. ~240 lines.

Sequencing & parallelism

  • WP01 first (soft enabler). WP02, WP03, WP04, WP07 are mutually independent — full parallel. WP06 depends on WP05.
  • MVP / highest-leverage: WP01 (stops the recurring red-main) + WP04 (closes a silent-typo gap).
  • The heaviest lane is WP05→WP06 (the Lane unification); everything else is light.

Deferred / tracked

  • The 3 charter/mission_type_profiles.py casts (owned by the shipped mission-type work).
  • SC-006 follow-up issue for the 6 residual _SourceMutation sites in test_single_mission_surface_resolver.py.