Fix race conditions in state persistence by reading fresh session before writing

Batch-clearing stale flags in list and blindly writing back the session
in review could clobbер concurrent changes. Use per-session get/set
instead of whole-state load/save, and re-read before clearing in_review.
This commit is contained in:
Chris Wanstrath 2026-03-19 11:24:18 -07:00
parent d10adac712
commit e8e5b850a0
2 changed files with 13 additions and 9 deletions

View File

@ -61,13 +61,13 @@ export async function action(opts: { json?: boolean }) {
)
const statuses = Object.fromEntries(statusEntries)
// Batch-clear stale in_review flags in a single write
if (staleReviewBranches.length > 0) {
const freshState = await state.load(root)
for (const branch of staleReviewBranches) {
if (freshState.sessions[branch]) freshState.sessions[branch].in_review = false
// Clear stale in_review flags via setSession to avoid clobbering concurrent writes
for (const branch of staleReviewBranches) {
const fresh = await state.getSession(root, branch)
if (fresh) {
fresh.in_review = false
await state.setSession(root, fresh).catch(() => {})
}
await state.save(root, freshState).catch(() => {})
}
if (opts.json) {

View File

@ -69,7 +69,7 @@ Your thoughts, in brief.
if (extra) prompt += "\n\n" + extra
session.in_review = true
await state.setSession(root, session).catch(() => {})
await state.setSession(root, session)
try {
if (opts.print) {
@ -82,8 +82,12 @@ Your thoughts, in brief.
}
} finally {
spin.stop()
session.in_review = false
await state.setSession(root, session).catch(() => {})
// Load fresh session to avoid clobbering changes made during the review
const fresh = await state.getSession(root, session.branch)
if (fresh) {
fresh.in_review = false
await state.setSession(root, fresh).catch(() => {})
}
if (!opts.print) await saveChanges(session.worktree, session.branch).catch(() => {})
}
}