Skip to content

0.1.64-beta4 — loops answer each other again

Pre-release
Pre-release

Choose a tag to compare

@scgopi scgopi released this 07 Sep 01:12
· 246 commits to main since this release

This is why loops appeared to go quiet and stop answering each other. Two fixes, from opposite ends of the same failure, that together restore loop-to-loop mail.

Follow-ups were duplicated and lost (#309)

drainPendingFollowUps awaited the actor once per item. Two drains could interleave over the same snapshot, and writing pendingFollowUps = remaining at the end made the second one a lost update.

That did not merely duplicate mail — it lost it. Review measured the old behaviour delivering 12 times for 4 messages; against this change, exactly 4.

The drain now takes and clears in a single actor step, folds retries in front, and refuses to re-enter.

Duplicates and loss are fixed. Ordering is improved but not yet correct, so issue #304 stays open: a turn that ends mid-drain can still reorder deliveries, and it gets there with a single drain, which is precisely the case the in-flight guard cannot see.

A loop's own idle notification knocked it out of the state that receives mail (#310, closes #306)

Claude Code fires an idle_prompt notification roughly 60 seconds after a turn ends. The hook mapped every notification to awaitingInput — but follow-ups are delivered only while presence is idle.

So a loop would settle to idle, wait, and then its own idle notification would flip it out of the one state in which mail is delivered. Measured at 60.0 s and 60.1 s on two loops, with 0 of 18 watched posts delivered.

The practical effect: mail watch and --follow-up were silently dead for most Claude loops, most of the time. Not slow — dead, with no error to show for it.

The notification hook now reads what the notification actually means. Where no reporter is present it falls back to the old behaviour, so nothing regresses.

The sidebar was over-reporting too

The same audit found every NEEDS YOU surface treated a loop idle for over a minute as needing a human. So the sidebar was calling for you when nothing was waiting on you.

Known, and deliberately not fixed here (#311)

A follow-up staged later can still jump the queue when cached presence disagrees with a live read, and that presence read has no deadline. Both are pre-existing and neither is made worse by these two fixes — the reviewer checked specifically. They are filed as #311 rather than held against this build.


Verified on the merged tree: 1663 tests · 175 suites · 0 failures · swiftlint 0 errors · swift-format clean. FollowUpDrainTests and FollowUpMessageTests each observed executing. Bundle identity verified dev.graphcode.app in both the Info.plist and the code signature. #309 carried an independent review that wrote five of its own tests and ran them against both heads.