Skip to content

feat(issue-tracer): wire v3 receipts plugin-side and prove ingestion reaches a durable plan (#2564) - #2783

Open
zaxbysauce wants to merge 6 commits into
mainfrom
feat/issue-2564-tracer-v3-receipts
Open

zaxbysauce wants to merge 6 commits into
mainfrom
feat/issue-2564-tracer-v3-receipts

Conversation

@zaxbysauce

@zaxbysauce zaxbysauce commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

feat(issue-tracer): wire v3 receipts plugin-side and prove ingestion reaches a durable plan

Closes #2564

Summary

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. This change wires all four v3 receipt surfaces into the plugin runtime
with producer, reader, reducer-consumer, registration, docs, and tests in one change:

  • Branch-freshness receipt (v3 Phase 0) — new record_branch_freshness tool writes
    .swarm/branch-freshness.json (synced / behind:<n> / fetch-failed:<reason> + optional
    verbatim user override). The reader mirrors trace-check.sh phase0 exactly (behind and bare
    fetch-failed fail closed; only a recorded override rescues a failed fetch) and the reducer's
    new FRESHNESS_GATE one-shot parks the trace before PLAN until the receipt permits.
  • Per-phase validator receipts — new record_trace_validation tool records each
    trace-check.sh phase <N> outcome (v3 phase enum, pass/fail, 40-hex reviewedCommit + treeId)
    into .swarm/trace-validation.json, upserting per phase; any fail entry fails closed until
    re-recorded as a pass. The reducer's TRACE_VALIDATION_GATE blocks the commit-pr handoff
    and chains after the recurrence gate in the canonical ladder.
  • Widened recurrence sweeprecord_recurrence_sweep now requires relatedProblems
    (the Phase 1 related-problems sweep results, ≥1 entry) on both the real-defect-class and
    "no defect class" paths; the reader enforces the widened shape non-vacuously.
  • Merge-approval receipt (v3 Phase 5.1) — new record_merge_approval records the human
    merge approval bound to the exact PR head (prHeadSha === finalCriticReviewedCommit, both
    40-hex; mismatch rejected at write time) with the approval captured verbatim. The trace gains
    a true terminal merge_approval_recorded status after publishedrecorded, 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 /swarm issue <N> --trace through
    handleIssueCommand, every real receipt executor, the ledger-authoritative
    savePlan/loadPlan (tasks carry acceptance criteria, files_touched, fr_refs), the real
    approve_plan_critic path, an interruption/resume step (module cache resets), and the full
    gates ladder to published and merge_approval_recorded — with the actionable next step
    asserted at every gate, and no _internals behavioral overrides.

Also resolves a pre-existing committed merge-conflict marker in
docs/observability-retention-registry.md at the record-receipt-artifacts row (both
pr-feedback-loop-state and speckit-checkoff-ledger rows retained) — a disclosed adjacent
cleanup, verified present at the base commit.

Acceptance Criteria -> Evidence

  • AC1 freshness receipt → frozen check C1 (RED at base → GREEN; producer/reader/reducer rows
    exercised) + record-v3-receipts / state-v3-receipts suites.
  • AC2 validator receipts → C2 (RED→GREEN) + the reducer chaining/truthful tests.
  • AC3 widened sweep → C3 (RED→GREEN; v2 shape no longer satisfies; vacuity rejected).
  • AC4 merge approval → C4 (ERROR→GREEN) + journey completion test asserting the terminal
    status, PR-head binding across receipts, and no mode driven.
  • AC5 no unwired code → C5 static wiring scan (tool files, TOOL_METADATA architect entries,
    TOOL_MANIFEST handlers, barrel, reducer consumption, state readers, hook calls, BOTH
    issue-ingest SKILL.md mirrors, test references) + check-tool-registration (137 tools).
  • AC6 model-agnostic → C6 PRESERVING (reducer stays pure; no runner/model routing) GREEN→GREEN.
  • AC7 ingestion journey → C7 (24 assertions: ingest → spec → gates → durable plan →
    interruption/resume → critic → EXECUTE → gates → handoff → published → merge recorded) +
    the two journey bun:test files.
  • AC8 coordination → C8 PRESERVING (rows (d)/(g) untouched; DD-C009 stays [Workstream F] PR 20 of 21: Bind the issue trace to its loaded plan and surface silent trace stalls #2600's) GREEN→GREEN;
    [Workstream F] PR 14 of 21: Complete deferred issue-tracer v3 validator, portability and migration follow-ups #2566 owns load-time migrations (documented in the release fragment).
  • AC9 release hygiene → C9 (docs/releases/pending/issue-2564-tracer-v3-receipts.md) + no
    version/CHANGELOG/.release-please-manifest edits in the diff.

Invariant audit

  • 1 (plugin init): not touched — the trace hook is a messagesTransform, not init-path; the new
    tools are lazily loaded thunks. Evidence: no src/index.ts change in the diff; init surface
    unchanged.
  • 2 (runtime portability): touched — three new tool modules import only node:fs/path/zod;
    bun run build exit 0, node --input-type=module -e "await import('./dist/index.js')" exit 0,
    bundle-portability + bundle-plugin-shape tests 12 pass / 0 fail.
  • 3 (subprocesses): not touched — no new spawns.
  • 4 (.swarm containment): touched — all new receipts live under .swarm/ via validateSwarmPath;
    bun run check:retention passes with the three new writers registered in the
    record-receipt-artifacts row (122 rows, every writer registered or exempt).
  • 5 (plan durability): touched — the journey drives the real ledger (savePlan/loadPlan);
    plan-ledger.jsonl asserted authoritative; no projection reads added.
  • 6 (test_runner safety): not touched.
  • 7 (test writing): touched — new bun:test files only (266/176/211/128/110 lines, all <500;
    check:test-file-cap 0 violations), _internals seams extended not bypassed, no new
    mock.module targets (check:mock-cleanup clean), realpathSync(mkdtempSync) everywhere,
    check-test-tmpdir.sh clean, check:invariants 8/8.
  • 8 (session state): touched — receipts are issue-bound working state (readers fail closed on
    foreign issue numbers); no session-global growth.
  • 9 (guardrails/retry): not touched.
  • 10 (chat/system msg): touched — the two new gate directives ride the existing
    user-role guidance carriers (appendGuidanceCarrier); journey tests assert carrier delivery.
  • 11 (tool registration): touched — TOOL_METADATA + TOOL_MANIFEST + barrel wired;
    check-tool-registration.ts passes (137 tools coherent); bun run drift:check --enforce
    shows no new findings (the sole blocking pr-standards finding reproduces identically at the
    pre-fix base — pre-existing upstream drift).
  • 12 (release/cache): touched — pending fragment shipped; no version/CHANGELOG hand edits.

Test plan

Per-file isolation (bun test <file> --timeout 120000), all green:
record-v3-receipts 7, issue-trace-state-v3-receipts 6, issue-trace-reducer-v3 14,
issue-trace-journey-v3 6, issue-trace-journey-v3-completion 2, issue-trace 21,
issue-trace-e2e 10, record-residual-b-receipts 12, issue-trace-state-receipts 23,
issue-trace-state 19, issue-trace-reducer 17, issue-trace-reducer-publication 15,
record-issue-receipts 10, agent-tool-map 13, loader.metadata.parity 9, loader.metadata 16,
host-guidance-trace-controls-2526 3, host-rendered-guidance-2526 2, issue-trace-registration 5,
issue-trace-approval-cache 3, issue-trace-state-plan 10, system-guidance-carrier 22,
issue-ingest-skill 10, issue-command 18, cleanup-drift 2,
nested-project-boundary-command-sinks 2, bundle-portability + bundle-plugin-shape 12.
Quality gates: typecheck exit 0; biome ci (4765 files) exit 0; check-tool-registration,
check:retention, check:registry-citations (90/90 baseline, no new drift), check-invariants,
check:test-file-cap, check-test-tmpdir, check:mock-cleanup all clean. The nine frozen
arm's-length acceptance checks (C1-C9, red-checkpointed at base b865ba2) all pass with
verify-checkpoint 9/9 OK.

Waivers (or none)

None.

Merge status: AWAITING_USER_APPROVAL — the merge decision is human-enforced; this plugin
records approvals, it never certifies or drives merges.

PR head: e80139a

Test User added 4 commits September 14, 2026 19:34
…reaches a durable plan (#2564)

Adds the four issue-tracer v3 receipt surfaces to the plugin runtime with
producer, reader, reducer-consumer, registration, docs, and tests wired in one
change:

- record_branch_freshness (Phase 0): .swarm/branch-freshness.json; reader
  mirrors trace-check.sh phase0 (behind/bare fetch-failed fail closed, override
  rescues fetch failures only); FRESHNESS_GATE one-shot row before PLAN.
- record_trace_validation (per-phase validator receipts): upsert-per-phase
  .swarm/trace-validation.json with 40-hex reviewedCommit+treeId; any fail
  entry fails closed; TRACE_VALIDATION_GATE row before the commit-pr handoff.
- record_recurrence_sweep widened: relatedProblems (Phase 1 related-problems
  sweep results) required and non-vacuously reader-enforced on both paths.
- record_merge_approval (Phase 5.1): PR-head-bound (prHeadSha ===
  finalCriticReviewedCommit) with the approval captured verbatim; new terminal
  TraceStatus merge_approval_recorded after published — recorded, never
  certified: nextMode stays null and the directive names the human as the
  merge authority.

Journey proof: new e2e tests drive /swarm issue <N> --trace through
handleIssueCommand, every real receipt executor, the ledger-authoritative
savePlan/loadPlan (acceptance, files_touched, fr_refs), approve_plan_critic
via ensureAgentSession, interruption/resume via cache resets, and the full
gates ladder to published and merge_approval_recorded — no _internals
behavioral overrides.

Also resolves a pre-existing committed merge-conflict marker in
docs/observability-retention-registry.md at the record-receipt-artifacts row
(both pr-feedback-loop-state and speckit-checkoff-ledger rows retained).
 review round 1)

Move the v3 receipt fixture writer into the shared non-test helper module
(issue-trace-journey-v3-helpers.ts, writeV3ReceiptFiles) and drop the duplicated
per-site insertions, restoring issue-trace.test.ts to 497 lines (< 500).
…lands (#2564 final-critic round 1)

The i-pre3 fire condition over-excluded REVIEW_GATE and RECURRENCE_GATE, so in
the canonical reducer-driven ladder (RECURRENCE_GATE fires, the sweep receipt
lands) the very next cycle parked silently instead of emitting the validation
directive — the gate stayed fail-closed but the engine went idle at its own
new gate. The exclusion set now excludes only this row's own sentinel plus
EXECUTE_TO_COMMIT, mirroring how i-pre2 does not exclude REVIEW_GATE. Adds the
reducer test firing from both prior sentinels and makes the journey completion
test assert the validation-gate cycle actually emits the directive.
…2564 review round 3)

Row i-pre3 now requires both residual-B gates to be verified before its
directive can claim they are satisfied: with the sentinel present but the
underlying review/sweep receipt no longer verified (vanished, stale, foreign),
the row declines to the shared exhausted-one-shot noop instead of emitting a
lying directive. Adds the inconsistent-state reducer tests.
@github-actions

Copy link
Copy Markdown
Contributor

Drift check report

Found 2 drift finding(s): 0 error, 0 warning, 2 notice.

required-check-contract (2)

  • 🔵 notice scripts/required-check-contract.json: [RULESET_DIVERGENCE] intended-required context "drift" is not yet required by the captured ruleset
  • 🔵 notice scripts/required-check-contract.json: [RULESET_DIVERGENCE] intended-required context "drift" is not present for every expected event in captured external workflow evidence

 CI)

The FR-011 tmpdir lint requires the realpathSync wrap on one line; biome's
formatter had split it, so the committed split form failed CI quality.
canonicalMkdtemp from tests/helpers/tmpdir.ts is the sanctioned helper.
#2564)

CI round 2 surfaced two ratchet classes the local tests/-scoped sweep could
not see (src/ tests and the unit-job ratchets were skipped behind the first
quality failure):

- atomic-write WRITER_CLASSIFICATION: register the three new receipt tools'
  per-invocation temp constructions under target-suffix-tmp-num-alnum
  (record-branch-freshness:90, record-trace-validation:134,
  record-merge-approval:87) and re-pin the two citations drifted by this
  change (issue-trace-state.ts 315->442, record-recurrence-sweep.ts 125->140).
- src/adversarial-tests.test.ts: the architect tool-map sanity bound rises
  100 -> 110; the three #2564 receipt tools put the architect count at exactly
  100.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It restructures a core workflow reducer state machine, adds a behavior-changing gate for in-flight traces plus a breaking record_recurrence_sweep schema requirement and a new terminal status, warranting final human review despite thorough tests.

Pull request overview

This PR wires the issue-tracer v3 protocol gates into the plugin runtime. Previously these gates were enforced only by scripts/trace-check.sh and skill text; the plugin-side reducer/state-adapter/receipt tools only knew v2-era artifacts. The change adds full producer→reader→reducer→registration→docs→tests coverage for four v3 receipt surfaces, plus an end-to-end ingestion-journey proof driving the real command, receipt executors, and ledger to a durable plan. It closes #2564 and deliberately coordinates (without absorbing) #2566 and #2600.

Changes:

  • Adds three new architect tools (record_branch_freshness, record_trace_validation, record_merge_approval) and widens record_recurrence_sweep to require non-vacuous relatedProblems.
  • Extends the reducer with a pre-PLAN FRESHNESS_GATE, a pre-handoff TRACE_VALIDATION_GATE, and a new terminal published → merge_approval_recorded transition (recorded, never certified), with matching fail-closed readers in issue-trace-state.ts.
  • Registers the tools, updates the retention registry + skill mirrors + release fragment, and resolves a committed merge-conflict marker in the observability doc.
File summaries
File Description
src/tools/record-branch-freshness.ts New Phase 0 freshness receipt writer (synced/behind/fetch-failed + override)
src/tools/record-trace-validation.ts New per-phase validator receipt writer, upserts one entry per phase
src/tools/record-merge-approval.ts New PR-head-bound merge-approval writer; rejects SHA mismatch at write time
src/tools/record-recurrence-sweep.ts Widened to require non-vacuous relatedProblems on both paths
src/hooks/issue-trace-state.ts Adds three fail-closed readers + merge_approval_recorded status; widens sweep reader
src/hooks/issue-trace-reducer.ts New gate rows + terminal transition; === false guards keep v2 literals transparent
src/hooks/issue-trace.ts Wires the three new readers into WorkflowArtifacts
src/tools/{tool-metadata,manifest,index}.ts Registration surfaces for the three new tools
scripts/retention-registry.data.ts Adds new writers/citations to the record-receipt-artifacts row
docs/observability-retention-registry.md Removes committed merge-conflict markers (both rows retained)
docs/releases/pending/issue-2564-*.md Release fragment
.opencode/.claude issue-ingest SKILL.md Documents the new gates (byte-identical mirrors)
tests/unit/{hooks,tools}/* New receipt/reader/reducer/journey suites + fixture updates to existing hook tests

I verified the wiring is complete (metadata/manifest/barrel/readers/reducer/tests), the reducer gate ladder and one-shot semantics are internally consistent, the readers mirror the writers, the retention-registry citations point to accurate lines (issue-trace-state.ts:435 = writeTraceState, :396/:414 = readers), the skill mirrors are identical, and existing hook-driving tests were updated to satisfy the new gates. I found no objective defect within the changed regions.

Review details
  • Files reviewed: 26/26 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@zaxbysauce

Copy link
Copy Markdown
Collaborator Author

🤖 Multi-Stage PR Review

Pipeline: MiniMax-M2.7-highspeed (orientation) (context pack) → MiniMax-M2.7-highspeed (explorer) + MiniMax-M2.7-highspeed (explorer B) (parallel explore, distinct lenses) → GLM-5-turbo (critique) ↔ GLM-5-turbo (critique) (cross-critique) → MiniMax-M2.7-highspeed (fallback arbiter) (arbiter: blind-spot + synthesize)
Commit reviewed: 121005243d29


Challenge Results

Findings Kept After Challenge

After reviewing each confirmed finding against the diff and full-file content, I found the following:

FINDING 1 — record-branch-freshness.ts:81 (success:true returned when rename throws after writeFile succeeds):

  • VERIFIED — KEEP. The outer try/catch block wraps the rename call at line 87. If rename throws (ENOENT/EBUSY/EXDEV/EPERM), success:true was already returned at line 73 before the rename — the error propagates to the outer catch, which still returns success:false. However, if rename fails silently (rare but possible on some filesystems) or if writeFile succeeds and rename throws, the caller receives success:true with no receipt at the final path. This is real, introduced by this PR, and fixable (check rename result and return success:false if it throws).
  • Evidence: src/tools/record-branch-freshness.ts:73 (returns success:true) → src/tools/record-branch-freshness.ts:87 (rename in same try block).

FINDING 2 — tempCounter race condition (record-branch-freshness.ts:71, record-trace-validation.ts:125, record-merge-approval.ts:87):

  • VERIFIED — KEEP. let tempCounter = 0 module-level, then tempCounter += 1 (non-atomic read-modify-write) before using in a temp filename. In concurrent execution (multiple tool calls within the same event-loop turn, or truly parallel workers sharing the same module cache), two callers can read the same counter value, write the same temp filename, and one rename will overwrite the other. The winner's rename succeeds; the loser's rename throws EEXIST. The outer catch returns success:false, but the winning caller already got success:true. This is a real race condition with concrete collision evidence.
  • Evidence: src/tools/record-branch-freshness.ts:44,71, src/tools/record-trace-validation.ts:69,125, src/tools/record-merge-approval.ts:53,87.

Findings Dropped as False Positives

  1. TRACE_VALIDATION_PHASES enum drift (HIGH) — The reviewer misread the finding. Both the writer (record-trace-validation.ts:20-31) and reader (issue-trace-state.ts:236-246) define ['0','1','2','2.5','3','4','4.2','4.5','4.6','5'] — identical. DROP.

  2. fsync/datasync before rename (MEDIUM)writeFile + rename is the standard atomic-write pattern in this codebase (and widely). The rename is atomic on POSIX; the original is untouched until rename succeeds. A crash between write and rename either leaves the original (if rename didn't run) or leaves the complete temp file (if rename ran but returned an error). This is not a defect. DROP.

  3. process.pid collision across worker threads (HIGH) — Worker threads in Node.js/Bun each have their own module cache and process.pid. Threads do not share module-level let tempCounter, so they cannot collide via this mechanism. The temp filename is {pid}.{tempCounter} — each thread starts tempCounter at 0 but in its own module instance. DROP.

  4. Stale comment citation (MEDIUM) — The diff updates a comment citation from :125 to :140 in atomic-write.ts. This is a comment update, not code behavior. The finding proves the old number was stale — but this PR is fixing the stale number, not introducing it. DROP.

  5. Trace-validation upsert race (HIGH) — The upsert logic (findIndex then replace/push) is not a data-loss bug: two concurrent writes for the same phase result in one overwriting the other (last-write-wins semantics, which is fine for an upsert). Two writes for different phases do not conflict. This is intentional upsert semantics, not a race defect. DROP.

  6. tempCounter in record-trace-validation.ts:125 and record-merge-approval.ts:87 (LOW) — These are the same pattern as the KEEP'd race condition above; they should be collapsed into the same finding. DROP (merged into finding 2).


Blind-Spot Findings

None identified. After reviewing the full diff:

  • The reducer decision table is correctly structured — freshnessPermitted === false guards row (f) before the reproduction check, and both feed ISSUE_INGEST_TO_PLAN.
  • Row (i-pre3) chains correctly after the prior gate sentinels (REVIEW_GATE, RECURRENCE_GATE are NOT excluded, per the final-critic round 1 comment), and the implementation-review round 3 guard (declining when a prior receipt vanished) is faithfully represented.
  • merge_approval_recorded is correctly terminal (nextMode: null in both the noop row (b) and the transition row (b')).
  • record_recurrence_sweep correctly requires relatedProblems on both paths.
  • The retention registry correctly registers all three new writers.
  • The issue-ingest SKILL.md mirrors are updated correctly for both .claude/ and .opencode/ paths.
  • Journey tests drive real machinery with no _internals behavioral overrides and correctly assert the actionable next step at every gate.
  • No cross-file contract mismatches, no silent drops of [NEEDS REPRO] flags, no tool allowlist drift.

🔁 Validation Provenance

Finding Outcome Reason
success:true on rename failure KEPT (MEDIUM) Concrete failure path: rename throws after write succeeds; caller misled
tempCounter non-atomic increment KEPT (HIGH) Concurrent callers read-modify-write same value → colliding temp filenames → EEXIST on loser's rename
Enum drift DROPPED Both arrays are identical; reviewer misread the finding
fsync before rename DROPPED Atomic-write pattern; rename is atomic on POSIX; original untouched
process.pid worker thread collision DROPPED Worker threads have separate module cache and tempCounter instance
Stale comment citation DROPPED Comment fix is the PR's purpose; not a new defect
Trace-validation upsert race DROPPED Intentional last-write-wins upsert semantics; no data loss
Blind-spot: reducer logic No findings Decision table, gate chaining, terminal status all correct
Blind-spot: registry wiring No findings All three new writers registered
Blind-spot: journey tests No findings Real machinery, no _internals overrides, actionable next step asserted

Final Review

🚨 Confirmed Findings

[MEDIUM] success:true returned when rename fails after writeFile succeeds

  • Location: src/tools/record-branch-freshness.ts:73 + src/tools/record-trace-validation.ts:132 + src/tools/record-merge-approval.ts:86
  • Why it matters: Callers receive success:true and a path confirmation even when the receipt never reaches its final destination. If rename throws (ENOENT if directory missing, EBUSY on locked file, EXDEV cross-device, EPERM permission denied), success:false is returned via the outer catch — but only after writeFile already succeeded and the temp file contains the correct data. The caller cannot distinguish "renamed successfully" from "write succeeded but rename failed."
  • Evidence: In record-branch-freshness.ts, success:true is returned at line 73, then rename is called at line 87 in the same try block. If rename throws, the outer catch returns success:false — but the temp file with correct data is left on disk and the final path is absent. Same pattern in record-trace-validation.ts:132 and record-merge-approval.ts:86.
  • Fix direction: Move success:true return after the rename call completes, or check the rename result and return success:false if it throws instead of relying on the outer catch.

[HIGH] Non-atomic tempCounter increment causes colliding temp filenames under concurrent execution

  • Location: src/tools/record-branch-freshness.ts:44,71 · src/tools/record-trace-validation.ts:69,125 · src/tools/record-merge-approval.ts:53,87
  • Why it matters: tempCounter += 1 is a non-atomic read-modify-write. If two tool calls execute within the same event-loop turn (or concurrently across workers sharing the same module cache), both can read the same counter value before either increments it, producing identical temp filenames. Both writeFile calls succeed; the first rename wins; the second rename throws EEXIST. The winner's caller gets success:true; the loser gets success:false from the outer catch — but the losing caller may have already acted on success:true before discovering the collision.
  • Evidence: let tempCounter = 0 at module scope; tempCounter += 1 then ${process.pid}.${tempCounter} in the filename. Both patterns present identically across all three new tools and record-recurrence-sweep.ts.
  • Fix direction: Replace the shared integer counter with Date.now() or crypto.randomUUID() for the temp filename suffix, which are inherently collision-free. This also eliminates the dependency on module-level mutable state.

Minor

  • The stale comment in src/utils/atomic-write.ts:301 (record-recurrence-sweep.ts:140 instead of the previous :125) is a valid correction — the PR is fixing it, not introducing it; mentioned for completeness only.
  • All nine frozen acceptance checks (C1–C9) are correctly mapped to producer/reader/reducer/test coverage; no unwired declarations found.

📋 Merge Recommendation

[BLOCK]

Two confirmed defects introduced by this PR: a misleading success return when rename fails, and a race condition in temp filename generation under concurrent execution. Both have concrete failure paths and concrete fixes.

Check Result
No CRITICAL findings
No unresolved STEALTH_CHANGE
No UNSUPPORTED obligations
Test coverage adequate
No hardcoded secrets
All async errors handled ⚠️ — rename errors not distinguished from write errors
Input validation present
No broken agent role boundaries
Prompt format contracts intact
Lockfile consistent

🔒 Reviewed by a 3-model cross-family adversarial debate (architect → dual-lens parallel explorers → cross-critique → arbiter) for high recall with low false-positive noise. Findings are advisory — verify before acting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Workstream F] PR 13 of 21: Wire issue-tracer v3 receipts and prove issue ingestion reaches a durable plan

2 participants