nightralph 0.0.29 → 0.0.32
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 +30 -19
- package/dist/index.js +37 -15
- package/dist/index.js.map +2 -2
- package/dist/meta.json +4 -4
- package/dist/orchestrator.js +37 -15
- package/dist/orchestrator.js.map +2 -2
- package/dist/src/orchestrator.d.ts +1 -1
- package/dist/src/orchestrator.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -26,12 +26,18 @@ so they can't drift as long as you install the skills with this package.
|
|
|
26
26
|
- [Workflow](#workflow)
|
|
27
27
|
* [Create Issues](#create-issues)
|
|
28
28
|
* [Examples](#examples)
|
|
29
|
+
* [Interface](#interface)
|
|
30
|
+
+ [`--spec ` option](#--spec--option)
|
|
29
31
|
- [How It Works](#how-it-works)
|
|
30
32
|
* [Select a ticket](#select-a-ticket)
|
|
31
33
|
* [Worktrees](#worktrees)
|
|
32
34
|
* [Progress](#progress)
|
|
33
35
|
- [Keep Your Machine Awake](#keep-your-machine-awake)
|
|
34
36
|
* [Mac OS](#mac-os)
|
|
37
|
+
+ [Claude Opus 4.6](#claude-opus-46)
|
|
38
|
+
+ [Claude Sonnet 5](#claude-sonnet-5)
|
|
39
|
+
+ [`pi` + OpenRouter model](#pi--openrouter-model)
|
|
40
|
+
+ [`codex` + Luna](#codex--luna)
|
|
35
41
|
|
|
36
42
|
<!-- tocstop -->
|
|
37
43
|
|
|
@@ -107,7 +113,6 @@ before a ticket can be marked `done`.
|
|
|
107
113
|
> then follow with `to-tickets`.
|
|
108
114
|
>
|
|
109
115
|
|
|
110
|
-
|
|
111
116
|
### Examples
|
|
112
117
|
|
|
113
118
|
After you have the tickets, use the `nightralph` loop to execute.
|
|
@@ -124,6 +129,9 @@ npx nightralph pi -m openrouter/z-ai/glm-5.3-flash
|
|
|
124
129
|
# Dry run to inspect the dependency graph and prompt
|
|
125
130
|
npx nightralph codex --dry-run
|
|
126
131
|
|
|
132
|
+
# Use codex with a specific model
|
|
133
|
+
npx nightralph codex -m gpt-5.6-luna
|
|
134
|
+
|
|
127
135
|
# Specify a feature by name
|
|
128
136
|
npx nightralph claude -m claude-opus-4-6 --spec my-feature
|
|
129
137
|
|
|
@@ -133,15 +141,11 @@ npx nightralph claude -m claude-opus-4-6 --max-turns 30
|
|
|
133
141
|
# Same thing, using the positional shorthand
|
|
134
142
|
npx nightralph claude -m claude-opus-4-6 30
|
|
135
143
|
|
|
136
|
-
# Start pi at medium
|
|
137
|
-
npx nightralph pi -m openrouter/z-ai/glm-5.3-flash --
|
|
144
|
+
# Start pi at medium effort and allow one escalated retry
|
|
145
|
+
npx nightralph pi -m openrouter/z-ai/glm-5.3-flash --effort medium --retries 1
|
|
138
146
|
```
|
|
139
147
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
A feature name that resolves to `.scratch/<name>/`.
|
|
143
|
-
The spec file is `.scratch/<name>/spec.md` and the issues directory
|
|
144
|
-
is `.scratch/<name>/issues/`.
|
|
148
|
+
### Interface
|
|
145
149
|
|
|
146
150
|
Flags:
|
|
147
151
|
|
|
@@ -156,8 +160,8 @@ Flags:
|
|
|
156
160
|
| `--timeout` | no | `3600` | Kill the agent after N seconds. A killed agent is not a failure: its work is kept (see Notes) |
|
|
157
161
|
| `--test-cmd <cmd>` | no | auto | Run in each worktree after the agent exits; non-zero exit rejects the ticket. Auto-detects `npm test`. Pass `""` to disable. Shares the agent's `--timeout`. The command runs in a fresh git worktree, which contains only tracked files, so a project that needs an install step should include it, for example `--test-cmd 'npm ci && npm test'` |
|
|
158
162
|
| `--max-turns <n>` | no | -- | Max agentic turns per ticket. Forwarded verbatim as `--max-turns <n>` to the provider CLI. Only `claude` accepts it; `codex` and `pi` reject it as an unknown option and the agent exits immediately. Applies to every agent spawn, including a re-spawn after a merge conflict. When omitted, `claude` applies no turn limit, so `--timeout` is the only cap. Reaching the limit is an error exit, so the ticket is recorded as failed |
|
|
159
|
-
| `--
|
|
160
|
-
| `--retries <n>` | no | `
|
|
163
|
+
| `--effort <level>` | no | -- | Starting effort/reasoning level. Each provider has its own ladder: `claude` supports `low`, `medium`, `high`, `xhigh`, `max` (forwarded as `--effort`); `codex` supports `low`, `medium`, `high` (forwarded as `-c model_reasoning_effort=<level>`); `pi` supports `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max` (forwarded as `--thinking`). Omitted = provider default. Each retry steps up from here (see `--retries`) |
|
|
164
|
+
| `--retries <n>` | no | `3` | Extra attempts per ticket after a failed run. Each retry starts from a fresh worktree and raises the effort level one rung (see Notes). `0` disables retries |
|
|
161
165
|
| `--retry-delay <n>` | no | `30` | Seconds to wait before the first retry; doubles each further retry (30s, 60s, 120s, ...). `0` disables the wait |
|
|
162
166
|
|
|
163
167
|
|
|
@@ -185,15 +189,15 @@ Flags:
|
|
|
185
189
|
ticket is recorded as failed. Non-zero exit, exit 0 with no new
|
|
186
190
|
commits, and a red test command all count as failures; a timeout
|
|
187
191
|
does not (see below). Each retry discards the previous worktree
|
|
188
|
-
and starts from a fresh one.
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
one level up from the previous attempt, stopping at
|
|
192
|
-
|
|
193
|
-
are spaced with exponential backoff controlled by
|
|
194
|
-
the first retry waits `--retry-delay` seconds,
|
|
195
|
-
double that, and so on. This lets provider
|
|
196
|
-
burning the next attempt. Retry
|
|
192
|
+
and starts from a fresh one. Each retry also raises the effort
|
|
193
|
+
level one rung up the provider's ladder: without `--effort` the
|
|
194
|
+
first retry uses `high`; with `--effort <level>` each retry
|
|
195
|
+
steps one level up from the previous attempt, stopping at the
|
|
196
|
+
provider's max (`max` for claude/pi, `high` for codex).
|
|
197
|
+
Retries are spaced with exponential backoff controlled by
|
|
198
|
+
`--retry-delay`: the first retry waits `--retry-delay` seconds,
|
|
199
|
+
the second waits double that, and so on. This lets provider
|
|
200
|
+
outages clear before burning the next attempt. Retry
|
|
197
201
|
logs are written to `<dir>/../logs/<ticket>.attempt<n>.log`
|
|
198
202
|
(and `.attempt<n>.test.log` for the test command) so the first
|
|
199
203
|
attempt's log is kept.
|
|
@@ -237,6 +241,13 @@ Flags:
|
|
|
237
241
|
tool-use proposals so the agent runs non-interactively)
|
|
238
242
|
|
|
239
243
|
|
|
244
|
+
#### `--spec <name>` option
|
|
245
|
+
|
|
246
|
+
A feature name that resolves to `.scratch/<name>/`.
|
|
247
|
+
The spec file is `.scratch/<name>/spec.md` and the issues directory
|
|
248
|
+
is `.scratch/<name>/issues/`.
|
|
249
|
+
|
|
250
|
+
|
|
240
251
|
## How It Works
|
|
241
252
|
|
|
242
253
|
All currently eligible tickets are grouped into a
|
package/dist/index.js
CHANGED
|
@@ -1376,13 +1376,7 @@ var EFFORT_LADDERS = {
|
|
|
1376
1376
|
"xhigh",
|
|
1377
1377
|
"max"
|
|
1378
1378
|
],
|
|
1379
|
-
codex: [
|
|
1380
|
-
"minimal",
|
|
1381
|
-
"low",
|
|
1382
|
-
"medium",
|
|
1383
|
-
"high",
|
|
1384
|
-
"xhigh"
|
|
1385
|
-
]
|
|
1379
|
+
codex: ["low", "medium", "high"]
|
|
1386
1380
|
};
|
|
1387
1381
|
var ALL_EFFORT_LEVELS = [
|
|
1388
1382
|
"off",
|
|
@@ -1536,12 +1530,21 @@ function spawnAgent(opts) {
|
|
|
1536
1530
|
if (opts.model) {
|
|
1537
1531
|
args.push("--model", opts.model);
|
|
1538
1532
|
}
|
|
1539
|
-
if (opts.maxTurns) {
|
|
1540
|
-
args.push("--max-turns", String(opts.maxTurns));
|
|
1541
|
-
}
|
|
1542
1533
|
const providerName = basename2(opts.agentCmd);
|
|
1543
1534
|
const isClaude = providerName === "claude";
|
|
1544
1535
|
const isPi = providerName === "pi";
|
|
1536
|
+
if (opts.maxTurns) {
|
|
1537
|
+
if (isClaude) {
|
|
1538
|
+
args.push(
|
|
1539
|
+
"--max-turns",
|
|
1540
|
+
String(opts.maxTurns)
|
|
1541
|
+
);
|
|
1542
|
+
} else if (opts.onLine) {
|
|
1543
|
+
opts.onLine(
|
|
1544
|
+
`Warning: --max-turns not supported by ${providerName}, skipping`
|
|
1545
|
+
);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1545
1548
|
if (opts.effort && providerName in EFFORT_LADDERS) {
|
|
1546
1549
|
const ladder = EFFORT_LADDERS[providerName];
|
|
1547
1550
|
if (!ladder.includes(opts.effort)) {
|
|
@@ -1555,7 +1558,10 @@ function spawnAgent(opts) {
|
|
|
1555
1558
|
} else if (isClaude) {
|
|
1556
1559
|
args.push("--effort", opts.effort);
|
|
1557
1560
|
} else if (providerName === "codex") {
|
|
1558
|
-
args.push(
|
|
1561
|
+
args.push(
|
|
1562
|
+
"-c",
|
|
1563
|
+
`model_reasoning_effort=${opts.effort}`
|
|
1564
|
+
);
|
|
1559
1565
|
}
|
|
1560
1566
|
}
|
|
1561
1567
|
const prefix = opts.label ? ` [${opts.label}] ` : " ";
|
|
@@ -2214,10 +2220,17 @@ async function runWaves(tickets, specBody, agentCmd, model, timeout, logsDir, di
|
|
|
2214
2220
|
);
|
|
2215
2221
|
}
|
|
2216
2222
|
if (waveCompleted === 0) {
|
|
2223
|
+
const remaining3 = findReadyTickets(tickets).filter((t) => !failedNums.has(t.num));
|
|
2224
|
+
if (remaining3.length === 0) {
|
|
2225
|
+
d.log(
|
|
2226
|
+
"\nNo tickets completed this wave and no ready tickets remain. Stopping."
|
|
2227
|
+
);
|
|
2228
|
+
break;
|
|
2229
|
+
}
|
|
2217
2230
|
d.log(
|
|
2218
|
-
|
|
2231
|
+
`
|
|
2232
|
+
No tickets completed this wave. ${remaining3.length} ready ticket${remaining3.length === 1 ? "" : "s"} remain; continuing.`
|
|
2219
2233
|
);
|
|
2220
|
-
break;
|
|
2221
2234
|
}
|
|
2222
2235
|
}
|
|
2223
2236
|
const remaining = tickets.filter(
|
|
@@ -2548,10 +2561,19 @@ Merge stopped at ${mergeResult.stoppedAt.branch}`
|
|
|
2548
2561
|
}
|
|
2549
2562
|
}
|
|
2550
2563
|
if (waveCompleted === 0) {
|
|
2564
|
+
const remaining3 = findReadyTickets(
|
|
2565
|
+
opts.tickets
|
|
2566
|
+
).filter((t) => !failedNums.has(t.num));
|
|
2567
|
+
if (remaining3.length === 0) {
|
|
2568
|
+
d.log(
|
|
2569
|
+
"\nNo tickets completed this wave and no ready tickets remain. Stopping."
|
|
2570
|
+
);
|
|
2571
|
+
break;
|
|
2572
|
+
}
|
|
2551
2573
|
d.log(
|
|
2552
|
-
|
|
2574
|
+
`
|
|
2575
|
+
No tickets completed this wave. ${remaining3.length} ready ticket${remaining3.length === 1 ? "" : "s"} remain; continuing.`
|
|
2553
2576
|
);
|
|
2554
|
-
break;
|
|
2555
2577
|
}
|
|
2556
2578
|
}
|
|
2557
2579
|
const remaining = opts.tickets.filter(
|