Partition-Aware Implement-Claim Precondition

Mission: implement-claim-precondition-partition-01KXGWSP Type: software-dev · Kind: Bug · Priority: P1 · Milestone: 3.2.x Tracker: fixes #2533 · parent epic #2624 · cross-linked #2160

Purpose

When a solo, pull-request-bound mission runs on its own feature branch, an agent cannot claim a work package: spec-kitty agent action implement WP## aborts with "Planning artifacts not committed" even though the spec, plan, and tasks are already committed on that feature branch. The operator's only workaround is to hand-edit meta.json (flatten the mission) or force-stage files onto the wrong branch. This mission removes that blocker by making the claim precondition aware of where each planning artifact actually lives, so PR-bound missions can move from planning into implementation without manual git surgery.

This is the write/claim-side twin of the already-shipped read-side fix (WP08, commit 52211737b, which routed the empty-coord status surface cleanly to primary). The read resolver now treats a solo coord mission's surface as PRIMARY; the claim precondition has not yet been reconciled with the same kind-based artifact partition, and that inconsistency is the defect.

Background & Domain Model

Artifact placement is kind-based, defined in one authority (src/mission_runtime/artifacts.py):

data-model.md, research.md, checklists, lanes.json, meta.json, retrospective — author, read, and commit on the primary target branch for every topology. They never transit coordination.

issue-matrix, analysis-report — route to the coordination branch under coord / lanes-with-coord topologies.

  • PRIMARY kindsspec.md, plan.md, tasks.md, tasks/WP*.md,
  • COORD kindsstatus.events.jsonl, status.json, acceptance-matrix,

The defect is a single-ref conflation (C-PLACE-1): the implement-claim precondition compares every feature-directory file against one collapsed ref — the coordination branch — for its idempotency check. Because PRIMARY planning artifacts live on the feature branch and are absent on the coordination branch, they all read as "changed", the staging set is non-empty, and the claim aborts. The write path (commit_router) and the read resolver (surface_resolver, WP08) already honor the per-kind partition; the claim precondition is the lone remaining consumer on the collapsed single ref.

Domain Language

Canonical termMeaningAvoid
PRIMARY partitionArtifact kinds that live on the primary/target branch for every topology"feature files" (ambiguous)
COORD partitionArtifact kinds that route to the coordination branch"shared files"
Placement refThe CommitTarget an artifact resolves to for commit/diff"the branch" (which branch?)
Topology derivationHow a mission is classified single_branch / lanes / coord / lanes_with_coordconflating with placement

User Scenarios & Testing

Primary actor: an implementing agent (or the operator) claiming a work package during the implement loop.

Acceptance Scenarios

1. Solo PR-bound coord mission — claim succeeds. Given a solo PR-bound mission with topology: coord whose spec.md, plan.md, tasks.md, and lanes.json are committed on the feature/target branch (and absent on the empty coordination branch), When an agent runs spec-kitty agent action implement WP01, Then the claim proceeds, no "Planning artifacts not committed" message is emitted, no manual git add -f is required, and the mission topology is unchanged.

2. Coord-with-lanes mission — no coordination regression. Given a lanes_with_coord mission, When the claim precondition runs, Then COORD-partition artifacts (status.events.jsonl, status.json, matrices, analysis report) are still compared against and routed to the coordination ref, exactly as before.

3. Move-task staging — unchanged. Given the move-task path that reuses the shared staging core, When it stages planning artifacts, Then its behavior is unchanged (guarded by a test-only regression).

4. Write-side: dirty PRIMARY on coord lands on primary. Given a coord mission with a genuinely-dirty PRIMARY artifact (e.g. spec.md) that must be committed, When the planning-artifact commit runs, Then the PRIMARY artifact is committed to the primary/target ref (never the coordination branch), while a dirty COORD status file still commits to the coord ref.

Edge Cases

feature branch is still correctly detected as needing a commit (the fix must not blind the check — it must compare against the correct ref, not skip it).

precondition short-circuits when the mission does not route through coordination).

  • A PRIMARY artifact with genuine uncommitted working-tree changes on the
  • A flattened mission (coordination_branch removed) continues to work (the

Requirements

Functional Requirements

IDRequirementStatus
FR-001The implement-claim precondition MUST classify each candidate planning artifact by its canonical kind and compare it against the ref for that kind's partition — PRIMARY kinds against the primary/target branch, COORD kinds against the coordination ref — instead of comparing all files against a single collapsed coordination ref.Planned
FR-002For a solo PR-bound coord-topology mission whose spec.md/plan.md/tasks.md/tasks/WP*.md/lanes.json are committed on the feature/target branch, spec-kitty agent action implement WP## MUST succeed: no "Planning artifacts not committed" abort and no manual staging instruction.Planned
FR-003The write-side commit path that persists any residual planning-artifact changes MUST route PRIMARY kinds to the primary/target ref and never onto the coordination branch (the write-side twin of the comparison fix).Planned
FR-004The defect MUST be reproduced by a red-first regression exercised through the pre-existing precondition entry point (_ensure_planning_artifacts_committed_git, reached via agent action implement): the test asserts a non-empty planning-artifact staging set before the fix and an empty one after, with topology unchanged.Planned
FR-005The move-task planning-artifact staging path that reuses the same staging core MUST retain correct behavior, guarded by a focused (test-only) regression.Planned
FR-006Architecture documentation that still describes the retired single-ref placement model (docs/architecture/branch-target-routing.md, docs/architecture/execution-lanes.md See-Also) MUST be corrected to the kind-based partition.Planned

Non-Functional Requirements

IDRequirementThreshold / MeasureStatus
NFR-001The fix MUST NOT alter mission topology derivation.The existing test test_create_pr_bound_on_non_primary_branch_still_defaults_to_coord remains green and unmodified; no change under mission_create.py.Planned
NFR-002No regression to coordination-routed artifacts.A regression test for a lanes_with_coord mission passes; status/matrix/analysis artifacts still diff against and commit to the coordination ref.Planned
NFR-003New and changed code meets the repo quality bar.ruff and mypy --strict report zero new issues; each touched function has cyclomatic complexity ≤ 15; every new branch/helper has a focused test in the same change.Planned
NFR-004The fix reuses the single per-kind partition authority.No new artifact-kind→partition mapping literal is introduced outside src/mission_runtime/artifacts.py; classification goes through kind_for_mission_file / is_primary_artifact_kind.Planned

Constraints

IDConstraintStatus
C-001Boundary guard: _resolve_claim_commit_target and status-event placement MUST remain coord-targeted. Only the planning-artifact comparison/destination is corrected; the planning→primary / status→coord asymmetry is preserved.Active
C-002Boundary guard: the single-ref placement mint (_assemble_artifact_placement_fragment / ArtifactPlacementFragment, mission_runtime/) MUST NOT be modified. The fix lives in the consumer (implement-claim). mission_runtime/ stays read-only for this mission.Active
C-003Out of scope: the pr_bound ⇒ coord topology derivation (mission_create.py:216-217) — owned by #2602.Active
C-004Deferred (record as a follow-up per Directive 003; do NOT implement here): retiring the bespoke resolve_planning_artifact_staging path into commit_router.commit_for_mission, and correcting the now-false C-PLACE-1 docstring — owned by the #2160 placement-seam SSOT cluster.Active
C-005This mission itself runs under LANES topology, coord-free (single primary ref for its own artifacts).Active

Success Criteria

IDCriterion
SC-001A dogfooding PR-bound mission can claim and implement a work package end-to-end with zero manual git intervention.
SC-002Zero occurrences of the false "Planning artifacts not committed" abort across the reproduction scenarios.
SC-003The new red-first regression fails before the change and passes after; the existing implement, move-task, and coordination test suites remain green.
SC-004Architecture docs describe only the kind-based partition — no reader can find the retired single-ref placement claim.

Key Entities

mission_runtime/artifacts.py; the single authority the fix consumes.

commit/diff; PRIMARY → target branch, COORD → coordination branch.

(_ensure_planning_artifacts_committed_gitresolve_planning_artifact_staging_files_changed_vs_ref) that this mission makes partition-aware.

  • MissionArtifactKind partition — the PRIMARY vs COORD split in
  • Placement ref (CommitTarget) — the branch an artifact resolves to for
  • Implement-claim precondition — the gate

Assumptions

authoritative; this mission consumes them rather than redefining any mapping.

is present and only the write/claim side remains inconsistent.

merges); the mission is intentionally created coord-free to avoid the very topology it fixes.

  • The per-kind partition sets in mission_runtime/artifacts.py are correct and
  • WP08 (52211737b) has landed on the base branch, so the read-side surface fix
  • The mission lands via a manually opened pull request at completion (operator

Out of Scope / Deferred

implement-claim staging onto commit_router.commit_for_mission and fixing the false C-PLACE-1 docstring (#2160 cluster).

  • Out of scope — changing the pr_bound ⇒ coord topology derivation (#2602).
  • Deferred follow-up (to be filed, not implemented) — consolidating the