fix(AlgorithmNudge): latch sweep-delegation to once per inline stretch - #2123
Open
pai-scaffolde wants to merge 1 commit into
Open
pai-scaffolde wants to merge 1 commit into
pai-scaffolde wants to merge 1 commit into
Conversation
Through a long verification sweep the sweep-delegation row fired again every 20 tool calls once the 5-minute cooldown lapsed — three times in 60 inline calls in simulation. The cooldown was never the right bound: it is a clock, and the thing the row asks about is a stretch. Every re-ask after the first is about calls the model has just made and can still see, which is the same "state the model cannot observe" rule that retired the `principal` row. Latch the row instead: a new `sweepDelegationFired` flag is set when it fires and cleared only by an Agent dispatch, so each inline stretch is asked about exactly once and a genuinely new stretch is never silenced by a clock that happens to still be running. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Reproduced on a fresh LifeOS 7.40.4 install (macOS, Claude Code in the Claude desktop app); the fix was applied to that install and run there before filing.
Observed
During a long verification sweep — Bash/Read/Grep, no dispatches — the
sweep-delegationrow kept coming back: once at 20 inline calls, then again every 20 calls once the 5-minute cooldown lapsed. Simulated against the unpatched hook, 60 inline calls produce 3 fires of the same question:Root cause
AlgorithmNudge.hook.ts:822-823bounds the row withcooled(state, 'sweep-delegation', now)and a counter reset. A cooldown is a clock; what the row asks about is a stretch. The first ask is legitimate — "20+ consecutive inline calls" is an aggregate the model never counted. Every later ask in the same stretch is about calls the model has just made and can still see in its own context, which is the bound this file already states for itself and the reason theprincipalrow was cut on 2026-07-30: a row may only ask about state the model CANNOT observe. The clock also gets it wrong in the other direction — a dispatch followed by 20 fresh inline calls inside five minutes is exactly when the question is live, and the cooldown silences it.Fix
Latch instead of cool. A
sweepDelegationFiredflag is set when the row fires and cleared only by an Agent dispatch, alongside the existingbuildCallsSinceDispatch/workCallsSinceDispatchresets. One question per inline stretch, and a new stretch always re-arms it.cooled()is untouched and still bounds every other row.How tested
Simulation harness:
run(input)called directly withPostToolUsepayloads under a tempHOME(the hook derives its state dir fromhomedir(), so state lands in the temp tree, not the install). 60 Bash calls, then oneAgentdispatch, then 60 more; every 20 calls the recorded nudge timestamps in the state file are rewound 6 minutes, which is the 5-minute cooldown elapsing during a real sweep. Counted lines containing "consecutive inline tool calls, zero dispatches":Transpiles (
bun build --target=bun --no-bundle LifeOS/install/hooks/AlgorithmNudge.hook.ts, exit 0). Running on the install since 2026-09-14.Independent of #2083 (late-ISA re-arm): different state field, different block; both apply cleanly in either order. Verified by three-way applying each patch on top of the other — the only conflict is the
@versionline (3.2.3 here vs 3.3.0 there), identical in both directions; every other hunk lands, the merged file transpiles, and the simulation above still reports 1 fire per stretch on it.Repro on a clean tree: check out
upstream/main, pointHOMEat a temp dir, and driverun()with 60PostToolUsepayloads for a non-dispatch tool on onesession_id, rewindinglastNudgeAtby 6 minutes every 20 calls; the row fires 3 times before this change and once after.🤖 Generated with Claude Code