Repository navigation
fix(audit): parse only the final turn of long transcripts - #263
DorianZheng wants to merge 1 commit into
Conversation
The Stop gate's snapshot reader decoded the whole transcript with JSON::PP to find the last real user message, at about 5 MiB/s. To stay inside its 15 s alarm, callers capped the file at 64 MiB. Transcripts only grow, so once a session passed the cap, every Stop produced an incomplete snapshot that the auditor must FAIL, blocking the session for good. Scan back from the end of the file instead and decode only the final turn, at most 64 MiB (verdict_audit_final_turn_max_bytes). Earlier history is hashed for source_sha256, and the decoded turn bytes must hash the same in the full-file pass, so the snapshot contract and its stability checks stay as they were. A 52.8 MiB transcript drops from about 10 s to 0.3 s. Rejected: raising the cap and alarm (cost still grows with the session), JSON::XS when installed (not core Perl), recording the turn offset at UserPromptSubmit (new cross-hook state), and last_assistant_message alone (no tool evidence for the auditor). Design: #262
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
TL;DRThe PR author must acknowledge the current diff and description before requesting review. Author review acknowledgmentAwaiting the PR author's acknowledgment. @DorianZheng: read the current diff and description, then check: Apply boxlite-writing. Does How it works explain the diff's mechanism or rationale? Use the form best suited to the change. Check drafts too, and repeat this review Unacknowledged PRs are converted to draft. After this check passes, click Ready for review when you want reviews. |
TL;DR
Sessions past 64 MiB no longer block every Stop: the gate parses only the final turn, read back from the end of the transcript.
Design doc: #262
Documentation: ARCHITECTURE.md and hooks README.
How it works
_verdict_audit_snapshot_final_turnJSON-decoded every line from byte 0 to find the last real user message, at about 5 MiB/s. Callers capped transcripts at 64 MiB to fit its 15 s alarm, so past the cap every Stop got an incomplete snapshot that the auditor must FAIL.source_sha256and must see the same final-turn bytes that were decoded; pass 2 re-hashes, as before.verdict_audit_final_turn_max_bytes(64 MiB) limits decoded bytes and replaces the three caller copies. There is no whole-file ceiling, so the 15 s alarm bounds hashing. The custom extractor path keeps its 64 MiB whole-file read.Verification
make test:plugin TEST_FILTER=preflight-verdict-check.test.sh→ 231 passed, 3 failed; the 66 MiB session ended onextract truncated-block.make test:plugin TEST_FILTER=<suite>→ 0 failures each.make test:writing test:parity test:architecture→ exit 0.