Batch stale review-flag writes and fix review cleanup ordering
Move in_review flag set before try block so it is always visible, and consolidate per-session state writes into a single batch to avoid repeated disk I/O during list. Also guard against missing status entries with fallback defaults. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3ba550d80a
commit
a682539db3
|
|
@ -33,25 +33,23 @@ export async function action(opts: { json?: boolean }) {
|
|||
if (sessions.length === 0) {
|
||||
if (opts.json) {
|
||||
console.log("[]")
|
||||
return
|
||||
}
|
||||
console.log("◆ No active sessions.")
|
||||
if ((await vm.status()) !== "running") {
|
||||
console.log(`\n${red}VM is not running.${reset}`)
|
||||
} else {
|
||||
console.log("◆ No active sessions.")
|
||||
if ((await vm.status()) !== "running") {
|
||||
console.log(`\n${red}VM is not running.${reset}`)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Determine status for each session in parallel
|
||||
const staleReviewSessions: state.Session[] = []
|
||||
const statusEntries = await Promise.all(
|
||||
sessions.map(async (s): Promise<[string, string]> => {
|
||||
const active = await vm.isClaudeActive(s.worktree, s.branch)
|
||||
if (active && s.in_review) return [s.branch, "review"]
|
||||
// Self-heal: clear stale in_review flag if Claude is not active
|
||||
if (!active && s.in_review) {
|
||||
s.in_review = false
|
||||
await state.setSession(root, s).catch(() => {})
|
||||
}
|
||||
// Collect stale in_review flags for batch self-heal below
|
||||
if (!active && s.in_review) staleReviewSessions.push(s)
|
||||
if (active) return [s.branch, "active"]
|
||||
const dirty = await git.isDirty(s.worktree)
|
||||
if (dirty) return [s.branch, "dirty"]
|
||||
|
|
@ -61,6 +59,18 @@ export async function action(opts: { json?: boolean }) {
|
|||
)
|
||||
const statuses = Object.fromEntries(statusEntries)
|
||||
|
||||
// Batch self-heal stale in_review flags with a single state write
|
||||
if (staleReviewSessions.length > 0 && !opts.json) {
|
||||
const current = await state.load(root).catch(() => null)
|
||||
if (current) {
|
||||
for (const s of staleReviewSessions) {
|
||||
s.in_review = false
|
||||
if (current.sessions[s.branch]) current.sessions[s.branch].in_review = false
|
||||
}
|
||||
await state.save(root, current).catch(() => {})
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.json) {
|
||||
const withStatus = sessions.map(s => ({ ...s, status: statuses[s.branch] }))
|
||||
console.log(JSON.stringify(withStatus, null, 2))
|
||||
|
|
@ -82,8 +92,8 @@ export async function action(opts: { json?: boolean }) {
|
|||
|
||||
for (const s of sessions) {
|
||||
const prompt = (s.prompt ?? "").split("\n")[0]
|
||||
const status = statuses[s.branch]
|
||||
const { icon, color: bc } = styles[status]
|
||||
const status = statuses[s.branch] ?? "idle"
|
||||
const { icon, color: bc } = styles[status] ?? styles.idle
|
||||
const maxPrompt = cols - prefixWidth
|
||||
const truncated = maxPrompt > 3 && prompt.length > maxPrompt ? prompt.slice(0, maxPrompt - 3) + "..." : prompt
|
||||
console.log(`${icon} ${bc}${s.branch.padEnd(branchWidth)}${reset} ${dim}${truncated}${reset}`)
|
||||
|
|
|
|||
|
|
@ -68,11 +68,10 @@ Your thoughts, in brief.
|
|||
`
|
||||
if (extra) prompt += "\n\n" + extra
|
||||
|
||||
try {
|
||||
// Mark session as in review inside try so finally always clears it
|
||||
session.in_review = true
|
||||
await state.setSession(root, session)
|
||||
session.in_review = true
|
||||
await state.setSession(root, session)
|
||||
|
||||
try {
|
||||
if (opts.print) {
|
||||
spin.text = "Running review…"
|
||||
const result = await vm.claude(session.worktree, { print: prompt })
|
||||
|
|
@ -82,11 +81,9 @@ Your thoughts, in brief.
|
|||
spin.succeed("Session ready")
|
||||
await vm.claude(session.worktree, { prompt })
|
||||
}
|
||||
|
||||
await saveChanges(session.worktree, session.branch)
|
||||
} finally {
|
||||
// Clear review state — use .catch() per error handling conventions
|
||||
// so a disk error here doesn't mask the original exception
|
||||
// Always attempt save and clear review state
|
||||
await saveChanges(session.worktree, session.branch).catch(() => {})
|
||||
session.in_review = false
|
||||
await state.setSession(root, session).catch(() => {})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user