fix: auto-commit before branch switch and migrate legacy flat sessions

ensureSliceBranch() now auto-commits dirty files before git checkout,
preventing "would be overwritten" errors when doctor/STATE.md rebuild
leaves uncommitted changes between slice dispatches. (closes #63)

On startup, migrate any .jsonl session files from the flat
~/.gsd/sessions/ directory into the per-cwd subdirectory so /resume
can find sessions created before per-directory scoping was added.
(closes #64)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lex Christopherson 2026-03-11 17:07:54 -06:00
parent 10c7189480
commit 5eb02e9a1c
2 changed files with 36 additions and 1 deletions

View file

@ -8,7 +8,7 @@ import {
InteractiveMode,
runPrintMode,
} from '@mariozechner/pi-coding-agent'
import { readFileSync } from 'node:fs'
import { existsSync, readdirSync, renameSync, readFileSync } from 'node:fs'
import { join } from 'node:path'
import { agentDir, sessionsDir, authFilePath } from './app-paths.js'
import { initResources } from './resource-loader.js'
@ -180,6 +180,30 @@ if (isPrintMode) {
const cwd = process.cwd()
const safePath = `--${cwd.replace(/^[/\\]/, '').replace(/[/\\:]/g, '-')}--`
const projectSessionsDir = join(sessionsDir, safePath)
// Migrate legacy flat sessions: before per-directory scoping, all .jsonl session
// files lived directly in ~/.gsd/sessions/. Move them into the correct per-cwd
// subdirectory so /resume can find them.
if (existsSync(sessionsDir)) {
try {
const entries = readdirSync(sessionsDir)
const flatJsonl = entries.filter(f => f.endsWith('.jsonl'))
if (flatJsonl.length > 0) {
const { mkdirSync } = await import('node:fs')
mkdirSync(projectSessionsDir, { recursive: true })
for (const file of flatJsonl) {
const src = join(sessionsDir, file)
const dst = join(projectSessionsDir, file)
if (!existsSync(dst)) {
renameSync(src, dst)
}
}
}
} catch {
// Non-fatal — don't block startup if migration fails
}
}
const sessionManager = SessionManager.create(cwd, projectSessionsDir)
initResources(agentDir)

View file

@ -86,6 +86,17 @@ export function ensureSliceBranch(basePath: string, milestoneId: string, sliceId
created = true;
}
// Auto-commit dirty files before checkout to prevent "would be overwritten" errors.
// This handles cases where doctor, STATE.md rebuild, or agent work left uncommitted changes.
const status = runGit(basePath, ["status", "--short"]);
if (status.trim()) {
runGit(basePath, ["add", "-A"]);
const staged = runGit(basePath, ["diff", "--cached", "--stat"]);
if (staged.trim()) {
runGit(basePath, ["commit", "-m", `"chore: auto-commit before switching to ${branch}"`]);
}
}
runGit(basePath, ["checkout", branch]);
return created;
}