Multi-agent audit + aggressive cleanup across server/web/coder/booterm, delivered behind a DEFER discipline so none of the in-flight files were touched. Removes dead code/deps/columns, dedups server + coder helpers, and splits the oversized modules (tools.ts, opencode-server.ts, sentinel-summaries, turn.ts, TerminalPane.tsx) behind stable contracts. Adds 78 parity/unit tests (server 587, coder 323); fixes two latent bugs (ChatPane queue keys, FileViewerOverlay blank-line parity). Intended tag: v2.7.12-audit-cleanup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
46 lines
1.8 KiB
TypeScript
46 lines
1.8 KiB
TypeScript
/**
|
|
* Session-delete work-loss guard (coder side).
|
|
*
|
|
* Session delete itself lives in apps/server (Docker), which CANNOT see the
|
|
* host worktree dirs (/tmp/booworktrees) or run git on them. Only BooCoder
|
|
* (host systemd) can. So the server's DELETE route calls these endpoints
|
|
* pre-delete to learn whether a session's worktree holds work at risk, and to
|
|
* stash it. The server owns the gate; coder owns the git truth.
|
|
*/
|
|
import type { FastifyInstance } from 'fastify';
|
|
import type { Sql } from '../db.js';
|
|
import { checkWorktreeWorkAtRisk, stashWorktree } from '../services/worktree-risk.js';
|
|
|
|
export function registerWorktreeSafetyRoutes(app: FastifyInstance, sql: Sql): void {
|
|
// GET risk for a session's worktree(s). One row per session today (PK on
|
|
// session_id); the loop already handles the Phase-1.5 multi-worktree case.
|
|
app.get<{ Params: { sessionId: string } }>(
|
|
'/api/sessions/:sessionId/worktree-risk',
|
|
async (req) => {
|
|
const rows = await sql<{ worktree_path: string }[]>`
|
|
SELECT path AS worktree_path FROM worktrees WHERE session_id = ${req.params.sessionId}
|
|
`;
|
|
const reports = [];
|
|
for (const row of rows) {
|
|
reports.push(await checkWorktreeWorkAtRisk(row.worktree_path));
|
|
}
|
|
return { reports };
|
|
},
|
|
);
|
|
|
|
// Stash a session's worktree(s) — clears the dirty risk; recoverable.
|
|
app.post<{ Params: { sessionId: string } }>(
|
|
'/api/sessions/:sessionId/worktree-stash',
|
|
async (req) => {
|
|
const rows = await sql<{ worktree_path: string }[]>`
|
|
SELECT path AS worktree_path FROM worktrees WHERE session_id = ${req.params.sessionId}
|
|
`;
|
|
const results = [];
|
|
for (const row of rows) {
|
|
results.push({ worktreePath: row.worktree_path, ...(await stashWorktree(row.worktree_path)) });
|
|
}
|
|
return { results };
|
|
},
|
|
);
|
|
}
|