Fix list command to skip empty JSON output and batch stale-review cleanup

Collapse redundant empty-session branch so --json falls through to the
normal serialization path instead of printing "[]" separately. Replace
per-branch load/save loop with a single state cycle to avoid racing
concurrent writes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Wanstrath 2026-03-19 11:29:22 -07:00
parent e8e5b850a0
commit 2da22b940a

View File

@ -30,14 +30,10 @@ export async function action(opts: { json?: boolean }) {
} catch {} } catch {}
} }
if (sessions.length === 0) { if (sessions.length === 0 && !opts.json) {
if (opts.json) { console.log("◆ No active sessions.")
console.log("[]") if ((await vm.status()) !== "running") {
} else { console.log(`\n${red}VM is not running.${reset}`)
console.log("◆ No active sessions.")
if ((await vm.status()) !== "running") {
console.log(`\n${red}VM is not running.${reset}`)
}
} }
return return
} }
@ -61,13 +57,13 @@ export async function action(opts: { json?: boolean }) {
) )
const statuses = Object.fromEntries(statusEntries) const statuses = Object.fromEntries(statusEntries)
// Clear stale in_review flags via setSession to avoid clobbering concurrent writes // Clear stale in_review flags in a single load/save cycle
for (const branch of staleReviewBranches) { if (staleReviewBranches.length > 0) {
const fresh = await state.getSession(root, branch) const fresh = await state.load(root)
if (fresh) { for (const branch of staleReviewBranches) {
fresh.in_review = false if (fresh.sessions[branch]) fresh.sessions[branch].in_review = false
await state.setSession(root, fresh).catch(() => {})
} }
await state.save(root, fresh).catch(() => {})
} }
if (opts.json) { if (opts.json) {
@ -76,13 +72,13 @@ export async function action(opts: { json?: boolean }) {
return return
} }
const styles: Record<string, { icon: string; color: string }> = { const styleDefs: [string, string, string][] = [
idle: { icon: `${dim}${reset}`, color: dim }, ["idle", dim, "◯"], ["active", cyan, "◎"], ["dirty", yellow, "◐"],
active: { icon: `${cyan}${reset}`, color: cyan }, ["saved", green, "●"], ["review", magenta, "⦿"],
dirty: { icon: `${yellow}${reset}`, color: yellow }, ]
saved: { icon: `${green}${reset}`, color: green }, const styles = Object.fromEntries(
review: { icon: `${magenta}⦿${reset}`, color: magenta }, styleDefs.map(([k, c, ch]) => [k, { icon: `${c}${ch}${reset}`, color: c }])
} )
const branchWidth = Math.max(6, ...sessions.map((s) => s.branch.length)) const branchWidth = Math.max(6, ...sessions.map((s) => s.branch.length))
const cols = process.stdout.columns || 80 const cols = process.stdout.columns || 80
const prefixWidth = branchWidth + 4 const prefixWidth = branchWidth + 4