Data Model — Mission-Type Single-Source + Gate Wiring

This mission adds no persistent data. The "model" here is the set of in-code contracts (return shapes, exception shapes, finding shapes) that the WPs must honor.

E-1 — Canonical mission-type accessor (doctrine layer)

ElementShapeNotes
builtin_mission_type_ids()tuple[str, ...]Sorted (lexicographic). Cached (@functools.cache). Derived from MissionTypeRepository.default().ids().
frozenset conveniencefrozenset[str]Same members as the tuple; for membership/default consumers (Roster B, D base set).

Invariants:

  • Exactly one filesystem scan per process (NFR-002); repeated calls return identical results.
  • Importing any src/charter/* module triggers zero calls to this accessor (NFR-001).
  • Loud-fails transitively: if MissionTypeRepository raises (id≠stem / invalid schema), the accessor raises.

E-2 — Roster derivations

RosterFileContainerExtra members preserved
A CANONICAL_MISSION_TYPEScharter/mission_type_profiles.pytuple/iterablenone
B _BUILTIN_MISSION_TYPE_IDScharter/pack_context.pyfrozensetnone
C _BUILTIN_MISSION_TYPESmigrations/m_3_2_0rc35_...pylistnone (live-read at apply())
D ALLOWED_MISSION_TYPEScharter/activations.pyset/frozenset{any, generic} sentinels
E _MISSION_IDENTIFIER_ANSWERScharter/synthesizer/interview_mapping.pymappingsoftware_dev underscore alias

E-3 — ActionIndex / ActionIndexError

ElementShapeNotes
ActionIndex (existing)frozen dataclass, 7 list[str] artifact-kind fields + actionUnchanged shape.
ActionIndexError(ValueError) (new)co-located in action_index.pyMessage: index path + offending key + found type.

load_action_index decision table:

Input stateBehavior
File missingReturn ActionIndex(action=action) (silent fallback) — unchanged
File present, valid, empty contentReturn empty-content ActionIndex — no raise
File present, non-mapping rootraise ActionIndexError
File present, artifact-kind field not a list (e.g. directives: "x")raise ActionIndexError
File present, unparseable YAML (YAMLError)raise ActionIndexError

E-4 — Doctrine-health cross-grain finding (#2666)

ElementShapeNotes
Cross-grain check resultfolded into existing DoctrineHealthReport health + a --json finding entryOn CrossGrainDoubleDeclarationError: report unhealthy, RC=1, structured finding (mission type + colliding URN). On success: healthy, no exit-code change.

E-5 — builtin_missions_root() (#2668)

ElementShapeNotes
builtin_missions_root()Pathsrc/doctrine/missionsPublic module-level accessor; classmethod _default_built_in_dir delegates (or is replaced). Replaces 2 # noqa: SLF001 cross-class calls.