Data Model: Owned issue-verdict authority (#6320)
No new persisted entities or schema changes. This records the existing entities the fix threads a fact through, and the one behavioral state change.
Entities (existing, unchanged shape)
OwnedCheckout (the threaded fact)
- Fields used:
mission_slug, owned checkout root. - Source:
specify_cli.core.owned_mission; resolved via_owned_checkout.resolve_owned_or_refuse. - Carried as the keyword arg
owned=(defaultingNone). Additive only.
issue-matrix.json (unchanged format)
the locked re-read/splice/write; gates work-package approval.
its contents or format (C-002).
- Per-mission record of criterion verdicts for cited GitHub issues.
- Written by
specify_cli.tasks.issue_matrix.write_issue_matrix(alreadyowned-capable) through - This mission changes which directory the matrix is resolved in for an owned mission, not
Write-target gate (behavior, not data)
mission_runtime.write_target_degrade.{resolve_write_target_or_degrade, _mission_meta_exists, assert_coord_write_materialized}.
coordination.surface_resolver.resolve_for_write→_mission_meta_existscurrently readsread_primary_meta(repo_root, …)at the repository root.
State transition (the fix)
For an owned-only mission handed a valid owned fact:
Before: issue-verdict --owned-checkout P
→ resolve_for_write(R, slug) → _mission_meta_exists(R, slug) = False
→ terminus_write raise → REFUSE (coord_surface_unmaterialized / MISSION_NOT_FOUND)
After: issue-verdict --owned-checkout P
→ resolve_for_write(R, slug, owned=P) → _mission_meta_exists(R, slug, owned=P) = True
→ resolve_placement_only(..., owned=P).write_dir(ISSUE_MATRIX)
→ write_issue_matrix(..., owned=P) → verdict recorded in P's issue-matrix.json
Invariant preserved (NFR-001): an owned fact that resolves no real mission still refuses fail-closed — no silent fallback to R.
Invariant preserved (FR-005): the three unrelated callers of assert_coord_write_materialized pass no owned (default None) and resolve exactly as before.