Retry a timed-out follow-up whose send then fails; fix the gate after #320 - #321
Merged
Merged
Conversation
…e formatting DrainWedgeVerificationTests.swift passed deliveryDeadline: last, but GraphStore.init declares it right after graph:, so the test target did not compile. swift-format --strict also rejected ProjectPersistence.swift; this is the formatter's own output for that file. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014niBD1D1yQ7F2gjV2K54eB
#320 kept a timed-out delivery on the queue until its abandoned send reported a verdict. A late success removed it, exactly once. A late failure went through staged(_:), which only writes the memory log and returns a marked copy — the return was discarded, in finishTimedOutDelivery and in the drain's fold-back alike, so the item left the live queue. A target that was idle and answering never received text it was owed, while a send that failed before the deadline was retained for retry. Both failures are now the same: staged once, kept in place, retried by a drain the verdict itself kicks rather than the next poll. DeliveryWedgeTests' hung-send test asserted a delivery its own closure could never record — the hung branch returned without appending — so its last expectation was unreachable whatever the store did. The closure now records the late success and the test checks it is not sent twice. A second test covers the late failure and fails on main. Both await the wedged command's return instead of a ten-second settle: the deadline is what returns it, and the bystander's mail, queued mid-drain, moves on the pass after. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014niBD1D1yQ7F2gjV2K54eB
Owner
Author
|
Gate on
Also, #318's |
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.
Makes
maingreen after #320 and fixes the defect its exactly-once bookkeeping left behind. Two commits: the gate fixes the Release loop verified (.claude/handoff/gate-fixes-320.patch, applied as-is), then the store fix with tests.Gate fixes (commit 1)
DrainWedgeVerificationTests.swiftpasseddeliveryDeadline:last, butGraphStore.initdeclares it second, right aftergraph:. Swift matches an argument list in declaration order, so the test target did not compile; the reportedmessageNode/refreshUsageerrors were downstream noise. Moved it to where it is declared.ProjectPersistence.swiftfailedswift-format --strictat 61:10, 62:1, 67:14. Reformatted with the formatter on that file only.The defect (commit 2)
#320 keeps a timed-out delivery on the queue until its abandoned send reports a verdict. A late success is removed, exactly once — correct. A late failure went through
staged(_:), which only writes the memory log and returns a marked copy; the return was discarded in bothfinishTimedOutDeliveryand the drain's fold-back, so the item silently left the live queue. A target that was idle and answering never received text it was owed, while a send that failed before the deadline was retained for retry (the!deliveredbranch on main). Both failures are now treated the same: staged once, kept in place on the queue, and retried by a drain the verdict itself kicks — a failure learned this late has no command to ride the drain of, so without its own it waited for the next poll, or for good if none came.The test that was failing
DeliveryWedgeTests.aHungDeliveryStillFreezesEveryOtherLoopsFollowUpsasserteddeliveredwould contain the hung one's message, but its ownonDeliverMessageclosure never appended for the hung node — the hung branch returnedtruewithout recording. The last expectation was unreachable whatever the store did, and the store was in fact correct for that path: the send succeeded late, so the message must not be sent again. The closure now records its late success, and the test checks two further drains send nothing more. The new testaTimedOutSendThatThenFailsIsRetriedExactlyOncecovers the late-failure path and fails on main'sGraphStore:Both tests now await the wedged command's return instead of a ten-second settle — the deadline is what returns it — and then refresh, because the bystander's message is queued mid-drain and moves on the pass after. The two suites run in 0.3s instead of 24s.
Not covered here: a send that never reports at all stays parked in
pendingDeliveryAttempts, unstaged, until the daemon restarts. Same as #320's main; noted so it is not mistaken for fixed.Gate
In flight from
worktrees/fix-320-lost, private DerivedData; numbers posted below when it finishes.make checkexit 0 (swiftlint 0 errors, swift-format clean)DeliveryWedgeTests+DrainWedgeVerificationTests: exit 0, 6 tests; red on main'sGraphStore.swift(exit 65, the new test only)🤖 Generated with Claude Code
https://claude.ai/code/session_014niBD1D1yQ7F2gjV2K54eB