description: "Work package task list for canonical state authority & single metadata writer"


Work Packages: Canonical State Authority & Single Metadata Writer

Inputs: Design documents from /kitty-specs/051-canonical-state-authority-single-metadata-writer/ Prerequisites: plan.md (required), spec.md (user stories), research.md, data-model.md, quickstart.md

Tests: Included — this sprint requires focused tests for canonical-state behavior and metadata-writer behavior per the spec requirements.

Organization: Fine-grained subtasks (Txxx) roll up into work packages (WPxx). Each work package must be independently deliverable and testable.

Prompt Files: Each work package references a matching prompt file in /tasks/ generated by /spec-kitty.tasks.


Work Package WP01: Create feature_metadata.py Module (Priority: P0)

Goal: Create the single metadata writer API at src/specify_cli/feature_metadata.py — TypedDict definitions, atomic writes, schema validation, and all mutation helpers. This is the foundation that all other WPs depend on. Independent Test: Import feature_metadata and exercise every public function against a temp directory. All tests pass, formatting is consistent, atomic write handles interruption. Prompt: /tasks/WP01-create-feature-metadata-module.md Requirement Refs: FR-002, FR-003, FR-004, FR-005, FR-007, FR-008, FR-010, NFR-001, NFR-002, NFR-003

Included Subtasks

  • ✅ T001 Create src/specify_cli/feature_metadata.py with TypedDict definitions
  • ✅ T002 Implement load_meta() — relocate from upgrade/feature_meta.py, add error handling
  • ✅ T003 Implement validate_meta() — check required fields, return error list
  • ✅ T004 Implement _atomic_write() — temp file + os.replace(), cleanup on failure
  • ✅ T005 Implement write_meta() — validate, serialize with standard format, atomic write
  • ✅ T006 Implement mutation helpers — record_acceptance(), record_merge(), finalize_merge(), set_vcs_lock(), set_documentation_state(), set_target_branch() with bounded history
  • ✅ T007 Unit tests in tests/specify_cli/test_feature_metadata.py

Implementation Notes

  • Standard format: json.dumps(meta, indent=2, ensure_ascii=False, sort_keys=True) + "\n"
  • Extends existing write_feature_meta() convention — adds sort_keys=True
  • Bounded history: cap acceptance_history and merge_history at 20 entries (retain most recent)
  • Unknown fields preserved during read-modify-write (forward compatibility)
  • Each mutation helper: load → mutate → validate → write

Parallel Opportunities

  • None — this is the foundational WP.

Dependencies

  • None (starting package).

Risks & Mitigations

  • Risk: sort_keys=True addition changes diff output for existing meta.json files → Mitigation: Only reformats on actual mutations, not bulk reformatting.
  • Risk: os.replace() behavior on Windows → Mitigation: Use tempfile.mkstemp() in same directory to stay on same filesystem.

Work Package WP02: Canonical Acceptance Refactor (Priority: P1) 🎯 MVP

Goal: Replace Activity Log body-text parsing in acceptance with materialize() from canonical status model. Migrate acceptance and orchestrator meta.json writes to feature_metadata.py. This is the highest-impact change — acceptance correctness no longer depends on markdown body content. Independent Test: Run acceptance on a feature where Activity Log sections have been deleted from all WP files. Acceptance succeeds because it reads canonical status.events.jsonl instead. Prompt: /tasks/WP02-canonical-acceptance-refactor.md Requirement Refs: FR-001, FR-009, FR-011, NFR-002, C-001, C-004

Included Subtasks

  • ✅ T008 Replace Activity Log parsing in acceptance.py (~lines 355-392) with materialize() call
  • ✅ T009 Replace Activity Log parsing in acceptance_support.py (~lines 457-492) with same logic
  • ✅ T010 Migrate acceptance.py:538 meta.json write to record_acceptance()
  • ✅ T011 Migrate acceptance_support.py:620 meta.json write to record_acceptance()
  • ✅ T012 Migrate orchestrator_api/commands.py:787 meta.json write to record_acceptance() (fixes missing newline)
  • ✅ T013 Integration tests proving canonical state authority and orchestrator parity

Implementation Notes

  • The acceptance validation currently checks 3 rules against Activity Log entries. Replace with one check: is snapshot[wp_id].lane == "done" for all WPs.
  • Handle missing event log explicitly: raise error, do not fall back to Activity Log.
  • Orchestrator acceptance currently writes only accepted_at and accepted_by. After migration, record_acceptance() normalizes both paths to write the same fields.
  • Both acceptance.py and scripts/tasks/acceptance_support.py have mirrored implementations — apply same change to both.

Parallel Opportunities

  • T008 and T009 are identical logic applied to different files — can be done simultaneously.
  • T010-T012 are mechanical write-site migrations — can parallel with T008-T009.

Dependencies

  • Depends on WP01 (record_acceptance() and feature_metadata.py must exist).

Risks & Mitigations

  • Risk: Legacy features without status.events.jsonl → Mitigation: Explicit error message ("no canonical state found for {feature}"), not silent fallback to Activity Log.
  • Risk: Acceptance validation changes behavior subtly → Mitigation: Integration tests with both deleted and corrupted Activity Log.

Work Package WP03: Migrate VCS, Merge, and Feature Creation Writes (Priority: P1)

Goal: Migrate the remaining non-acceptance meta.json write sites to feature_metadata.py. Fixes 2 missing-trailing-newline bugs in feature.py. Independent Test: Run spec-kitty implement (VCS lock), merge flow, and feature creation — verify all produce consistently formatted meta.json through the single writer. Prompt: /tasks/WP03-migrate-vcs-merge-feature-writes.md Requirement Refs: FR-002, FR-004, FR-009, NFR-004

Included Subtasks

  • ✅ T014 [P] Migrate implement.py:591,601 VCS lock writes to set_vcs_lock()
  • ✅ T015 [P] Migrate tasks_cli.py:573 merge metadata write to record_merge()
  • ✅ T016 [P] Migrate tasks_cli.py:592 finalize merge write to finalize_merge()
  • ✅ T017 [P] Migrate feature.py:632,658 feature creation writes to write_meta() (fixes missing newline bugs)
  • ✅ T018 Tests for each migrated write site

Implementation Notes

  • Each migration is a mechanical replacement: replace json.dumps() + write_text() with the appropriate feature_metadata.py function call.
  • feature.py:632 creates the initial meta.json — use write_meta() directly (not a mutation helper, since there's no existing file to load).
  • feature.py:658 adds documentation_state — use set_documentation_state().
  • All 4 subtasks touch different files and can proceed in parallel.

Parallel Opportunities

  • T014, T015, T016, T017 are fully independent (different files).

Dependencies

  • Depends on WP01 (mutation helpers must exist).
  • Can run in parallel with WP02.

Risks & Mitigations

  • Risk: Feature creation path writes initial meta.json (not read-modify-write) → Mitigation: write_meta() handles both fresh and existing files.

Work Package WP04: Migrate doc_state.py Write Sites (Priority: P2)

Goal: Refactor doc_state.py's 8 write functions to delegate file I/O to feature_metadata.py while keeping validation logic in doc_state.py. Independent Test: Call each doc_state setter, verify meta.json has consistent formatting (sorted keys, ensure_ascii=False, trailing newline) matching the standard. Prompt: /tasks/WP04-migrate-doc-state-writes.md Requirement Refs: FR-002, FR-009, NFR-004

Included Subtasks

  • ✅ T019 Refactor doc_state.py read/write pattern to use load_meta() and write_meta() from feature_metadata.py
  • ✅ T020 [P] Update individual field setters: set_iteration_mode(), set_divio_types_selected(), set_generators_configured(), set_audit_metadata()
  • ✅ T021 [P] Update composite writers: write_documentation_state(), initialize_documentation_state(), update_documentation_state(), ensure_documentation_state()
  • ✅ T022 Tests verifying consistent formatting across all doc_state write paths

Implementation Notes

  • doc_state.py currently uses json.dump(meta, f, indent=2) via file handle — replace with load_meta() for reads and write_meta() for writes.
  • Keep all validation logic (checking iteration_mode values, divio types, generator fields, coverage_percentage range) in doc_state.py.
  • Only delegate the file I/O layer.
  • The meta_file parameter in doc_state functions takes a Path to meta.json — convert to feature_dir (parent directory) when calling load_meta()/write_meta().

Parallel Opportunities

  • T020 and T021 are independent groups of functions.

Dependencies

  • Depends on WP01 (load_meta() and write_meta() must exist).
  • Can run in parallel with WP02 and WP03.

Risks & Mitigations

  • Risk: doc_state.py validation logic tightly coupled with I/O → Mitigation: Keep validation functions intact, only replace the json.load()/json.dump() calls.

Work Package WP05: Compatibility Wrapper & Codebase Sweep (Priority: P2)

Goal: Add compatibility re-exports in upgrade/feature_meta.py, verify zero direct meta.json writes remain outside feature_metadata.py, and add integration tests proving the full canonical-state + single-writer system works end-to-end. Independent Test: Grep entire src/specify_cli/ for direct meta.json writes — zero results outside feature_metadata.py. Integration tests pass with corrupted compatibility views. Prompt: /tasks/WP05-compatibility-wrapper-codebase-sweep.md Requirement Refs: FR-002, FR-006, FR-009, NFR-002, C-001

Included Subtasks

  • ✅ T023 Update upgrade/feature_meta.py — thin re-exports for load_feature_meta() and write_feature_meta()
  • ✅ T024 Verify migration callers (m_2_0_6_consistency_sweep.py) work through wrapper
  • ✅ T025 Codebase sweep — test that greps for direct meta.json writes outside feature_metadata.py and fails on violations
  • ✅ T026 Integration test: end-to-end acceptance flow reads canonical state, writes through single API
  • ✅ T027 Integration test: corrupt compatibility views (Activity Log + frontmatter lane), verify correctness preserved

Implementation Notes

  • upgrade/feature_meta.py keeps its inference functions (infer_target_branch, infer_mission, infer_created_at, build_baseline_feature_meta) — these are upgrade-specific, not metadata writer concerns.
  • Only load_feature_meta() and write_feature_meta() become thin wrappers.
  • The codebase sweep test (T025) should be a pytest test that uses subprocess or pathlib to scan source files — catches regressions if someone adds a direct write later.
  • Integration tests create a complete feature directory with status.events.jsonl, WP files, and meta.json, then exercise the full acceptance flow.

Parallel Opportunities

  • T023-T024 (wrapper) and T025 (sweep) are independent.
  • T026-T027 (integration tests) depend on all prior WPs being complete.

Dependencies

  • Depends on WP02, WP03, and WP04 (all write sites must be migrated before sweep can pass).

Risks & Mitigations

  • Risk: Migration callers in frozen code break → Mitigation: T024 specifically tests migration compatibility.
  • Risk: Future developers bypass the API → Mitigation: T025 sweep test catches direct writes in CI.

Dependency & Execution Summary

WP01 (foundation) ─────────────────────────────────────┐
  ├─→ WP02 (canonical acceptance)  ─────────────────────┤
  ├─→ WP03 (VCS/merge/creation migration)  ────────────┤──→ WP05 (sweep + integration)
  └─→ WP04 (doc_state migration)  ─────────────────────┘
  • Sequence: WP01 first, then WP02/WP03/WP04 in parallel, then WP05.
  • Parallelization: WP02, WP03, and WP04 are fully independent after WP01 completes. Run 3 agents simultaneously.
  • MVP Scope: WP01 + WP02 delivers the core value — canonical state authority for acceptance + single metadata writer for acceptance paths.

Requirements Coverage Summary

Requirement IDCovered By Work Package(s)
FR-001WP02
FR-002WP01, WP02, WP03, WP04, WP05
FR-003WP01
FR-004WP01, WP03
FR-005WP01
FR-006WP05
FR-007WP01
FR-008WP01
FR-009WP02, WP03, WP04, WP05
FR-010WP01
FR-011WP02
NFR-001WP01
NFR-002WP01, WP02, WP05
NFR-003WP01
NFR-004WP03, WP04
C-001WP02, WP05
C-002All (scoped to Phase 3+4 only)
C-003WP01
C-004WP02
C-005All

Subtask Index (Reference)

Subtask IDSummaryWork PackagePriorityParallel?
T001TypedDict definitions in feature_metadata.pyWP01P0No
T002Implement load_meta()WP01P0No
T003Implement validate_meta()WP01P0No
T004Implement _atomic_write()WP01P0No
T005Implement write_meta()WP01P0No
T006Implement mutation helpers with bounded historyWP01P0No
T007Unit tests for feature_metadata.pyWP01P0No
T008Replace Activity Log parsing in acceptance.pyWP02P1No
T009Replace Activity Log parsing in acceptance_support.pyWP02P1Yes
T010Migrate acceptance.py meta.json writeWP02P1Yes
T011Migrate acceptance_support.py meta.json writeWP02P1Yes
T012Migrate orchestrator_api meta.json writeWP02P1Yes
T013Integration tests for canonical acceptanceWP02P1No
T014Migrate implement.py VCS lock writesWP03P1Yes
T015Migrate tasks_cli.py merge metadata writeWP03P1Yes
T016Migrate tasks_cli.py finalize merge writeWP03P1Yes
T017Migrate feature.py creation writesWP03P1Yes
T018Tests for migrated VCS/merge/creation writesWP03P1No
T019Refactor doc_state.py I/O to use feature_metadata.pyWP04P2No
T020Update individual field setters in doc_state.pyWP04P2Yes
T021Update composite writers in doc_state.pyWP04P2Yes
T022Tests for doc_state formatting consistencyWP04P2No
T023Compatibility re-exports in upgrade/feature_meta.pyWP05P2No
T024Verify migration callers work through wrapperWP05P2No
T025Codebase sweep test for direct meta.json writesWP05P2Yes
T026End-to-end acceptance integration testWP05P2No
T027Corrupted compatibility views integration testWP05P2No

<!-- status-model:start -->

Canonical Status (Generated)

<!-- status-model:end -->

  • WP01: done
  • WP02: done
  • WP03: done
  • WP04: done
  • WP05: done