Repository navigation
fix(app): one replan moves the plan rev once across sessions - #1844
Merged
Merged
Conversation
appPlans.Rev read the planner's plan before it took revMu. A session that read the old plan could take the lock after another session had counted the new one, count the old plan again, and leave the next read to count the new plan a third time. The plan is now read under revMu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Review note: two replans between two reads move it once in total, so "by one" per replan was not true. Co-Authored-By: Claude Opus 5.5 <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.
Found by the review of #1841 on 25 October 2026 and left out of that PR.
Problem
appPlans.Rev(go/cmd/ftw/app_link.go) gives the plan a number that moves when the planner replans, so the app can tell a new plan from the same one sent again. Every app session on the box shares oneappPlans. With two sessions, for example a phone and a watch, one replan could move the number more than once.Cause
Revread the planner's latest plan before it tookrevMu. A slow session could read the old plan, then wait for the lock while another session read the new plan and counted it. When the slow session got the lock, its old plan's timestamp differed from the one just stored, so it counted again and stored the old timestamp. The next read then counted the new plan a third time. One replan moved the number from 1 to 4. #1841 makes each message re-read until its plan is stable, so the cost is the jump and extra pushes, not a mixed plan.Fix
Revreads the plan underrevMu. Reads are then counted in the order they happen, and the planner's latest plan only moves forward, so each replan moves the number once. A plan copy that only adds the shadow result keeps itsGeneratedAtMsand still moves nothing.The lock order is
revMu, then the planner's read lock. Nothing that holds the planner's lock callsRev.Evidence
TestPlanRevMovesOncePerReplanAcrossSessionsholdsrevMu, lets a session startRevagainst the old plan, installs a new plan, and counts it as another session'sRevwould under the lock. On master, 10 of 10 runs:On this branch it passes. Its 50 ms wait cannot make it fail here: the session reads the plan only once it holds the lock. On master, a session slower than 50 ms to reach the lock would make it pass by mistake.
go test -race -count=2 -run 'TestPlanRev|Plan|AppLink' ./cmd/ftw/passes.go vet ./...passes.go test ./internal/... ./cmd/ftw/...passes.Review
An independent review (Sonnet) found no bug. It checked every write to the planner's latest plan: the shadow copy keeps
GeneratedAtMs, the solve andInstallPlanpublish fresh plans, andRestoreDiagnosticruns before the app link starts. It traced the lock orderplanMu,revMu, then the planner's read lock, and found no path the other way: plan-change hooks run after the planner unlocks, andPlanFeedpushes on its own goroutine. With the fix reverted, the test failed 5 of 5 runs with the message above.Its notes: the changeset said a replan moves the number "by one", but two replans between two reads move it once in total; the second commit says "at most once". It also noted that the 50 ms wait only matters on master, and that a stress test with many sessions and plans would guard a future regression more strongly. I kept the single deterministic test.
Patch changeset.
🤖 Generated with Claude Code