Repository navigation
Read the numbered terminator Claude shows after an export's final LF - #3570
Merged
Merged
Conversation
Every read-file export ends in LF, and Claude's Read numbers the empty row after it. ReadResultObserved.frames decoded that row as a ninth foreign frame, so read_export's all-lines gate refused all eight real parts and 358869593c89 sat at emitted forever on the installed b685915. frames() now drops exactly one final empty row, after the consecutive numbering holds, and only when it is not the only row. Every other empty or foreign row stays a frame the unchanged gate refuses. The test fake shown() modelled the Read from splitlines(), which never has that row, so every read-file test checked a Read Claude never produces. It now numbers physical LF rows of real export text; whole reads carry the terminator, partial pages do not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dR85kyFKcc2tQAJLhK
|
debt-src at bd6aaa3, every finding: |
lines[-1][:100] on a final part shorter than 100 characters kept the whole record, so the negative case fed a valid export and expected refusal. Drop the last character instead and assert the result differs from the line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dR85kyFKcc2tQAJLhK
My busy-begin test defined a second module-level stored_attempts(db, bridge, message) after the async stored_attempts(bridge), so Python kept the later one and the five async callers called a three-argument sync function with one argument. The one held-connection caller now selects HarnessDelivery on the held SQLite connection directly; the shadowing helper is gone and the async reader is the module's only one. CheckedProblemOrder.work_instructions pasted the whole voice file into every rendered order although UnitInstructions.render already carries it in each unit's system prompt: about a third of order bytes were that copy. The copy and its import are deleted; the test asserting the copy is deleted and the voice joins the UnitInstructions carrier test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnH6dR85kyFKcc2tQAJLhK
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
claude_protocol.py+7/-1,tests/test_monitor_delivery.pyreworked. The second commit makestruncated-finalactually truncate:[:100]on a final part under 100 characters cut nothing.str.splitlinescalls on export text in the test module: 8 → 0.The bug
The one-event delivery from #3546 exports a large message as one JSON string per line, and every export ends in LF. Claude's Read numbers the empty row after that final LF. On the live record (
...a8ec5ff4d019a77d"\n9\t),ReadResultObserved.frames()decoded 9 frames: 8MonitorPartplus 1ForeignMonitorFramefor the empty row, so 8 parts.LineMonitorBridge.read_export's all-lines gate (len(parts) != len(frames)) therefore refused the notice. Every read-file delivery was dead on arrival.Why tests were green: the fake
shown()built Read output fromsplitlines(), which never has that row. Every read-file test checked a Read Claude does not produce.Mechanism changed
ReadResultObserved.frames()(cli_bridges/claude_protocol.py:679) still splits on physical LF only and still parses the leading numbered block. It validates the whole number sequence, terminal row included, with the existing consecutive rule. Only then does it pop at most one final row whose payload is exactly empty, and never when that row is the only row, so an empty Read still proves nothing. Interior empty rows, a second terminal empty row, gapped terminal numbers, foreign or truncated final payloads and failed Reads all stay unconfirmed.read_export's reference, identity, part and all-lines gates are unchanged.Tests
shown(text, start)now numbers the physical LF rows of real text. Whole-export callers passexport.read_text(newline=''), so they carry the terminator; partial pages pass explicit excerpts, with the terminator only when they reach the end.truncated-final,interior-empty,two-terminal-empties,terminal-gap,foreign-terminal.last-pagenow reaches the end with the terminator;repeated-pagestops before it.Assumed
Commit 3: the shadowed delivery reader and the duplicate voice carrier
stored_attemptsdefined twice.tests/test_monitor_delivery.py:59declaresasync def stored_attempts(bridge). My #3546 busy-begin test (fbe666a) then declared a module-leveldef stored_attempts(db, bridge, message)at line 217, so Python kept the second definition. The five async callers (lines 97, 108, 432, 449, 832) were calling a three-argument sync function with one argument; that is the main-CIstored_attempts() missing 2 required positional arguments. The second helper is deleted. Its one caller now selectsHarnessDeliverydirectly on the held SQLite connection (no coordinator read underBEGIN EXCLUSIVE). Census over src/tools/tests: onestored_attemptsdefinition and its 5 async callers; no other module declares or calls the name.The voice file sent twice per unit.
CheckedProblemOrder.work_instructions(todos.py) appendedCommanderPackage.voice()to every rendered order, whileUnitInstructions.render(unit_instructions.py:28) already puts the same file in each unit's system prompt. In the 6 h before this change that copy was 178 KB of 502 KB of direct order bytes (29 of 70 orders). The copy and the now-unused import are deleted.test_work_instructions_carry_the_owner_voicetested the deleted copy and is deleted; the voice joins the sourcestest_unit_prompt_carries_every_rule_under_its_audiencealready requires of the real carrier.The decoder (
cli_bridges/) is byte-identical to fbc4b10.Results
truncated-finalexport case on fbc4b10: passed in 5.41 s.src/bytes are identical to fbc4b10.Not run (per order)
Commit 3: the empty-journal, exact-body/reopen, wrong-complete-parts and held-BEGIN controls, plus test_unit_instructions and test_order_claims, are unrun; root selects them.
pytest, mypy, ratchets, import probes, live Read, install. I ran only py_compile and the order's AST check, which prints
1.Open P876 targets
Stale-backlog attention and noisy replies, end-to-end latency, installed busy/idle Read cost. 358869593c89 stays historical evidence; it is never replayed.
🤖 Generated with Claude Code
https://claude.ai/code/session_01RnH6dR85kyFKcc2tQAJLhK