Data Model: Gate-command Read-surface (Phase 1)

Not a persistence model — the "data" is the planning-read site map and the kind → surface decision the gate commands must adopt.

Kind → read surface (the rule, post-#2106)

For mission M (topology T, target branch B, coord branch C):

planning_read_dir(M, kind):
    if is_primary_artifact_kind(kind):     # SPEC, DATA_MODEL, RESEARCH, CHECKLIST,
        return primary_dir(B)              #   FINALIZED_EXECUTION_PLAN, TASKS_INDEX,
                                           #   WORK_PACKAGE_TASK, LANE_STATE, PRIMARY_METADATA
    # status/bookkeeping kind → its placed surface (coord under coord topology)
    return status_read_dir(M)              # STATUS_STATE, ISSUE_MATRIX, ACCEPTANCE_MATRIX,
                                           #   ANALYSIS_REPORT

This is exactly resolve_planning_read_dir (_read_path_resolver.py:1244). The mission makes every gate command CONSUME it instead of reconstructing the path.

Planning-read site map (the M-of-N enumeration)

#Sitefile:lineKind readCurrent resolverVerdict
1setup_plan spec.mdmission.py:2224SPECresolve_handle_to_read_path (coord)RESIDUAL (IC-02)
2-7accept spec/plan/tasks/research/data-modelacceptance/__init__.py:1179-1187planning kindsstatus_feature_dir (coord)RESIDUAL (IC-03)
8-9accept _missing_artifactsacceptance/__init__.py:596planning kindsstatus_feature_dir (coord)RESIDUAL (IC-03)
10map-requirements WP tasks/*.mdtasks.py:3727WORK_PACKAGE_TASKresolve_feature_dir_for_mission (coord)RESIDUAL (IC-04)
11record-analysis double-resolutionmission.py:1980planningmanual coord-then-primaryCOLLAPSE (IC-04)
12-13primary-anchor helper pairmission.py:1308,1327planningbespoke primary-anchorRETIRE → seam (IC-01)
14finalize-tasks COMMITmission.py (finalize-tasks cmd)planning (WRITE)resolves protected primary main (dogfood repro)RESIDUAL — write-side → fixed by WP00 (IC-00); ratchet write arm WP06
14bwrite-branch resolverscore/paths.py:617 get_feature_target_branch, core/git_ops.py:371 resolve_target_branchplanning (WRITE)candidate_feature_dir_for_mission → coord → fallback mainRESIDUAL — write-side → fixed by WP00 (IC-00) (mirror resolve_merge_target_branch:665)
accept STATUS reads (events, acceptance-matrix)acceptance/__init__.py:1174,749STATUS_STATE / ACCEPTANCE_MATRIXstatus_feature_dirKEEP (coord)
check-prerequisites_primary_anchored_feature_dirplanningprimary-anchoredOK (not residual)
finalize-tasks read(primary-anchored)planningprimary-anchoredOK (only the COMMIT is residual — row 14)
record-analysis writeprimary_feature_dir_for_missionANALYSIS_REPORTprimaryOK

Self-bookkeeping allowlist (FR-003, distinct from the partition)

FileTodayRequired
meta.jsonkind=None → not allowlisted → preflight blocksallowlisted as self-bookkeeping
.kittify/encoding-provenance/global.jsonlkind=None → blocksallowlisted as self-bookkeeping

Allowlist lives at artifacts.py:113 (_COORD_RESIDUE_FILENAMES / a dedicated self-bookkeeping list) — separate from the coord-residue partition. Invariant preserved: a stale primary spec.md is still "real dirt" (not allowlisted).

Lock-the-fix guards (Lane B — fixes exist, add scenario-driving guards)

IssueSeam (verified)Guard entry point
#2091runtime/next/runtime_bridge.py (resolve_mid8 + guard)next → coord branch well-formed (no empty mid8)
#2088ownership/validation.py:161 (_dependency_reachability)finalize-tasks --validate-only → dep-ordered overlap allowed
#2074mission_type.py:632 (_read_mission_mid8 reads <dir>/meta.json)re-pin fixture to production-shaped meta.json