Skip to content

fix: scope evidence supersession and transcript veto to the right session (#218, #219) - #252

Open
mikehasa wants to merge 2 commits into
mainfrom
fix/receipt-integrity-218-219
Open

mikehasa wants to merge 2 commits into
mainfrom
fix/receipt-integrity-218-219

Conversation

@mikehasa

Copy link
Copy Markdown
Owner

Summary

Two evidence-attribution integrity gaps (reported as #218, #219) where a passing check leaked across a session boundary and produced a false receipt — the exact failure mode this product must never have. Both were reproduced against source before fixing; each ships regression tests that pin the bug and the legitimate behaviors that must keep working (verified pre-fix/post-fix: the bug tests fail on the old source and pass on the fix).

Fixes

#218 — a pass in an unrelated session falsely supersedes another session's finding

supersession._scope_key groups evidence by a per-project/org namespace_fingerprint (plus section + evidence type) with no session component, and annotate_supersession runs store-wide before Task assignment — so a passing check in an unlinked second session that merely reused the same project + section + command retired the first session's finding on an inferred command match, flipping its Task to finding_superseded and zeroing its failed tally.

Fix: gate the inferred bases (same_command / command_shape) on session identity via a new _same_session() (shared non-empty session id or transcript id; both absent → refuse, the safe direction). The explicit agent_declared basis (supersedes_check_event_id) is exempt and still crosses a linked continuation. _scope_key is unchanged, so cross-project/cross-section supersession stays structurally blocked. An unrelated-session pass now leaves the finding fully standing.

#219 — a check with a conflicting transcript still verifies the Task

The transcript-compat veto _evidence_work_fact_compatible was applied only on the explicit work/section-ref candidate path; the independent (client, session) candidate path added the Task with no transcript check, so a passing check with a matching client_session_id but a conflicting client_transcript_id still marked the Task verified and credited a checked step.

Fix: apply the same transcript-compatibility veto on the direct session-key path in api._attach_evidence_to_task_projection and in work_ledger._evidence_candidate_work_ids. The veto fires only on a genuine conflict (event names a transcript, the task recorded one for that session, and they differ), so session-only checks still credit as before, and the existing conflicting-session veto is untouched.

Testing

  • New regression tests in test_supersession.py, test_task_detail_api.py, test_work_ledger.py — each covering the bug case and the legitimate cases (same-session retry still supersedes; explicit declaration still crosses a linked continuation; matching transcript still verifies; session-only checks still credit).
  • Full suite: 2902 passed (PYTHONPATH=src .venv/bin/python -m pytest -q), on top of current main (0.10.10).

Fixes #218
Fixes #219

mikehasa and others added 2 commits September 15, 2026 00:29
… session

Two receipt-integrity gaps where a passing check was applied or credited across
an unrelated or identity-incompatible session, producing a false superseded /
verified receipt. Each was reproduced against source, keeps the legitimate cases
working, and adds regression tests for both the bug and those legitimate cases.

- supersession: gate the INFERRED bases (same_command / command_shape) on
  session identity, so a pass in an unrelated, unlinked session that merely
  reuses the same project + section + command no longer retires another
  session's finding (and no longer zeroes its failed tally). The EXPLICIT
  agent_declared basis is exempt and still crosses a linked continuation, and
  the unchanged scope key still blocks cross-project / cross-section
  supersession. (#218)
- api / work_ledger: apply the transcript-compatibility veto on the direct
  (client, session) attribution path, not only the explicit section-ref path,
  so a passing check whose client_transcript_id conflicts with the task's own
  no longer marks the Task verified or credits a checked step. The veto fires
  only on a genuine conflict, so session-only checks still credit. (#219)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant