description: "Work package task list — Decompose the merge.py God-Module (#2057)"
Work Packages: Decompose the merge.py God-Module (#2057)
Inputs: Design documents from /kitty-specs/decompose-merge-god-module-01KVXHDK/ Prerequisites: spec.md, plan.md, research.md, data-model.md, contracts/cli-surface-contract.md, quickstart.md
Tests: Test work is explicit and load-bearing. WP01 captures the golden CLI characterization test FIRST (byte-identity proof). Every seam WP ships focused per-seam tests (≥90% coverage of moved code). The executor WP adds a #1827 phase-boundary regression test.
Organization: This is a strictly-linear WP chain — WP01 → WP02 → … → WP11, each WP depending ONLY on the immediately-preceding WP. This keeps lanes nesting cleanly (avoiding the multi-lane divergence that plagued #2058).
Ownership model (zero owned_files overlap): each seam WP owns ONLY its new/extended seam module(s) + its test file. src/specify_cli/cli/commands/merge.py is owned SOLELY by the final WP (WP11). Seam WPs make small, documented out-of-map wiring edits to merge.py to import-from / re-export the relocated seam; those edits are not ownership claims.
Prompt Files: Each WP references a matching prompt file in /tasks/.
Subtask Format: [Txxx] [P?] Description
- [P] indicates the subtask can proceed in parallel (different files/components) within a WP. Across WPs the chain is strictly serial.
Path Conventions
- Single Python project:
src/specify_cli/,tests/. Seam package:src/specify_cli/merge/. Shim:src/specify_cli/cli/commands/merge.py.
Work Package WP01: Golden CLI characterization harness (Priority: P1) 🎯 GATE
Goal: Capture the spec-kitty merge byte-identity contract against the PRE-refactor module via Typer CliRunner on the fully registered app. Independent Test: Golden test passes on the current module and pins help/flags/dry-run-JSON/error-paths. Prompt: /tasks/WP01-golden-cli-harness.md Requirement Refs: FR-001, C-005
Included Subtasks
- ✅ T001 Author
tests/specify_cli/cli/commands/test_merge_cli_golden.pyinvoking the registered app (WP01) - ✅ T002 Snapshot
merge --help, every flag/default + hidden--featurealias (WP01) - ✅ T003 Pin the
--json-without---dry-runerror string + exit 1 (WP01) - ✅ T004 Pin the
--dry-run --jsonpayload key set + headline error/exit-code paths (WP01) - ✅ T005 Run on the pre-refactor module; record the baseline as the byte-identity proof (WP01)
Dependencies
- None (gate; authored first per ATDD; gates the entire chain).
Risks & Mitigations
- Re-wrapping the command instead of the registered app → invoke through the real app object.
Work Package WP02: Shared constants seam — merge/_constants.py (Priority: P1)
Goal: Centralize shared literals / type aliases / logger into merge/_constants.py (S1192-safe foundation). Independent Test: merge/_constants.py imports cleanly; golden test still green; constants byte-identical. Prompt: /tasks/WP02-constants-seam.md Requirement Refs: FR-003, C-008, NFR-003
Included Subtasks
- ✅ T006 Create
src/specify_cli/merge/_constants.pywith the shared literals/aliases/logger (WP02) - ✅ T007 Preserve
LINEAR_HISTORY_REJECTION_TOKENSorder/membership byte-for-byte (WP02) - ✅ T008 Wire
merge.pyto import from_constants+ re-export for__all__(WP02) - ✅ T009 Add
tests/merge/test_constants_seam.pycovering the moved constants (WP02)
Dependencies
- WP01.
Risks & Mitigations
- Constant drift → assert exact tuple in the seam test.
Work Package WP03: Git primitives seam — merge/git_probes.py (Priority: P1)
Goal: Relocate branch/tree/porcelain git primitives incl. public path_is_under_worktrees. Independent Test: git_probes imports cleanly; path_is_under_worktrees re-exported; doctor/mission importers green. Prompt: /tasks/WP03-git-probes-seam.md Requirement Refs: FR-003, FR-006, C-006
Included Subtasks
- ✅ T010 Create
src/specify_cli/merge/git_probes.py; move branch/tree/porcelain primitives (WP03) - ✅ T011 Re-export
path_is_under_worktreesfrom the shim (doctor.py + agent/mission.py importers) (WP03) - ✅ T012 Wire
merge.pyimport-from + re-export; confirm one-way imports (WP03) - ✅ T013 Add
tests/merge/test_git_probes_seam.py(≥90% of moved code) (WP03)
Dependencies
- WP02.
Risks & Mitigations
- Breaking doctor/mission imports → re-export and run those importers' tests.
Work Package WP04: Slug/state/target resolution seam — merge/resolve.py (Priority: P1)
Goal: Relocate slug extraction, merge-state load/clear/cleanup, and target-branch resolution. Independent Test: resolve imports cleanly; _resolve_mission_slug/_resolve_target_branch re-exported; resolver tests green. Prompt: /tasks/WP04-resolve-seam.md Requirement Refs: FR-003, FR-006, C-002
Included Subtasks
- ✅ T014 Create
src/specify_cli/merge/resolve.py; move slug/state/target resolvers (consumingmerge/state.py) (WP04) - ✅ T015 Re-export the test-imported resolvers from the shim (WP04)
- ✅ T016 Wire
merge.pyimport-from + re-export (WP04) - ✅ T017 Add
tests/merge/test_resolve_seam.py(≥90% of moved code) (WP04)
Dependencies
- WP03.
Risks & Mitigations
- State-key candidate ordering → preserve exactly; cover in seam test.
Work Package WP05: Preflight seam — extend merge/preflight.py (Priority: P1)
Goal: Relocate git/target/mission-branch/review-artifact/hollow-review preflights; split _collect_hollow_review_warnings (CC21) to ≤15. Independent Test: Preflight importers green; _collect_hollow_review_warnings ≤15 CC; existing preflight tests pass. Prompt: /tasks/WP05-preflight-seam.md Requirement Refs: FR-003, FR-005, FR-006, C-002
Included Subtasks
- ✅ T018 Relocate preflight functions into
merge/preflight.py(+push_preflight.pysupport) (WP05) - ✅ T019 Split
_collect_hollow_review_warningsinto helpers, each ≤15 CC (WP05) - ✅ T020 Re-export test-imported preflight symbols from the shim (WP05)
- ✅ T021 Wire
merge.pyimport-from + re-export (WP05) - ✅ T022 Extend
tests/merge/test_preflight.py/ add focused tests for the split (≥90%) (WP05)
Dependencies
- WP04.
Risks & Mitigations
- Review-artifact gate behavior → keep
post_merge.review_artifact_consistencyas leaf dep; cover both branches.
Work Package WP06: Forecast seam — merge/forecast.py (Priority: P1)
Goal: Extract the dry-run preview + JSON/human payload build out of the merge body. Independent Test: Dry-run JSON key set unchanged (golden test green); forecast unit tests pass. Prompt: /tasks/WP06-forecast-seam.md Requirement Refs: FR-001, FR-003, FR-004
Included Subtasks
- ✅ T023 Create
src/specify_cli/merge/forecast.py; move dry-run preview/payload build (WP06) - ✅ T024 Preserve dry-run JSON key set +
REJECTED_REVIEW_ARTIFACT_CONFLICTemission (WP06) - ✅ T025 Wire
merge.pyimport-from (WP06) - ✅ T026 Add
tests/merge/test_forecast_seam.py(≥90% of moved code) (WP06)
Dependencies
- WP05.
Risks & Mitigations
- Dry-run schema drift → assert exact key set; golden test re-run.
Work Package WP07: Mission-number bake seam — extend merge/ordering.py (Priority: P1)
Goal: Relocate the mission-number bake cluster into merge/ordering.py. Independent Test: _bake_mission_number_into_mission_branch re-exported; idempotency tests pass. Prompt: /tasks/WP07-ordering-bake-seam.md Requirement Refs: FR-003, FR-006, C-002
Included Subtasks
- ✅ T027 Relocate the bake cluster into
merge/ordering.py(WP07) - ✅ T028 Re-export
_bake_mission_number_into_mission_branchfrom the shim (WP07) - ✅ T029 Wire
merge.pyimport-from + re-export; keep lazy imports lazy (WP07) - ✅ T030 Extend
tests/merge/test_mission_number_*/ add focused bake tests (≥90%) (WP07)
Dependencies
- WP06.
Risks & Mitigations
_write_mission_number_to_branch(154 LOC) git-worktree heavy → relocate verbatim; lazy imports unchanged.
Work Package WP08: Done-bookkeeping seam — merge/done_bookkeeping.py (Priority: P1)
Goal: Relocate done/approved transition emission + done asserts + resume reconcile; split _mark_wp_merged_done (CC22) and _assert_merged_wps_done_on_target (CC16) to ≤15. Independent Test: _mark_wp_merged_done re-exported (orchestrator_api importer green); done-recording tests pass; both split fns ≤15 CC. Prompt: /tasks/WP08-done-bookkeeping-seam.md Requirement Refs: FR-003, FR-005, FR-006
Included Subtasks
- ✅ T031 Create
src/specify_cli/merge/done_bookkeeping.py; move done/approved emission + asserts + reconcile (WP08) - ✅ T032 Split
_mark_wp_merged_done(PLANNED-fallback/force-done/dedup) into helpers ≤15 CC (WP08) - ✅ T033 Split
_assert_merged_wps_done_on_targetto ≤15 CC (WP08) - ✅ T034 Re-export
_mark_wp_merged_done+ asserts from the shim (orchestrator_api/commands.py importer) (WP08) - ✅ T035 Wire
merge.pyimport-from + re-export (WP08) - ✅ T036 Add
tests/merge/test_done_bookkeeping_seam.py(≥90%, exercises split branches) (WP08)
Dependencies
- WP07.
Risks & Mitigations
- Intricate dedup/force branching → focused tests per branch; preserve behavior exactly.
Work Package WP09: Bookkeeping-projection / snapshot seam — merge/bookkeeping_projection.py (Priority: P1)
Goal: Relocate the status-surface trust + snapshot/restore + projection cluster. Independent Test: Trust/projection tests pass; _restore_final_bookkeeping_snapshots signature stable for the executor split. Prompt: /tasks/WP09-bookkeeping-projection-seam.md Requirement Refs: FR-003, FR-006, INV-6
Included Subtasks
- ✅ T037 Create
src/specify_cli/merge/bookkeeping_projection.py; move trust + snapshot/restore + projection (WP09) - ✅ T038 Preserve
_restore_final_bookkeeping_snapshotssignature/behavior for INV-6 (WP09) - ✅ T039 Wire
merge.pyimport-from + re-export (WP09) - ✅ T040 Add
tests/merge/test_bookkeeping_projection_seam.py(≥90% of moved code) (WP09)
Dependencies
- WP08.
Risks & Mitigations
- Path-trust assertions are security-sensitive → cover trusted + rejected paths.
Work Package WP10: Executor seam + CC-102 decomposition — merge/executor.py (Priority: P1) 🎯 HIGH-RISK
Goal: Relocate _run_lane_based_merge + _run_lane_based_merge_locked and internally decompose the CC-102 driver into ~9 phase helpers (each ≤15) via a _MergeRunState dataclass; preserve #1827 ordering (INV-5) and the ~6 snapshot-restore-on-exception sites exactly (INV-6). Independent Test: Executor + phase-boundary #1827 regression tests pass; every executor function ≤15 CC; recovery/resume/coord-topology suites green. Prompt: /tasks/WP10-executor-decomposition.md Requirement Refs: FR-003, FR-005, FR-006, FR-007
Included Subtasks
- ✅ T041 Define
_MergeRunStatedataclass threading shared mutable state (WP10) - ✅ T042 Create
merge/executor.py; move_run_lane_based_merge+ the locked driver (WP10) - ✅ T043 Decompose
_run_lane_based_merge_lockedinto ~9 phase helpers, each ≤15 CC (WP10) - ✅ T044 Preserve #1827 baseline record→commit→assert ordering + restore-on-error (INV-5/INV-6) (WP10)
- ✅ T045 Re-export
_run_lane_based_merge[_locked]from the shim (WP10) - ✅ T046 Add
tests/merge/test_executor_phase_boundary.py(#1827 ordering + restore regression) (WP10)
Dependencies
- WP09.
Risks & Mitigations
- THE mission risk → thread state via dataclass not closures; keep lazy imports lazy (C-007); add the phase-boundary regression test before claiming done.
Work Package WP11: Shim thinning + #2057 pointer comment + full gate sweep (Priority: P1)
Goal: Decompose the merge command (CC71) into _dispatch_abort/_dispatch_resume/_dispatch_dry_run/_run_real_merge (≤15 each); install the #2057 pointer comment; finalize re-exports + __all__ byte-stability; run the full gate sweep. Sole owner of cli/commands/merge.py. Independent Test: Golden test byte-identical; merge.py ~120 LOC; radon/ruff/mypy clean; all ~41 importers + 3 src consumers green. Prompt: /tasks/WP11-shim-thinning-gate-sweep.md Requirement Refs: FR-001, FR-002, FR-005, FR-006, NFR-001, NFR-002, NFR-003
Included Subtasks
- ✅ T047 Decompose the
mergecommand into dispatch helpers, each ≤15 CC (WP11) - ✅ T048 Install the top-of-file #2057 decomposition pointer comment (FR-002 convention) (WP11)
- ✅ T049 Finalize shim re-exports; assert
__all__ordering byte-stable (WP11) - ✅ T050 Run the full gate sweep: golden test, radon ≤15, ruff, mypy --strict, coverage ≥90% (WP11)
- ✅ T051 Verify the 3 src consumers + ~41 test files import cleanly with zero edits (WP11)
Dependencies
- WP10.
Risks & Mitigations
__all__drift → assert exact ordering; golden test is the final byte-identity gate.