Skip to content
20 changes: 19 additions & 1 deletion .claude/skills/issue-ingest/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ its receipt gates ARE the mechanical implementation for the parts it owns):

- **Reproduction before localization→PLAN** — `record_issue_reproduction` evidence or a
typed `--no-repro` waiver (else the engine emits a one-shot reproduction-required directive).
- **Branch freshness before PLAN (issue-tracer v3 Phase 0, issue #2564)** — the trace records
the fetch outcome with `record_branch_freshness` (`synced`, `behind:<n>`, or
`fetch-failed:<reason>` plus the verbatim user override when the user accepted a stale base).
`behind` and a bare `fetch-failed` fail closed (else the engine emits a one-shot
freshness-required directive).
- **Plan-critic gate before EXECUTE** — the reducer will not advance to EXECUTE until the
plan-critic approval is observed.
- **Authoritative plan state** — read through the ledger-aware loader, never the projection.
Expand All @@ -93,9 +98,22 @@ its receipt gates ARE the mechanical implementation for the parts it owns):
- **Recurrence sweep before commit-pr handoff** — the defect class must be characterized,
searched with explicit predicates, every hit dispositioned, and a guardrail installed
with proof it catches the original defect (or the "no defect class" fast path recorded);
record it with `record_recurrence_sweep` (else the engine emits a one-shot sweep directive).
record it with `record_recurrence_sweep`, including `relatedProblems` — the Phase 1
related-problems sweep results (at least one entry) on BOTH paths (else the engine emits
a one-shot sweep directive).
- **Per-phase validator receipts before commit-pr handoff (issue-tracer v3, issue #2564)** —
run the phase validator (`trace-check.sh phase <N>`) for every completed phase and record
each outcome with `record_trace_validation` (phase, pass/fail, the reviewedCommit and
treeId it reported); any fail entry fails closed until re-recorded as a pass (else the
engine emits a one-shot validator directive).
- **Honest completion** — `publication_handoff` is NOT "resolved"; terminal `published` needs
an issue-bound publication receipt.
- **Merge approval recorded, never certified (issue-tracer v3 Phase 5.1, issue #2564)** —
after publication, the human merge approval is captured with `record_merge_approval`
(prHeadSha equal to finalCriticReviewedCommit, userApprovalVerbatim quoted verbatim);
the trace reaches its true terminal `merge_approval_recorded` status. The merge decision
stays human-enforced — the plugin records it for audit and never certifies, drives, or
green-lights the merge itself.
- **Durable delivery** — a transition persists only after its directive is delivered.

With these receipts the Full-Resolution Contract is mechanically composed into this trace
Expand Down
20 changes: 19 additions & 1 deletion .opencode/skills/issue-ingest/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ its receipt gates ARE the mechanical implementation for the parts it owns):

- **Reproduction before localization→PLAN** — `record_issue_reproduction` evidence or a
typed `--no-repro` waiver (else the engine emits a one-shot reproduction-required directive).
- **Branch freshness before PLAN (issue-tracer v3 Phase 0, issue #2564)** — the trace records
the fetch outcome with `record_branch_freshness` (`synced`, `behind:<n>`, or
`fetch-failed:<reason>` plus the verbatim user override when the user accepted a stale base).
`behind` and a bare `fetch-failed` fail closed (else the engine emits a one-shot
freshness-required directive).
- **Plan-critic gate before EXECUTE** — the reducer will not advance to EXECUTE until the
plan-critic approval is observed.
- **Authoritative plan state** — read through the ledger-aware loader, never the projection.
Expand All @@ -93,9 +98,22 @@ its receipt gates ARE the mechanical implementation for the parts it owns):
- **Recurrence sweep before commit-pr handoff** — the defect class must be characterized,
searched with explicit predicates, every hit dispositioned, and a guardrail installed
with proof it catches the original defect (or the "no defect class" fast path recorded);
record it with `record_recurrence_sweep` (else the engine emits a one-shot sweep directive).
record it with `record_recurrence_sweep`, including `relatedProblems` — the Phase 1
related-problems sweep results (at least one entry) on BOTH paths (else the engine emits
a one-shot sweep directive).
- **Per-phase validator receipts before commit-pr handoff (issue-tracer v3, issue #2564)** —
run the phase validator (`trace-check.sh phase <N>`) for every completed phase and record
each outcome with `record_trace_validation` (phase, pass/fail, the reviewedCommit and
treeId it reported); any fail entry fails closed until re-recorded as a pass (else the
engine emits a one-shot validator directive).
- **Honest completion** — `publication_handoff` is NOT "resolved"; terminal `published` needs
an issue-bound publication receipt.
- **Merge approval recorded, never certified (issue-tracer v3 Phase 5.1, issue #2564)** —
after publication, the human merge approval is captured with `record_merge_approval`
(prHeadSha equal to finalCriticReviewedCommit, userApprovalVerbatim quoted verbatim);
the trace reaches its true terminal `merge_approval_recorded` status. The merge decision
stays human-enforced — the plugin records it for audit and never certifies, drives, or
green-lights the merge itself.
- **Durable delivery** — a transition persists only after its directive is delivered.

With these receipts the Full-Resolution Contract is mechanically composed into this trace
Expand Down
3 changes: 0 additions & 3 deletions docs/observability-retention-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,8 @@ per row.
| `council-criteria` | .swarm/council/{safeId(taskId)}.json | governed-content | one criteria file per task; council/ dir close-scoped (per-key) | indexed: single JSON per task | cleaned — council/ dir lifecycle | not a defect — this-gate |
| `council-evidence-files` | .swarm/evidence/{phase}/phase-council.json + .swarm/evidence/final-co… | governed-content | per-phase/per-final single artifacts; evidence/ close-scoped (session-scoped) | indexed: single JSON | cleaned — evidence/ dir lifecycle | not a defect — this-gate |
| `record-receipt-artifacts` | .swarm/{implementation-review,issue-publication,reproduction,recurren… | governed-content | single rewritten receipt files; bounded fields (global) | indexed: single small JSONs | untouched (cross-run receipts by design — issue-tracer… | not a defect — this-gate |
<<<<<<< HEAD
| `pr-feedback-loop-state` | .swarm/pr-feedback-loop-state.json + pr-feedback-evidence/{seq}.json + pr-feedback-loop-cleanups/ | operational | one rewritten state (200-correlation FIFO) + one evidence JSON per oversight dispatch + one receipt per cancellation (per-trigger) | full-file: Zod-validated state read | retained — cross-run idempotency basis (digests/budgets); close: neither | not a defect — this-gate; direct-file exemption (#2502) |
=======
| `speckit-checkoff-ledger` | .swarm/speckit-checkoff-ledger.json | derived-rebuildable | single rewritten JSON, one entry per projected feature (MAX_SPEC_FILES 100) (none) | full-file: 512 KiB bounded read (speckit-checkoff.ts readBounded) | retained — derived state, rebuilt on next /swarm sdd project; close: neither | not a defect — this-gate; direct-file exemption (#2501) |
>>>>>>> origin/main
| `spec-drift-artifacts` | .swarm/spec.md + .swarm/spec-staleness.json + .swarm/spec-snapshot.md… | authoritative | single-session drift state; spec-archive/ + spec.md + staleness + snapshot all in close c… (session-scoped) | full-file: bounded spec reads (effective-spec.ts:11-14) | archived+cleaned — unconditional removal so next sessi… | not a defect — this-gate; direct-file exemption (#2036) |
| `workflow-wal-dirs` | .swarm/coder-settlements/{taskId}.json + .swarm/task-repairs/{taskId}… | authoritative | per-task WAL files; all four dirs in ACTIVE_STATE_DIRS_TO_CLEAN (session-scoped) | indexed: single JSON per task | cleaned — all four dirs archived+cleaned | not a defect — this-gate; direct-file exemption (#2036) |
| `summaries` | .swarm/summaries/{S*}.json | governed-content | summaries.retention_days (default 7) enforced by the retention sweep via cleanupSummaries; listing capped MAX_SUMMARIES_LISTED 500 (global) | indexed: per-file reads; listing newest-first capped 500 | untouched — the sweep owns the retention_days horizon | not a defect — #2483 |
Expand Down
60 changes: 60 additions & 0 deletions docs/releases/pending/issue-2564-tracer-v3-receipts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Wire issue-tracer v3 receipts plugin-side and prove issue ingestion reaches a durable plan (issue #2564)

## What

- **Branch-freshness receipt (v3 Phase 0)**: new `record_branch_freshness` tool writes
`.swarm/branch-freshness.json` (`synced` / `behind:<n>` / `fetch-failed:<reason>` plus an
optional verbatim user override). The reader mirrors `trace-check.sh phase0` exactly —
`behind` and a bare `fetch-failed` fail closed; only a recorded override rescues a failed
fetch — and the reducer parks the trace with a one-shot `FRESHNESS_GATE` directive before
the PLAN transition until the receipt permits.
- **Per-phase validator receipts**: new `record_trace_validation` tool records each
`trace-check.sh phase <N>` outcome (v3 phase enum 0..5 including 2.5/4.2/4.5/4.6, pass/fail,
reviewedCommit + treeId, both 40-hex) into `.swarm/trace-validation.json`, upserting per phase.
The reducer's new `TRACE_VALIDATION_GATE` blocks the commit-pr handoff while any recorded phase
is failing or none is recorded.
- **Widened recurrence-sweep receipt**: `record_recurrence_sweep` now requires
`relatedProblems` — the Phase 1 related-problems sweep results, at least one
`{ref, note?}` entry — on both the real-defect-class and "no defect class" paths, and the
reader enforces the widened shape non-vacuously (missing key / empty array / blank refs no
longer satisfy the gate).
- **Merge-approval receipt (v3 Phase 5.1)**: new `record_merge_approval` tool records the
human merge approval bound to the exact PR head (`prHeadSha === finalCriticReviewedCommit`,
both 40-hex; mismatch rejected at write time) with the approval quoted verbatim. The trace
gains a true terminal `merge_approval_recorded` status after `published` — RECORDED, NEVER
CERTIFIED: `nextMode` stays null and the directive names the human as the merge authority,
inheriting trace-check.sh's "human-enforced gate; presence and binding only" posture.
- **Journey proof**: new end-to-end tests drive a real `/swarm issue <N> --trace` input
through `handleIssueCommand`, the real receipt tool executors, the real ledger
(`savePlan`/`loadPlan` — plan tasks carry acceptance criteria, files, and requirement
references), the real `approve_plan_critic` path, an interruption/resume step (module
cache resets), the gates ladder, publication, and the merge-approval recording — no
`_internals` behavioral overrides.

## Why

Issue #2564: the issue-tracer v3 protocol's gates were enforced only by the skill text and
`scripts/trace-check.sh` — the plugin-side reducer, state adapter, and receipt tools knew only
the v2-era artifacts, so the runtime could neither observe nor enforce the v3 receipts, and no
test wired the ingestion command, the real receipt tools, and the reducer together.

## Migration notes

- A recurrence-sweep receipt recorded before this change (v2 shape, without `relatedProblems`)
no longer satisfies the recurrence gate. An in-flight trace that already fired its recurrence
one-shot will wait quietly; re-running `/swarm issue <N> --trace` resets the trace state and
re-arms every gate, and the widened receipt is then recorded with `relatedProblems`. A
load-time receipt migration is deliberately out of scope here (#2566 owns validator,
portability, and migration follow-ups).
- `TraceStatus` grows `merge_approval_recorded`; state readers normalize unknown legacy
statuses to `in_progress` exactly as before, and `published` alone remains a valid resting
state until a merge-approval receipt is observed.

## Verification

- Frozen acceptance checks C1-C9 (arm's-length authored, red-checkpointed at base
`b865ba262`): all RED/ERROR at base, all GREEN post-fix; PRESERVING checks C6/C8 stayed
GREEN throughout (v2-shaped reducer literals stay transparent — the new gates fire only on
explicit `false`).
- The reducer remains a pure, model-agnostic module (no imports, no runner/model/host routing
anywhere in the trace engine).
18 changes: 11 additions & 7 deletions scripts/retention-registry.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2206,34 +2206,38 @@ export const RETENTION_REGISTRY: readonly RetentionRow[] = [
{
id: 'record-receipt-artifacts',
category: 5,
pathGrammar: '.swarm/{implementation-review,issue-publication,reproduction,recurrence-sweep}.json + .swarm/{issue-trace-state,issue-reference}.json',
pathGrammar: '.swarm/{implementation-review,issue-publication,reproduction,recurrence-sweep,branch-freshness,trace-validation,merge-approval}.json + .swarm/{issue-trace-state,issue-reference}.json',
canonicalRoot: 'project-swarm',
writerModules: [
'src/tools/record-implementation-review.ts',
'src/tools/record-issue-publication.ts',
'src/tools/record-issue-reproduction.ts',
'src/tools/record-recurrence-sweep.ts',
'src/tools/record-branch-freshness.ts',
'src/tools/record-trace-validation.ts',
'src/tools/record-merge-approval.ts',
'src/hooks/issue-trace-state.ts',
'src/commands/issue.ts',
],
writerCitations: [
'record-implementation-review.ts:87 / record-issue-publication.ts:74 / record-issue-reproduction.ts:85 / record-recurrence-sweep.ts:125 — atomic single JSONs with Zod-bounded fields',
'issue-trace-state.ts:308 writeTraceState + issue.ts:216-264 — transactional two-artifact write with rollback (:243-288)',
'record-branch-freshness.ts:92 / record-trace-validation.ts:136 / record-merge-approval.ts:89 — issue #2564 v3 receipts: atomic single JSONs, unique per-process temp names, trace-validation upserts one bounded entry per phase',
'issue-trace-state.ts:435 writeTraceState + issue.ts:216-264 — transactional two-artifact write with rollback (:243-288)',
],
readerCitations: ['issue-trace-state.ts:269,287 — full-file reads with legacy completed→status normalization (:242-252)'],
schemaVersion: 'per-artifact Zod schemas (commands ≤200, text ≤4000 chars)',
readerCitations: ['issue-trace-state.ts:396,414 — full-file reads with legacy completed→status normalization (:369-379); v3 readers branch-freshness/trace-validation/merge-approval co-located'],
schemaVersion: 'per-artifact Zod schemas (commands ≤200, text ≤4000 chars; v3 receipts ≤10 upserted entries, SHAs 40-hex)',
stateClass: 'governed-content',
privacyClass: 'metadata',
writeLimits: { bound: 'single rewritten receipt files; bounded fields', scope: 'global', citation: 'record-issue-reproduction.ts:28-31; record-recurrence-sweep.ts:47-61' },
readBound: { pattern: 'indexed', bound: 'single small JSONs', sync: true, citation: 'src/hooks/issue-trace-state.ts:287-302' },
writeLimits: { bound: 'single rewritten receipt files; bounded fields', scope: 'global', citation: 'record-issue-reproduction.ts:28-31; record-recurrence-sweep.ts:47-74; record-trace-validation.ts:37-56' },
readBound: { pattern: 'indexed', bound: 'single small JSONs', sync: true, citation: 'src/hooks/issue-trace-state.ts:414-429' },
lockModel: 'atomic writes; issue pair is transactional with rollback',
crashBehavior: 'temp+rename everywhere; fail-open reads',
closePolicy: 'untouched (cross-run receipts by design — issue-tracer gates read them)',
resetPolicy: 'not reset',
legacyCompatibility: 'legacy completed field normalized',
healthSignal: 'n/a',
owner: 'this-gate',
disposition: { kind: 'not-a-defect', proof: 'Single rewritten bounded receipt files (Zod-capped fields); no growth dimension (record-* tool schemas).' },
disposition: { kind: 'not-a-defect', proof: 'Single rewritten bounded receipt files (Zod-capped fields); no growth dimension (record-* tool schemas; trace-validation capped at one entry per v3 phase enum value).' },
},
{
id: 'pr-feedback-loop-state',
Expand Down
2 changes: 1 addition & 1 deletion src/adversarial-tests.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ describe('ADVERSARIAL: constants.architect-whitelist', () => {
// This test in the original file checks > 40
// Let's verify it's still a reasonable bound
expect(AGENT_TOOL_MAP.architect.length).toBeGreaterThan(40);
expect(AGENT_TOOL_MAP.architect.length).toBeLessThan(100);
expect(AGENT_TOOL_MAP.architect.length).toBeLessThan(110);
});

it('all roles should have at least 1 tool (except overlay/synthesis-only roles)', () => {
Expand Down
Loading
Loading