nightralph 0.0.6 → 0.0.8
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/README.md +8 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/meta.json +14 -8
- package/dist/orchestrator.js +89 -3
- package/dist/orchestrator.js.map +2 -2
- package/dist/src/orchestrator.d.ts +1 -0
- package/dist/src/orchestrator.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ so they can't drift as long as you install the skills with this package.
|
|
|
25
25
|
* [Install Dependency Skills](#install-dependency-skills)
|
|
26
26
|
- [Workflow](#workflow)
|
|
27
27
|
* [Create Issues](#create-issues)
|
|
28
|
-
* [
|
|
28
|
+
* [Examples](#examples)
|
|
29
29
|
- [How It Works](#how-it-works)
|
|
30
30
|
* [Select a ticket](#select-a-ticket)
|
|
31
31
|
* [Worktrees](#worktrees)
|
|
@@ -104,7 +104,7 @@ The `nightralph` CLI does the `tdd` part of the workflow.
|
|
|
104
104
|
>
|
|
105
105
|
|
|
106
106
|
|
|
107
|
-
###
|
|
107
|
+
### Examples
|
|
108
108
|
|
|
109
109
|
After you have the tickets, use the `nightralph` loop to execute.
|
|
110
110
|
The `to-tickets` skill produces markdown files at
|
|
@@ -114,6 +114,9 @@ The `to-tickets` skill produces markdown files at
|
|
|
114
114
|
# Auto-discover .scratch features and run with claude
|
|
115
115
|
npx nightralph claude -m claude-opus-4-6
|
|
116
116
|
|
|
117
|
+
# Run with pi and an OpenRouter model
|
|
118
|
+
npx nightralph pi -m openrouter/z-ai/glm-5.3-flash
|
|
119
|
+
|
|
117
120
|
# Dry run to inspect the dependency graph and prompt
|
|
118
121
|
npx nightralph codex --dry-run
|
|
119
122
|
|
|
@@ -131,7 +134,7 @@ Flags:
|
|
|
131
134
|
|
|
132
135
|
| Flag | Required | Default | Description |
|
|
133
136
|
|------|----------|---------|-------------|
|
|
134
|
-
| `<provider>` | yes | -- | Agent
|
|
137
|
+
| `<provider>` | yes | -- | Agent harness to spawn (e.g. `claude`, `codex`, `pi`) |
|
|
135
138
|
| `-m`, `--model` | no | -- | Model flag passed to the agent |
|
|
136
139
|
| `--spec <name>` | no | auto | Feature name (resolves `.scratch/<name>/`) |
|
|
137
140
|
| `--dry-run` | no | -- | Show wave order and prompt without running |
|
|
@@ -161,6 +164,8 @@ Notes:
|
|
|
161
164
|
actually be implemented without a permission prompt:
|
|
162
165
|
* `claude`: `--print --dangerously-skip-permissions`
|
|
163
166
|
* `codex`: `exec --full-auto`
|
|
167
|
+
* `pi`: `-p --approve --no-session`
|
|
168
|
+
(prompt delivered via temp file, not stdin)
|
|
164
169
|
|
|
165
170
|
|
|
166
171
|
## How It Works
|
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ yargs(hideBin(process.argv)).scriptName("nightralph").usage("$0 <command>").comm
|
|
|
69
69
|
"Execute tickets with the given provider",
|
|
70
70
|
(y) => y.positional("provider", {
|
|
71
71
|
type: "string",
|
|
72
|
-
describe: "Agent CLI to spawn (e.g. claude, codex)",
|
|
72
|
+
describe: "Agent CLI to spawn (e.g. claude, codex, pi)",
|
|
73
73
|
demandOption: true
|
|
74
74
|
}).option("m", {
|
|
75
75
|
alias: "model",
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env node\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport yargs from 'yargs'\nimport { hideBin } from 'yargs/helpers'\nimport { select } from '@inquirer/prompts'\nimport { setup, checkGhAuth, type TrackerKind } from './setup.js'\nimport {\n scanTickets,\n dryRun,\n dryRunIsolated,\n runWaves,\n runWavesIsolated,\n} from './orchestrator.js'\nimport {\n findFeatureDirs,\n resolveIssuesDir,\n getScriptDir,\n} from './resolve.js'\nimport { getRepoRoot, getRepoName } from './worktree.js'\n\nexport { findFeatureDirs, resolveIssuesDir }\n\nconst scriptDir = getScriptDir(import.meta.url)\n\nyargs(hideBin(process.argv))\n .scriptName('nightralph')\n .usage('$0 <command>')\n .command(\n 'setup',\n 'Install bundled skills and doc templates',\n y => y.option('claude', {\n type:'boolean',\n describe:'Also create .claude/skills/ symlinks',\n default:false,\n }),\n async argv => {\n const tracker = await select<TrackerKind>({\n message:'Issue tracker format',\n choices:[\n {\n name:'Local Markdown',\n value:'local' as const,\n description:'Issues as .md files in ' +\n '.scratch/',\n },\n {\n name:'GitHub Issues',\n value:'github' as const,\n description:'Issues via gh CLI',\n },\n ],\n })\n\n if (tracker === 'github') {\n if (!checkGhAuth()) {\n console.error(\n 'GitHub Issues requires the gh CLI, ' +\n 'authenticated.\\n' +\n 'Install: https://cli.github.com\\n' +\n 'Then run: gh auth login'\n )\n process.exit(2)\n }\n }\n\n setup({\n bundledSkillsDir:join(scriptDir, 'skills'),\n docsTemplatesDir:join(\n scriptDir, 'docs-templates'\n ),\n projectDir:process.cwd(),\n claude:argv.claude,\n tracker,\n })\n }\n )\n .command(\n '$0 <provider>',\n 'Execute tickets with the given provider',\n y => y\n .positional('provider', {\n type:'string',\n describe:'Agent CLI to spawn (e.g. claude, codex)',\n demandOption:true,\n })\n .option('m', {\n alias:'model',\n type:'string',\n describe:'Model passed to the agent',\n })\n .option('spec', {\n type:'string',\n describe:'Feature name ' +\n '(resolves .scratch/<name>/)',\n })\n .option('dry-run', {\n type:'boolean',\n describe:'Show wave order without running',\n default:false,\n })\n .option('timeout', {\n type:'number',\n describe:'Kill agent after N seconds',\n default:900,\n })\n .option('X', {\n type:'boolean',\n describe:'Stop on merge conflict instead of ' +\n 're-spawning',\n default:false,\n }),\n async argv => {\n await runExecute({\n provider:argv.provider as string,\n model:argv.model as string|undefined,\n spec:argv.spec as string|undefined,\n dryRun:argv.dryRun as boolean|undefined,\n timeout:argv.timeout as\n number|undefined,\n stopOnConflict:argv.X as\n boolean|undefined,\n })\n }\n )\n .strict()\n .demandCommand(1, 'Specify a command or provider')\n .help()\n .parse()\n\nfunction isGitRepo ():boolean {\n try {\n getRepoRoot()\n return true\n } catch {\n return false\n }\n}\n\nfunction extractFeatureName (spec:string):string {\n const parts = spec.split(\n /[\\\\/]/\n )\n const scratchIndex = parts.indexOf('.scratch')\n if (scratchIndex >= 0 && scratchIndex < parts.length - 1) {\n return parts[scratchIndex + 1]\n }\n return parts[parts.length - 2] ??\n parts[parts.length - 1] ?? 'feature'\n}\n\nasync function runExecute (argv:{\n provider:string\n model?:string\n spec?:string\n dryRun?:boolean\n timeout?:number\n stopOnConflict?:boolean\n}):Promise<void> {\n const { dir, spec } = await resolveIssuesDir(\n argv.spec\n )\n\n if (!existsSync(dir)) {\n console.error(`Directory not found: ${dir}`)\n process.exit(2)\n }\n if (!existsSync(spec)) {\n console.error(`Spec file not found: ${spec}`)\n process.exit(2)\n }\n\n const specBody = readFileSync(spec, 'utf8')\n const tickets = scanTickets(dir)\n\n if (tickets.length === 0) {\n console.log('No ticket files found. Exiting.')\n return\n }\n\n console.log(`Found ${tickets.length} tickets`)\n\n const knownNums = new Set(tickets.map(t => t.num))\n for (const t of tickets) {\n const unknown = t.blockers.filter(\n b => !knownNums.has(b)\n )\n if (unknown.length > 0) {\n console.warn(\n `${t.filename}: blockers ` +\n `[${unknown.join(', ')}] ` +\n 'not found in directory'\n )\n }\n t.blockers = t.blockers.filter(\n b => knownNums.has(b)\n )\n }\n\n const logsDir = join(dirname(dir), 'logs')\n const timeout = argv.timeout ?? 300\n const featureName = extractFeatureName(spec)\n const conflictStrategy = argv.stopOnConflict ?\n 'stop' :\n 'respawn'\n const progressPath = join(\n dirname(dir), 'progress.md'\n )\n\n if (argv.dryRun) {\n if (isGitRepo()) {\n const repoName = getRepoName()\n dryRunIsolated({\n tickets,\n specBody,\n repoName,\n conflictStrategy,\n progressPath,\n })\n } else {\n dryRun(tickets, specBody)\n }\n return\n }\n\n let result:{ allDone:boolean }\n\n if (isGitRepo()) {\n result = await runWavesIsolated({\n tickets,\n specBody,\n agentCmd:argv.provider,\n model:argv.model ?? null,\n timeout,\n logsDir,\n featureName,\n conflictStrategy,\n })\n } else {\n result = await runWaves(\n tickets, specBody,\n argv.provider, argv.model ?? null,\n timeout,\n logsDir,\n )\n }\n\n if (!result.allDone) {\n process.exit(1)\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;AAEA,SAAS,YAAY,oBAAoB;AACzC,SAAS,SAAS,YAAY;AAC9B,OAAO,WAAW;AAClB,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB,SAAS,OAAO,mBAAqC;AACrD;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP,SAAS,aAAa,mBAAmB;AAIzC,MAAM,YAAY,aAAa,YAAY,GAAG;AAE9C,MAAM,QAAQ,QAAQ,IAAI,CAAC,EACtB,WAAW,YAAY,EACvB,MAAM,cAAc,EACpB;AAAA,EACG;AAAA,EACA;AAAA,EACA,OAAK,EAAE,OAAO,UAAU;AAAA,IACpB,MAAK;AAAA,IACL,UAAS;AAAA,IACT,SAAQ;AAAA,EACZ,CAAC;AAAA,EACD,OAAM,SAAQ;AACV,UAAM,UAAU,MAAM,OAAoB;AAAA,MACtC,SAAQ;AAAA,MACR,SAAQ;AAAA,QACJ;AAAA,UACI,MAAK;AAAA,UACL,OAAM;AAAA,UACN,aAAY;AAAA,QAEhB;AAAA,QACA;AAAA,UACI,MAAK;AAAA,UACL,OAAM;AAAA,UACN,aAAY;AAAA,QAChB;AAAA,MACJ;AAAA,IACJ,CAAC;AAED,QAAI,YAAY,UAAU;AACtB,UAAI,CAAC,YAAY,GAAG;AAChB,gBAAQ;AAAA,UACJ;AAAA,QAIJ;AACA,gBAAQ,KAAK,CAAC;AAAA,MAClB;AAAA,IACJ;AAEA,UAAM;AAAA,MACF,kBAAiB,KAAK,WAAW,QAAQ;AAAA,MACzC,kBAAiB;AAAA,QACb;AAAA,QAAW;AAAA,MACf;AAAA,MACA,YAAW,QAAQ,IAAI;AAAA,MACvB,QAAO,KAAK;AAAA,MACZ;AAAA,IACJ,CAAC;AAAA,EACL;AACJ,EACC;AAAA,EACG;AAAA,EACA;AAAA,EACA,OAAK,EACA,WAAW,YAAY;AAAA,IACpB,MAAK;AAAA,IACL,UAAS;AAAA,
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport yargs from 'yargs'\nimport { hideBin } from 'yargs/helpers'\nimport { select } from '@inquirer/prompts'\nimport { setup, checkGhAuth, type TrackerKind } from './setup.js'\nimport {\n scanTickets,\n dryRun,\n dryRunIsolated,\n runWaves,\n runWavesIsolated,\n} from './orchestrator.js'\nimport {\n findFeatureDirs,\n resolveIssuesDir,\n getScriptDir,\n} from './resolve.js'\nimport { getRepoRoot, getRepoName } from './worktree.js'\n\nexport { findFeatureDirs, resolveIssuesDir }\n\nconst scriptDir = getScriptDir(import.meta.url)\n\nyargs(hideBin(process.argv))\n .scriptName('nightralph')\n .usage('$0 <command>')\n .command(\n 'setup',\n 'Install bundled skills and doc templates',\n y => y.option('claude', {\n type:'boolean',\n describe:'Also create .claude/skills/ symlinks',\n default:false,\n }),\n async argv => {\n const tracker = await select<TrackerKind>({\n message:'Issue tracker format',\n choices:[\n {\n name:'Local Markdown',\n value:'local' as const,\n description:'Issues as .md files in ' +\n '.scratch/',\n },\n {\n name:'GitHub Issues',\n value:'github' as const,\n description:'Issues via gh CLI',\n },\n ],\n })\n\n if (tracker === 'github') {\n if (!checkGhAuth()) {\n console.error(\n 'GitHub Issues requires the gh CLI, ' +\n 'authenticated.\\n' +\n 'Install: https://cli.github.com\\n' +\n 'Then run: gh auth login'\n )\n process.exit(2)\n }\n }\n\n setup({\n bundledSkillsDir:join(scriptDir, 'skills'),\n docsTemplatesDir:join(\n scriptDir, 'docs-templates'\n ),\n projectDir:process.cwd(),\n claude:argv.claude,\n tracker,\n })\n }\n )\n .command(\n '$0 <provider>',\n 'Execute tickets with the given provider',\n y => y\n .positional('provider', {\n type:'string',\n describe:'Agent CLI to spawn ' +\n '(e.g. claude, codex, pi)',\n demandOption:true,\n })\n .option('m', {\n alias:'model',\n type:'string',\n describe:'Model passed to the agent',\n })\n .option('spec', {\n type:'string',\n describe:'Feature name ' +\n '(resolves .scratch/<name>/)',\n })\n .option('dry-run', {\n type:'boolean',\n describe:'Show wave order without running',\n default:false,\n })\n .option('timeout', {\n type:'number',\n describe:'Kill agent after N seconds',\n default:900,\n })\n .option('X', {\n type:'boolean',\n describe:'Stop on merge conflict instead of ' +\n 're-spawning',\n default:false,\n }),\n async argv => {\n await runExecute({\n provider:argv.provider as string,\n model:argv.model as string|undefined,\n spec:argv.spec as string|undefined,\n dryRun:argv.dryRun as boolean|undefined,\n timeout:argv.timeout as\n number|undefined,\n stopOnConflict:argv.X as\n boolean|undefined,\n })\n }\n )\n .strict()\n .demandCommand(1, 'Specify a command or provider')\n .help()\n .parse()\n\nfunction isGitRepo ():boolean {\n try {\n getRepoRoot()\n return true\n } catch {\n return false\n }\n}\n\nfunction extractFeatureName (spec:string):string {\n const parts = spec.split(\n /[\\\\/]/\n )\n const scratchIndex = parts.indexOf('.scratch')\n if (scratchIndex >= 0 && scratchIndex < parts.length - 1) {\n return parts[scratchIndex + 1]\n }\n return parts[parts.length - 2] ??\n parts[parts.length - 1] ?? 'feature'\n}\n\nasync function runExecute (argv:{\n provider:string\n model?:string\n spec?:string\n dryRun?:boolean\n timeout?:number\n stopOnConflict?:boolean\n}):Promise<void> {\n const { dir, spec } = await resolveIssuesDir(\n argv.spec\n )\n\n if (!existsSync(dir)) {\n console.error(`Directory not found: ${dir}`)\n process.exit(2)\n }\n if (!existsSync(spec)) {\n console.error(`Spec file not found: ${spec}`)\n process.exit(2)\n }\n\n const specBody = readFileSync(spec, 'utf8')\n const tickets = scanTickets(dir)\n\n if (tickets.length === 0) {\n console.log('No ticket files found. Exiting.')\n return\n }\n\n console.log(`Found ${tickets.length} tickets`)\n\n const knownNums = new Set(tickets.map(t => t.num))\n for (const t of tickets) {\n const unknown = t.blockers.filter(\n b => !knownNums.has(b)\n )\n if (unknown.length > 0) {\n console.warn(\n `${t.filename}: blockers ` +\n `[${unknown.join(', ')}] ` +\n 'not found in directory'\n )\n }\n t.blockers = t.blockers.filter(\n b => knownNums.has(b)\n )\n }\n\n const logsDir = join(dirname(dir), 'logs')\n const timeout = argv.timeout ?? 300\n const featureName = extractFeatureName(spec)\n const conflictStrategy = argv.stopOnConflict ?\n 'stop' :\n 'respawn'\n const progressPath = join(\n dirname(dir), 'progress.md'\n )\n\n if (argv.dryRun) {\n if (isGitRepo()) {\n const repoName = getRepoName()\n dryRunIsolated({\n tickets,\n specBody,\n repoName,\n conflictStrategy,\n progressPath,\n })\n } else {\n dryRun(tickets, specBody)\n }\n return\n }\n\n let result:{ allDone:boolean }\n\n if (isGitRepo()) {\n result = await runWavesIsolated({\n tickets,\n specBody,\n agentCmd:argv.provider,\n model:argv.model ?? null,\n timeout,\n logsDir,\n featureName,\n conflictStrategy,\n })\n } else {\n result = await runWaves(\n tickets, specBody,\n argv.provider, argv.model ?? null,\n timeout,\n logsDir,\n )\n }\n\n if (!result.allDone) {\n process.exit(1)\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/meta.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"inputs": {
|
|
3
3
|
"src/index.ts": {
|
|
4
|
-
"bytes":
|
|
4
|
+
"bytes": 7011,
|
|
5
5
|
"imports": [],
|
|
6
6
|
"format": "esm"
|
|
7
7
|
},
|
|
8
8
|
"src/orchestrator.ts": {
|
|
9
|
-
"bytes":
|
|
9
|
+
"bytes": 30365,
|
|
10
10
|
"imports": [],
|
|
11
11
|
"format": "esm"
|
|
12
12
|
},
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"imports": [],
|
|
42
42
|
"exports": [],
|
|
43
43
|
"inputs": {},
|
|
44
|
-
"bytes":
|
|
44
|
+
"bytes": 10940
|
|
45
45
|
},
|
|
46
46
|
"dist/index.js": {
|
|
47
47
|
"imports": [
|
|
@@ -98,16 +98,16 @@
|
|
|
98
98
|
"entryPoint": "src/index.ts",
|
|
99
99
|
"inputs": {
|
|
100
100
|
"src/index.ts": {
|
|
101
|
-
"bytesInOutput":
|
|
101
|
+
"bytesInOutput": 5227
|
|
102
102
|
}
|
|
103
103
|
},
|
|
104
|
-
"bytes":
|
|
104
|
+
"bytes": 5460
|
|
105
105
|
},
|
|
106
106
|
"dist/orchestrator.js.map": {
|
|
107
107
|
"imports": [],
|
|
108
108
|
"exports": [],
|
|
109
109
|
"inputs": {},
|
|
110
|
-
"bytes":
|
|
110
|
+
"bytes": 47352
|
|
111
111
|
},
|
|
112
112
|
"dist/orchestrator.js": {
|
|
113
113
|
"imports": [
|
|
@@ -121,6 +121,11 @@
|
|
|
121
121
|
"kind": "import-statement",
|
|
122
122
|
"external": true
|
|
123
123
|
},
|
|
124
|
+
{
|
|
125
|
+
"path": "node:os",
|
|
126
|
+
"kind": "import-statement",
|
|
127
|
+
"external": true
|
|
128
|
+
},
|
|
124
129
|
{
|
|
125
130
|
"path": "node:path",
|
|
126
131
|
"kind": "import-statement",
|
|
@@ -149,6 +154,7 @@
|
|
|
149
154
|
],
|
|
150
155
|
"exports": [
|
|
151
156
|
"TICKET_RE",
|
|
157
|
+
"createPiStreamFormatter",
|
|
152
158
|
"dryRun",
|
|
153
159
|
"dryRunIsolated",
|
|
154
160
|
"findReadyTickets",
|
|
@@ -168,10 +174,10 @@
|
|
|
168
174
|
"entryPoint": "src/orchestrator.ts",
|
|
169
175
|
"inputs": {
|
|
170
176
|
"src/orchestrator.ts": {
|
|
171
|
-
"bytesInOutput":
|
|
177
|
+
"bytesInOutput": 23243
|
|
172
178
|
}
|
|
173
179
|
},
|
|
174
|
-
"bytes":
|
|
180
|
+
"bytes": 23717
|
|
175
181
|
},
|
|
176
182
|
"dist/setup.js.map": {
|
|
177
183
|
"imports": [],
|
package/dist/orchestrator.js
CHANGED
|
@@ -6,8 +6,10 @@ import {
|
|
|
6
6
|
mkdirSync,
|
|
7
7
|
readFileSync,
|
|
8
8
|
writeFileSync,
|
|
9
|
+
unlinkSync,
|
|
9
10
|
readdirSync
|
|
10
11
|
} from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
11
13
|
import { join, dirname, basename } from "node:path";
|
|
12
14
|
import { createInterface } from "node:readline";
|
|
13
15
|
import {
|
|
@@ -201,7 +203,15 @@ const PROVIDER_ARGS = {
|
|
|
201
203
|
"stream-json",
|
|
202
204
|
"--dangerously-skip-permissions"
|
|
203
205
|
],
|
|
204
|
-
codex: ["exec", "--full-auto"]
|
|
206
|
+
codex: ["exec", "--full-auto"],
|
|
207
|
+
pi: [
|
|
208
|
+
"-p",
|
|
209
|
+
"--verbose",
|
|
210
|
+
"--approve",
|
|
211
|
+
"--no-session",
|
|
212
|
+
"--mode",
|
|
213
|
+
"json"
|
|
214
|
+
]
|
|
205
215
|
};
|
|
206
216
|
function getProviderArgs(cmd) {
|
|
207
217
|
const name = basename(cmd);
|
|
@@ -242,6 +252,64 @@ function formatStreamLine(line) {
|
|
|
242
252
|
return null;
|
|
243
253
|
}
|
|
244
254
|
__name(formatStreamLine, "formatStreamLine");
|
|
255
|
+
function createPiStreamFormatter() {
|
|
256
|
+
const calls = /* @__PURE__ */ new Map();
|
|
257
|
+
return (line) => {
|
|
258
|
+
let obj;
|
|
259
|
+
try {
|
|
260
|
+
obj = JSON.parse(line);
|
|
261
|
+
} catch {
|
|
262
|
+
return line;
|
|
263
|
+
}
|
|
264
|
+
const evt = obj.assistantMessageEvent;
|
|
265
|
+
if (!evt) return null;
|
|
266
|
+
const type = evt.type;
|
|
267
|
+
const ci = evt.contentIndex ?? -1;
|
|
268
|
+
if (type === "text_delta") {
|
|
269
|
+
return evt.delta ?? null;
|
|
270
|
+
}
|
|
271
|
+
if (type === "toolcall_start") {
|
|
272
|
+
calls.set(ci, {
|
|
273
|
+
name: evt.toolName ?? "?",
|
|
274
|
+
buf: ""
|
|
275
|
+
});
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
if (type === "toolcall_delta" && calls.has(ci)) {
|
|
279
|
+
calls.get(ci).buf += evt.delta ?? "";
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
if (type === "toolcall_end" && calls.has(ci)) {
|
|
283
|
+
const call = calls.get(ci);
|
|
284
|
+
calls.delete(ci);
|
|
285
|
+
let label = "";
|
|
286
|
+
try {
|
|
287
|
+
const args = JSON.parse(call.buf);
|
|
288
|
+
label = String(
|
|
289
|
+
args.command ?? args.file_path ?? args.query ?? ""
|
|
290
|
+
).split("\n")[0].slice(0, 72);
|
|
291
|
+
} catch {
|
|
292
|
+
}
|
|
293
|
+
return `[${call.name}] ${label}`;
|
|
294
|
+
}
|
|
295
|
+
return null;
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
__name(createPiStreamFormatter, "createPiStreamFormatter");
|
|
299
|
+
function writePromptFile(prompt) {
|
|
300
|
+
const name = `nightralph-${Date.now()}-${Math.random().toString(36).slice(2)}.md`;
|
|
301
|
+
const filePath = join(tmpdir(), name);
|
|
302
|
+
writeFileSync(filePath, prompt);
|
|
303
|
+
return filePath;
|
|
304
|
+
}
|
|
305
|
+
__name(writePromptFile, "writePromptFile");
|
|
306
|
+
function cleanupPromptFile(filePath) {
|
|
307
|
+
try {
|
|
308
|
+
unlinkSync(filePath);
|
|
309
|
+
} catch {
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
__name(cleanupPromptFile, "cleanupPromptFile");
|
|
245
313
|
function spawnAgent(opts) {
|
|
246
314
|
const args = [
|
|
247
315
|
...getProviderArgs(opts.agentCmd)
|
|
@@ -249,8 +317,15 @@ function spawnAgent(opts) {
|
|
|
249
317
|
if (opts.model) {
|
|
250
318
|
args.push("--model", opts.model);
|
|
251
319
|
}
|
|
252
|
-
const
|
|
320
|
+
const providerName = basename(opts.agentCmd);
|
|
321
|
+
const isClaude = providerName === "claude";
|
|
322
|
+
const isPi = providerName === "pi";
|
|
253
323
|
const prefix = opts.label ? ` [${opts.label}] ` : " ";
|
|
324
|
+
let promptFile = null;
|
|
325
|
+
if (isPi) {
|
|
326
|
+
promptFile = writePromptFile(opts.prompt);
|
|
327
|
+
args.push(`@${promptFile}`);
|
|
328
|
+
}
|
|
254
329
|
const logStream = createWriteStream(
|
|
255
330
|
opts.logPath,
|
|
256
331
|
{ flags: "w" }
|
|
@@ -260,6 +335,7 @@ function spawnAgent(opts) {
|
|
|
260
335
|
cwd: opts.cwd
|
|
261
336
|
});
|
|
262
337
|
proc.stdout.pipe(logStream);
|
|
338
|
+
const piFormatter = isPi ? createPiStreamFormatter() : null;
|
|
263
339
|
const rl = createInterface({ input: proc.stdout });
|
|
264
340
|
rl.on("line", (line) => {
|
|
265
341
|
if (isClaude) {
|
|
@@ -267,6 +343,11 @@ function spawnAgent(opts) {
|
|
|
267
343
|
if (formatted !== null) {
|
|
268
344
|
console.log(`${prefix}${formatted}`);
|
|
269
345
|
}
|
|
346
|
+
} else if (piFormatter) {
|
|
347
|
+
const formatted = piFormatter(line);
|
|
348
|
+
if (formatted !== null) {
|
|
349
|
+
console.log(`${prefix}${formatted}`);
|
|
350
|
+
}
|
|
270
351
|
} else {
|
|
271
352
|
console.log(`${prefix}${line}`);
|
|
272
353
|
}
|
|
@@ -284,7 +365,9 @@ function spawnAgent(opts) {
|
|
|
284
365
|
proc.kill("SIGKILL");
|
|
285
366
|
}
|
|
286
367
|
}, opts.timeout * 1e3);
|
|
287
|
-
|
|
368
|
+
if (!promptFile) {
|
|
369
|
+
proc.stdin.write(opts.prompt);
|
|
370
|
+
}
|
|
288
371
|
proc.stdin.end();
|
|
289
372
|
return new Promise((resolve) => {
|
|
290
373
|
proc.on("close", (code) => {
|
|
@@ -292,6 +375,7 @@ function spawnAgent(opts) {
|
|
|
292
375
|
rl.close();
|
|
293
376
|
rlErr.close();
|
|
294
377
|
logStream.end();
|
|
378
|
+
if (promptFile) cleanupPromptFile(promptFile);
|
|
295
379
|
resolve(code ?? 1);
|
|
296
380
|
});
|
|
297
381
|
proc.on("error", (err) => {
|
|
@@ -299,6 +383,7 @@ function spawnAgent(opts) {
|
|
|
299
383
|
rl.close();
|
|
300
384
|
rlErr.close();
|
|
301
385
|
logStream.end();
|
|
386
|
+
if (promptFile) cleanupPromptFile(promptFile);
|
|
302
387
|
console.error(
|
|
303
388
|
"Agent process error:",
|
|
304
389
|
formatErrorMessage(err)
|
|
@@ -761,6 +846,7 @@ Finished: ${totalCompleted} completed` + (remaining.length > 0 ? `, ${remaining.
|
|
|
761
846
|
__name(runWavesIsolated, "runWavesIsolated");
|
|
762
847
|
export {
|
|
763
848
|
TICKET_RE,
|
|
849
|
+
createPiStreamFormatter,
|
|
764
850
|
dryRun,
|
|
765
851
|
dryRunIsolated,
|
|
766
852
|
findReadyTickets,
|
package/dist/orchestrator.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/orchestrator.ts"],
|
|
4
|
-
"sourcesContent": ["import { spawn } from 'node:child_process'\nimport {\n createWriteStream,\n mkdirSync,\n readFileSync,\n writeFileSync,\n readdirSync,\n} from 'node:fs'\nimport { join, dirname, basename } from 'node:path'\nimport { createInterface } from 'node:readline'\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'\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\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\nexport function markDone (ticket:Ticket):void {\n const updated = ticket.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\nexport function renderPrompt (\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. ' +\n 'Implement the ticket.',\n '',\n 'Time is limited. Follow these rules:',\n '- Spend at most 2 minutes reading existing ' +\n 'code. Read only the files directly relevant ' +\n 'to the ticket.',\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 '- Start writing code as soon as you understand ' +\n 'the immediate context. You can read more ' +\n 'files as needed while implementing.',\n '- Commit your work when finished.',\n '',\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:['exec', '--full-auto'],\n}\n\nexport function getProviderArgs (cmd:string):string[] {\n const name = basename(cmd)\n return PROVIDER_ARGS[name] ?? []\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 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}):Promise<number> {\n const args:string[] = [\n ...getProviderArgs(opts.agentCmd),\n ]\n if (opts.model) {\n args.push('--model', opts.model)\n }\n\n const isClaude = basename(opts.agentCmd) === 'claude'\n const prefix = opts.label ?\n ` [${opts.label}] ` :\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 })\n\n proc.stdout.pipe(logStream)\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 console.log(`${prefix}${formatted}`)\n }\n } else {\n console.log(`${prefix}${line}`)\n }\n })\n\n proc.stderr.pipe(logStream)\n const rlErr = createInterface({ input:proc.stderr })\n rlErr.on('line', line => {\n console.error(`${prefix}${line}`)\n })\n\n const timeout = setTimeout(() => {\n if (!proc.killed) {\n console.warn(\n 'Agent did not exit in ' +\n `${opts.timeout}s; killing.`\n )\n proc.kill('SIGKILL')\n }\n }, opts.timeout * 1000)\n\n proc.stdin.write(opts.prompt)\n proc.stdin.end()\n\n return new Promise<number>(resolve => {\n proc.on('close', code => {\n clearTimeout(timeout)\n rl.close()\n rlErr.close()\n logStream.end()\n resolve(code ?? 1)\n })\n proc.on('error', err => {\n clearTimeout(timeout)\n rl.close()\n rlErr.close()\n logStream.end()\n console.error(\n 'Agent process error:',\n formatErrorMessage(err)\n )\n resolve(1)\n })\n })\n}\n\nexport function dryRun (\n tickets:Array<Ticket>,\n specBody: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 )\n }\n}\n\nexport function dryRunIsolated (opts:{\n tickets:Array<Ticket>\n specBody:string\n repoName:string\n conflictStrategy:MergeConflictStrategy\n progressPath:string\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(opts.specBody, firstReady[0])\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 `\\nMerge strategy: ${strategyDesc}`\n )\n console.log(`Progress file: ${opts.progressPath}`)\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}):Promise<boolean> {\n await updateWorktreeFromBase(\n opts.worktreePath, opts.baseBranch\n )\n\n console.log(\n ` ${opts.ticket.filename}: respawning agent ` +\n 'to resolve merge conflict'\n )\n const prompt = renderPrompt(opts.specBody, opts.ticket)\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 exitCode = 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 })\n\n if (exitCode !== 0) {\n console.log(\n ` ${opts.ticket.filename}: respawned agent ` +\n `exited ${exitCode}`\n )\n return false\n }\n\n const merged = await mergeBranch(\n opts.repoRoot, opts.branch\n )\n if (!merged) {\n console.log(\n ` ${opts.ticket.filename}: merge still ` +\n 'conflicted after respawn'\n )\n }\n return merged\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):Promise<{ allDone:boolean }> {\n mkdirSync(logsDir, { recursive:true })\n\n let totalCompleted = 0\n let waveNum = 0\n\n while (true) {\n const ready = findReadyTickets(tickets)\n if (ready.length === 0) break\n\n waveNum++\n console.log(\n `\\nWave ${waveNum}: ` +\n ready.map(t => t.filename).join(', ')\n )\n\n const results = await Promise.allSettled(\n ready.map(async t => {\n const prompt = renderPrompt(specBody, t)\n const logPath = join(\n logsDir,\n t.filename.replace(/\\.md$/, '.log')\n )\n const label = t.filename.replace(\n /\\.md$/, ''\n )\n console.log(` Starting ${t.filename}`)\n const code = await spawnAgent({\n prompt,\n agentCmd,\n model,\n timeout,\n logPath,\n label,\n })\n return { ticket:t, exitCode:code }\n })\n )\n\n let waveCompleted = 0\n for (const r of results) {\n if (r.status === 'rejected') continue\n const { ticket, exitCode } = r.value\n if (exitCode !== 0) {\n console.log(\n ` ${ticket.filename}: ` +\n `agent exited ${exitCode}`\n )\n continue\n }\n\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n console.log(\n ` ${ticket.filename}: done`\n )\n }\n\n if (waveCompleted === 0) {\n console.log(\n '\\nNo tickets completed this wave. ' +\n 'Stopping.'\n )\n break\n }\n }\n\n const remaining = tickets.filter(\n t => t.status === 'ready-for-agent'\n )\n console.log(\n `\\nFinished: ${totalCompleted} completed` +\n (remaining.length > 0 ?\n `, ${remaining.length} remaining` :\n '')\n )\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}):Promise<{ allDone:boolean }> {\n mkdirSync(opts.logsDir, { recursive:true })\n\n const repoRoot = getRepoRoot()\n const repoName = getRepoName()\n const baseBranch = getCurrentBranch()\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 writeProgress(progressPath, progress)\n await commitProgress(\n repoRoot,\n progressPath,\n `nightralph: start ${opts.featureName}`\n )\n\n let totalCompleted = 0\n let waveNum = 0\n\n while (true) {\n const ready = findReadyTickets(opts.tickets)\n if (ready.length === 0) break\n\n waveNum++\n console.log(\n `\\nWave ${waveNum}: ` +\n ready.map(t => t.filename).join(', ')\n )\n\n const worktreeSettled = await Promise.allSettled(\n ready.map(t => createWorktree({\n repoRoot,\n repoName,\n baseBranch,\n ticket:t,\n }))\n )\n\n const activeTickets:Array<Ticket> = []\n const worktrees:Array<{\n worktreePath:string\n branchName:string\n }> = []\n\n for (let i = 0; i < worktreeSettled.length; i++) {\n const settled = worktreeSettled[i]\n const ticket = ready[i]\n if (settled.status === 'rejected') {\n console.log(\n ` ${ticket.filename}: failed to create ` +\n `worktree: ${formatErrorMessage(settled.reason)}`\n )\n continue\n }\n activeTickets.push(ticket)\n worktrees.push(settled.value)\n }\n\n const results = await Promise.allSettled(\n activeTickets.map((t, i) => {\n const prompt = renderPrompt(opts.specBody, t)\n const logPath = join(\n opts.logsDir,\n t.filename.replace(/\\.md$/, '.log')\n )\n const label = t.filename.replace(\n /\\.md$/, ''\n )\n console.log(` Starting ${t.filename}`)\n return spawnAgent({\n prompt,\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logPath,\n cwd:worktrees[i].worktreePath,\n label,\n })\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 < results.length; i++) {\n const r = results[i]\n if (r.status === 'rejected') continue\n const exitCode = r.value\n const ticket = activeTickets[i]\n const worktree = worktrees[i]\n\n if (exitCode !== 0) {\n console.log(\n ` ${ticket.filename}: ` +\n `agent exited ${exitCode}`\n )\n checkTicket(progress, ticket.num, {\n branch:worktree.branchName,\n exitCode,\n done:false,\n })\n writeProgress(progressPath, progress)\n await commitProgress(\n repoRoot,\n progressPath,\n `nightralph: ${ticket.filename} failed`\n )\n\n try {\n await removeWorktree(worktree.worktreePath)\n } catch (err) {\n console.error(\n ' Failed to remove worktree ' +\n `${worktree.worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n continue\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 console.log(\n ` ${ticket.filename}: ` +\n 'auto-committed remaining changes'\n )\n }\n }\n\n if (!hasNewCommits(\n repoRoot, baseBranch, worktree.branchName\n )) {\n console.log(\n ` ${ticket.filename}: agent exited 0 ` +\n 'but made no changes; leaving ticket ' +\n 'ready-for-agent'\n )\n continue\n }\n\n console.log(\n ` ${ticket.filename}: agent finished, ` +\n 'awaiting merge'\n )\n ticketsByNum.set(ticket.num, ticket)\n worktreePathsByNum.set(\n ticket.num, worktree.worktreePath\n )\n successfulBranches.push({\n branch:worktree.branchName,\n ticketNum:ticket.num,\n worktreePath:worktree.worktreePath,\n })\n }\n\n if (successfulBranches.length > 0) {\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 console.log(\n ` ${ticket.filename}: done`\n )\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n })\n writeProgress(progressPath, progress)\n await commitProgress(\n repoRoot,\n progressPath,\n `nightralph: ${ticket.filename} done`\n )\n\n const worktreePath = worktreePathsByNum.get(\n ticket.num\n )\n if (worktreePath) {\n try {\n await removeWorktree(worktreePath)\n } catch (err) {\n console.error(\n ' Failed to remove worktree ' +\n `${worktreePath}: ` +\n formatErrorMessage(err)\n )\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 }) :\n false\n\n if (recovered) {\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n console.log(\n ` ${ticket.filename}: done ` +\n '(resolved via respawn)'\n )\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n })\n writeProgress(progressPath, progress)\n await commitProgress(\n repoRoot,\n progressPath,\n `nightralph: ${ticket.filename} ` +\n 'done (respawn)'\n )\n\n if (worktreePath) {\n try {\n await removeWorktree(worktreePath)\n } catch (err) {\n console.error(\n ' Failed to remove worktree ' +\n `${worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n }\n } else {\n console.log(\n ` ${ticket.filename}: merge failed, ` +\n 'staying ready-for-agent'\n )\n }\n }\n }\n\n if (mergeResult.stoppedAt) {\n console.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(sb.worktreePath)\n } catch (err) {\n console.error(\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 console.log(\n '\\nNo tickets completed this wave. ' +\n 'Stopping.'\n )\n break\n }\n }\n\n const remaining = opts.tickets.filter(\n t => t.status === 'ready-for-agent'\n )\n console.log(\n `\\nFinished: ${totalCompleted} completed` +\n (remaining.length > 0 ?\n `, ${remaining.length} remaining` :\n '')\n )\n\n return { allDone:remaining.length === 0 }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { spawn } 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 {\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'\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\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\nexport function markDone (ticket:Ticket):void {\n const updated = ticket.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\nexport function renderPrompt (\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. ' +\n 'Implement the ticket.',\n '',\n 'Time is limited. Follow these rules:',\n '- Spend at most 2 minutes reading existing ' +\n 'code. Read only the files directly relevant ' +\n 'to the ticket.',\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 '- Start writing code as soon as you understand ' +\n 'the immediate context. You can read more ' +\n 'files as needed while implementing.',\n '- Commit your work when finished.',\n '',\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:['exec', '--full-auto'],\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\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 function createPiStreamFormatter ():((line:string) => string|null) {\n const calls = new Map<number, { name:string; buf:string }>()\n\n return (line:string):string|null => {\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 null\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 return (evt.delta as string|undefined) ??\n null\n }\n\n if (type === 'toolcall_start') {\n calls.set(ci, {\n name:(evt.toolName as\n string|undefined) ?? '?',\n buf:'',\n })\n return null\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 null\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 null\n }\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 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}):Promise<number> {\n const args:string[] = [\n ...getProviderArgs(opts.agentCmd),\n ]\n if (opts.model) {\n args.push('--model', opts.model)\n }\n\n const providerName = basename(opts.agentCmd)\n const isClaude = providerName === 'claude'\n const isPi = providerName === 'pi'\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 })\n\n proc.stdout.pipe(logStream)\n\n const piFormatter = isPi ?\n createPiStreamFormatter() :\n null\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 console.log(`${prefix}${formatted}`)\n }\n } else if (piFormatter) {\n const formatted = piFormatter(line)\n if (formatted !== null) {\n console.log(`${prefix}${formatted}`)\n }\n } else {\n console.log(`${prefix}${line}`)\n }\n })\n\n proc.stderr.pipe(logStream)\n const rlErr = createInterface({ input:proc.stderr })\n rlErr.on('line', line => {\n console.error(`${prefix}${line}`)\n })\n\n const timeout = setTimeout(() => {\n if (!proc.killed) {\n console.warn(\n 'Agent did not exit in ' +\n `${opts.timeout}s; killing.`\n )\n proc.kill('SIGKILL')\n }\n }, opts.timeout * 1000)\n\n if (!promptFile) {\n proc.stdin.write(opts.prompt)\n }\n proc.stdin.end()\n\n return new Promise<number>(resolve => {\n proc.on('close', code => {\n clearTimeout(timeout)\n rl.close()\n rlErr.close()\n logStream.end()\n if (promptFile) cleanupPromptFile(promptFile)\n resolve(code ?? 1)\n })\n proc.on('error', err => {\n clearTimeout(timeout)\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(1)\n })\n })\n}\n\nexport function dryRun (\n tickets:Array<Ticket>,\n specBody: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 )\n }\n}\n\nexport function dryRunIsolated (opts:{\n tickets:Array<Ticket>\n specBody:string\n repoName:string\n conflictStrategy:MergeConflictStrategy\n progressPath:string\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(opts.specBody, firstReady[0])\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 `\\nMerge strategy: ${strategyDesc}`\n )\n console.log(`Progress file: ${opts.progressPath}`)\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}):Promise<boolean> {\n await updateWorktreeFromBase(\n opts.worktreePath, opts.baseBranch\n )\n\n console.log(\n ` ${opts.ticket.filename}: respawning agent ` +\n 'to resolve merge conflict'\n )\n const prompt = renderPrompt(opts.specBody, opts.ticket)\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 exitCode = 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 })\n\n if (exitCode !== 0) {\n console.log(\n ` ${opts.ticket.filename}: respawned agent ` +\n `exited ${exitCode}`\n )\n return false\n }\n\n const merged = await mergeBranch(\n opts.repoRoot, opts.branch\n )\n if (!merged) {\n console.log(\n ` ${opts.ticket.filename}: merge still ` +\n 'conflicted after respawn'\n )\n }\n return merged\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):Promise<{ allDone:boolean }> {\n mkdirSync(logsDir, { recursive:true })\n\n let totalCompleted = 0\n let waveNum = 0\n\n while (true) {\n const ready = findReadyTickets(tickets)\n if (ready.length === 0) break\n\n waveNum++\n console.log(\n `\\nWave ${waveNum}: ` +\n ready.map(t => t.filename).join(', ')\n )\n\n const results = await Promise.allSettled(\n ready.map(async t => {\n const prompt = renderPrompt(specBody, t)\n const logPath = join(\n logsDir,\n t.filename.replace(/\\.md$/, '.log')\n )\n const label = t.filename.replace(\n /\\.md$/, ''\n )\n console.log(` Starting ${t.filename}`)\n const code = await spawnAgent({\n prompt,\n agentCmd,\n model,\n timeout,\n logPath,\n label,\n })\n return { ticket:t, exitCode:code }\n })\n )\n\n let waveCompleted = 0\n for (const r of results) {\n if (r.status === 'rejected') continue\n const { ticket, exitCode } = r.value\n if (exitCode !== 0) {\n console.log(\n ` ${ticket.filename}: ` +\n `agent exited ${exitCode}`\n )\n continue\n }\n\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n console.log(\n ` ${ticket.filename}: done`\n )\n }\n\n if (waveCompleted === 0) {\n console.log(\n '\\nNo tickets completed this wave. ' +\n 'Stopping.'\n )\n break\n }\n }\n\n const remaining = tickets.filter(\n t => t.status === 'ready-for-agent'\n )\n console.log(\n `\\nFinished: ${totalCompleted} completed` +\n (remaining.length > 0 ?\n `, ${remaining.length} remaining` :\n '')\n )\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}):Promise<{ allDone:boolean }> {\n mkdirSync(opts.logsDir, { recursive:true })\n\n const repoRoot = getRepoRoot()\n const repoName = getRepoName()\n const baseBranch = getCurrentBranch()\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 writeProgress(progressPath, progress)\n await commitProgress(\n repoRoot,\n progressPath,\n `nightralph: start ${opts.featureName}`\n )\n\n let totalCompleted = 0\n let waveNum = 0\n\n while (true) {\n const ready = findReadyTickets(opts.tickets)\n if (ready.length === 0) break\n\n waveNum++\n console.log(\n `\\nWave ${waveNum}: ` +\n ready.map(t => t.filename).join(', ')\n )\n\n const worktreeSettled = await Promise.allSettled(\n ready.map(t => createWorktree({\n repoRoot,\n repoName,\n baseBranch,\n ticket:t,\n }))\n )\n\n const activeTickets:Array<Ticket> = []\n const worktrees:Array<{\n worktreePath:string\n branchName:string\n }> = []\n\n for (let i = 0; i < worktreeSettled.length; i++) {\n const settled = worktreeSettled[i]\n const ticket = ready[i]\n if (settled.status === 'rejected') {\n console.log(\n ` ${ticket.filename}: failed to create ` +\n `worktree: ${formatErrorMessage(settled.reason)}`\n )\n continue\n }\n activeTickets.push(ticket)\n worktrees.push(settled.value)\n }\n\n const results = await Promise.allSettled(\n activeTickets.map((t, i) => {\n const prompt = renderPrompt(opts.specBody, t)\n const logPath = join(\n opts.logsDir,\n t.filename.replace(/\\.md$/, '.log')\n )\n const label = t.filename.replace(\n /\\.md$/, ''\n )\n console.log(` Starting ${t.filename}`)\n return spawnAgent({\n prompt,\n agentCmd:opts.agentCmd,\n model:opts.model,\n timeout:opts.timeout,\n logPath,\n cwd:worktrees[i].worktreePath,\n label,\n })\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 < results.length; i++) {\n const r = results[i]\n if (r.status === 'rejected') continue\n const exitCode = r.value\n const ticket = activeTickets[i]\n const worktree = worktrees[i]\n\n if (exitCode !== 0) {\n console.log(\n ` ${ticket.filename}: ` +\n `agent exited ${exitCode}`\n )\n checkTicket(progress, ticket.num, {\n branch:worktree.branchName,\n exitCode,\n done:false,\n })\n writeProgress(progressPath, progress)\n await commitProgress(\n repoRoot,\n progressPath,\n `nightralph: ${ticket.filename} failed`\n )\n\n try {\n await removeWorktree(worktree.worktreePath)\n } catch (err) {\n console.error(\n ' Failed to remove worktree ' +\n `${worktree.worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n continue\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 console.log(\n ` ${ticket.filename}: ` +\n 'auto-committed remaining changes'\n )\n }\n }\n\n if (!hasNewCommits(\n repoRoot, baseBranch, worktree.branchName\n )) {\n console.log(\n ` ${ticket.filename}: agent exited 0 ` +\n 'but made no changes; leaving ticket ' +\n 'ready-for-agent'\n )\n continue\n }\n\n console.log(\n ` ${ticket.filename}: agent finished, ` +\n 'awaiting merge'\n )\n ticketsByNum.set(ticket.num, ticket)\n worktreePathsByNum.set(\n ticket.num, worktree.worktreePath\n )\n successfulBranches.push({\n branch:worktree.branchName,\n ticketNum:ticket.num,\n worktreePath:worktree.worktreePath,\n })\n }\n\n if (successfulBranches.length > 0) {\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 console.log(\n ` ${ticket.filename}: done`\n )\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n })\n writeProgress(progressPath, progress)\n await commitProgress(\n repoRoot,\n progressPath,\n `nightralph: ${ticket.filename} done`\n )\n\n const worktreePath = worktreePathsByNum.get(\n ticket.num\n )\n if (worktreePath) {\n try {\n await removeWorktree(worktreePath)\n } catch (err) {\n console.error(\n ' Failed to remove worktree ' +\n `${worktreePath}: ` +\n formatErrorMessage(err)\n )\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 }) :\n false\n\n if (recovered) {\n markDone(ticket)\n waveCompleted++\n totalCompleted++\n console.log(\n ` ${ticket.filename}: done ` +\n '(resolved via respawn)'\n )\n checkTicket(progress, ticket.num, {\n branch:branchResult.branch,\n exitCode:0,\n })\n writeProgress(progressPath, progress)\n await commitProgress(\n repoRoot,\n progressPath,\n `nightralph: ${ticket.filename} ` +\n 'done (respawn)'\n )\n\n if (worktreePath) {\n try {\n await removeWorktree(worktreePath)\n } catch (err) {\n console.error(\n ' Failed to remove worktree ' +\n `${worktreePath}: ` +\n formatErrorMessage(err)\n )\n }\n }\n } else {\n console.log(\n ` ${ticket.filename}: merge failed, ` +\n 'staying ready-for-agent'\n )\n }\n }\n }\n\n if (mergeResult.stoppedAt) {\n console.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(sb.worktreePath)\n } catch (err) {\n console.error(\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 console.log(\n '\\nNo tickets completed this wave. ' +\n 'Stopping.'\n )\n break\n }\n }\n\n const remaining = opts.tickets.filter(\n t => t.status === 'ready-for-agent'\n )\n console.log(\n `\\nFinished: ${totalCompleted} completed` +\n (remaining.length > 0 ?\n `, ${remaining.length} remaining` :\n '')\n )\n\n return { allDone:remaining.length === 0 }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -22,6 +22,7 @@ export declare function markDone(ticket: Ticket): void;
|
|
|
22
22
|
export declare function renderPrompt(specBody: string, ticket: Ticket): string;
|
|
23
23
|
export declare function getProviderArgs(cmd: string): string[];
|
|
24
24
|
export declare function formatStreamLine(line: string): string | null;
|
|
25
|
+
export declare function createPiStreamFormatter(): ((line: string) => string | null);
|
|
25
26
|
export declare function spawnAgent(opts: {
|
|
26
27
|
prompt: string;
|
|
27
28
|
agentCmd: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator.ts"],"names":[],"mappings":"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"}
|