Analysis report transactions
spec-kitty agent mission record-analysis --mission <handle> --input-file <report> --report-only --json
opts into a report-only transaction. The ordinary command retains its broad
dirty-worktree refusal. The report still belongs to the authoritative primary
planning checkout; invoking from a clean linked lane does not change that owner.
The opt-in transaction requires the checked-out, unprotected planning branch,
clean material inputs and report, supported index entries, and no active Git
operation. It preserves unrelated staged blobs, partial staging, working bytes,
and untracked bytes. The canonical commit router uses git commit --only;
the transaction never stashes or resets operator work.
Material inputs
The shared recording/freshness manifest covers spec, plan, status-normalized tasks, individual WP definitions, mission metadata and package manifest, configured charter authority, local declarative mission/template/doctrine overrides, charter references and authority directories, and bundled authority content digests. Missing paths are recorded so their later creation invalidates analysis. WP lane/review fields use the canonical mutable-field vocabulary and are excluded from definition hashes. Runtime events, context-state and synthesis bookkeeping are excluded. Symlinks and external mutable org roots are refused.
Outcomes and recovery
The JSON response distinguishes failed_before_write, written_uncommitted,
committed_unqualified, committed, and unchanged. Identical semantic report
content, analyzer and current inputs reuse an already-qualified report without
changing its bytes or HEAD. Missing or pending receipts cannot qualify that
no-op; fresh analysis must produce and verify a new report commit instead.
A disk write alone is never success.
Pre/post checks compare HEAD, material inputs, unrelated index entries, dirty
working bytes, report bytes, commit parent and changed paths. These checks detect
cooperative-writer races; they cannot lock out arbitrary external editors. The
net is deliberately broad: because the guard snapshots the entire index and the
full working tree (including untracked files) minus the report path, any
unrelated change observed during the transaction window — not only a HEAD or
index race — flips the outcome to committed_unqualified. No unrelated work is
lost in that case; the report is simply left freshness-rejected and a rerun
re-qualifies it.
Before writing, the transaction creates a pending receipt in the local Git directory. Only successful verification qualifies that receipt. Freshness for an opt-in report requires its receipt, exact report digest and a reachable verified commit. Thus a process crash or an unrelated concurrent change cannot unlock the mission merely because the retained report exists.
Receipts are local qualification evidence, not portable attestations. Copying the report into another clone does not qualify it there. Preserve concurrent work, inspect retained commits, reconcile and commit material inputs, then rerun analysis and recording in the destination checkout. No recovery action resets concurrent work automatically. A failed written report must be reviewed and committed or removed by its owner before retrying; the dirty-report guard remains.