Tasks: One org-pack chain authority (#6006)

Mission: org-pack-chain-authority-01M4JXF5 · Branch: kitty/org-pack-chain-authority-stack (stacked on PR #6005) Planning base / merge target: kitty/org-pack-chain-authority-stack

Subtask completion is event-sourced via spec-kitty agent tasks mark-status Txxx --status done. Rows below are reference rows, not checkboxes.

Gate scope (operator ruling): the empty-allowlist gate (WP06) is path-scoped to src/charter/ + src/specify_cli/cli/commands/charter/; every chain-deriving caller in those surfaces migrates onto resolve_pack_chain() this mission. The ~12 non-charter callers + tree-wide gate are a named follow-up (see spec Out of Scope).

Subtask Index

IDDescriptionWPParallel
T001Add resolve_pack_chain(repo_root, *, strict) authorityWP01
T002Re-point resolve_org_root_chain to delegate to the authorityWP01
T003Re-point resolve_org_dirs onto resolve_pack_chain(strict=False) (preserve WARNING)WP01
T004Strict posture: raise naming the unfetched pack + spec-kitty charter fetchWP01
T005Red-first repro: two-pack lenient ordering + strict-raise-on-missingWP01
T006ruff/mypy clean, complexity ≤15WP01
T007effective_set: declared→strict authority; readable/fallback→lenient authorityWP02[P]
T008preset_application: _Roots.of/_available_mission_types→authorityWP02[P]
T009org_charter: resolve_org_root_chain→resolve_pack_chain (keep layer_roots pairing)WP02[P]
T010deactivate + _resynthesis_preflight: →resolve_pack_chainWP08[P]
T011interview + context (re-point) + pack_asset: →resolve_pack_chainWP08[P]
T012Behavioural positive control: pack-2 artifact observable via effective_set + preset_applicationWP02
T013ruff/mypy; confirm _org_scan_dirs flat-wins test green (NFR-005)WP02
T014list_cmd templates (:88): full-chain org template tierWP03[P]
T015list_cmd availability (:197/:245): full-chain org scanWP03[P]
T016invocation_context: remove dead ProjectContext.org_root + org_roots[0]WP03[P]
T017action_governance_bundle: drop legacy org_root param; migrate :209 to authority (lenient)WP03[P]
T018Update TestListAllLayersBackCompat (SUPERSEDE pack-2-hidden; KEEP two) + test_invocation_contextWP03
T019Reader regression repros; ruff/mypy; NFR-001 dict unchangedWP03
T020_scan_layer_dirs: add org_root_chain; one ORG pair per root last-declared-first; fallbackWP04[P]
T021list_available / list_available_detailed: thread org_root_chainWP04
T022activate: pass chain to scan; migrate activate.py resolve_org_root_chain callsWP04
T023Remove _activate_cascade_target; collapse call site to single manager.activateWP04
T024Retry-loop repro: pack-2 artifact activates via single scan; assert cascade helper goneWP04
T025ruff/mypy; pins test_pack_manager*, test_mission_type_path_layout_ssot greenWP04
T026requirement_kinds.py: frozen models, extra=forbidWP05[P]
T027resolve_org_requirement_kinds sibling: last-matching-file-wins, whole-file, fail-closedWP05[P]
T028load_requirement_kinds tier walk: built-in→org(strict chain)→project; module cacheWP05
T029Project tier .kittify/doctrine/missions/<type>/requirement-kinds.yaml (project wins) [Div A]WP05
T030Fail-closed: invalid refuses; missing-declared refuses via strict chain [Div B]; default constantWP05
T031Loader tests (override, corrupted-refusal, project-wins); ruff/mypyWP05
T032test_org_pack_chain_single_authority.py: AST census, path-scoped, module-ownership, empty allowlistWP06
T033Non-vacuity: planted-violation + owner-bypass + file-count-floor controlsWP06
T034Confirm invariant over the charter scope (zero in-scope violations)WP06
T035ruff/mypy; gate green over the charter scopeWP06
T036manifest_loader: migrate load_manifest's _resolve_existing_org_roots onto the authority (lenient)WP05
T037ruff/mypy; charter-CLI regression suites greenWP08
T038active_charter_service_builder: _self_resolve_existing_org_roots→authority (lenient)WP07[P]
T039_drg_helpers: resolve_existing_org_roots→authority (lenient)WP07[P]
T040language_vocabulary: resolve_existing_org_roots loop→authority (lenient)WP07[P]
T041profile_resolution + project_registration + skill_preparation: →authorityWP07[P]
T042charter/offering/resolver loops + charter/drg re-export→authority; ruff/mypyWP07

Work Packages

WP01 — Pack chain authority (foundation)

  • Goal: resolve_pack_chain(repo_root, *, strict) as the sole producer of the ordered, existing chain (last-declared-wins), strict + lenient. Prompt: tasks/WP01-pack-chain-authority.md
  • Requirements: FR-001, FR-007, NFR-004 · Subtasks: T001–T006 · Dependencies: none

WP02 — Migrate charter-activation core consumers

  • Goal: Route effective_set, preset_application, org_charter through the authority (strict/lenient per surface). Prompt: tasks/WP02-migrate-chain-consumers.md
  • Requirements: FR-002, FR-008, NFR-004, NFR-005 · Subtasks: T007, T008, T009, T012, T013 · Dependencies: WP01

WP03 — Fix the pack-1-only readers

  • Goal: charter list --all full chain; remove dead ProjectContext.org_root; drop action_governance_bundle legacy param (migrate its :209 call to the authority). Prompt: tasks/WP03-pack-one-only-readers.md
  • Requirements: FR-003, FR-005, NFR-001 · Subtasks: T014–T019 · Dependencies: WP01

WP04 — Retire the retry loop (widen ActiveCharterManager)

  • Goal: Remove _activate_cascade_target; widen ActiveCharterManager with org_root_chain; migrate activate.py chain calls. Prompt: tasks/WP04-retire-retry-loop.md
  • Requirements: FR-004, NFR-001, NFR-005 · Subtasks: T020–T025 · Dependencies: WP01

WP05 — Requirement-kinds loader seam (#5956) + manifest_loader migration

  • Goal: Model + load_requirement_kinds() through built-in→org(strict)→project, whole-file, fail-closed; and migrate load_manifest's existing chain call onto the authority. Prompt: tasks/WP05-requirement-kinds-loader.md
  • Requirements: FR-009, FR-010, FR-011, FR-002, SC-004 · Subtasks: T026–T031, T036 · Dependencies: WP01

WP06 — Empty-allowlist architectural gate (path-scoped; lands last)

  • Goal: AST-census gate scoped to src/charter/ + src/specify_cli/cli/commands/charter/, empty allowlist, non-vacuity controls. Prompt: tasks/WP06-empty-allowlist-gate.md
  • Requirements: FR-006, NFR-002 · Subtasks: T032–T035 · Dependencies: WP02, WP03, WP04, WP05, WP07, WP08

WP07 — Migrate remaining charter-activation/offering consumers

  • Goal: Route the remaining charter-tier primitive callers (active_charter_service_builder, _drg_helpers, language_vocabulary, profile_resolution, project_registration, skill_preparation, offering/resolver, charter/drg re-export) through the authority. Mechanical, lenient. Prompt: tasks/WP07-migrate-activation-offering.md
  • Requirements: FR-002 · Subtasks: T038–T042 · Dependencies: WP01

WP08 — Migrate CLI charter consumers

  • Goal: Route deactivate, _resynthesis_preflight, interview, context (re-point), pack_asset through the authority. Prompt: tasks/WP08-migrate-cli-charter.md
  • Requirements: FR-002 · Subtasks: T010, T011, T037 · Dependencies: WP01

Dependency graph

WP01 ──┬── WP02 ──┐
       ├── WP03 ──┤
       ├── WP04 ──┤
       ├── WP05 ──┼── WP06  (gate, path-scoped, last)
       ├── WP07 ──┤
       └── WP08 ──┘

MVP / sequencing

WP01 is the foundation. WP02–WP05, WP07, WP08 parallelize after it (each is a distinct, non-overlapping file set). WP06 (the gate) lands last — it goes red until every in-scope migration is complete.