Phase 1 Data Model: Coord/Primary Partition Regression Lock

This mission introduces no new persisted entities. It formalizes the value objects and enums that already encode placement, and locks their invariants. "Data model" here means the in-memory domain types the seam operates over.

Enum — MissionArtifactKind (existing, src/mission_runtime/artifacts.py:25-50)

14 members, partitioned by two frozensets. This mission locks membership; it does not add, remove, or re-home a member (C-002).

KindPartitionNotes
SPECprimarystrangle target (create-time write)
PLANprimary
TASKS_INDEXprimary
WORK_PACKAGE_TASKprimary
DATA_MODELprimary
RESEARCHprimary
CHECKLISTprimary
RETROSPECTIVEprimary
PRIMARY_METADATAprimary
STATUS_STATEcoordinationcarries status transitions / move-task bookkeeping
LANE_STATEcoordination
ACCEPTANCE_MATRIXcoordinationaccept-time write
ANALYSIS_REPORTcoordinationrecord-analysis write
(self-bookkeeping)coordinationop-records / lifecycle, _SELF_BOOKKEEPING_*

Invariant P-1: _PRIMARY_ARTIFACT_KINDS ∪ _PLACEMENT_ARTIFACT_KINDS = all members; the two sets are disjoint. (Ratchet-checkable.)

Enum — MissionTopology (existing, src/mission_runtime/context.py:64-67)

2×2 grid. Coord-routing is a predicate, not an equality test.

ValueCoord-routing? (routes_through_coordination)Lanes?
SINGLE_BRANCHno → all kinds to primaryno
LANESno → all kinds to primaryyes
COORDyesno
LANES_WITH_COORDyesyes
  • FLATTENED is a provenance flag, not a topology value.
  • Invariant T-1: coord-routing decisions consult routes_through_coordination(stored_topology) only — never topology == COORD or coordination_branch is not None (C-001).
  • Invariant T-2 (FR-012): stored_topology is read from meta.json; a lingering on-disk -coord husk is never authoritative (_husk_is_authoritative_surface).

Value Object — MissionArtifactHome (existing, artifacts.py:175-213)

The canonical output of a placement decision. Carries all three projections so no call site re-derives placement:

FieldTypeMeaning
read_surfacePath/surfacewhere to read this kind
write_surfacePath/surfacewhere to write this kind
commit_targetCommitTargetthe branch/ref a write commits to

home; call sites consume MissionArtifactHome, they do not assemble it (C-001).

  • Invariant H-1: artifact_home_for(kind, placement_ref) is the sole constructor of a

Value Object — CommitTarget (existing)

The commit destination for a write. Invariant C-1 (FR-011): a CommitTarget for a lifecycle/planning artifact is produced by the seam (write_target(kind)), never constructed inline as CommitTarget(ref=<current_checkout>). This is the new ratchet grammar.

Domain State — Coordination surface state (read-side, _read_path_resolver.py:663-706)

The seam must distinguish four states and behave correctly for each (FR-008, FR-012):

StateMeaningCorrect behavior
never-createdmission never declared a coordination_branch (non-coord topology)resolve to primary; no COORDINATION_BRANCH_DELETED
UNMATERIALIZEDcoord branch exists, worktree not yet createdresolve lifecycle reads via the branch ref
DELETEDcoord worktree removed mid-missionactionable error / re-materialize, not stale-primary fallback
materializedcoord worktree presentresolve to coord surface

Composition input — mid8 (write-side, coordination/workspace.py:161-226, branch_naming.py:176-207)

mid8; an empty mid8 MUST fail loudly at the composition seam, never compose kitty/mission-<slug>-git worktree add exit-128.

  • Invariant M-1 (FR-007): coord branch/worktree composition requires a non-empty

Relationships

MissionTopology --routes_through_coordination()--> {coord | primary} placement
MissionArtifactKind --frozenset membership--> {coordination | primary} partition
(kind, placement_ref) --artifact_home_for()--> MissionArtifactHome{read_surface, write_surface, commit_target}
seam.write_target(kind) --> CommitTarget   (never inline from checkout)
seam.read_dir(kind)     --> read_surface