nightralph 0.0.21 → 0.0.23
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/index.js +77 -8
- package/dist/index.js.map +2 -2
- package/dist/meta.json +10 -10
- package/dist/orchestrator.js +56 -6
- package/dist/orchestrator.js.map +2 -2
- package/dist/setup.js +2 -1
- package/dist/setup.js.map +2 -2
- package/dist/skills/codebase-design/DEEPENING.md +37 -0
- package/dist/skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/dist/skills/codebase-design/SKILL.md +114 -0
- package/dist/skills/codebase-design/agents/openai.yaml +3 -0
- package/dist/src/orchestrator.d.ts.map +1 -1
- package/dist/src/setup.d.ts +1 -1
- package/dist/src/setup.d.ts.map +1 -1
- package/dist/src/testcmd.d.ts +1 -0
- package/dist/src/testcmd.d.ts.map +1 -1
- package/dist/src/worktree.d.ts.map +1 -1
- package/dist/testcmd.js +9 -0
- package/dist/testcmd.js.map +2 -2
- package/dist/worktree.js +10 -1
- package/dist/worktree.js.map +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -27,7 +27,8 @@ var SKILL_DIRS = [
|
|
|
27
27
|
"domain-modeling",
|
|
28
28
|
"to-spec",
|
|
29
29
|
"to-tickets",
|
|
30
|
-
"tdd"
|
|
30
|
+
"tdd",
|
|
31
|
+
"codebase-design"
|
|
31
32
|
];
|
|
32
33
|
var DOC_TEMPLATES = [
|
|
33
34
|
"triage-labels.md",
|
|
@@ -295,7 +296,7 @@ function createWorktree(opts) {
|
|
|
295
296
|
return result;
|
|
296
297
|
}
|
|
297
298
|
__name(createWorktree, "createWorktree");
|
|
298
|
-
async function
|
|
299
|
+
async function removeWorktreeNow(worktreePath, opts) {
|
|
299
300
|
const args = [
|
|
300
301
|
"-C",
|
|
301
302
|
worktreePath,
|
|
@@ -306,6 +307,15 @@ async function removeWorktree(worktreePath, opts) {
|
|
|
306
307
|
args.push(worktreePath);
|
|
307
308
|
await execFileAsync("git", args);
|
|
308
309
|
}
|
|
310
|
+
__name(removeWorktreeNow, "removeWorktreeNow");
|
|
311
|
+
function removeWorktree(worktreePath, opts) {
|
|
312
|
+
const result = worktreeQueue.then(
|
|
313
|
+
() => removeWorktreeNow(worktreePath, opts)
|
|
314
|
+
);
|
|
315
|
+
worktreeQueue = result.catch(() => {
|
|
316
|
+
});
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
309
319
|
__name(removeWorktree, "removeWorktree");
|
|
310
320
|
function hasNewCommits(repoRoot, base, branch) {
|
|
311
321
|
const stdout = execFileSync(
|
|
@@ -1024,6 +1034,9 @@ function runTestCmd(opts) {
|
|
|
1024
1034
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1025
1035
|
detached: true
|
|
1026
1036
|
});
|
|
1037
|
+
if (child.pid !== void 0 && opts.registry) {
|
|
1038
|
+
opts.registry.add(child.pid);
|
|
1039
|
+
}
|
|
1027
1040
|
const chunks = [];
|
|
1028
1041
|
child.stdout.on("data", (d) => chunks.push(String(d)));
|
|
1029
1042
|
child.stderr.on("data", (d) => chunks.push(String(d)));
|
|
@@ -1042,6 +1055,9 @@ function runTestCmd(opts) {
|
|
|
1042
1055
|
if (settled) return;
|
|
1043
1056
|
settled = true;
|
|
1044
1057
|
clearTimeout(timer);
|
|
1058
|
+
if (child.pid !== void 0 && opts.registry) {
|
|
1059
|
+
opts.registry.delete(child.pid);
|
|
1060
|
+
}
|
|
1045
1061
|
chunks.push(String(err));
|
|
1046
1062
|
resolve({
|
|
1047
1063
|
exitCode: 1,
|
|
@@ -1052,6 +1068,9 @@ function runTestCmd(opts) {
|
|
|
1052
1068
|
if (settled) return;
|
|
1053
1069
|
settled = true;
|
|
1054
1070
|
clearTimeout(timer);
|
|
1071
|
+
if (child.pid !== void 0 && opts.registry) {
|
|
1072
|
+
opts.registry.delete(child.pid);
|
|
1073
|
+
}
|
|
1055
1074
|
resolve({
|
|
1056
1075
|
exitCode: code ?? 1,
|
|
1057
1076
|
output: chunks.join("")
|
|
@@ -1242,6 +1261,7 @@ function renderMergePrompt(specBody, ticket) {
|
|
|
1242
1261
|
"3. Commit the resolved files.",
|
|
1243
1262
|
"",
|
|
1244
1263
|
"Do NOT re-implement the ticket from scratch.",
|
|
1264
|
+
"Do NOT read or modify files outside your current directory (the worktree).",
|
|
1245
1265
|
"Do NOT run git push."
|
|
1246
1266
|
].join("\n");
|
|
1247
1267
|
}
|
|
@@ -1623,6 +1643,7 @@ function spawnAgent(opts) {
|
|
|
1623
1643
|
__name(finish, "finish");
|
|
1624
1644
|
proc.on("exit", (code) => {
|
|
1625
1645
|
graceTimer = setTimeout(() => {
|
|
1646
|
+
killProcessGroup(proc.pid);
|
|
1626
1647
|
proc.stdout.destroy();
|
|
1627
1648
|
proc.stderr.destroy();
|
|
1628
1649
|
finish(code ?? 1);
|
|
@@ -1733,7 +1754,7 @@ Test command: ${opts.testCmd ?? "(none)"}`
|
|
|
1733
1754
|
`Retries: ${opts.retries ?? DEFAULT_RETRIES}`
|
|
1734
1755
|
);
|
|
1735
1756
|
console.log(
|
|
1736
|
-
`Retry delay: ${opts.retryDelay ??
|
|
1757
|
+
`Retry delay: ${opts.retryDelay ?? 0}s`
|
|
1737
1758
|
);
|
|
1738
1759
|
console.log(
|
|
1739
1760
|
`
|
|
@@ -1746,7 +1767,8 @@ async function runTestGate(opts) {
|
|
|
1746
1767
|
const result = await runTestCmd({
|
|
1747
1768
|
cmd: opts.testCmd,
|
|
1748
1769
|
cwd: opts.worktreePath,
|
|
1749
|
-
timeout: opts.timeout
|
|
1770
|
+
timeout: opts.timeout,
|
|
1771
|
+
registry: opts.registry
|
|
1750
1772
|
});
|
|
1751
1773
|
const testLogPath = attemptLogPath(
|
|
1752
1774
|
opts.logsDir,
|
|
@@ -1822,7 +1844,8 @@ async function respawnAndRetryMerge(opts) {
|
|
|
1822
1844
|
worktreePath: opts.worktreePath,
|
|
1823
1845
|
timeout: opts.timeout,
|
|
1824
1846
|
logsDir: opts.logsDir,
|
|
1825
|
-
log
|
|
1847
|
+
log,
|
|
1848
|
+
registry: runningAgents
|
|
1826
1849
|
});
|
|
1827
1850
|
if (!passed) {
|
|
1828
1851
|
log(
|
|
@@ -1938,7 +1961,12 @@ async function runTicketAttempt(opts) {
|
|
|
1938
1961
|
opts.baseBranch,
|
|
1939
1962
|
worktree.branchName
|
|
1940
1963
|
)) {
|
|
1941
|
-
|
|
1964
|
+
await removeWorktreeQuietly(worktree.worktreePath, d);
|
|
1965
|
+
return {
|
|
1966
|
+
kind: "no-commits",
|
|
1967
|
+
worktreePath: worktree.worktreePath,
|
|
1968
|
+
branchName: worktree.branchName
|
|
1969
|
+
};
|
|
1942
1970
|
}
|
|
1943
1971
|
if (opts.testCmd) {
|
|
1944
1972
|
const passed = await runTestGate({
|
|
@@ -1948,7 +1976,8 @@ async function runTicketAttempt(opts) {
|
|
|
1948
1976
|
timeout: opts.timeout,
|
|
1949
1977
|
logsDir: opts.logsDir,
|
|
1950
1978
|
attempt: opts.attempt,
|
|
1951
|
-
log: /* @__PURE__ */ __name((msg) => d.log(msg), "log")
|
|
1979
|
+
log: /* @__PURE__ */ __name((msg) => d.log(msg), "log"),
|
|
1980
|
+
registry: runningAgents
|
|
1952
1981
|
});
|
|
1953
1982
|
if (!passed) {
|
|
1954
1983
|
await removeWorktreeQuietly(
|
|
@@ -1977,7 +2006,11 @@ async function runTicketAttempts(opts) {
|
|
|
1977
2006
|
const maxAttempts = opts.retries + 1;
|
|
1978
2007
|
const isPi = basename2(opts.agentCmd) === "pi";
|
|
1979
2008
|
let thinking = opts.thinking;
|
|
1980
|
-
let outcome = {
|
|
2009
|
+
let outcome = {
|
|
2010
|
+
kind: "no-commits",
|
|
2011
|
+
worktreePath: "",
|
|
2012
|
+
branchName: ""
|
|
2013
|
+
};
|
|
1981
2014
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1982
2015
|
if (attempt === 1) {
|
|
1983
2016
|
d.log(` Starting ${ticket.filename}`);
|
|
@@ -2238,6 +2271,18 @@ async function runWavesIsolated(opts) {
|
|
|
2238
2271
|
d.log(
|
|
2239
2272
|
` ${ticket.filename}: failed to create worktree: ${formatErrorMessage(outcome.error)}`
|
|
2240
2273
|
);
|
|
2274
|
+
checkTicket(progress, ticket.num, {
|
|
2275
|
+
branch: "",
|
|
2276
|
+
exitCode: -1,
|
|
2277
|
+
done: false
|
|
2278
|
+
});
|
|
2279
|
+
await saveProgress(
|
|
2280
|
+
repoRoot,
|
|
2281
|
+
progressPath,
|
|
2282
|
+
progress,
|
|
2283
|
+
`nightralph: ${ticket.filename} worktree error`,
|
|
2284
|
+
d
|
|
2285
|
+
);
|
|
2241
2286
|
continue;
|
|
2242
2287
|
}
|
|
2243
2288
|
if (outcome.kind === "error") {
|
|
@@ -2246,6 +2291,18 @@ async function runWavesIsolated(opts) {
|
|
|
2246
2291
|
d.log(
|
|
2247
2292
|
` ${ticket.filename}: attempt error: ` + formatErrorMessage(outcome.error)
|
|
2248
2293
|
);
|
|
2294
|
+
checkTicket(progress, ticket.num, {
|
|
2295
|
+
branch: outcome.branchName ?? "",
|
|
2296
|
+
exitCode: -1,
|
|
2297
|
+
done: false
|
|
2298
|
+
});
|
|
2299
|
+
await saveProgress(
|
|
2300
|
+
repoRoot,
|
|
2301
|
+
progressPath,
|
|
2302
|
+
progress,
|
|
2303
|
+
`nightralph: ${ticket.filename} error`,
|
|
2304
|
+
d
|
|
2305
|
+
);
|
|
2249
2306
|
continue;
|
|
2250
2307
|
}
|
|
2251
2308
|
if (outcome.kind === "no-commits") {
|
|
@@ -2254,6 +2311,18 @@ async function runWavesIsolated(opts) {
|
|
|
2254
2311
|
d.log(
|
|
2255
2312
|
` ${ticket.filename}: agent exited 0 but made no changes; leaving ticket ready-for-agent`
|
|
2256
2313
|
);
|
|
2314
|
+
checkTicket(progress, ticket.num, {
|
|
2315
|
+
branch: outcome.branchName,
|
|
2316
|
+
exitCode: 0,
|
|
2317
|
+
done: false
|
|
2318
|
+
});
|
|
2319
|
+
await saveProgress(
|
|
2320
|
+
repoRoot,
|
|
2321
|
+
progressPath,
|
|
2322
|
+
progress,
|
|
2323
|
+
`nightralph: ${ticket.filename} no commits`,
|
|
2324
|
+
d
|
|
2325
|
+
);
|
|
2257
2326
|
continue;
|
|
2258
2327
|
}
|
|
2259
2328
|
if (outcome.kind === "failed") {
|