Phase 1 Data Model — Resolution & Activation Foundation
This mission changes resolution seams and an authority source, not persisted data. No schema migration, no new stored entity. The "entities" are the code-level seams whose identity and invariants the mission pins. Revised for DR-1 (unified resolver): the former Seam 1 (door) and Seam 2 (default_missions_root) collapse into one primitive.
Seam 1 — Built-in-pack-root resolver (the unified primitive)
root (packs/built-in); the missions tree is <that root>/missions.
kernel.sibling_paths.resolve_installed_sibling). Consumed downward by:
pack_paths.py:204 is retired),
is not an input to pack-root location — it stays the asset-copy/template override (C-009).
kernel is layer-legal and adds no upward edge.
same env (default / PACKS_ROOT / both-vars).
no fall-through to specify_cli/missions/dev_root, never a nonexistent path. NB (delta review): since built_in_root() only verifies packs/built-in exists, default_missions_root = built_in_root()/"missions" must re-add an .is_dir() check on the /missions leaf + raise MissionsRootNotFound — a bare join would return a nonexistent path and regress this invariant.
depends on that specific type).
- Represents: the single function that reads
SPEC_KITTY_PACKS_ROOTand locates the built-in pack - Owner (after):
kernel(the PACKS_ROOT-aware entry point, built on the existing env-agnostic doctrine.pack_paths._resolve_built_in(delegates; its ownSPEC_KITTY_PACKS_ROOTread atdoctrine.missions.repository.default_missions_root=built_in_root()/"missions",kernel.paths.get_package_asset_root(the door) =<root>/missions,specify_cli.runtime.home.get_package_asset_root(thin delegation; legacy fallbacks removed).- Inputs:
SPEC_KITTY_PACKS_ROOT(pack-root location), install layout.SPEC_KITTY_TEMPLATE_ROOT - Invariants:
- I-1: exactly one
SPEC_KITTY_PACKS_ROOTread + one built-in-pack-root resolution body (NFR-001). - I-2: lives in
kernel; kernel imports nodoctrine/specify_cli(C-005). Reading an env var in - I-3:
default_missions_root()andget_package_asset_root()resolve the same tree under the - I-4: fails closed (
MissionsRootNotFound/SiblingPathNotFound/PackRootNotFoundtranslation) — - I-5: the
PackRootNotFoundtranslation survives at thedoctrine.pack_pathsboundary (a consumer - I-6: the sibling shape is owned once (kernel
built-inpattern +missionsleaf name), FR-012.
Seam 2 — Activation authority (activated_mission_types)
provisioned by copying packs/default.yaml's authored list.
- Represents: the single source of which mission types a project has.
- Owner:
charter.PackContext.activated_mission_types, sourced from configmission_type_activations, - State resolution (after):
(the _read_activated_kinds FR-039 fallback is a different contract, untouched).
resolver — so Seam 2 has no runtime dependency on Seam 1's env (keeps IC-02→IC-05 decoupled).
- Invariants:
- I-7: no implicit "all four" backfill site remains (NFR-001), scoped to
mission_type_activations - I-8: provisioning never intersects the built-in catalog — custom types survive (FR-010).
- I-9: provisioning is idempotent — byte-identical config on re-run (NFR-004).
- I-10: provisioning copies the authored list; it does not re-derive via the env-sensitive
| Config state | Result (after) |
|---|---|
mission_type_activations present (non-empty) | that set, verbatim (custom entries preserved) |
mission_type_activations: [] (authored empty) | empty set — unchanged (C-008/FR-039) |
| key absent, project provisioned | from the provisioned charter |
key absent, unprovisionable install (no default.yaml) | fail closed, actionable error (FR-011) |
| key absent (old behavior) | ~~silent all-four backfill~~ removed (FR-008) |
Roster note
"The four built-in types" is never a literal — the roster is the disk-scanned, cached builtin_mission_type_id_set(). Assertions reference the function, not a hardcoded set.
Explicitly unchanged (scope fence)
and are not repointed (C-003).
mission-typeis not anArtifactKind—MissionTypeNotAnArtifactKindstill raised (C-001).- Availability readers
list_available_missions/_build_discovery_contextremain filesystem-based