nightralph 0.0.38 → 0.0.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/meta.json CHANGED
@@ -27,7 +27,7 @@
27
27
  "format": "esm"
28
28
  },
29
29
  "src/worktree.ts": {
30
- "bytes": 5108,
30
+ "bytes": 5906,
31
31
  "imports": [
32
32
  {
33
33
  "path": "node:child_process",
@@ -142,7 +142,7 @@
142
142
  "format": "esm"
143
143
  },
144
144
  "src/orchestrator.ts": {
145
- "bytes": 68622,
145
+ "bytes": 68690,
146
146
  "imports": [
147
147
  {
148
148
  "path": "node:child_process",
@@ -239,7 +239,7 @@
239
239
  "format": "esm"
240
240
  },
241
241
  "src/index.ts": {
242
- "bytes": 10105,
242
+ "bytes": 10174,
243
243
  "imports": [
244
244
  {
245
245
  "path": "node:fs",
@@ -310,7 +310,7 @@
310
310
  "imports": [],
311
311
  "exports": [],
312
312
  "inputs": {},
313
- "bytes": 180825
313
+ "bytes": 182428
314
314
  },
315
315
  "dist/index.js": {
316
316
  "imports": [
@@ -472,16 +472,16 @@
472
472
  "entryPoint": "src/index.ts",
473
473
  "inputs": {
474
474
  "src/index.ts": {
475
- "bytesInOutput": 6800
475
+ "bytesInOutput": 6856
476
476
  },
477
477
  "src/setup.ts": {
478
478
  "bytesInOutput": 4816
479
479
  },
480
480
  "src/orchestrator.ts": {
481
- "bytesInOutput": 47516
481
+ "bytesInOutput": 47579
482
482
  },
483
483
  "src/worktree.ts": {
484
- "bytesInOutput": 3788
484
+ "bytesInOutput": 4523
485
485
  },
486
486
  "src/progress.ts": {
487
487
  "bytesInOutput": 4419
@@ -493,13 +493,13 @@
493
493
  "bytesInOutput": 7931
494
494
  },
495
495
  "src/testcmd.ts": {
496
- "bytesInOutput": 1911
496
+ "bytesInOutput": 1914
497
497
  },
498
498
  "src/resolve.ts": {
499
499
  "bytesInOutput": 1937
500
500
  }
501
501
  },
502
- "bytes": 84559
502
+ "bytes": 85416
503
503
  }
504
504
  }
505
505
  }
@@ -20,6 +20,7 @@ import {
20
20
  getCurrentBranch,
21
21
  createWorktree,
22
22
  removeWorktree,
23
+ buildBranchName,
23
24
  hasNewCommits,
24
25
  isDirty,
25
26
  commitDirty
@@ -863,7 +864,11 @@ function dryRunIsolated(opts) {
863
864
  );
864
865
  for (const t of ready) {
865
866
  const num = String(t.num).padStart(2, "0");
866
- const branchName = `${opts.repoName}/${num}-${t.slug}`;
867
+ const branchName = buildBranchName(
868
+ opts.repoRoot,
869
+ opts.repoName,
870
+ t
871
+ );
867
872
  const worktreePath = `../${opts.repoName}.${num}-${t.slug}`;
868
873
  console.log(` worktree: ${worktreePath}`);
869
874
  console.log(` branch: ${branchName}`);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/orchestrator.ts"],
4
- "sourcesContent": ["import { spawn, execFile } from 'node:child_process'\nimport {\n createWriteStream,\n mkdirSync,\n readFileSync,\n writeFileSync,\n unlinkSync,\n readdirSync,\n} from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join, dirname, basename } from 'node:path'\nimport { createInterface } from 'node:readline'\nimport { promisify } from 'node:util'\n\nconst execFileAsync = promisify(execFile)\nimport {\n getRepoRoot,\n getRepoName,\n getCurrentBranch,\n createWorktree,\n removeWorktree,\n hasNewCommits,\n isDirty,\n commitDirty,\n} from './worktree.js'\nimport {\n generateProgress,\n readProgress,\n mergeProgress,\n writeProgress,\n commitProgress,\n checkTicket,\n type ProgressData,\n} from './progress.js'\nimport {\n mergeBranch,\n mergeWave,\n updateWorktreeFromBase,\n type MergeConflictStrategy,\n} from './merge.js'\nimport {\n createDisplay,\n type RunProgress,\n type Display,\n} from './display.js'\nimport { runTestCmd } from './testcmd.js'\n\nexport type Ticket = {\n num:number\n slug:string\n filename:string\n filepath:string\n body:string\n status:string\n blockers:number[]\n}\n\nexport function formatErrorMessage (error:unknown):string {\n return error instanceof Error ?\n error.message :\n String(error)\n}\n\n// Removes a ticket's worktree, logging and swallowing any\n// failure instead of letting it interrupt the wave.\nasync function removeWorktreeQuietly (\n worktreePath:string,\n d:Display\n):Promise<void> {\n try {\n await removeWorktree(worktreePath, { force:true })\n } catch (err) {\n d.log(\n ' Failed to remove worktree ' +\n `${worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n}\n\nasync function commitTicketFiles (\n repoRoot:string,\n tickets:Ticket[],\n d:Display\n):Promise<void> {\n const paths = tickets.map(t => t.filepath)\n if (paths.length === 0) return\n try {\n await execFileAsync(\n 'git',\n ['add', '--force', ...paths],\n { cwd:repoRoot }\n )\n try {\n await execFileAsync(\n 'git',\n ['diff', '--cached', '--quiet',\n '--', ...paths],\n { cwd:repoRoot }\n )\n return\n } catch {\n // staged files differ from HEAD\n }\n await execFileAsync(\n 'git',\n ['commit', '-m',\n 'nightralph: update ticket checklists',\n '--', ...paths],\n { cwd:repoRoot }\n )\n } catch (err) {\n d.log(\n ' Failed to commit ticket updates: ' +\n formatErrorMessage(err)\n )\n }\n}\n\nexport const TICKET_RE = /^(\\d+)-(.+)\\.md$/\n\nexport function parseTicketFilename (\n filename:string\n):{ num:number; slug:string }|null {\n const m = filename.match(TICKET_RE)\n if (!m) return null\n return { num:Number(m[1]), slug:m[2] }\n}\n\nexport function parseStatus (body:string):string {\n const m = body.match(/\\*\\*Status:\\*\\*\\s*(.+)/i)\n return m ? m[1].trim().toLowerCase() : ''\n}\n\nexport function parseBlockers (body:string):number[] {\n const m = body.match(/\\*\\*Blocked by:\\*\\*\\s*(.+)/i)\n if (!m) return []\n const text = m[1]\n if (/none/i.test(text)) return []\n const nums:number[] = []\n const re = /(\\d+)/g\n let match\n while ((match = re.exec(text))) {\n nums.push(Number(match[1]))\n }\n return nums\n}\n\nexport function scanTickets (dir:string):Ticket[] {\n const files = readdirSync(dir)\n .filter(f => TICKET_RE.test(f))\n .sort((a, b) => a.localeCompare(\n b,\n undefined,\n { numeric:true, sensitivity:'base' }\n ))\n\n return files.map(filename => {\n const parsed = parseTicketFilename(filename)!\n const filepath = join(dir, filename)\n const body = readFileSync(filepath, 'utf8')\n return {\n num:parsed.num,\n slug:parsed.slug,\n filename,\n filepath,\n body,\n status:parseStatus(body),\n blockers:parseBlockers(body),\n }\n })\n}\n\nexport function findReadyTickets (\n tickets:ReadonlyArray<Ticket>\n):Ticket[] {\n const doneNums = new Set(\n tickets\n .filter(t => t.status === 'done')\n .map(t => t.num)\n )\n return tickets.filter(t => {\n if (t.status !== 'ready-for-agent') return false\n return t.blockers.every(b => doneNums.has(b))\n })\n}\n\n// Matches an agent-reported completed item. Agents echo items\n// as markdown checklist lines (`- [x] item`) as often as bare\n// `[x] item` lines, so the bullet prefix is optional.\nexport const COMPLETED_RE = /^\\s*[-*+]?\\s*\\[x\\]\\s+(.+)$/i\nexport const TOOL_USE_RE = /^\\[[\\w.]+\\]/\n\n// Matches one checklist line in a ticket file: optional indent\n// and bullet, the `[ ]` / `[x]` box, and the item text.\nconst CHECKBOX_RE = /^(\\s*[-*+] )\\[( |x|X)\\]( .*)$/\n\n// The unchecked-box variant, used for the actual flip to [x].\nconst UNCHECKED_BOX_RE = /^(\\s*[-*+] )\\[( )\\]/\n\n// Normalizes checklist text for matching: agents echo an item as\n// one logical line while ticket files wrap items across lines,\n// so compare with whitespace runs collapsed, case-insensitively.\nfunction normalizeItemText (s:string):string {\n return s.replace(/\\s+/g, ' ').trim().toLowerCase()\n}\n\n// Drops an optional markdown bullet/checkbox prefix so items match\n// whether or not the caller already stripped the `[x]` marker.\nfunction stripCheckboxPrefix (s:string):string {\n return s.replace(/^\\s*[-*+]?\\s*\\[[ xX]\\]\\s+/, '')\n}\n\ntype ParsedItem = { start:number; text:string }\n\n// Parses the checklist items out of a ticket body. An item is its\n// checkbox line plus any immediately following indented lines\n// (wrapped text), so items written across multiple lines can be\n// matched by their full text. Code fences are skipped.\nfunction parseChecklistItems (\n lines:string[]\n):ParsedItem[] {\n const items:ParsedItem[] = []\n let inFence = false\n let i = 0\n while (i < lines.length) {\n if (/^\\s*```/.test(lines[i])) {\n inFence = !inFence\n i++\n continue\n }\n if (inFence) {\n i++\n continue\n }\n const m = lines[i].match(CHECKBOX_RE)\n if (!m) {\n i++\n continue\n }\n const start = i\n let text = m[3]\n i++\n while (\n i < lines.length &&\n /^\\s+\\S/.test(lines[i]) &&\n !CHECKBOX_RE.test(lines[i])\n ) {\n text += ' ' + lines[i].trim()\n i++\n }\n items.push({\n start,\n text:normalizeItemText(text),\n })\n }\n return items\n}\n\nexport function checkItems (\n ticket:Ticket,\n completedItems:string[]\n):void {\n if (completedItems.length === 0) return\n // Read from disk: a merge or respawn may have changed the\n // file since the ticket was scanned, and writing the stale\n // body would drop those edits.\n let body:string\n try {\n body = readFileSync(ticket.filepath, 'utf8')\n } catch {\n body = ticket.body\n }\n const wanted = new Set(\n completedItems.map(item =>\n normalizeItemText(stripCheckboxPrefix(item))\n )\n )\n const lines = body.split('\\n')\n let changed = false\n for (const item of parseChecklistItems(lines)) {\n if (!wanted.has(item.text)) continue\n const flipped = lines[item.start].replace(\n UNCHECKED_BOX_RE,\n '$1[x]'\n )\n if (flipped !== lines[item.start]) {\n lines[item.start] = flipped\n changed = true\n }\n }\n if (!changed) return\n body = lines.join('\\n')\n writeFileSync(ticket.filepath, body)\n ticket.body = body\n}\n\n// Checks off every remaining unchecked item in a ticket body,\n// ignoring fenced code blocks.\nfunction checkAllItems (body:string):string {\n const lines = body.split('\\n')\n let inFence = false\n for (let i = 0; i < lines.length; i++) {\n if (/^\\s*```/.test(lines[i])) {\n inFence = !inFence\n continue\n }\n if (inFence) continue\n lines[i] = lines[i].replace(\n UNCHECKED_BOX_RE,\n '$1[x]'\n )\n }\n return lines.join('\\n')\n}\n\nexport function markDone (ticket:Ticket):void {\n // Re-read from disk: the merge may have brought the agent's\n // own edits to the ticket file into the repo, and writing\n // the body scanned at startup would drop them.\n let body:string\n try {\n body = readFileSync(ticket.filepath, 'utf8')\n } catch {\n body = ticket.body\n }\n // A done ticket's items are complete by definition, so check\n // off anything the agent did not report instead of leaving\n // the file claiming done with unchecked items.\n body = checkAllItems(body)\n const updated = body.replace(\n /\\*\\*Status:\\*\\*\\s*.+/i,\n '**Status:** done'\n )\n writeFileSync(ticket.filepath, updated)\n ticket.status = 'done'\n ticket.body = updated\n}\n\n// Drops one markdown section from a spec. Used to keep the\n// per-ticket prompt short: the User Stories list is useful\n// to humans and to to-tickets but not to an implementing agent.\nexport function stripSpecSection (\n specBody:string,\n heading:string\n):string {\n const out:string[] = []\n let skipping = false\n let skipLevel = 0\n let inFence = false\n\n for (const line of specBody.split('\\n')) {\n // Toggle fence state on lines starting with ``` (after\n // optional whitespace)\n if (/^\\s*```/.test(line)) {\n inFence = !inFence\n }\n\n // Only check for headings outside of code fences\n if (!inFence) {\n const m = /^(#{1,6})\\s+(.*?)\\s*$/.exec(line)\n if (m) {\n const level = m[1].length\n if (skipping && level <= skipLevel) {\n skipping = false\n }\n if (!skipping && m[2] === heading) {\n skipping = true\n skipLevel = level\n continue\n }\n }\n }\n if (!skipping) out.push(line)\n }\n\n return out.join('\\n')\n}\n\nexport function renderPrompt (\n specBody:string,\n ticket:Ticket,\n opts:{ testCmd:string }\n):string {\n return [\n '---- SPEC CONTEXT ----',\n specBody,\n '',\n '---- TICKET ----',\n ticket.filename,\n ticket.body,\n '',\n '---- AGENT INSTRUCTIONS ----',\n 'You are an autonomous coding agent. ' +\n 'Implement the ticket using /tdd.',\n '',\n 'Follow these rules:',\n '- Read the files directly relevant to the ' +\n 'ticket before writing code. Also read any ' +\n 'AGENTS.md in or above the directories you ' +\n 'will touch, plus CONTEXT.md and the ' +\n 'relevant docs/adr/ entries if they exist. ' +\n 'If they do not exist, proceed silently.',\n '- Work ONLY on this ticket. Do not fix ' +\n 'unrelated problems you notice.',\n '- Do NOT research external APIs or services ' +\n 'via web search. Use the spec and ticket ' +\n 'body as your sole reference for API shapes.',\n '- Use /tdd for every checklist item. For ' +\n 'each item, write a failing test at the ' +\n 'seams named in the spec\\'s Testing ' +\n 'Decisions section, then write only ' +\n 'enough code to make it pass, then ' +\n 'refactor.',\n '- While iterating, run only the tests ' +\n 'relevant to what you changed. Run ' +\n `\\`${opts.testCmd}\\` in full once, as the ` +\n 'final gate before your last commit. Do ' +\n 'not commit with failing tests. The ' +\n 'orchestrator runs the same command after ' +\n 'you exit and rejects the ticket if it ' +\n 'fails.',\n '- If the project has a lint script, run it ' +\n 'and fix what it reports.',\n '- INTEGRITY: never delete, skip, weaken, or ' +\n 'write tautological tests to force a green ' +\n 'result. Only report a checklist item done ' +\n 'when its real tests genuinely pass. If an ' +\n 'item cannot be completed honestly, leave ' +\n 'it unchecked and say what blocked you.',\n '- Do NOT read or modify files outside ' +\n 'your current directory (the worktree).',\n '- Do NOT run git push.',\n '- Commit after each checklist item, and make ' +\n 'sure everything is committed when finished.',\n '- After completing each checklist item in the ' +\n 'ticket, print a line: [x] <item text> ' +\n '(matching the checklist text exactly).',\n '- Before your final commit, record reusable ' +\n 'learnings in the nearest AGENTS.md (in or ' +\n 'above the directories you modified; ' +\n 'prefer that over the repo root). Good ' +\n 'additions: module conventions, gotchas, ' +\n 'files that must change together, how to ' +\n 'test that area, environment requirements. ' +\n 'Do NOT add ticket-specific details or ' +\n 'temporary debugging notes. Only write ' +\n 'when you have knowledge that would help ' +\n 'future work in that directory.',\n '',\n ].join('\\n')\n}\n\nexport function renderMergePrompt (\n specBody:string,\n ticket:Ticket\n):string {\n return [\n '---- SPEC CONTEXT ----',\n specBody,\n '',\n '---- TICKET ----',\n ticket.filename,\n ticket.body,\n '',\n '---- AGENT INSTRUCTIONS ----',\n 'You are an autonomous coding agent resolving ' +\n 'a merge conflict.',\n '',\n 'Another agent already implemented this ticket ' +\n 'on a feature branch. The branch was then ' +\n 'merged with the base branch, but conflicts ' +\n 'arose. The working tree may contain conflict ' +\n 'markers that need resolution.',\n '',\n 'Your task:',\n '1. Find and resolve all conflict markers ' +\n '(<<<<<<< / ======= / >>>>>>>).',\n '2. When AGENTS.md or other docs conflict, ' +\n 'keep both sides\\' additions rather than ' +\n 'picking one.',\n '3. Make sure the code compiles and tests pass.',\n '4. Commit the resolved files.',\n '',\n 'Do NOT re-implement the ticket from scratch.',\n 'Do NOT read or modify files outside your ' +\n 'current directory (the worktree).',\n 'Do NOT run git push.',\n ].join('\\n')\n}\n\nfunction listTickets (tickets:ReadonlyArray<Ticket>):void {\n console.log('\\nTickets:')\n for (const t of tickets) {\n const blockerStr = t.blockers.length > 0 ?\n `blocked by [${t.blockers.join(', ')}]` :\n 'no blockers'\n console.log(\n ` ${t.filename} ` +\n `(${t.status}) ${blockerStr}`\n )\n }\n}\n\nfunction * simulateWaves (\n tickets:ReadonlyArray<Ticket>\n):Generator<{ wave:number; ready:Array<Ticket> }> {\n const sim = new Map(\n tickets.map(t => [t.num, t.status])\n )\n let wave = 1\n while (true) {\n const doneNums = new Set(\n [...sim.entries()]\n .filter(([, s]) => s === 'done')\n .map(([n]) => n)\n )\n const ready = [...tickets].filter(t => {\n if (sim.get(t.num) !== 'ready-for-agent') {\n return false\n }\n return t.blockers.every(\n b => doneNums.has(b)\n )\n })\n if (ready.length === 0) break\n yield { wave, ready }\n for (const t of ready) {\n sim.set(t.num, 'done')\n }\n wave++\n }\n}\n\nfunction detectDeadlocks (\n tickets:ReadonlyArray<Ticket>\n):Array<Ticket> {\n const doneNums = new Set<number>()\n const ready = new Set<number>()\n\n for (const t of tickets) {\n if (t.status === 'ready-for-agent') {\n ready.add(t.num)\n } else if (t.status === 'done') {\n doneNums.add(t.num)\n }\n }\n\n let changed = true\n while (changed) {\n changed = false\n for (const num of ready) {\n const ticket = tickets.find(t =>\n t.num === num\n )!\n if (ticket.blockers.every(\n b => doneNums.has(b)\n )) {\n doneNums.add(num)\n ready.delete(num)\n changed = true\n }\n }\n }\n\n return [...ready].map(num =>\n tickets.find(t => t.num === num)!\n )\n}\n\nconst PROVIDER_ARGS:Record<string, string[]> = {\n claude:[\n '--print', '--verbose',\n '--output-format', 'stream-json',\n '--dangerously-skip-permissions',\n ],\n // codex removed --full-auto; this is the counterpart\n // of claude's --dangerously-skip-permissions, and the\n // workspace-write sandbox would block commits because\n // a worktree's .git link points outside the tree\n codex:['exec', '--dangerously-bypass-approvals-and-sandbox'],\n pi:[\n '-p', '--verbose',\n '--approve', '--no-session',\n '--mode', 'json',\n ],\n}\n\nexport function getProviderArgs (cmd:string):string[] {\n const name = basename(cmd)\n return PROVIDER_ARGS[name] ?? []\n}\n\n// Per-provider effort ladders.\nexport const EFFORT_LADDERS = {\n pi:['off', 'minimal', 'low', 'medium',\n 'high', 'xhigh', 'max'],\n claude:['low', 'medium', 'high',\n 'xhigh', 'max'],\n codex:['low', 'medium', 'high'],\n} as const\n\nexport type ProviderName =\n keyof typeof EFFORT_LADDERS\n\nexport type EffortLevel =\n typeof EFFORT_LADDERS[ProviderName][number]\n\nexport const ALL_EFFORT_LEVELS:EffortLevel[] = [\n 'off', 'minimal', 'low', 'medium',\n 'high', 'xhigh', 'max',\n]\n\n// Step up the effort ladder for a given provider.\n// Without a starting level, the first retry jumps to high.\n// Otherwise, step one rung up and stop at the provider's max.\nexport function escalateEffort (\n provider:ProviderName,\n level?:EffortLevel\n):EffortLevel {\n if (!level) return 'high'\n const ladder = EFFORT_LADDERS[provider]\n const i = (ladder as readonly string[])\n .indexOf(level)\n if (i === -1) return level\n return ladder[\n Math.min(i + 1, ladder.length - 1)\n ] as EffortLevel\n}\n\nexport function formatStreamLine (\n line:string\n):string|null {\n let obj:Record<string, unknown>\n try {\n obj = JSON.parse(line) as Record<string, unknown>\n } catch {\n return line\n }\n\n if (obj.type === 'assistant') {\n const msg = obj.message as\n Record<string, unknown>|undefined\n const content = msg?.content as\n Array<Record<string, unknown>>|undefined\n if (!content) return null\n for (const block of content) {\n if (block.type === 'text') {\n return String(block.text)\n }\n }\n return null\n }\n\n if (obj.type === 'result') {\n const sub = obj.subtype as string|undefined ?? 'done'\n const cost = obj.total_cost_usd as number|undefined\n const costStr = cost != null ?\n ` ($${cost.toFixed(2)})` :\n ''\n return `${sub}${costStr}`\n }\n\n if (obj.type === 'system') {\n const sub = obj.subtype as string|undefined\n if (sub === 'api_retry') {\n const error = obj.error as string|undefined\n return `retry: ${error ?? 'unknown'}`\n }\n }\n\n return null\n}\n\nexport type PiStreamFormatter = {\n process:(line:string) => string[]\n flush:() => string[]\n}\n\nexport function createPiStreamFormatter (\n):PiStreamFormatter {\n const calls = new Map<\n number, { name:string; buf:string }\n >()\n let textBuf = ''\n\n function drainLines ():string[] {\n const parts = textBuf.split('\\n')\n if (parts.length === 1) return []\n textBuf = parts[parts.length - 1]\n return parts.slice(0, -1)\n }\n\n function flushBuf ():string[] {\n if (textBuf.length === 0) return []\n const out = textBuf\n textBuf = ''\n return [out]\n }\n\n function process (line:string):string[] {\n let obj:Record<string, unknown>\n try {\n obj = JSON.parse(line) as\n Record<string, unknown>\n } catch {\n return [line]\n }\n\n const evt = obj.assistantMessageEvent as\n Record<string, unknown>|undefined\n if (!evt) return []\n\n const type = evt.type as string|undefined\n const ci = evt.contentIndex as\n number|undefined ?? -1\n\n if (type === 'text_delta') {\n const delta =\n (evt.delta as string|undefined) ?? ''\n textBuf += delta\n return drainLines()\n }\n\n if (type === 'toolcall_start') {\n const flushed = flushBuf()\n calls.set(ci, {\n name:(evt.toolName as\n string|undefined) ?? '?',\n buf:'',\n })\n return flushed\n }\n\n if (\n type === 'toolcall_delta' &&\n calls.has(ci)\n ) {\n calls.get(ci)!.buf +=\n (evt.delta as string|undefined) ?? ''\n return []\n }\n\n if (\n type === 'toolcall_end' &&\n calls.has(ci)\n ) {\n const call = calls.get(ci)!\n calls.delete(ci)\n let label = ''\n try {\n const args = JSON.parse(call.buf) as\n Record<string, unknown>\n label = String(\n args.command ??\n args.file_path ??\n args.query ?? ''\n ).split('\\n')[0].slice(0, 72)\n } catch {\n // unparseable tool args\n }\n return [`[${call.name}] ${label}`]\n }\n\n return []\n }\n\n return { process, flush:flushBuf }\n}\n\nfunction writePromptFile (prompt:string):string {\n const name = `nightralph-${Date.now()}-` +\n `${Math.random().toString(36).slice(2)}.md`\n const filePath = join(tmpdir(), name)\n writeFileSync(filePath, prompt)\n return filePath\n}\n\nfunction cleanupPromptFile (filePath:string):void {\n try {\n unlinkSync(filePath)\n } catch {\n // already removed\n }\n}\n\nexport type AgentResult = {\n exitCode:number\n completedItems:string[]\n // true when the orchestrator killed the agent at\n // the timeout; exitCode is non-zero in that case\n timedOut:boolean\n}\n\n// How long to wait after the process exits before giving up on a\n// graceful pipe close and forcing the streams shut. A grandchild\n// (dev server, watcher) that inherited the agent's stdout can keep\n// the pipe open after the agent itself has been killed, which would\n// otherwise leave spawnAgent's promise pending forever.\nconst CLOSE_GRACE_MS = 2000\n\n// Agents are spawned with detached:true so they become their own\n// process group leader; this lets us kill the whole tree (agent +\n// any children it spawned, like dev servers) with one signal to\n// -pid instead of leaving orphans behind. Exported for reuse by\n// signal handling (Ctrl-C / SIGTERM).\nexport function killProcessGroup (pid:number|undefined):void {\n if (pid === undefined) return\n try {\n process.kill(-pid, 'SIGKILL')\n } catch {\n // The group kill failed (e.g. the group was already\n // reaped, or the pid is not a group leader). Fall back\n // to killing the process directly so a still-running\n // pid never escapes the kill.\n try {\n process.kill(pid, 'SIGKILL')\n } catch {\n // Process is already gone.\n }\n }\n}\n\n// Tracks every agent process spawnAgent currently has running, so\n// a Ctrl-C or SIGTERM to the orchestrator itself can kill them all\n// instead of leaving them running after the orchestrator exits.\nconst runningAgents = new Set<number>()\n\nexport function killRunningAgents ():number {\n let killed = 0\n for (const pid of runningAgents) {\n killProcessGroup(pid)\n killed++\n }\n return killed\n}\n\nexport function spawnAgent (opts:{\n prompt:string\n agentCmd:string\n model:string|null\n timeout:number\n logPath:string\n cwd?:string\n label?:string\n maxTurns?:number\n effort?:EffortLevel\n onLine?:(line:string) => void\n}):Promise<AgentResult> {\n const args:string[] = [\n ...getProviderArgs(opts.agentCmd),\n ]\n if (opts.model) {\n args.push('--model', opts.model)\n }\n const providerName = basename(opts.agentCmd)\n const isClaude = providerName === 'claude'\n const isPi = providerName === 'pi'\n\n if (opts.maxTurns) {\n if (isClaude) {\n args.push(\n '--max-turns',\n String(opts.maxTurns)\n )\n } else if (opts.onLine) {\n opts.onLine(\n 'Warning: --max-turns not ' +\n `supported by ${providerName}, ` +\n 'skipping'\n )\n }\n }\n if (opts.effort && providerName in EFFORT_LADDERS) {\n const ladder = EFFORT_LADDERS[\n providerName as ProviderName\n ]\n if (\n !(ladder as readonly string[])\n .includes(opts.effort)\n ) {\n if (opts.onLine) {\n opts.onLine(\n 'Warning: effort ' +\n `'${opts.effort}' not ` +\n 'supported by ' +\n `${providerName}, skipping`\n )\n }\n } else if (isPi) {\n args.push('--thinking', opts.effort)\n } else if (isClaude) {\n args.push('--effort', opts.effort)\n } else if (providerName === 'codex') {\n args.push(\n '-c',\n `model_reasoning_effort=${opts.effort}`\n )\n }\n }\n const prefix = opts.label ?\n ` [${opts.label}] ` :\n ' '\n\n let promptFile:string|null = null\n if (isPi) {\n promptFile = writePromptFile(opts.prompt)\n args.push(`@${promptFile}`)\n }\n\n const logStream = createWriteStream(\n opts.logPath,\n { flags:'w' }\n )\n const proc = spawn(opts.agentCmd, args, {\n stdio:['pipe', 'pipe', 'pipe'],\n cwd:opts.cwd,\n detached:true,\n })\n\n if (proc.pid !== undefined) runningAgents.add(proc.pid)\n\n proc.stdout.pipe(logStream)\n\n const piFormatter = isPi ?\n createPiStreamFormatter() :\n null\n\n const completedItems:string[] = []\n const seenItems = new Set<string>()\n\n function collectCompleted (text:string):void {\n // Reported items arrive as one multi-line text block\n // (claude), as drained single lines (pi), or as raw\n // lines (other providers); matching per line covers all\n // three, including summaries with several [x] lines.\n for (const line of text.split('\\n')) {\n const match = line.match(COMPLETED_RE)\n if (!match) continue\n const item = match[1].trim()\n if (!item || seenItems.has(item)) continue\n seenItems.add(item)\n completedItems.push(item)\n }\n }\n\n const rl = createInterface({ input:proc.stdout })\n rl.on('line', line => {\n if (isClaude) {\n const formatted = formatStreamLine(line)\n if (formatted !== null) {\n collectCompleted(formatted)\n const output = `${prefix}${formatted}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.log(output)\n }\n }\n } else if (piFormatter) {\n const lines = piFormatter.process(line)\n for (const formatted of lines) {\n collectCompleted(formatted)\n const output = `${prefix}${formatted}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.log(output)\n }\n }\n } else {\n collectCompleted(line)\n const output = `${prefix}${line}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.log(output)\n }\n }\n })\n\n proc.stderr.pipe(logStream)\n const rlErr = createInterface({ input:proc.stderr })\n rlErr.on('line', line => {\n if (isClaude && !TOOL_USE_RE.test(line)) return\n const output = `${prefix}${line}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.error(output)\n }\n })\n\n let timedOut = false\n const timeout = setTimeout(() => {\n if (proc.killed) return\n timedOut = true\n const msg = 'agent timed out after ' +\n `${opts.timeout}s; killing it`\n // The status display repaints the screen, so a\n // bare console.warn would be painted over. Route\n // the reason through onLine and into the ticket\n // log so it is visible in both places.\n logStream.write(`nightralph: ${msg}\\n`)\n if (opts.onLine) {\n opts.onLine(`${prefix}${msg}`)\n } else {\n console.warn(`${prefix}${msg}`)\n }\n killProcessGroup(proc.pid)\n }, opts.timeout * 1000)\n\n // An agent that exits before draining stdin (bad flags,\n // auth failure) closes its end of the pipe; writing to it\n // then raises EPIPE on proc.stdin. Without a listener that\n // is an uncaught 'error' event that kills the orchestrator.\n proc.stdin.on('error', err => {\n logStream.write(\n 'nightralph: stdin write failed: ' +\n `${formatErrorMessage(err)}\\n`\n )\n })\n\n if (!promptFile) {\n proc.stdin.write(opts.prompt)\n }\n proc.stdin.end()\n\n return new Promise<AgentResult>(resolve => {\n let settled = false\n let graceTimer:ReturnType<typeof setTimeout>|undefined\n\n function finish (exitCode:number):void {\n if (settled) return\n settled = true\n clearTimeout(timeout)\n if (graceTimer) clearTimeout(graceTimer)\n if (proc.pid !== undefined) {\n runningAgents.delete(proc.pid)\n }\n if (piFormatter) {\n for (const line of piFormatter.flush()) {\n collectCompleted(line)\n const output = `${prefix}${line}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.log(output)\n }\n }\n }\n rl.close()\n rlErr.close()\n logStream.end()\n if (promptFile) cleanupPromptFile(promptFile)\n resolve({ exitCode, completedItems, timedOut })\n }\n\n // The process itself has exited, but 'close' waits for its\n // stdio streams to close too -- a grandchild that inherited\n // stdout/stderr can hold those pipes open indefinitely. Give\n // it a grace period, then destroy the streams ourselves so\n // the run does not hang forever on someone else's fd.\n proc.on('exit', code => {\n graceTimer = setTimeout(() => {\n killProcessGroup(proc.pid)\n proc.stdout.destroy()\n proc.stderr.destroy()\n finish(code ?? 1)\n }, CLOSE_GRACE_MS)\n })\n\n proc.on('close', code => {\n finish(code ?? 1)\n })\n proc.on('error', err => {\n if (settled) return\n settled = true\n if (graceTimer) clearTimeout(graceTimer)\n clearTimeout(timeout)\n if (proc.pid !== undefined) {\n runningAgents.delete(proc.pid)\n }\n rl.close()\n rlErr.close()\n logStream.end()\n if (promptFile) cleanupPromptFile(promptFile)\n console.error(\n 'Agent process error:',\n formatErrorMessage(err)\n )\n resolve({\n exitCode:1,\n completedItems,\n timedOut,\n })\n })\n })\n}\n\nexport function dryRun (\n tickets:Array<Ticket>,\n specBody:string,\n testCmd:string\n):void {\n listTickets(tickets)\n\n console.log('\\nSimulated wave order:')\n for (const { wave, ready } of simulateWaves(tickets)) {\n console.log(\n ` Wave ${wave}: ` +\n ready.map(t => t.filename).join(', ')\n )\n }\n\n const stuck = detectDeadlocks(tickets)\n if (stuck.length > 0) {\n console.log(\n '\\nDeadlocked tickets: ' +\n stuck.map(t => t.filename).join(', ')\n )\n }\n\n const firstReady = findReadyTickets(tickets)\n if (firstReady.length > 0) {\n console.log(\n '\\nPrompt for first ready ticket ' +\n `(${firstReady[0].filename}):\\n`\n )\n console.log(\n renderPrompt(specBody, firstReady[0],\n { testCmd })\n )\n }\n}\n\nexport function dryRunIsolated (opts:{\n tickets:Array<Ticket>\n specBody:string\n repoName:string\n conflictStrategy:MergeConflictStrategy\n progressPath:string\n testCmd:string\n effort?:EffortLevel\n retries?:number\n retryDelay?:number\n}):void {\n listTickets(opts.tickets)\n\n console.log('\\nSimulated wave order:')\n for (const { wave, ready } of simulateWaves(\n opts.tickets\n )) {\n console.log(\n ` Wave ${wave}: ` +\n ready.map(t => t.filename).join(', ')\n )\n for (const t of ready) {\n const num = String(t.num).padStart(2, '0')\n const branchName =\n `${opts.repoName}/${num}-${t.slug}`\n const worktreePath =\n `../${opts.repoName}.${num}-${t.slug}`\n console.log(` worktree: ${worktreePath}`)\n console.log(` branch: ${branchName}`)\n }\n }\n\n const stuck = detectDeadlocks(opts.tickets)\n if (stuck.length > 0) {\n console.log(\n '\\nDeadlocked tickets: ' +\n stuck.map(t => t.filename).join(', ')\n )\n }\n\n const firstReady = findReadyTickets(opts.tickets)\n if (firstReady.length > 0) {\n console.log(\n '\\nPrompt for first ready ticket ' +\n `(${firstReady[0].filename}):\\n`\n )\n console.log(\n renderPrompt(\n opts.specBody, firstReady[0],\n { testCmd:opts.testCmd }\n )\n )\n }\n\n const strategyDesc =\n opts.conflictStrategy === 'respawn' ?\n 'respawn (re-run agent on conflict)' :\n 'stop (stop merging on conflict)'\n console.log(\n `\\nTest command: ${opts.testCmd}`\n )\n console.log(\n `Effort: ${opts.effort ?? '(provider default)'}`\n )\n console.log(\n `Retries: ${opts.retries ?? DEFAULT_RETRIES}`\n )\n console.log(\n 'Retry delay: ' +\n `${opts.retryDelay ?? 0}s`\n )\n console.log(\n `\\nMerge strategy: ${strategyDesc}`\n )\n console.log(`Progress file: ${opts.progressPath}`)\n}\n\n// Runs the project's test command in a ticket's worktree.\n// Writes the output to a per-ticket log either way, and\n// returns true only when the suite is green.\nasync function runTestGate (opts:{\n testCmd:string\n ticket:Ticket\n worktreePath:string\n timeout:number\n logsDir:string\n attempt?:number\n log:(msg:string) => void\n registry?:Set<number>\n}):Promise<boolean> {\n const result = await runTestCmd({\n cmd:opts.testCmd,\n cwd:opts.worktreePath,\n timeout:opts.timeout,\n registry:opts.registry,\n })\n const testLogPath = attemptLogPath(\n opts.logsDir, opts.ticket, opts.attempt ?? 1,\n '.test.log'\n )\n writeFileSync(testLogPath, result.output)\n\n if (result.exitCode !== 0) {\n opts.log(\n ` ${opts.ticket.filename}: tests failed ` +\n `(exit ${result.exitCode}); ` +\n `see ${testLogPath}`\n )\n return false\n }\n\n opts.log(` ${opts.ticket.filename}: tests passed`)\n return true\n}\n\n// Re-runs the agent in a ticket's existing worktree\n// after a merge conflict, then retries the merge once.\n// Called at most once per ticket per wave.\nasync function respawnAndRetryMerge (opts:{\n repoRoot:string\n baseBranch:string\n branch:string\n ticket:Ticket\n worktreePath:string\n specBody:string\n agentCmd:string\n model:string|null\n timeout:number\n logsDir:string\n testCmd:string\n maxTurns?:number\n onLine?:(msg:string) => void\n}):Promise<boolean> {\n const log = (msg:string):void => {\n if (opts.onLine) {\n opts.onLine(msg)\n } else {\n console.log(msg)\n }\n }\n\n await updateWorktreeFromBase(\n opts.worktreePath, opts.baseBranch\n )\n\n const msg1 = ` ${opts.ticket.filename}: respawning agent ` +\n 'to resolve merge conflict'\n if (opts.onLine) {\n opts.onLine(msg1)\n } else {\n console.log(msg1)\n }\n\n const prompt = renderMergePrompt(\n opts.specBody, opts.ticket\n )\n const logPath = join(\n opts.logsDir,\n opts.ticket.filename.replace(/\\.md$/, '.respawn.log')\n )\n const label = opts.ticket.filename.replace(\n /\\.md$/, ''\n )\n const result = await spawnAgent({\n prompt,\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logPath,\n cwd:opts.worktreePath,\n label,\n maxTurns:opts.maxTurns,\n onLine:opts.onLine,\n })\n\n if (result.exitCode !== 0) {\n const msg2 = ` ${opts.ticket.filename}: respawned agent ` +\n `exited ${result.exitCode}`\n if (opts.onLine) {\n opts.onLine(msg2)\n } else {\n console.log(msg2)\n }\n return false\n }\n\n const passed = await runTestGate({\n testCmd:opts.testCmd,\n ticket:opts.ticket,\n worktreePath:opts.worktreePath,\n timeout:opts.timeout,\n logsDir:opts.logsDir,\n log,\n registry:runningAgents,\n })\n if (!passed) {\n log(\n ` ${opts.ticket.filename}: tests failed ` +\n 'after conflict respawn; not merging'\n )\n return false\n }\n\n const mergeResult = await mergeBranch(\n opts.repoRoot, opts.branch\n )\n if (!mergeResult.success) {\n const msg3 = ` ${opts.ticket.filename}: merge still ` +\n 'conflicted after respawn'\n if (opts.onLine) {\n opts.onLine(msg3)\n } else {\n console.log(msg3)\n }\n if (mergeResult.stderr) {\n const stderrMsg =\n ` git: ${mergeResult.stderr.trim()}`\n if (opts.onLine) {\n opts.onLine(stderrMsg)\n } else {\n console.log(stderrMsg)\n }\n }\n }\n return mergeResult.success\n}\n\nexport const DEFAULT_RETRIES = 3\n\n// Seconds to wait before the first retry; each later retry\n// doubles the wait so a provider outage is waited out instead\n// of burning every attempt back to back.\nexport const DEFAULT_RETRY_DELAY = 30\n\nexport function retryDelayFor (base:number, attempt:number):number {\n return base * 2 ** (attempt - 2)\n}\n\nfunction sleep (ms:number):Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n// Log file for one attempt: the first attempt keeps the\n// plain name so existing tooling still finds it, later\n// attempts get their own file instead of overwriting it.\nfunction attemptLogPath (\n logsDir:string,\n ticket:Ticket,\n attempt:number,\n ext:string\n):string {\n const stem = ticket.filename.replace(/\\.md$/, '')\n const suffix = attempt > 1 ? `.attempt${attempt}` : ''\n return join(logsDir, `${stem}${suffix}${ext}`)\n}\n\ntype TicketOutcome =\n | { kind:'worktree-error'; error:unknown }\n | {\n kind:'error'\n error:unknown\n worktreePath?:string\n branchName?:string\n }\n | {\n kind:'no-commits'\n worktreePath:string\n branchName:string\n }\n | {\n kind:'failed'\n reason:'exit'|'tests'\n branchName:string\n exitCode:number\n completedItems:string[]\n }\n | {\n kind:'ready'\n worktreePath:string\n branchName:string\n completedItems:string[]\n }\n\ntype TicketAttemptOpts = {\n ticket:Ticket\n repoRoot:string\n repoName:string\n baseBranch:string\n specBody:string\n agentCmd:string\n model:string|null\n timeout:number\n logsDir:string\n testCmd:string\n maxTurns?:number\n effort?:EffortLevel\n d:Display\n}\n\n// One attempt at a ticket: a fresh worktree, one agent run,\n// and the checks that decide whether the branch can merge.\n// A failed attempt removes its worktree before returning.\nasync function runTicketAttempt (\n opts:TicketAttemptOpts&{ attempt:number }\n):Promise<TicketOutcome> {\n const { ticket, d } = opts\n\n let worktree:{ worktreePath:string; branchName:string }\n try {\n worktree = await createWorktree({\n repoRoot:opts.repoRoot,\n repoName:opts.repoName,\n baseBranch:opts.baseBranch,\n ticket,\n })\n } catch (error) {\n return { kind:'worktree-error', error }\n }\n\n d.setTicketStatus(ticket.num, 'in-progress')\n const agentResult = await spawnAgent({\n prompt:renderPrompt(\n opts.specBody, ticket,\n { testCmd:opts.testCmd }\n ),\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logPath:attemptLogPath(\n opts.logsDir, ticket, opts.attempt, '.log'\n ),\n cwd:worktree.worktreePath,\n label:ticket.filename.replace(/\\.md$/, ''),\n maxTurns:opts.maxTurns,\n effort:opts.effort,\n onLine:(line) => d.log(line),\n })\n\n // A timeout kill is not the agent reporting failure.\n // Keep whatever it committed and let the test gate and\n // merge decide, instead of discarding the worktree.\n if (agentResult.timedOut) {\n d.log(\n ` ${ticket.filename}: timed out; ` +\n 'keeping the work it committed'\n )\n } else if (agentResult.exitCode !== 0) {\n d.log(\n ` ${ticket.filename}: ` +\n `agent exited ${agentResult.exitCode}`\n )\n await removeWorktreeQuietly(worktree.worktreePath, d)\n return {\n kind:'failed',\n reason:'exit',\n branchName:worktree.branchName,\n exitCode:agentResult.exitCode,\n completedItems:agentResult.completedItems,\n }\n }\n\n if (isDirty(worktree.worktreePath)) {\n const committed = await commitDirty(\n worktree.worktreePath,\n 'nightralph: auto-commit ' +\n `${ticket.filename} remaining changes`\n )\n if (committed) {\n d.log(\n ` ${ticket.filename}: ` +\n 'auto-committed remaining changes'\n )\n }\n }\n\n if (!hasNewCommits(\n opts.repoRoot, opts.baseBranch, worktree.branchName\n )) {\n await removeWorktreeQuietly(worktree.worktreePath, d)\n return {\n kind:'no-commits',\n worktreePath:worktree.worktreePath,\n branchName:worktree.branchName,\n }\n }\n\n const passed = await runTestGate({\n testCmd:opts.testCmd,\n ticket,\n worktreePath:worktree.worktreePath,\n timeout:opts.timeout,\n logsDir:opts.logsDir,\n attempt:opts.attempt,\n log:(msg) => d.log(msg),\n registry:runningAgents,\n })\n if (!passed) {\n await removeWorktreeQuietly(\n worktree.worktreePath, d\n )\n return {\n kind:'failed',\n reason:'tests',\n branchName:worktree.branchName,\n exitCode:1,\n completedItems:agentResult.completedItems,\n }\n }\n\n return {\n kind:'ready',\n worktreePath:worktree.worktreePath,\n branchName:worktree.branchName,\n completedItems:agentResult.completedItems,\n }\n}\n\n// Runs a ticket until an attempt is ready to merge or the\n// retry cap is hit. Each retry starts from a fresh worktree\n// and a higher effort level.\nasync function runTicketAttempts (\n opts:TicketAttemptOpts&{ retries:number; retryDelay:number }\n):Promise<TicketOutcome> {\n const { ticket, d } = opts\n const maxAttempts = opts.retries + 1\n const providerName = basename(opts.agentCmd)\n const isKnown = providerName in EFFORT_LADDERS\n let effort = opts.effort\n let outcome:TicketOutcome = {\n kind:'no-commits', worktreePath:'', branchName:'',\n }\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n if (attempt === 1) {\n d.log(` Starting ${ticket.filename}`)\n } else {\n if (isKnown) {\n effort = escalateEffort(\n providerName as ProviderName,\n effort\n )\n }\n const delay = retryDelayFor(opts.retryDelay, attempt)\n d.log(\n ` ${ticket.filename}: retrying ` +\n `(attempt ${attempt}/${maxAttempts}` +\n (isKnown && effort ?\n `, effort ${effort}` : '') +\n (delay > 0 ?\n `, waiting ${delay}s` : '') +\n ')'\n )\n if (delay > 0) await sleep(delay * 1000)\n }\n try {\n outcome = await runTicketAttempt({\n ...opts, attempt, effort,\n })\n } catch (error) {\n d.log(\n ` ${ticket.filename}: attempt ${attempt} ` +\n `threw: ${formatErrorMessage(error)}`\n )\n return { kind:'error', error }\n }\n if (\n outcome.kind === 'ready' ||\n outcome.kind === 'worktree-error'\n ) {\n return outcome\n }\n }\n return outcome\n}\n\n// Wraps writeProgress + commitProgress so callers do not each\n// need to guard against a commit failure (e.g. a git lock held\n// by a concurrent process) crashing the run.\nasync function saveProgress (\n repoRoot:string,\n progressPath:string,\n progress:ProgressData,\n message:string,\n d:Display\n):Promise<void> {\n writeProgress(progressPath, progress)\n try {\n await commitProgress(repoRoot, progressPath, message)\n } catch (err) {\n d.log(\n ' Failed to commit progress: ' +\n formatErrorMessage(err)\n )\n }\n}\n\nfunction runProgress (tickets:ReadonlyArray<Ticket>):RunProgress {\n return {\n completed:tickets.filter(t => t.status === 'done').length,\n total:tickets.length,\n }\n}\n\nexport async function runWaves (\n tickets:Ticket[],\n specBody:string,\n agentCmd:string,\n model:string|null,\n timeout:number,\n logsDir:string,\n testCmd:string,\n display?:Display,\n maxTurns?:number,\n effort?:EffortLevel,\n retries?:number,\n retryDelay?:number,\n):Promise<{ allDone:boolean }> {\n mkdirSync(logsDir, { recursive:true })\n\n const d = display ?? createDisplay()\n const maxAttempts = (retries ?? DEFAULT_RETRIES) + 1\n const delayBase = retryDelay ?? 0\n const providerName = basename(agentCmd)\n const isKnown = providerName in EFFORT_LADDERS\n let totalWaves = 0\n for (const _ of simulateWaves(tickets)) totalWaves++\n\n let totalCompleted = 0\n let waveNum = 0\n const failedNums = new Set<number>()\n\n while (true) {\n const ready = findReadyTickets(tickets).filter(\n t => !failedNums.has(t.num)\n )\n if (ready.length === 0) break\n\n waveNum++\n const readyNums = new Set(ready.map(t => t.num))\n const remaining = tickets.filter(t =>\n t.status === 'ready-for-agent' &&\n !readyNums.has(t.num)\n )\n d.startWave(\n waveNum,\n totalWaves,\n ready.map(t => ({\n num:t.num,\n filename:t.filename,\n })),\n runProgress(tickets),\n remaining.map(t => ({\n num:t.num,\n filename:t.filename,\n })),\n )\n\n const results = await Promise.allSettled(\n ready.map(async t => {\n const prompt = renderPrompt(specBody, t,\n { testCmd })\n const label = t.filename.replace(\n /\\.md$/, ''\n )\n d.setTicketStatus(t.num, 'in-progress')\n d.log(` Starting ${t.filename}`)\n let level = effort\n let result = await spawnAgent({\n prompt,\n agentCmd,\n model,\n timeout,\n logPath:attemptLogPath(logsDir, t, 1, '.log'),\n label,\n maxTurns,\n effort:level,\n onLine:(line) => d.log(line),\n })\n // In-place runs have no worktree or test\n // gate, so a non-zero exit is the only\n // failure that can be retried here.\n for (\n let attempt = 2;\n result.exitCode !== 0 &&\n !result.timedOut &&\n attempt <= maxAttempts;\n attempt++\n ) {\n if (isKnown) {\n level = escalateEffort(\n providerName as ProviderName,\n level\n )\n }\n const delay = retryDelayFor(delayBase, attempt)\n d.log(\n ` ${t.filename}: agent exited ` +\n `${result.exitCode}; retrying ` +\n `(attempt ${attempt}/${maxAttempts}` +\n (isKnown && level ?\n `, effort ${level}` : '') +\n (delay > 0 ?\n `, waiting ${delay}s` : '') +\n ')'\n )\n if (delay > 0) await sleep(delay * 1000)\n result = await spawnAgent({\n prompt,\n agentCmd,\n model,\n timeout,\n logPath:attemptLogPath(\n logsDir, t, attempt, '.log'\n ),\n label,\n maxTurns,\n effort:level,\n onLine:(line) => d.log(line),\n })\n }\n return { ticket:t, result }\n })\n )\n\n let waveCompleted = 0\n for (const r of results) {\n if (r.status === 'rejected') continue\n const { ticket, result } = r.value\n if (result.exitCode !== 0) {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n d.log(\n ` ${ticket.filename}: ` +\n `agent exited ${result.exitCode}`\n )\n continue\n }\n\n checkItems(ticket, result.completedItems)\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n d.setTicketStatus(ticket.num, 'done')\n d.log(\n ` ${ticket.filename}: done`\n )\n }\n\n if (waveCompleted === 0) {\n const remaining = findReadyTickets(tickets)\n .filter(t => !failedNums.has(t.num))\n if (remaining.length === 0) {\n d.log(\n '\\nNo tickets completed this wave ' +\n 'and no ready tickets remain. ' +\n 'Stopping.'\n )\n break\n }\n d.log(\n '\\nNo tickets completed this wave. ' +\n `${remaining.length} ready ticket` +\n `${remaining.length === 1 ? '' : 's'} ` +\n 'remain; continuing.'\n )\n }\n }\n\n const remaining = tickets.filter(\n t => t.status === 'ready-for-agent'\n )\n d.log(\n `\\nFinished: ${totalCompleted} completed` +\n (remaining.length > 0 ?\n `, ${remaining.length} remaining` :\n '') +\n (failedNums.size > 0 ?\n `, ${failedNums.size} failed` :\n '')\n )\n d.cleanup()\n\n return { allDone:remaining.length === 0 }\n}\n\nexport async function runWavesIsolated (opts:{\n tickets:Array<Ticket>\n specBody:string\n agentCmd:string\n model:string|null\n timeout:number\n logsDir:string\n featureName:string\n conflictStrategy:MergeConflictStrategy\n display?:Display\n testCmd:string\n maxTurns?:number\n // starting effort level; unset = provider's default\n effort?:EffortLevel\n // extra attempts per ticket after a failure; default 3\n retries?:number\n // seconds to wait before the first retry; default 30\n retryDelay?:number\n}):Promise<{ allDone:boolean }> {\n mkdirSync(opts.logsDir, { recursive:true })\n\n const d = opts.display ?? createDisplay()\n const retries = opts.retries ?? DEFAULT_RETRIES\n const retryDelay = opts.retryDelay ?? 0\n let totalWaves = 0\n for (const _ of simulateWaves(opts.tickets)) totalWaves++\n\n const repoRoot = getRepoRoot()\n const repoName = getRepoName()\n const baseBranch = getCurrentBranch()\n\n if (isDirty(repoRoot)) {\n throw new Error(\n 'Working tree is dirty; commit or stash ' +\n 'changes before running'\n )\n }\n\n const progressPath = join(\n dirname(opts.logsDir), 'progress.md'\n )\n const progress:ProgressData = mergeProgress(\n generateProgress(opts.featureName, opts.tickets),\n readProgress(progressPath)\n )\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: start ${opts.featureName}`,\n d,\n )\n\n let totalCompleted = 0\n let waveNum = 0\n const failedNums = new Set<number>()\n\n while (true) {\n const ready = findReadyTickets(opts.tickets).filter(\n t => !failedNums.has(t.num)\n )\n if (ready.length === 0) break\n\n waveNum++\n const readyNums = new Set(ready.map(t => t.num))\n const remaining = opts.tickets.filter(t =>\n t.status === 'ready-for-agent' &&\n !readyNums.has(t.num)\n )\n d.startWave(\n waveNum,\n totalWaves,\n ready.map(t => ({\n num:t.num,\n filename:t.filename,\n })),\n runProgress(opts.tickets),\n remaining.map(t => ({\n num:t.num,\n filename:t.filename,\n })),\n )\n\n // Each ticket runs its own attempt loop in parallel.\n // Progress is recorded afterwards, sequentially, so\n // commits on the base branch never race each other.\n const outcomes = await Promise.all(\n ready.map(t => runTicketAttempts({\n ticket:t,\n repoRoot,\n repoName,\n baseBranch,\n specBody:opts.specBody,\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logsDir:opts.logsDir,\n testCmd:opts.testCmd,\n maxTurns:opts.maxTurns,\n effort:opts.effort,\n retries,\n retryDelay,\n d,\n }))\n )\n\n let waveCompleted = 0\n const successfulBranches:Array<{\n branch:string\n ticketNum:number\n worktreePath:string\n }> = []\n const ticketsByNum = new Map<number, Ticket>()\n const worktreePathsByNum = new Map<number, string>()\n\n for (let i = 0; i < outcomes.length; i++) {\n const outcome = outcomes[i]\n const ticket = ready[i]\n\n if (outcome.kind === 'worktree-error') {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n d.log(\n ` ${ticket.filename}: failed to create ` +\n `worktree: ${formatErrorMessage(outcome.error)}`\n )\n checkTicket(progress, ticket.num, {\n branch:'',\n exitCode:-1,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n 'worktree error',\n d,\n )\n continue\n }\n\n if (outcome.kind === 'error') {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n d.log(\n ` ${ticket.filename}: attempt error: ` +\n formatErrorMessage(outcome.error)\n )\n checkTicket(progress, ticket.num, {\n branch:outcome.branchName ?? '',\n exitCode:-1,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} error`,\n d,\n )\n continue\n }\n\n if (outcome.kind === 'no-commits') {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n d.log(\n ` ${ticket.filename}: agent exited 0 ` +\n 'but made no changes; leaving ticket ' +\n 'ready-for-agent'\n )\n checkTicket(progress, ticket.num, {\n branch:outcome.branchName,\n exitCode:0,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n 'no commits',\n d,\n )\n continue\n }\n\n if (outcome.kind === 'failed') {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n if (outcome.reason === 'exit') {\n checkItems(ticket, outcome.completedItems)\n }\n // Acceptance criteria are not met when the\n // suite is red, so checklist items the agent\n // claimed are not checked off in that case.\n checkTicket(progress, ticket.num, {\n branch:outcome.branchName,\n exitCode:outcome.exitCode,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n (outcome.reason === 'tests' ?\n 'tests failed' :\n 'failed'),\n d,\n )\n continue\n }\n\n checkItems(ticket, outcome.completedItems)\n d.log(\n ` ${ticket.filename}: agent finished, ` +\n 'awaiting merge'\n )\n ticketsByNum.set(ticket.num, ticket)\n worktreePathsByNum.set(\n ticket.num, outcome.worktreePath\n )\n successfulBranches.push({\n branch:outcome.branchName,\n ticketNum:ticket.num,\n worktreePath:outcome.worktreePath,\n })\n }\n\n if (successfulBranches.length > 0) {\n await commitTicketFiles(\n repoRoot,\n successfulBranches\n .map(sb =>\n ticketsByNum.get(sb.ticketNum)!\n ),\n d,\n )\n\n const mergeResult = await mergeWave({\n repoRoot,\n baseBranch,\n branches:successfulBranches,\n strategy:opts.conflictStrategy,\n })\n\n for (const branchResult of mergeResult.merged) {\n const ticket = ticketsByNum.get(\n branchResult.ticketNum\n )\n if (!ticket) continue\n\n if (branchResult.merged) {\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n d.setTicketStatus(ticket.num, 'done')\n d.log(\n ` ${ticket.filename}: done`\n )\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} done`,\n d,\n )\n\n const worktreePath = worktreePathsByNum.get(\n ticket.num\n )\n if (worktreePath) {\n await removeWorktreeQuietly(\n worktreePath, d\n )\n }\n } else {\n const worktreePath = worktreePathsByNum.get(\n ticket.num\n )\n const recovered =\n opts.conflictStrategy === 'respawn' &&\n worktreePath ?\n await respawnAndRetryMerge({\n repoRoot,\n baseBranch,\n branch:branchResult.branch,\n ticket,\n worktreePath,\n specBody:opts.specBody,\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logsDir:opts.logsDir,\n testCmd:opts.testCmd,\n maxTurns:opts.maxTurns,\n onLine:(msg) => d.log(msg),\n }) :\n false\n\n if (recovered) {\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n d.setTicketStatus(ticket.num, 'done')\n d.log(\n ` ${ticket.filename}: done ` +\n '(resolved via respawn)'\n )\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n 'done (respawn)',\n d,\n )\n\n if (worktreePath) {\n try {\n await removeWorktree(\n worktreePath,\n { force:true }\n )\n } catch (err) {\n d.log(\n ' Failed to remove worktree ' +\n `${worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n }\n } else {\n // Without this the ticket stays\n // ready-for-agent and the wave loop\n // would re-run it forever; excluding it\n // from later waves of this run ends the\n // loop while the file keeps its status\n // for the next run.\n failedNums.add(ticket.num)\n d.log(\n ` ${ticket.filename}: merge failed, ` +\n 'staying ready-for-agent'\n )\n if (branchResult.stderr) {\n d.log(\n ' git: ' +\n branchResult.stderr.trim()\n )\n }\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n 'merge failed',\n d,\n )\n }\n }\n }\n\n if (mergeResult.stoppedAt) {\n d.log(\n '\\nMerge stopped at ' +\n `${mergeResult.stoppedAt.branch}`\n )\n\n for (const sb of successfulBranches) {\n const ticket = ticketsByNum.get(sb.ticketNum)\n if (ticket && ticket.status === 'done') continue\n try {\n await removeWorktree(\n sb.worktreePath,\n { force:true }\n )\n } catch (err) {\n d.log(\n ' Failed to remove worktree ' +\n `${sb.worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n }\n\n break\n }\n }\n\n if (waveCompleted === 0) {\n const remaining = findReadyTickets(\n opts.tickets\n ).filter(t => !failedNums.has(t.num))\n if (remaining.length === 0) {\n d.log(\n '\\nNo tickets completed this wave ' +\n 'and no ready tickets remain. ' +\n 'Stopping.'\n )\n break\n }\n d.log(\n '\\nNo tickets completed this wave. ' +\n `${remaining.length} ready ticket` +\n `${remaining.length === 1 ? '' : 's'} ` +\n 'remain; continuing.'\n )\n }\n }\n\n const remaining = opts.tickets.filter(\n t => t.status === 'ready-for-agent'\n )\n d.log(\n `\\nFinished: ${totalCompleted} completed` +\n (remaining.length > 0 ?\n `, ${remaining.length} remaining` :\n '') +\n (failedNums.size > 0 ?\n `, ${failedNums.size} failed` :\n '')\n )\n d.cleanup()\n\n return { allDone:remaining.length === 0 }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { spawn, execFile } from 'node:child_process'\nimport {\n createWriteStream,\n mkdirSync,\n readFileSync,\n writeFileSync,\n unlinkSync,\n readdirSync,\n} from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join, dirname, basename } from 'node:path'\nimport { createInterface } from 'node:readline'\nimport { promisify } from 'node:util'\n\nconst execFileAsync = promisify(execFile)\nimport {\n getRepoRoot,\n getRepoName,\n getCurrentBranch,\n createWorktree,\n removeWorktree,\n buildBranchName,\n hasNewCommits,\n isDirty,\n commitDirty,\n} from './worktree.js'\nimport {\n generateProgress,\n readProgress,\n mergeProgress,\n writeProgress,\n commitProgress,\n checkTicket,\n type ProgressData,\n} from './progress.js'\nimport {\n mergeBranch,\n mergeWave,\n updateWorktreeFromBase,\n type MergeConflictStrategy,\n} from './merge.js'\nimport {\n createDisplay,\n type RunProgress,\n type Display,\n} from './display.js'\nimport { runTestCmd } from './testcmd.js'\n\nexport type Ticket = {\n num:number\n slug:string\n filename:string\n filepath:string\n body:string\n status:string\n blockers:number[]\n}\n\nexport function formatErrorMessage (error:unknown):string {\n return error instanceof Error ?\n error.message :\n String(error)\n}\n\n// Removes a ticket's worktree, logging and swallowing any\n// failure instead of letting it interrupt the wave.\nasync function removeWorktreeQuietly (\n worktreePath:string,\n d:Display\n):Promise<void> {\n try {\n await removeWorktree(worktreePath, { force:true })\n } catch (err) {\n d.log(\n ' Failed to remove worktree ' +\n `${worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n}\n\nasync function commitTicketFiles (\n repoRoot:string,\n tickets:Ticket[],\n d:Display\n):Promise<void> {\n const paths = tickets.map(t => t.filepath)\n if (paths.length === 0) return\n try {\n await execFileAsync(\n 'git',\n ['add', '--force', ...paths],\n { cwd:repoRoot }\n )\n try {\n await execFileAsync(\n 'git',\n ['diff', '--cached', '--quiet',\n '--', ...paths],\n { cwd:repoRoot }\n )\n return\n } catch {\n // staged files differ from HEAD\n }\n await execFileAsync(\n 'git',\n ['commit', '-m',\n 'nightralph: update ticket checklists',\n '--', ...paths],\n { cwd:repoRoot }\n )\n } catch (err) {\n d.log(\n ' Failed to commit ticket updates: ' +\n formatErrorMessage(err)\n )\n }\n}\n\nexport const TICKET_RE = /^(\\d+)-(.+)\\.md$/\n\nexport function parseTicketFilename (\n filename:string\n):{ num:number; slug:string }|null {\n const m = filename.match(TICKET_RE)\n if (!m) return null\n return { num:Number(m[1]), slug:m[2] }\n}\n\nexport function parseStatus (body:string):string {\n const m = body.match(/\\*\\*Status:\\*\\*\\s*(.+)/i)\n return m ? m[1].trim().toLowerCase() : ''\n}\n\nexport function parseBlockers (body:string):number[] {\n const m = body.match(/\\*\\*Blocked by:\\*\\*\\s*(.+)/i)\n if (!m) return []\n const text = m[1]\n if (/none/i.test(text)) return []\n const nums:number[] = []\n const re = /(\\d+)/g\n let match\n while ((match = re.exec(text))) {\n nums.push(Number(match[1]))\n }\n return nums\n}\n\nexport function scanTickets (dir:string):Ticket[] {\n const files = readdirSync(dir)\n .filter(f => TICKET_RE.test(f))\n .sort((a, b) => a.localeCompare(\n b,\n undefined,\n { numeric:true, sensitivity:'base' }\n ))\n\n return files.map(filename => {\n const parsed = parseTicketFilename(filename)!\n const filepath = join(dir, filename)\n const body = readFileSync(filepath, 'utf8')\n return {\n num:parsed.num,\n slug:parsed.slug,\n filename,\n filepath,\n body,\n status:parseStatus(body),\n blockers:parseBlockers(body),\n }\n })\n}\n\nexport function findReadyTickets (\n tickets:ReadonlyArray<Ticket>\n):Ticket[] {\n const doneNums = new Set(\n tickets\n .filter(t => t.status === 'done')\n .map(t => t.num)\n )\n return tickets.filter(t => {\n if (t.status !== 'ready-for-agent') return false\n return t.blockers.every(b => doneNums.has(b))\n })\n}\n\n// Matches an agent-reported completed item. Agents echo items\n// as markdown checklist lines (`- [x] item`) as often as bare\n// `[x] item` lines, so the bullet prefix is optional.\nexport const COMPLETED_RE = /^\\s*[-*+]?\\s*\\[x\\]\\s+(.+)$/i\nexport const TOOL_USE_RE = /^\\[[\\w.]+\\]/\n\n// Matches one checklist line in a ticket file: optional indent\n// and bullet, the `[ ]` / `[x]` box, and the item text.\nconst CHECKBOX_RE = /^(\\s*[-*+] )\\[( |x|X)\\]( .*)$/\n\n// The unchecked-box variant, used for the actual flip to [x].\nconst UNCHECKED_BOX_RE = /^(\\s*[-*+] )\\[( )\\]/\n\n// Normalizes checklist text for matching: agents echo an item as\n// one logical line while ticket files wrap items across lines,\n// so compare with whitespace runs collapsed, case-insensitively.\nfunction normalizeItemText (s:string):string {\n return s.replace(/\\s+/g, ' ').trim().toLowerCase()\n}\n\n// Drops an optional markdown bullet/checkbox prefix so items match\n// whether or not the caller already stripped the `[x]` marker.\nfunction stripCheckboxPrefix (s:string):string {\n return s.replace(/^\\s*[-*+]?\\s*\\[[ xX]\\]\\s+/, '')\n}\n\ntype ParsedItem = { start:number; text:string }\n\n// Parses the checklist items out of a ticket body. An item is its\n// checkbox line plus any immediately following indented lines\n// (wrapped text), so items written across multiple lines can be\n// matched by their full text. Code fences are skipped.\nfunction parseChecklistItems (\n lines:string[]\n):ParsedItem[] {\n const items:ParsedItem[] = []\n let inFence = false\n let i = 0\n while (i < lines.length) {\n if (/^\\s*```/.test(lines[i])) {\n inFence = !inFence\n i++\n continue\n }\n if (inFence) {\n i++\n continue\n }\n const m = lines[i].match(CHECKBOX_RE)\n if (!m) {\n i++\n continue\n }\n const start = i\n let text = m[3]\n i++\n while (\n i < lines.length &&\n /^\\s+\\S/.test(lines[i]) &&\n !CHECKBOX_RE.test(lines[i])\n ) {\n text += ' ' + lines[i].trim()\n i++\n }\n items.push({\n start,\n text:normalizeItemText(text),\n })\n }\n return items\n}\n\nexport function checkItems (\n ticket:Ticket,\n completedItems:string[]\n):void {\n if (completedItems.length === 0) return\n // Read from disk: a merge or respawn may have changed the\n // file since the ticket was scanned, and writing the stale\n // body would drop those edits.\n let body:string\n try {\n body = readFileSync(ticket.filepath, 'utf8')\n } catch {\n body = ticket.body\n }\n const wanted = new Set(\n completedItems.map(item =>\n normalizeItemText(stripCheckboxPrefix(item))\n )\n )\n const lines = body.split('\\n')\n let changed = false\n for (const item of parseChecklistItems(lines)) {\n if (!wanted.has(item.text)) continue\n const flipped = lines[item.start].replace(\n UNCHECKED_BOX_RE,\n '$1[x]'\n )\n if (flipped !== lines[item.start]) {\n lines[item.start] = flipped\n changed = true\n }\n }\n if (!changed) return\n body = lines.join('\\n')\n writeFileSync(ticket.filepath, body)\n ticket.body = body\n}\n\n// Checks off every remaining unchecked item in a ticket body,\n// ignoring fenced code blocks.\nfunction checkAllItems (body:string):string {\n const lines = body.split('\\n')\n let inFence = false\n for (let i = 0; i < lines.length; i++) {\n if (/^\\s*```/.test(lines[i])) {\n inFence = !inFence\n continue\n }\n if (inFence) continue\n lines[i] = lines[i].replace(\n UNCHECKED_BOX_RE,\n '$1[x]'\n )\n }\n return lines.join('\\n')\n}\n\nexport function markDone (ticket:Ticket):void {\n // Re-read from disk: the merge may have brought the agent's\n // own edits to the ticket file into the repo, and writing\n // the body scanned at startup would drop them.\n let body:string\n try {\n body = readFileSync(ticket.filepath, 'utf8')\n } catch {\n body = ticket.body\n }\n // A done ticket's items are complete by definition, so check\n // off anything the agent did not report instead of leaving\n // the file claiming done with unchecked items.\n body = checkAllItems(body)\n const updated = body.replace(\n /\\*\\*Status:\\*\\*\\s*.+/i,\n '**Status:** done'\n )\n writeFileSync(ticket.filepath, updated)\n ticket.status = 'done'\n ticket.body = updated\n}\n\n// Drops one markdown section from a spec. Used to keep the\n// per-ticket prompt short: the User Stories list is useful\n// to humans and to to-tickets but not to an implementing agent.\nexport function stripSpecSection (\n specBody:string,\n heading:string\n):string {\n const out:string[] = []\n let skipping = false\n let skipLevel = 0\n let inFence = false\n\n for (const line of specBody.split('\\n')) {\n // Toggle fence state on lines starting with ``` (after\n // optional whitespace)\n if (/^\\s*```/.test(line)) {\n inFence = !inFence\n }\n\n // Only check for headings outside of code fences\n if (!inFence) {\n const m = /^(#{1,6})\\s+(.*?)\\s*$/.exec(line)\n if (m) {\n const level = m[1].length\n if (skipping && level <= skipLevel) {\n skipping = false\n }\n if (!skipping && m[2] === heading) {\n skipping = true\n skipLevel = level\n continue\n }\n }\n }\n if (!skipping) out.push(line)\n }\n\n return out.join('\\n')\n}\n\nexport function renderPrompt (\n specBody:string,\n ticket:Ticket,\n opts:{ testCmd:string }\n):string {\n return [\n '---- SPEC CONTEXT ----',\n specBody,\n '',\n '---- TICKET ----',\n ticket.filename,\n ticket.body,\n '',\n '---- AGENT INSTRUCTIONS ----',\n 'You are an autonomous coding agent. ' +\n 'Implement the ticket using /tdd.',\n '',\n 'Follow these rules:',\n '- Read the files directly relevant to the ' +\n 'ticket before writing code. Also read any ' +\n 'AGENTS.md in or above the directories you ' +\n 'will touch, plus CONTEXT.md and the ' +\n 'relevant docs/adr/ entries if they exist. ' +\n 'If they do not exist, proceed silently.',\n '- Work ONLY on this ticket. Do not fix ' +\n 'unrelated problems you notice.',\n '- Do NOT research external APIs or services ' +\n 'via web search. Use the spec and ticket ' +\n 'body as your sole reference for API shapes.',\n '- Use /tdd for every checklist item. For ' +\n 'each item, write a failing test at the ' +\n 'seams named in the spec\\'s Testing ' +\n 'Decisions section, then write only ' +\n 'enough code to make it pass, then ' +\n 'refactor.',\n '- While iterating, run only the tests ' +\n 'relevant to what you changed. Run ' +\n `\\`${opts.testCmd}\\` in full once, as the ` +\n 'final gate before your last commit. Do ' +\n 'not commit with failing tests. The ' +\n 'orchestrator runs the same command after ' +\n 'you exit and rejects the ticket if it ' +\n 'fails.',\n '- If the project has a lint script, run it ' +\n 'and fix what it reports.',\n '- INTEGRITY: never delete, skip, weaken, or ' +\n 'write tautological tests to force a green ' +\n 'result. Only report a checklist item done ' +\n 'when its real tests genuinely pass. If an ' +\n 'item cannot be completed honestly, leave ' +\n 'it unchecked and say what blocked you.',\n '- Do NOT read or modify files outside ' +\n 'your current directory (the worktree).',\n '- Do NOT run git push.',\n '- Commit after each checklist item, and make ' +\n 'sure everything is committed when finished.',\n '- After completing each checklist item in the ' +\n 'ticket, print a line: [x] <item text> ' +\n '(matching the checklist text exactly).',\n '- Before your final commit, record reusable ' +\n 'learnings in the nearest AGENTS.md (in or ' +\n 'above the directories you modified; ' +\n 'prefer that over the repo root). Good ' +\n 'additions: module conventions, gotchas, ' +\n 'files that must change together, how to ' +\n 'test that area, environment requirements. ' +\n 'Do NOT add ticket-specific details or ' +\n 'temporary debugging notes. Only write ' +\n 'when you have knowledge that would help ' +\n 'future work in that directory.',\n '',\n ].join('\\n')\n}\n\nexport function renderMergePrompt (\n specBody:string,\n ticket:Ticket\n):string {\n return [\n '---- SPEC CONTEXT ----',\n specBody,\n '',\n '---- TICKET ----',\n ticket.filename,\n ticket.body,\n '',\n '---- AGENT INSTRUCTIONS ----',\n 'You are an autonomous coding agent resolving ' +\n 'a merge conflict.',\n '',\n 'Another agent already implemented this ticket ' +\n 'on a feature branch. The branch was then ' +\n 'merged with the base branch, but conflicts ' +\n 'arose. The working tree may contain conflict ' +\n 'markers that need resolution.',\n '',\n 'Your task:',\n '1. Find and resolve all conflict markers ' +\n '(<<<<<<< / ======= / >>>>>>>).',\n '2. When AGENTS.md or other docs conflict, ' +\n 'keep both sides\\' additions rather than ' +\n 'picking one.',\n '3. Make sure the code compiles and tests pass.',\n '4. Commit the resolved files.',\n '',\n 'Do NOT re-implement the ticket from scratch.',\n 'Do NOT read or modify files outside your ' +\n 'current directory (the worktree).',\n 'Do NOT run git push.',\n ].join('\\n')\n}\n\nfunction listTickets (tickets:ReadonlyArray<Ticket>):void {\n console.log('\\nTickets:')\n for (const t of tickets) {\n const blockerStr = t.blockers.length > 0 ?\n `blocked by [${t.blockers.join(', ')}]` :\n 'no blockers'\n console.log(\n ` ${t.filename} ` +\n `(${t.status}) ${blockerStr}`\n )\n }\n}\n\nfunction * simulateWaves (\n tickets:ReadonlyArray<Ticket>\n):Generator<{ wave:number; ready:Array<Ticket> }> {\n const sim = new Map(\n tickets.map(t => [t.num, t.status])\n )\n let wave = 1\n while (true) {\n const doneNums = new Set(\n [...sim.entries()]\n .filter(([, s]) => s === 'done')\n .map(([n]) => n)\n )\n const ready = [...tickets].filter(t => {\n if (sim.get(t.num) !== 'ready-for-agent') {\n return false\n }\n return t.blockers.every(\n b => doneNums.has(b)\n )\n })\n if (ready.length === 0) break\n yield { wave, ready }\n for (const t of ready) {\n sim.set(t.num, 'done')\n }\n wave++\n }\n}\n\nfunction detectDeadlocks (\n tickets:ReadonlyArray<Ticket>\n):Array<Ticket> {\n const doneNums = new Set<number>()\n const ready = new Set<number>()\n\n for (const t of tickets) {\n if (t.status === 'ready-for-agent') {\n ready.add(t.num)\n } else if (t.status === 'done') {\n doneNums.add(t.num)\n }\n }\n\n let changed = true\n while (changed) {\n changed = false\n for (const num of ready) {\n const ticket = tickets.find(t =>\n t.num === num\n )!\n if (ticket.blockers.every(\n b => doneNums.has(b)\n )) {\n doneNums.add(num)\n ready.delete(num)\n changed = true\n }\n }\n }\n\n return [...ready].map(num =>\n tickets.find(t => t.num === num)!\n )\n}\n\nconst PROVIDER_ARGS:Record<string, string[]> = {\n claude:[\n '--print', '--verbose',\n '--output-format', 'stream-json',\n '--dangerously-skip-permissions',\n ],\n // codex removed --full-auto; this is the counterpart\n // of claude's --dangerously-skip-permissions, and the\n // workspace-write sandbox would block commits because\n // a worktree's .git link points outside the tree\n codex:['exec', '--dangerously-bypass-approvals-and-sandbox'],\n pi:[\n '-p', '--verbose',\n '--approve', '--no-session',\n '--mode', 'json',\n ],\n}\n\nexport function getProviderArgs (cmd:string):string[] {\n const name = basename(cmd)\n return PROVIDER_ARGS[name] ?? []\n}\n\n// Per-provider effort ladders.\nexport const EFFORT_LADDERS = {\n pi:['off', 'minimal', 'low', 'medium',\n 'high', 'xhigh', 'max'],\n claude:['low', 'medium', 'high',\n 'xhigh', 'max'],\n codex:['low', 'medium', 'high'],\n} as const\n\nexport type ProviderName =\n keyof typeof EFFORT_LADDERS\n\nexport type EffortLevel =\n typeof EFFORT_LADDERS[ProviderName][number]\n\nexport const ALL_EFFORT_LEVELS:EffortLevel[] = [\n 'off', 'minimal', 'low', 'medium',\n 'high', 'xhigh', 'max',\n]\n\n// Step up the effort ladder for a given provider.\n// Without a starting level, the first retry jumps to high.\n// Otherwise, step one rung up and stop at the provider's max.\nexport function escalateEffort (\n provider:ProviderName,\n level?:EffortLevel\n):EffortLevel {\n if (!level) return 'high'\n const ladder = EFFORT_LADDERS[provider]\n const i = (ladder as readonly string[])\n .indexOf(level)\n if (i === -1) return level\n return ladder[\n Math.min(i + 1, ladder.length - 1)\n ] as EffortLevel\n}\n\nexport function formatStreamLine (\n line:string\n):string|null {\n let obj:Record<string, unknown>\n try {\n obj = JSON.parse(line) as Record<string, unknown>\n } catch {\n return line\n }\n\n if (obj.type === 'assistant') {\n const msg = obj.message as\n Record<string, unknown>|undefined\n const content = msg?.content as\n Array<Record<string, unknown>>|undefined\n if (!content) return null\n for (const block of content) {\n if (block.type === 'text') {\n return String(block.text)\n }\n }\n return null\n }\n\n if (obj.type === 'result') {\n const sub = obj.subtype as string|undefined ?? 'done'\n const cost = obj.total_cost_usd as number|undefined\n const costStr = cost != null ?\n ` ($${cost.toFixed(2)})` :\n ''\n return `${sub}${costStr}`\n }\n\n if (obj.type === 'system') {\n const sub = obj.subtype as string|undefined\n if (sub === 'api_retry') {\n const error = obj.error as string|undefined\n return `retry: ${error ?? 'unknown'}`\n }\n }\n\n return null\n}\n\nexport type PiStreamFormatter = {\n process:(line:string) => string[]\n flush:() => string[]\n}\n\nexport function createPiStreamFormatter (\n):PiStreamFormatter {\n const calls = new Map<\n number, { name:string; buf:string }\n >()\n let textBuf = ''\n\n function drainLines ():string[] {\n const parts = textBuf.split('\\n')\n if (parts.length === 1) return []\n textBuf = parts[parts.length - 1]\n return parts.slice(0, -1)\n }\n\n function flushBuf ():string[] {\n if (textBuf.length === 0) return []\n const out = textBuf\n textBuf = ''\n return [out]\n }\n\n function process (line:string):string[] {\n let obj:Record<string, unknown>\n try {\n obj = JSON.parse(line) as\n Record<string, unknown>\n } catch {\n return [line]\n }\n\n const evt = obj.assistantMessageEvent as\n Record<string, unknown>|undefined\n if (!evt) return []\n\n const type = evt.type as string|undefined\n const ci = evt.contentIndex as\n number|undefined ?? -1\n\n if (type === 'text_delta') {\n const delta =\n (evt.delta as string|undefined) ?? ''\n textBuf += delta\n return drainLines()\n }\n\n if (type === 'toolcall_start') {\n const flushed = flushBuf()\n calls.set(ci, {\n name:(evt.toolName as\n string|undefined) ?? '?',\n buf:'',\n })\n return flushed\n }\n\n if (\n type === 'toolcall_delta' &&\n calls.has(ci)\n ) {\n calls.get(ci)!.buf +=\n (evt.delta as string|undefined) ?? ''\n return []\n }\n\n if (\n type === 'toolcall_end' &&\n calls.has(ci)\n ) {\n const call = calls.get(ci)!\n calls.delete(ci)\n let label = ''\n try {\n const args = JSON.parse(call.buf) as\n Record<string, unknown>\n label = String(\n args.command ??\n args.file_path ??\n args.query ?? ''\n ).split('\\n')[0].slice(0, 72)\n } catch {\n // unparseable tool args\n }\n return [`[${call.name}] ${label}`]\n }\n\n return []\n }\n\n return { process, flush:flushBuf }\n}\n\nfunction writePromptFile (prompt:string):string {\n const name = `nightralph-${Date.now()}-` +\n `${Math.random().toString(36).slice(2)}.md`\n const filePath = join(tmpdir(), name)\n writeFileSync(filePath, prompt)\n return filePath\n}\n\nfunction cleanupPromptFile (filePath:string):void {\n try {\n unlinkSync(filePath)\n } catch {\n // already removed\n }\n}\n\nexport type AgentResult = {\n exitCode:number\n completedItems:string[]\n // true when the orchestrator killed the agent at\n // the timeout; exitCode is non-zero in that case\n timedOut:boolean\n}\n\n// How long to wait after the process exits before giving up on a\n// graceful pipe close and forcing the streams shut. A grandchild\n// (dev server, watcher) that inherited the agent's stdout can keep\n// the pipe open after the agent itself has been killed, which would\n// otherwise leave spawnAgent's promise pending forever.\nconst CLOSE_GRACE_MS = 2000\n\n// Agents are spawned with detached:true so they become their own\n// process group leader; this lets us kill the whole tree (agent +\n// any children it spawned, like dev servers) with one signal to\n// -pid instead of leaving orphans behind. Exported for reuse by\n// signal handling (Ctrl-C / SIGTERM).\nexport function killProcessGroup (pid:number|undefined):void {\n if (pid === undefined) return\n try {\n process.kill(-pid, 'SIGKILL')\n } catch {\n // The group kill failed (e.g. the group was already\n // reaped, or the pid is not a group leader). Fall back\n // to killing the process directly so a still-running\n // pid never escapes the kill.\n try {\n process.kill(pid, 'SIGKILL')\n } catch {\n // Process is already gone.\n }\n }\n}\n\n// Tracks every agent process spawnAgent currently has running, so\n// a Ctrl-C or SIGTERM to the orchestrator itself can kill them all\n// instead of leaving them running after the orchestrator exits.\nconst runningAgents = new Set<number>()\n\nexport function killRunningAgents ():number {\n let killed = 0\n for (const pid of runningAgents) {\n killProcessGroup(pid)\n killed++\n }\n return killed\n}\n\nexport function spawnAgent (opts:{\n prompt:string\n agentCmd:string\n model:string|null\n timeout:number\n logPath:string\n cwd?:string\n label?:string\n maxTurns?:number\n effort?:EffortLevel\n onLine?:(line:string) => void\n}):Promise<AgentResult> {\n const args:string[] = [\n ...getProviderArgs(opts.agentCmd),\n ]\n if (opts.model) {\n args.push('--model', opts.model)\n }\n const providerName = basename(opts.agentCmd)\n const isClaude = providerName === 'claude'\n const isPi = providerName === 'pi'\n\n if (opts.maxTurns) {\n if (isClaude) {\n args.push(\n '--max-turns',\n String(opts.maxTurns)\n )\n } else if (opts.onLine) {\n opts.onLine(\n 'Warning: --max-turns not ' +\n `supported by ${providerName}, ` +\n 'skipping'\n )\n }\n }\n if (opts.effort && providerName in EFFORT_LADDERS) {\n const ladder = EFFORT_LADDERS[\n providerName as ProviderName\n ]\n if (\n !(ladder as readonly string[])\n .includes(opts.effort)\n ) {\n if (opts.onLine) {\n opts.onLine(\n 'Warning: effort ' +\n `'${opts.effort}' not ` +\n 'supported by ' +\n `${providerName}, skipping`\n )\n }\n } else if (isPi) {\n args.push('--thinking', opts.effort)\n } else if (isClaude) {\n args.push('--effort', opts.effort)\n } else if (providerName === 'codex') {\n args.push(\n '-c',\n `model_reasoning_effort=${opts.effort}`\n )\n }\n }\n const prefix = opts.label ?\n ` [${opts.label}] ` :\n ' '\n\n let promptFile:string|null = null\n if (isPi) {\n promptFile = writePromptFile(opts.prompt)\n args.push(`@${promptFile}`)\n }\n\n const logStream = createWriteStream(\n opts.logPath,\n { flags:'w' }\n )\n const proc = spawn(opts.agentCmd, args, {\n stdio:['pipe', 'pipe', 'pipe'],\n cwd:opts.cwd,\n detached:true,\n })\n\n if (proc.pid !== undefined) runningAgents.add(proc.pid)\n\n proc.stdout.pipe(logStream)\n\n const piFormatter = isPi ?\n createPiStreamFormatter() :\n null\n\n const completedItems:string[] = []\n const seenItems = new Set<string>()\n\n function collectCompleted (text:string):void {\n // Reported items arrive as one multi-line text block\n // (claude), as drained single lines (pi), or as raw\n // lines (other providers); matching per line covers all\n // three, including summaries with several [x] lines.\n for (const line of text.split('\\n')) {\n const match = line.match(COMPLETED_RE)\n if (!match) continue\n const item = match[1].trim()\n if (!item || seenItems.has(item)) continue\n seenItems.add(item)\n completedItems.push(item)\n }\n }\n\n const rl = createInterface({ input:proc.stdout })\n rl.on('line', line => {\n if (isClaude) {\n const formatted = formatStreamLine(line)\n if (formatted !== null) {\n collectCompleted(formatted)\n const output = `${prefix}${formatted}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.log(output)\n }\n }\n } else if (piFormatter) {\n const lines = piFormatter.process(line)\n for (const formatted of lines) {\n collectCompleted(formatted)\n const output = `${prefix}${formatted}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.log(output)\n }\n }\n } else {\n collectCompleted(line)\n const output = `${prefix}${line}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.log(output)\n }\n }\n })\n\n proc.stderr.pipe(logStream)\n const rlErr = createInterface({ input:proc.stderr })\n rlErr.on('line', line => {\n if (isClaude && !TOOL_USE_RE.test(line)) return\n const output = `${prefix}${line}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.error(output)\n }\n })\n\n let timedOut = false\n const timeout = setTimeout(() => {\n if (proc.killed) return\n timedOut = true\n const msg = 'agent timed out after ' +\n `${opts.timeout}s; killing it`\n // The status display repaints the screen, so a\n // bare console.warn would be painted over. Route\n // the reason through onLine and into the ticket\n // log so it is visible in both places.\n logStream.write(`nightralph: ${msg}\\n`)\n if (opts.onLine) {\n opts.onLine(`${prefix}${msg}`)\n } else {\n console.warn(`${prefix}${msg}`)\n }\n killProcessGroup(proc.pid)\n }, opts.timeout * 1000)\n\n // An agent that exits before draining stdin (bad flags,\n // auth failure) closes its end of the pipe; writing to it\n // then raises EPIPE on proc.stdin. Without a listener that\n // is an uncaught 'error' event that kills the orchestrator.\n proc.stdin.on('error', err => {\n logStream.write(\n 'nightralph: stdin write failed: ' +\n `${formatErrorMessage(err)}\\n`\n )\n })\n\n if (!promptFile) {\n proc.stdin.write(opts.prompt)\n }\n proc.stdin.end()\n\n return new Promise<AgentResult>(resolve => {\n let settled = false\n let graceTimer:ReturnType<typeof setTimeout>|undefined\n\n function finish (exitCode:number):void {\n if (settled) return\n settled = true\n clearTimeout(timeout)\n if (graceTimer) clearTimeout(graceTimer)\n if (proc.pid !== undefined) {\n runningAgents.delete(proc.pid)\n }\n if (piFormatter) {\n for (const line of piFormatter.flush()) {\n collectCompleted(line)\n const output = `${prefix}${line}`\n if (opts.onLine) {\n opts.onLine(output)\n } else {\n console.log(output)\n }\n }\n }\n rl.close()\n rlErr.close()\n logStream.end()\n if (promptFile) cleanupPromptFile(promptFile)\n resolve({ exitCode, completedItems, timedOut })\n }\n\n // The process itself has exited, but 'close' waits for its\n // stdio streams to close too -- a grandchild that inherited\n // stdout/stderr can hold those pipes open indefinitely. Give\n // it a grace period, then destroy the streams ourselves so\n // the run does not hang forever on someone else's fd.\n proc.on('exit', code => {\n graceTimer = setTimeout(() => {\n killProcessGroup(proc.pid)\n proc.stdout.destroy()\n proc.stderr.destroy()\n finish(code ?? 1)\n }, CLOSE_GRACE_MS)\n })\n\n proc.on('close', code => {\n finish(code ?? 1)\n })\n proc.on('error', err => {\n if (settled) return\n settled = true\n if (graceTimer) clearTimeout(graceTimer)\n clearTimeout(timeout)\n if (proc.pid !== undefined) {\n runningAgents.delete(proc.pid)\n }\n rl.close()\n rlErr.close()\n logStream.end()\n if (promptFile) cleanupPromptFile(promptFile)\n console.error(\n 'Agent process error:',\n formatErrorMessage(err)\n )\n resolve({\n exitCode:1,\n completedItems,\n timedOut,\n })\n })\n })\n}\n\nexport function dryRun (\n tickets:Array<Ticket>,\n specBody:string,\n testCmd:string\n):void {\n listTickets(tickets)\n\n console.log('\\nSimulated wave order:')\n for (const { wave, ready } of simulateWaves(tickets)) {\n console.log(\n ` Wave ${wave}: ` +\n ready.map(t => t.filename).join(', ')\n )\n }\n\n const stuck = detectDeadlocks(tickets)\n if (stuck.length > 0) {\n console.log(\n '\\nDeadlocked tickets: ' +\n stuck.map(t => t.filename).join(', ')\n )\n }\n\n const firstReady = findReadyTickets(tickets)\n if (firstReady.length > 0) {\n console.log(\n '\\nPrompt for first ready ticket ' +\n `(${firstReady[0].filename}):\\n`\n )\n console.log(\n renderPrompt(specBody, firstReady[0],\n { testCmd })\n )\n }\n}\n\nexport function dryRunIsolated (opts:{\n tickets:Array<Ticket>\n specBody:string\n repoRoot:string\n repoName:string\n conflictStrategy:MergeConflictStrategy\n progressPath:string\n testCmd:string\n effort?:EffortLevel\n retries?:number\n retryDelay?:number\n}):void {\n listTickets(opts.tickets)\n\n console.log('\\nSimulated wave order:')\n for (const { wave, ready } of simulateWaves(\n opts.tickets\n )) {\n console.log(\n ` Wave ${wave}: ` +\n ready.map(t => t.filename).join(', ')\n )\n for (const t of ready) {\n const num = String(t.num).padStart(2, '0')\n const branchName = buildBranchName(\n opts.repoRoot, opts.repoName, t\n )\n const worktreePath =\n `../${opts.repoName}.${num}-${t.slug}`\n console.log(` worktree: ${worktreePath}`)\n console.log(` branch: ${branchName}`)\n }\n }\n\n const stuck = detectDeadlocks(opts.tickets)\n if (stuck.length > 0) {\n console.log(\n '\\nDeadlocked tickets: ' +\n stuck.map(t => t.filename).join(', ')\n )\n }\n\n const firstReady = findReadyTickets(opts.tickets)\n if (firstReady.length > 0) {\n console.log(\n '\\nPrompt for first ready ticket ' +\n `(${firstReady[0].filename}):\\n`\n )\n console.log(\n renderPrompt(\n opts.specBody, firstReady[0],\n { testCmd:opts.testCmd }\n )\n )\n }\n\n const strategyDesc =\n opts.conflictStrategy === 'respawn' ?\n 'respawn (re-run agent on conflict)' :\n 'stop (stop merging on conflict)'\n console.log(\n `\\nTest command: ${opts.testCmd}`\n )\n console.log(\n `Effort: ${opts.effort ?? '(provider default)'}`\n )\n console.log(\n `Retries: ${opts.retries ?? DEFAULT_RETRIES}`\n )\n console.log(\n 'Retry delay: ' +\n `${opts.retryDelay ?? 0}s`\n )\n console.log(\n `\\nMerge strategy: ${strategyDesc}`\n )\n console.log(`Progress file: ${opts.progressPath}`)\n}\n\n// Runs the project's test command in a ticket's worktree.\n// Writes the output to a per-ticket log either way, and\n// returns true only when the suite is green.\nasync function runTestGate (opts:{\n testCmd:string\n ticket:Ticket\n worktreePath:string\n timeout:number\n logsDir:string\n attempt?:number\n log:(msg:string) => void\n registry?:Set<number>\n}):Promise<boolean> {\n const result = await runTestCmd({\n cmd:opts.testCmd,\n cwd:opts.worktreePath,\n timeout:opts.timeout,\n registry:opts.registry,\n })\n const testLogPath = attemptLogPath(\n opts.logsDir, opts.ticket, opts.attempt ?? 1,\n '.test.log'\n )\n writeFileSync(testLogPath, result.output)\n\n if (result.exitCode !== 0) {\n opts.log(\n ` ${opts.ticket.filename}: tests failed ` +\n `(exit ${result.exitCode}); ` +\n `see ${testLogPath}`\n )\n return false\n }\n\n opts.log(` ${opts.ticket.filename}: tests passed`)\n return true\n}\n\n// Re-runs the agent in a ticket's existing worktree\n// after a merge conflict, then retries the merge once.\n// Called at most once per ticket per wave.\nasync function respawnAndRetryMerge (opts:{\n repoRoot:string\n baseBranch:string\n branch:string\n ticket:Ticket\n worktreePath:string\n specBody:string\n agentCmd:string\n model:string|null\n timeout:number\n logsDir:string\n testCmd:string\n maxTurns?:number\n onLine?:(msg:string) => void\n}):Promise<boolean> {\n const log = (msg:string):void => {\n if (opts.onLine) {\n opts.onLine(msg)\n } else {\n console.log(msg)\n }\n }\n\n await updateWorktreeFromBase(\n opts.worktreePath, opts.baseBranch\n )\n\n const msg1 = ` ${opts.ticket.filename}: respawning agent ` +\n 'to resolve merge conflict'\n if (opts.onLine) {\n opts.onLine(msg1)\n } else {\n console.log(msg1)\n }\n\n const prompt = renderMergePrompt(\n opts.specBody, opts.ticket\n )\n const logPath = join(\n opts.logsDir,\n opts.ticket.filename.replace(/\\.md$/, '.respawn.log')\n )\n const label = opts.ticket.filename.replace(\n /\\.md$/, ''\n )\n const result = await spawnAgent({\n prompt,\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logPath,\n cwd:opts.worktreePath,\n label,\n maxTurns:opts.maxTurns,\n onLine:opts.onLine,\n })\n\n if (result.exitCode !== 0) {\n const msg2 = ` ${opts.ticket.filename}: respawned agent ` +\n `exited ${result.exitCode}`\n if (opts.onLine) {\n opts.onLine(msg2)\n } else {\n console.log(msg2)\n }\n return false\n }\n\n const passed = await runTestGate({\n testCmd:opts.testCmd,\n ticket:opts.ticket,\n worktreePath:opts.worktreePath,\n timeout:opts.timeout,\n logsDir:opts.logsDir,\n log,\n registry:runningAgents,\n })\n if (!passed) {\n log(\n ` ${opts.ticket.filename}: tests failed ` +\n 'after conflict respawn; not merging'\n )\n return false\n }\n\n const mergeResult = await mergeBranch(\n opts.repoRoot, opts.branch\n )\n if (!mergeResult.success) {\n const msg3 = ` ${opts.ticket.filename}: merge still ` +\n 'conflicted after respawn'\n if (opts.onLine) {\n opts.onLine(msg3)\n } else {\n console.log(msg3)\n }\n if (mergeResult.stderr) {\n const stderrMsg =\n ` git: ${mergeResult.stderr.trim()}`\n if (opts.onLine) {\n opts.onLine(stderrMsg)\n } else {\n console.log(stderrMsg)\n }\n }\n }\n return mergeResult.success\n}\n\nexport const DEFAULT_RETRIES = 3\n\n// Seconds to wait before the first retry; each later retry\n// doubles the wait so a provider outage is waited out instead\n// of burning every attempt back to back.\nexport const DEFAULT_RETRY_DELAY = 30\n\nexport function retryDelayFor (base:number, attempt:number):number {\n return base * 2 ** (attempt - 2)\n}\n\nfunction sleep (ms:number):Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n// Log file for one attempt: the first attempt keeps the\n// plain name so existing tooling still finds it, later\n// attempts get their own file instead of overwriting it.\nfunction attemptLogPath (\n logsDir:string,\n ticket:Ticket,\n attempt:number,\n ext:string\n):string {\n const stem = ticket.filename.replace(/\\.md$/, '')\n const suffix = attempt > 1 ? `.attempt${attempt}` : ''\n return join(logsDir, `${stem}${suffix}${ext}`)\n}\n\ntype TicketOutcome =\n | { kind:'worktree-error'; error:unknown }\n | {\n kind:'error'\n error:unknown\n worktreePath?:string\n branchName?:string\n }\n | {\n kind:'no-commits'\n worktreePath:string\n branchName:string\n }\n | {\n kind:'failed'\n reason:'exit'|'tests'\n branchName:string\n exitCode:number\n completedItems:string[]\n }\n | {\n kind:'ready'\n worktreePath:string\n branchName:string\n completedItems:string[]\n }\n\ntype TicketAttemptOpts = {\n ticket:Ticket\n repoRoot:string\n repoName:string\n baseBranch:string\n specBody:string\n agentCmd:string\n model:string|null\n timeout:number\n logsDir:string\n testCmd:string\n maxTurns?:number\n effort?:EffortLevel\n d:Display\n}\n\n// One attempt at a ticket: a fresh worktree, one agent run,\n// and the checks that decide whether the branch can merge.\n// A failed attempt removes its worktree before returning.\nasync function runTicketAttempt (\n opts:TicketAttemptOpts&{ attempt:number }\n):Promise<TicketOutcome> {\n const { ticket, d } = opts\n\n let worktree:{ worktreePath:string; branchName:string }\n try {\n worktree = await createWorktree({\n repoRoot:opts.repoRoot,\n repoName:opts.repoName,\n baseBranch:opts.baseBranch,\n ticket,\n })\n } catch (error) {\n return { kind:'worktree-error', error }\n }\n\n d.setTicketStatus(ticket.num, 'in-progress')\n const agentResult = await spawnAgent({\n prompt:renderPrompt(\n opts.specBody, ticket,\n { testCmd:opts.testCmd }\n ),\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logPath:attemptLogPath(\n opts.logsDir, ticket, opts.attempt, '.log'\n ),\n cwd:worktree.worktreePath,\n label:ticket.filename.replace(/\\.md$/, ''),\n maxTurns:opts.maxTurns,\n effort:opts.effort,\n onLine:(line) => d.log(line),\n })\n\n // A timeout kill is not the agent reporting failure.\n // Keep whatever it committed and let the test gate and\n // merge decide, instead of discarding the worktree.\n if (agentResult.timedOut) {\n d.log(\n ` ${ticket.filename}: timed out; ` +\n 'keeping the work it committed'\n )\n } else if (agentResult.exitCode !== 0) {\n d.log(\n ` ${ticket.filename}: ` +\n `agent exited ${agentResult.exitCode}`\n )\n await removeWorktreeQuietly(worktree.worktreePath, d)\n return {\n kind:'failed',\n reason:'exit',\n branchName:worktree.branchName,\n exitCode:agentResult.exitCode,\n completedItems:agentResult.completedItems,\n }\n }\n\n if (isDirty(worktree.worktreePath)) {\n const committed = await commitDirty(\n worktree.worktreePath,\n 'nightralph: auto-commit ' +\n `${ticket.filename} remaining changes`\n )\n if (committed) {\n d.log(\n ` ${ticket.filename}: ` +\n 'auto-committed remaining changes'\n )\n }\n }\n\n if (!hasNewCommits(\n opts.repoRoot, opts.baseBranch, worktree.branchName\n )) {\n await removeWorktreeQuietly(worktree.worktreePath, d)\n return {\n kind:'no-commits',\n worktreePath:worktree.worktreePath,\n branchName:worktree.branchName,\n }\n }\n\n const passed = await runTestGate({\n testCmd:opts.testCmd,\n ticket,\n worktreePath:worktree.worktreePath,\n timeout:opts.timeout,\n logsDir:opts.logsDir,\n attempt:opts.attempt,\n log:(msg) => d.log(msg),\n registry:runningAgents,\n })\n if (!passed) {\n await removeWorktreeQuietly(\n worktree.worktreePath, d\n )\n return {\n kind:'failed',\n reason:'tests',\n branchName:worktree.branchName,\n exitCode:1,\n completedItems:agentResult.completedItems,\n }\n }\n\n return {\n kind:'ready',\n worktreePath:worktree.worktreePath,\n branchName:worktree.branchName,\n completedItems:agentResult.completedItems,\n }\n}\n\n// Runs a ticket until an attempt is ready to merge or the\n// retry cap is hit. Each retry starts from a fresh worktree\n// and a higher effort level.\nasync function runTicketAttempts (\n opts:TicketAttemptOpts&{ retries:number; retryDelay:number }\n):Promise<TicketOutcome> {\n const { ticket, d } = opts\n const maxAttempts = opts.retries + 1\n const providerName = basename(opts.agentCmd)\n const isKnown = providerName in EFFORT_LADDERS\n let effort = opts.effort\n let outcome:TicketOutcome = {\n kind:'no-commits', worktreePath:'', branchName:'',\n }\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n if (attempt === 1) {\n d.log(` Starting ${ticket.filename}`)\n } else {\n if (isKnown) {\n effort = escalateEffort(\n providerName as ProviderName,\n effort\n )\n }\n const delay = retryDelayFor(opts.retryDelay, attempt)\n d.log(\n ` ${ticket.filename}: retrying ` +\n `(attempt ${attempt}/${maxAttempts}` +\n (isKnown && effort ?\n `, effort ${effort}` : '') +\n (delay > 0 ?\n `, waiting ${delay}s` : '') +\n ')'\n )\n if (delay > 0) await sleep(delay * 1000)\n }\n try {\n outcome = await runTicketAttempt({\n ...opts, attempt, effort,\n })\n } catch (error) {\n d.log(\n ` ${ticket.filename}: attempt ${attempt} ` +\n `threw: ${formatErrorMessage(error)}`\n )\n return { kind:'error', error }\n }\n if (\n outcome.kind === 'ready' ||\n outcome.kind === 'worktree-error'\n ) {\n return outcome\n }\n }\n return outcome\n}\n\n// Wraps writeProgress + commitProgress so callers do not each\n// need to guard against a commit failure (e.g. a git lock held\n// by a concurrent process) crashing the run.\nasync function saveProgress (\n repoRoot:string,\n progressPath:string,\n progress:ProgressData,\n message:string,\n d:Display\n):Promise<void> {\n writeProgress(progressPath, progress)\n try {\n await commitProgress(repoRoot, progressPath, message)\n } catch (err) {\n d.log(\n ' Failed to commit progress: ' +\n formatErrorMessage(err)\n )\n }\n}\n\nfunction runProgress (tickets:ReadonlyArray<Ticket>):RunProgress {\n return {\n completed:tickets.filter(t => t.status === 'done').length,\n total:tickets.length,\n }\n}\n\nexport async function runWaves (\n tickets:Ticket[],\n specBody:string,\n agentCmd:string,\n model:string|null,\n timeout:number,\n logsDir:string,\n testCmd:string,\n display?:Display,\n maxTurns?:number,\n effort?:EffortLevel,\n retries?:number,\n retryDelay?:number,\n):Promise<{ allDone:boolean }> {\n mkdirSync(logsDir, { recursive:true })\n\n const d = display ?? createDisplay()\n const maxAttempts = (retries ?? DEFAULT_RETRIES) + 1\n const delayBase = retryDelay ?? 0\n const providerName = basename(agentCmd)\n const isKnown = providerName in EFFORT_LADDERS\n let totalWaves = 0\n for (const _ of simulateWaves(tickets)) totalWaves++\n\n let totalCompleted = 0\n let waveNum = 0\n const failedNums = new Set<number>()\n\n while (true) {\n const ready = findReadyTickets(tickets).filter(\n t => !failedNums.has(t.num)\n )\n if (ready.length === 0) break\n\n waveNum++\n const readyNums = new Set(ready.map(t => t.num))\n const remaining = tickets.filter(t =>\n t.status === 'ready-for-agent' &&\n !readyNums.has(t.num)\n )\n d.startWave(\n waveNum,\n totalWaves,\n ready.map(t => ({\n num:t.num,\n filename:t.filename,\n })),\n runProgress(tickets),\n remaining.map(t => ({\n num:t.num,\n filename:t.filename,\n })),\n )\n\n const results = await Promise.allSettled(\n ready.map(async t => {\n const prompt = renderPrompt(specBody, t,\n { testCmd })\n const label = t.filename.replace(\n /\\.md$/, ''\n )\n d.setTicketStatus(t.num, 'in-progress')\n d.log(` Starting ${t.filename}`)\n let level = effort\n let result = await spawnAgent({\n prompt,\n agentCmd,\n model,\n timeout,\n logPath:attemptLogPath(logsDir, t, 1, '.log'),\n label,\n maxTurns,\n effort:level,\n onLine:(line) => d.log(line),\n })\n // In-place runs have no worktree or test\n // gate, so a non-zero exit is the only\n // failure that can be retried here.\n for (\n let attempt = 2;\n result.exitCode !== 0 &&\n !result.timedOut &&\n attempt <= maxAttempts;\n attempt++\n ) {\n if (isKnown) {\n level = escalateEffort(\n providerName as ProviderName,\n level\n )\n }\n const delay = retryDelayFor(delayBase, attempt)\n d.log(\n ` ${t.filename}: agent exited ` +\n `${result.exitCode}; retrying ` +\n `(attempt ${attempt}/${maxAttempts}` +\n (isKnown && level ?\n `, effort ${level}` : '') +\n (delay > 0 ?\n `, waiting ${delay}s` : '') +\n ')'\n )\n if (delay > 0) await sleep(delay * 1000)\n result = await spawnAgent({\n prompt,\n agentCmd,\n model,\n timeout,\n logPath:attemptLogPath(\n logsDir, t, attempt, '.log'\n ),\n label,\n maxTurns,\n effort:level,\n onLine:(line) => d.log(line),\n })\n }\n return { ticket:t, result }\n })\n )\n\n let waveCompleted = 0\n for (const r of results) {\n if (r.status === 'rejected') continue\n const { ticket, result } = r.value\n if (result.exitCode !== 0) {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n d.log(\n ` ${ticket.filename}: ` +\n `agent exited ${result.exitCode}`\n )\n continue\n }\n\n checkItems(ticket, result.completedItems)\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n d.setTicketStatus(ticket.num, 'done')\n d.log(\n ` ${ticket.filename}: done`\n )\n }\n\n if (waveCompleted === 0) {\n const remaining = findReadyTickets(tickets)\n .filter(t => !failedNums.has(t.num))\n if (remaining.length === 0) {\n d.log(\n '\\nNo tickets completed this wave ' +\n 'and no ready tickets remain. ' +\n 'Stopping.'\n )\n break\n }\n d.log(\n '\\nNo tickets completed this wave. ' +\n `${remaining.length} ready ticket` +\n `${remaining.length === 1 ? '' : 's'} ` +\n 'remain; continuing.'\n )\n }\n }\n\n const remaining = tickets.filter(\n t => t.status === 'ready-for-agent'\n )\n d.log(\n `\\nFinished: ${totalCompleted} completed` +\n (remaining.length > 0 ?\n `, ${remaining.length} remaining` :\n '') +\n (failedNums.size > 0 ?\n `, ${failedNums.size} failed` :\n '')\n )\n d.cleanup()\n\n return { allDone:remaining.length === 0 }\n}\n\nexport async function runWavesIsolated (opts:{\n tickets:Array<Ticket>\n specBody:string\n agentCmd:string\n model:string|null\n timeout:number\n logsDir:string\n featureName:string\n conflictStrategy:MergeConflictStrategy\n display?:Display\n testCmd:string\n maxTurns?:number\n // starting effort level; unset = provider's default\n effort?:EffortLevel\n // extra attempts per ticket after a failure; default 3\n retries?:number\n // seconds to wait before the first retry; default 30\n retryDelay?:number\n}):Promise<{ allDone:boolean }> {\n mkdirSync(opts.logsDir, { recursive:true })\n\n const d = opts.display ?? createDisplay()\n const retries = opts.retries ?? DEFAULT_RETRIES\n const retryDelay = opts.retryDelay ?? 0\n let totalWaves = 0\n for (const _ of simulateWaves(opts.tickets)) totalWaves++\n\n const repoRoot = getRepoRoot()\n const repoName = getRepoName()\n const baseBranch = getCurrentBranch()\n\n if (isDirty(repoRoot)) {\n throw new Error(\n 'Working tree is dirty; commit or stash ' +\n 'changes before running'\n )\n }\n\n const progressPath = join(\n dirname(opts.logsDir), 'progress.md'\n )\n const progress:ProgressData = mergeProgress(\n generateProgress(opts.featureName, opts.tickets),\n readProgress(progressPath)\n )\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: start ${opts.featureName}`,\n d,\n )\n\n let totalCompleted = 0\n let waveNum = 0\n const failedNums = new Set<number>()\n\n while (true) {\n const ready = findReadyTickets(opts.tickets).filter(\n t => !failedNums.has(t.num)\n )\n if (ready.length === 0) break\n\n waveNum++\n const readyNums = new Set(ready.map(t => t.num))\n const remaining = opts.tickets.filter(t =>\n t.status === 'ready-for-agent' &&\n !readyNums.has(t.num)\n )\n d.startWave(\n waveNum,\n totalWaves,\n ready.map(t => ({\n num:t.num,\n filename:t.filename,\n })),\n runProgress(opts.tickets),\n remaining.map(t => ({\n num:t.num,\n filename:t.filename,\n })),\n )\n\n // Each ticket runs its own attempt loop in parallel.\n // Progress is recorded afterwards, sequentially, so\n // commits on the base branch never race each other.\n const outcomes = await Promise.all(\n ready.map(t => runTicketAttempts({\n ticket:t,\n repoRoot,\n repoName,\n baseBranch,\n specBody:opts.specBody,\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logsDir:opts.logsDir,\n testCmd:opts.testCmd,\n maxTurns:opts.maxTurns,\n effort:opts.effort,\n retries,\n retryDelay,\n d,\n }))\n )\n\n let waveCompleted = 0\n const successfulBranches:Array<{\n branch:string\n ticketNum:number\n worktreePath:string\n }> = []\n const ticketsByNum = new Map<number, Ticket>()\n const worktreePathsByNum = new Map<number, string>()\n\n for (let i = 0; i < outcomes.length; i++) {\n const outcome = outcomes[i]\n const ticket = ready[i]\n\n if (outcome.kind === 'worktree-error') {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n d.log(\n ` ${ticket.filename}: failed to create ` +\n `worktree: ${formatErrorMessage(outcome.error)}`\n )\n checkTicket(progress, ticket.num, {\n branch:'',\n exitCode:-1,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n 'worktree error',\n d,\n )\n continue\n }\n\n if (outcome.kind === 'error') {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n d.log(\n ` ${ticket.filename}: attempt error: ` +\n formatErrorMessage(outcome.error)\n )\n checkTicket(progress, ticket.num, {\n branch:outcome.branchName ?? '',\n exitCode:-1,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} error`,\n d,\n )\n continue\n }\n\n if (outcome.kind === 'no-commits') {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n d.log(\n ` ${ticket.filename}: agent exited 0 ` +\n 'but made no changes; leaving ticket ' +\n 'ready-for-agent'\n )\n checkTicket(progress, ticket.num, {\n branch:outcome.branchName,\n exitCode:0,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n 'no commits',\n d,\n )\n continue\n }\n\n if (outcome.kind === 'failed') {\n failedNums.add(ticket.num)\n d.setTicketStatus(ticket.num, 'failed')\n if (outcome.reason === 'exit') {\n checkItems(ticket, outcome.completedItems)\n }\n // Acceptance criteria are not met when the\n // suite is red, so checklist items the agent\n // claimed are not checked off in that case.\n checkTicket(progress, ticket.num, {\n branch:outcome.branchName,\n exitCode:outcome.exitCode,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n (outcome.reason === 'tests' ?\n 'tests failed' :\n 'failed'),\n d,\n )\n continue\n }\n\n checkItems(ticket, outcome.completedItems)\n d.log(\n ` ${ticket.filename}: agent finished, ` +\n 'awaiting merge'\n )\n ticketsByNum.set(ticket.num, ticket)\n worktreePathsByNum.set(\n ticket.num, outcome.worktreePath\n )\n successfulBranches.push({\n branch:outcome.branchName,\n ticketNum:ticket.num,\n worktreePath:outcome.worktreePath,\n })\n }\n\n if (successfulBranches.length > 0) {\n await commitTicketFiles(\n repoRoot,\n successfulBranches\n .map(sb =>\n ticketsByNum.get(sb.ticketNum)!\n ),\n d,\n )\n\n const mergeResult = await mergeWave({\n repoRoot,\n baseBranch,\n branches:successfulBranches,\n strategy:opts.conflictStrategy,\n })\n\n for (const branchResult of mergeResult.merged) {\n const ticket = ticketsByNum.get(\n branchResult.ticketNum\n )\n if (!ticket) continue\n\n if (branchResult.merged) {\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n d.setTicketStatus(ticket.num, 'done')\n d.log(\n ` ${ticket.filename}: done`\n )\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} done`,\n d,\n )\n\n const worktreePath = worktreePathsByNum.get(\n ticket.num\n )\n if (worktreePath) {\n await removeWorktreeQuietly(\n worktreePath, d\n )\n }\n } else {\n const worktreePath = worktreePathsByNum.get(\n ticket.num\n )\n const recovered =\n opts.conflictStrategy === 'respawn' &&\n worktreePath ?\n await respawnAndRetryMerge({\n repoRoot,\n baseBranch,\n branch:branchResult.branch,\n ticket,\n worktreePath,\n specBody:opts.specBody,\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logsDir:opts.logsDir,\n testCmd:opts.testCmd,\n maxTurns:opts.maxTurns,\n onLine:(msg) => d.log(msg),\n }) :\n false\n\n if (recovered) {\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n d.setTicketStatus(ticket.num, 'done')\n d.log(\n ` ${ticket.filename}: done ` +\n '(resolved via respawn)'\n )\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n 'done (respawn)',\n d,\n )\n\n if (worktreePath) {\n try {\n await removeWorktree(\n worktreePath,\n { force:true }\n )\n } catch (err) {\n d.log(\n ' Failed to remove worktree ' +\n `${worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n }\n } else {\n // Without this the ticket stays\n // ready-for-agent and the wave loop\n // would re-run it forever; excluding it\n // from later waves of this run ends the\n // loop while the file keeps its status\n // for the next run.\n failedNums.add(ticket.num)\n d.log(\n ` ${ticket.filename}: merge failed, ` +\n 'staying ready-for-agent'\n )\n if (branchResult.stderr) {\n d.log(\n ' git: ' +\n branchResult.stderr.trim()\n )\n }\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n done:false,\n })\n await saveProgress(\n repoRoot,\n progressPath,\n progress,\n `nightralph: ${ticket.filename} ` +\n 'merge failed',\n d,\n )\n }\n }\n }\n\n if (mergeResult.stoppedAt) {\n d.log(\n '\\nMerge stopped at ' +\n `${mergeResult.stoppedAt.branch}`\n )\n\n for (const sb of successfulBranches) {\n const ticket = ticketsByNum.get(sb.ticketNum)\n if (ticket && ticket.status === 'done') continue\n try {\n await removeWorktree(\n sb.worktreePath,\n { force:true }\n )\n } catch (err) {\n d.log(\n ' Failed to remove worktree ' +\n `${sb.worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n }\n\n break\n }\n }\n\n if (waveCompleted === 0) {\n const remaining = findReadyTickets(\n opts.tickets\n ).filter(t => !failedNums.has(t.num))\n if (remaining.length === 0) {\n d.log(\n '\\nNo tickets completed this wave ' +\n 'and no ready tickets remain. ' +\n 'Stopping.'\n )\n break\n }\n d.log(\n '\\nNo tickets completed this wave. ' +\n `${remaining.length} ready ticket` +\n `${remaining.length === 1 ? '' : 's'} ` +\n 'remain; continuing.'\n )\n }\n }\n\n const remaining = opts.tickets.filter(\n t => t.status === 'ready-for-agent'\n )\n d.log(\n `\\nFinished: ${totalCompleted} completed` +\n (remaining.length > 0 ?\n `, ${remaining.length} remaining` :\n '') +\n (failedNums.size > 0 ?\n `, ${failedNums.size} failed` :\n '')\n )\n d.cleanup()\n\n return { allDone:remaining.length === 0 }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["process", "remaining"]
7
7
  }
@@ -67,6 +67,7 @@ export declare function dryRun(tickets: Array<Ticket>, specBody: string, testCmd
67
67
  export declare function dryRunIsolated(opts: {
68
68
  tickets: Array<Ticket>;
69
69
  specBody: string;
70
+ repoRoot: string;
70
71
  repoName: string;
71
72
  conflictStrategy: MergeConflictStrategy;
72
73
  progressPath: string;