MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / recoverOrphanedSandbox

Function recoverOrphanedSandbox

src/agent/git-sandbox.ts:429–473  ·  view source on GitHub ↗
(
  repoRoot: string,
  signal?: AbortSignal,
)

Source from the content-addressed store, hash-verified

427 * Not wired into the loop here (out of scope); exported for the caller to use.
428 */
429export async function recoverOrphanedSandbox(
430 repoRoot: string,
431 signal?: AbortSignal,
432): Promise<OrphanedSandbox | null> {
433 try {
434 if (!(await isGitRepo(repoRoot, signal))) return null;
435
436 // 1. The persisted recovery record, if any.
437 let record: SandboxRecoveryRecord | null = null;
438 try {
439 const raw = await fs.readFile(recoveryRecordPath(repoRoot), 'utf-8');
440 const parsed = JSON.parse(raw);
441 if (parsed && parsed.version === 1 && typeof parsed.branch === 'string') {
442 record = parsed as SandboxRecoveryRecord;
443 }
444 } catch {
445 /* no record (clean shutdown) or unreadable — fall through to git scan */
446 }
447
448 // 2. Leftover sandbox branches.
449 const br = await git(['branch', '--list', 'qodex/sandbox-*', '--format=%(refname:short)'], { cwd: repoRoot, signal });
450 const branches = br.exitCode === 0
451 ? br.stdout.split('\n').map((s) => s.trim()).filter(Boolean)
452 : [];
453
454 // 3. Leftover WIP stashes from a killed sandbox.
455 const sl = await git(['stash', 'list', '--format=%gd %gs'], { cwd: repoRoot, signal });
456 const stashes = sl.exitCode === 0
457 ? sl.stdout.split('\n')
458 .map((l) => l.trim())
459 .filter((l) => l.includes('qodex-sandbox-wip-'))
460 .map((l) => {
461 const sp = l.split(/\s+/);
462 return { ref: sp[0] ?? '', message: l.slice((sp[0] ?? '').length).trim() };
463 })
464 .filter((s) => s.ref)
465 : [];
466
467 if (!record && branches.length === 0 && stashes.length === 0) return null;
468 return { record, branches, stashes };
469 } catch (e: any) {
470 logger.debug('recoverOrphanedSandbox failed', { err: e?.message });
471 return null;
472 }
473}

Callers

nothing calls this directly

Calls 4

isGitRepoFunction · 0.85
recoveryRecordPathFunction · 0.85
debugMethod · 0.80
gitFunction · 0.50

Tested by

no test coverage detected