ralphctl 0.4.3 → 0.4.5
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/{add-MG26JWBP.mjs → add-DVPVHENV.mjs} +7 -7
- package/dist/{add-ZZYL4BSF.mjs → add-YVXM34RP.mjs} +6 -6
- package/dist/{chunk-LDSG7G2T.mjs → chunk-BSB4EDGR.mjs} +2 -2
- package/dist/{chunk-RQGD5WS6.mjs → chunk-CBMFRQ4Y.mjs} +3 -3
- package/dist/{chunk-Q4AVHUZL.mjs → chunk-FNAAA32W.mjs} +3 -3
- package/dist/{chunk-EGUFQNRB.mjs → chunk-GQ2WFKBN.mjs} +3 -3
- package/dist/{chunk-LCY32RW4.mjs → chunk-OFILN7QL.mjs} +183 -39
- package/dist/{chunk-MDE6KPJQ.mjs → chunk-OGEXYSFS.mjs} +5 -5
- package/dist/{chunk-TDBEEHTS.mjs → chunk-PYZEQ2VK.mjs} +5 -5
- package/dist/{chunk-57UWLHRH.mjs → chunk-VAZ3LJBI.mjs} +12 -1
- package/dist/{chunk-D2HWXEHH.mjs → chunk-WDMLPXOD.mjs} +2 -2
- package/dist/{chunk-WZTY77GY.mjs → chunk-XN2UIHBY.mjs} +10 -3
- package/dist/{chunk-WOMGKKZY.mjs → chunk-XPLYLRIM.mjs} +319 -15
- package/dist/{chunk-2FT37OZX.mjs → chunk-ZLWSPLWI.mjs} +53 -7
- package/dist/cli.mjs +19 -17
- package/dist/create-Z635FQKO.mjs +15 -0
- package/dist/{handle-SYVCFI6Y.mjs → handle-23EFF3BE.mjs} +1 -1
- package/dist/{mount-2ANLHHQE.mjs → mount-H2IH3MWE.mjs} +1455 -1193
- package/dist/{project-JF47ZWMF.mjs → project-DQHF4ISP.mjs} +3 -3
- package/dist/prompts/sprint-feedback.md +4 -0
- package/dist/prompts/task-evaluation.md +44 -2
- package/dist/prompts/task-execution.md +5 -0
- package/dist/{resolver-PG2DZEBX.mjs → resolver-OVPYVW6Q.mjs} +3 -3
- package/dist/{sprint-54DOSIJK.mjs → sprint-4E26AB5F.mjs} +4 -4
- package/dist/start-2WH4BTDB.mjs +19 -0
- package/package.json +1 -1
- package/dist/create-PQK6KKRD.mjs +0 -15
- package/dist/start-2SZTBKGF.mjs +0 -19
|
@@ -10,18 +10,18 @@ import {
|
|
|
10
10
|
getAiProvider,
|
|
11
11
|
log,
|
|
12
12
|
setAiProvider
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XN2UIHBY.mjs";
|
|
14
14
|
import {
|
|
15
15
|
ensureError,
|
|
16
16
|
wrapAsync
|
|
17
17
|
} from "./chunk-IWXBJD2D.mjs";
|
|
18
18
|
import {
|
|
19
19
|
assertSafeCwd
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-WDMLPXOD.mjs";
|
|
21
21
|
import {
|
|
22
22
|
IOError,
|
|
23
23
|
SpawnError
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-VAZ3LJBI.mjs";
|
|
25
25
|
|
|
26
26
|
// src/integration/ui/tui/runtime/screen.ts
|
|
27
27
|
var ENTER_ALT_SCREEN = "\x1B[?1049h";
|
|
@@ -166,6 +166,34 @@ var ProcessManager = class _ProcessManager {
|
|
|
166
166
|
this.handlersInstalled = true;
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Wire a task-scoped AbortSignal to a terminate callback. When the signal
|
|
171
|
+
* aborts, the callback fires once. Returns a disposer that detaches the
|
|
172
|
+
* listener — call it in a `finally` after the child exits so listeners
|
|
173
|
+
* don't accumulate across repeated runs.
|
|
174
|
+
*
|
|
175
|
+
* If the signal is already aborted, terminate runs on the next microtask
|
|
176
|
+
* so the caller always observes a consistent async flow.
|
|
177
|
+
*/
|
|
178
|
+
registerAbort(signal, terminate) {
|
|
179
|
+
let fired = false;
|
|
180
|
+
const handler = () => {
|
|
181
|
+
if (fired) return;
|
|
182
|
+
fired = true;
|
|
183
|
+
try {
|
|
184
|
+
terminate();
|
|
185
|
+
} catch (err) {
|
|
186
|
+
log.error(`Error in abort-signal handler: ${err instanceof Error ? err.message : String(err)}`);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
if (signal.aborted) {
|
|
190
|
+
queueMicrotask(handler);
|
|
191
|
+
}
|
|
192
|
+
signal.addEventListener("abort", handler, { once: true });
|
|
193
|
+
return () => {
|
|
194
|
+
signal.removeEventListener("abort", handler);
|
|
195
|
+
};
|
|
196
|
+
}
|
|
169
197
|
/**
|
|
170
198
|
* Check if a shutdown is in progress.
|
|
171
199
|
* Used by execution loops to break immediately on Ctrl+C.
|
|
@@ -296,7 +324,8 @@ var processLifecycleAdapter = {
|
|
|
296
324
|
ensureHandlers: () => {
|
|
297
325
|
ProcessManager.getInstance().ensureHandlers();
|
|
298
326
|
},
|
|
299
|
-
isShuttingDown: () => ProcessManager.getInstance().isShuttingDown()
|
|
327
|
+
isShuttingDown: () => ProcessManager.getInstance().isShuttingDown(),
|
|
328
|
+
registerAbort: (signal, terminate) => ProcessManager.getInstance().registerAbort(signal, terminate)
|
|
300
329
|
};
|
|
301
330
|
|
|
302
331
|
// src/integration/ai/providers/claude.ts
|
|
@@ -491,6 +520,15 @@ async function spawnHeadless(options, provider) {
|
|
|
491
520
|
reject(new SpawnError("Cannot spawn during shutdown", "", 1));
|
|
492
521
|
return;
|
|
493
522
|
}
|
|
523
|
+
let detachAbort = null;
|
|
524
|
+
if (options.abortSignal) {
|
|
525
|
+
detachAbort = manager.registerAbort(options.abortSignal, () => {
|
|
526
|
+
try {
|
|
527
|
+
child.kill("SIGTERM");
|
|
528
|
+
} catch {
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
}
|
|
494
532
|
const MAX_STDOUT_SIZE = 1e7;
|
|
495
533
|
const MAX_PROMPT_SIZE = 1e6;
|
|
496
534
|
if (options.prompt) {
|
|
@@ -512,6 +550,7 @@ async function spawnHeadless(options, provider) {
|
|
|
512
550
|
stderr += data.toString();
|
|
513
551
|
});
|
|
514
552
|
child.on("close", (code) => {
|
|
553
|
+
detachAbort?.();
|
|
515
554
|
void (async () => {
|
|
516
555
|
const exitCode = code ?? 1;
|
|
517
556
|
const { result, sessionId: parsedSessionId, model: parsedModel } = p.parseJsonOutput(rawStdout);
|
|
@@ -533,6 +572,7 @@ async function spawnHeadless(options, provider) {
|
|
|
533
572
|
});
|
|
534
573
|
});
|
|
535
574
|
child.on("error", (err) => {
|
|
575
|
+
detachAbort?.();
|
|
536
576
|
reject(new SpawnError(`Failed to spawn ${p.binary} CLI: ${err.message}`, "", 1));
|
|
537
577
|
});
|
|
538
578
|
});
|
|
@@ -558,6 +598,9 @@ async function spawnWithRetry(options, retryOptions, provider) {
|
|
|
558
598
|
if (attempt > 0 && elapsed >= totalTimeoutMs) {
|
|
559
599
|
throw new SpawnError(`Total retry timeout exceeded (${String(totalTimeoutMs)}ms)`, "", 1, resumeSessionId);
|
|
560
600
|
}
|
|
601
|
+
if (options.abortSignal?.aborted) {
|
|
602
|
+
throw new SpawnError("Aborted by caller", "", 1, resumeSessionId);
|
|
603
|
+
}
|
|
561
604
|
const r = await wrapAsync(async () => spawnHeadless({ ...options, resumeSessionId }, p), ensureError);
|
|
562
605
|
if (r.ok) return r.value;
|
|
563
606
|
const err = r.error;
|
|
@@ -614,7 +657,8 @@ var ProviderAiSessionAdapter = class {
|
|
|
614
657
|
args: options.args,
|
|
615
658
|
env: options.env,
|
|
616
659
|
prompt,
|
|
617
|
-
resumeSessionId: options.resumeSessionId
|
|
660
|
+
resumeSessionId: options.resumeSessionId,
|
|
661
|
+
abortSignal: options.abortSignal
|
|
618
662
|
},
|
|
619
663
|
provider
|
|
620
664
|
);
|
|
@@ -632,7 +676,8 @@ var ProviderAiSessionAdapter = class {
|
|
|
632
676
|
args: options.args,
|
|
633
677
|
env: options.env,
|
|
634
678
|
prompt,
|
|
635
|
-
resumeSessionId: options.resumeSessionId
|
|
679
|
+
resumeSessionId: options.resumeSessionId,
|
|
680
|
+
abortSignal: options.abortSignal
|
|
636
681
|
},
|
|
637
682
|
{ maxRetries: options.maxRetries },
|
|
638
683
|
provider
|
|
@@ -651,7 +696,8 @@ var ProviderAiSessionAdapter = class {
|
|
|
651
696
|
args: options.args,
|
|
652
697
|
env: options.env,
|
|
653
698
|
prompt,
|
|
654
|
-
resumeSessionId: sessionId
|
|
699
|
+
resumeSessionId: sessionId,
|
|
700
|
+
abortSignal: options.abortSignal
|
|
655
701
|
},
|
|
656
702
|
void 0,
|
|
657
703
|
provider
|
package/dist/cli.mjs
CHANGED
|
@@ -41,26 +41,26 @@ import {
|
|
|
41
41
|
ticketRefineCommand,
|
|
42
42
|
ticketRemoveCommand,
|
|
43
43
|
ticketShowCommand
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-XPLYLRIM.mjs";
|
|
45
45
|
import {
|
|
46
46
|
projectAddCommand
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-PYZEQ2VK.mjs";
|
|
48
48
|
import {
|
|
49
49
|
sprintCreateCommand
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-FNAAA32W.mjs";
|
|
51
51
|
import {
|
|
52
52
|
ticketAddCommand
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-OGEXYSFS.mjs";
|
|
54
54
|
import {
|
|
55
55
|
createOnboardPipeline,
|
|
56
56
|
executePipeline,
|
|
57
57
|
getTasks,
|
|
58
58
|
sprintStartCommand
|
|
59
|
-
} from "./chunk-
|
|
60
|
-
import "./chunk-
|
|
59
|
+
} from "./chunk-OFILN7QL.mjs";
|
|
60
|
+
import "./chunk-ZLWSPLWI.mjs";
|
|
61
61
|
import {
|
|
62
62
|
truncate
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-GQ2WFKBN.mjs";
|
|
64
64
|
import {
|
|
65
65
|
EXIT_ERROR,
|
|
66
66
|
exitWithCode
|
|
@@ -69,11 +69,11 @@ import {
|
|
|
69
69
|
getSharedDeps,
|
|
70
70
|
setSharedDeps
|
|
71
71
|
} from "./chunk-747KW2RW.mjs";
|
|
72
|
-
import "./chunk-
|
|
72
|
+
import "./chunk-BSB4EDGR.mjs";
|
|
73
73
|
import {
|
|
74
74
|
getCurrentSprintOrThrow,
|
|
75
75
|
getSprint
|
|
76
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-CBMFRQ4Y.mjs";
|
|
77
77
|
import {
|
|
78
78
|
colors,
|
|
79
79
|
error,
|
|
@@ -85,7 +85,7 @@ import {
|
|
|
85
85
|
setCurrentSprint,
|
|
86
86
|
showError,
|
|
87
87
|
showSuccess
|
|
88
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-XN2UIHBY.mjs";
|
|
89
89
|
import {
|
|
90
90
|
ensureError,
|
|
91
91
|
wrapAsync
|
|
@@ -93,10 +93,10 @@ import {
|
|
|
93
93
|
import {
|
|
94
94
|
ensureDir,
|
|
95
95
|
getDataDir
|
|
96
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-WDMLPXOD.mjs";
|
|
97
97
|
import {
|
|
98
98
|
DomainError
|
|
99
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-VAZ3LJBI.mjs";
|
|
100
100
|
|
|
101
101
|
// src/application/entrypoint.ts
|
|
102
102
|
import { Command } from "commander";
|
|
@@ -382,7 +382,7 @@ Examples:
|
|
|
382
382
|
if (opts?.export) args.push("--export");
|
|
383
383
|
await sprintInsightsCommand(args);
|
|
384
384
|
});
|
|
385
|
-
sprint.command("start [id]").description("Run automated implementation loop").option("-s, --session", "Interactive AI session (collaborate with your AI provider)").option("-t, --step", "Step through tasks with approval between each").option("-c, --count <n>", "Limit to N tasks").option("--no-commit", "Skip automatic git commit after each task completes").option("--concurrency <n>", "Max parallel tasks (default: auto based on unique repos)").option("--max-retries <n>", "Max rate-limit retries per task (default: 5)").option("--fail-fast", "Stop launching new tasks on first failure").option("-f, --force", "Skip precondition checks (e.g., unplanned tickets)").option("--refresh-check", "Force re-run check scripts even if they already ran this sprint").option("-b, --branch", "Create sprint branch (ralphctl/<sprint-id>) in all repos").option("--branch-name <name>", "Use a custom branch name for sprint execution").option("--max-budget-usd <amount>", "Max USD budget per AI task (Claude only)").option("--fallback-model <model>", "Fallback model when primary is overloaded (Claude only)").option("--max-turns <number>", "Max agentic turns per task (Claude only, default: 200)").addHelpText(
|
|
385
|
+
sprint.command("start [id]").description("Run automated implementation loop").option("-s, --session", "Interactive AI session (collaborate with your AI provider)").option("-t, --step", "Step through tasks with approval between each").option("-c, --count <n>", "Limit to N tasks").option("--no-commit", "Skip automatic git commit after each task completes").option("--concurrency <n>", "Max parallel tasks (default: auto based on unique repos)").option("--max-retries <n>", "Max rate-limit retries per task (default: 5)").option("--fail-fast", "Stop launching new tasks on first failure").option("-f, --force", "Skip precondition checks (e.g., unplanned tickets)").option("--refresh-check", "Force re-run check scripts even if they already ran this sprint").option("-b, --branch", "Create sprint branch (ralphctl/<sprint-id>) in all repos").option("--branch-name <name>", "Use a custom branch name for sprint execution").option("--resume-dirty", "Resume with uncommitted changes intact (skips prompt)").option("--reset-on-resume", "Hard-reset working tree to HEAD before resuming (destructive; skips prompt)").option("--max-budget-usd <amount>", "Max USD budget per AI task (Claude only)").option("--fallback-model <model>", "Fallback model when primary is overloaded (Claude only)").option("--max-turns <number>", "Max agentic turns per task (Claude only, default: 200)").addHelpText(
|
|
386
386
|
"after",
|
|
387
387
|
`
|
|
388
388
|
Exit Codes:
|
|
@@ -418,6 +418,8 @@ Branch Management:
|
|
|
418
418
|
if (opts?.refreshCheck) args.push("--refresh-check");
|
|
419
419
|
if (opts?.branch) args.push("--branch");
|
|
420
420
|
if (opts?.branchName) args.push("--branch-name", opts.branchName);
|
|
421
|
+
if (opts?.resumeDirty) args.push("--resume-dirty");
|
|
422
|
+
if (opts?.resetOnResume) args.push("--reset-on-resume");
|
|
421
423
|
if (opts?.maxBudgetUsd) args.push("--max-budget-usd", opts.maxBudgetUsd);
|
|
422
424
|
if (opts?.fallbackModel) args.push("--fallback-model", opts.fallbackModel);
|
|
423
425
|
if (opts?.maxTurns) args.push("--max-turns", opts.maxTurns);
|
|
@@ -747,14 +749,14 @@ function isQuietCommand(argv) {
|
|
|
747
749
|
}
|
|
748
750
|
async function main() {
|
|
749
751
|
if (process.env["COMP_CWORD"] && process.env["COMP_POINT"] && process.env["COMP_LINE"]) {
|
|
750
|
-
const { handleCompletionRequest } = await import("./handle-
|
|
752
|
+
const { handleCompletionRequest } = await import("./handle-23EFF3BE.mjs");
|
|
751
753
|
if (await handleCompletionRequest(program)) return;
|
|
752
754
|
}
|
|
753
755
|
const argv = process.argv;
|
|
754
756
|
const isBare = argv.length <= 2;
|
|
755
757
|
const isInteractive = argv[2] === "interactive";
|
|
756
758
|
if (isBare || isInteractive) {
|
|
757
|
-
const { mountInkApp } = await import("./mount-
|
|
759
|
+
const { mountInkApp } = await import("./mount-H2IH3MWE.mjs");
|
|
758
760
|
const { fallback } = await mountInkApp({ initialView: "repl" });
|
|
759
761
|
if (!fallback) return;
|
|
760
762
|
printBanner();
|
|
@@ -765,10 +767,10 @@ async function main() {
|
|
|
765
767
|
return;
|
|
766
768
|
}
|
|
767
769
|
if (argv[2] === "sprint" && argv[3] === "start") {
|
|
768
|
-
const { parseSprintStartArgs } = await import("./start-
|
|
770
|
+
const { parseSprintStartArgs } = await import("./start-2WH4BTDB.mjs");
|
|
769
771
|
const parsed = parseSprintStartArgs(argv.slice(4));
|
|
770
772
|
if (parsed.ok) {
|
|
771
|
-
const { mountInkApp } = await import("./mount-
|
|
773
|
+
const { mountInkApp } = await import("./mount-H2IH3MWE.mjs");
|
|
772
774
|
const { getSharedDeps: getSharedDeps2 } = await import("./bootstrap-FMHG6DRY.mjs");
|
|
773
775
|
let sprintId;
|
|
774
776
|
try {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
sprintCreateCommand
|
|
4
|
+
} from "./chunk-FNAAA32W.mjs";
|
|
5
|
+
import "./chunk-CFUVE2BP.mjs";
|
|
6
|
+
import "./chunk-747KW2RW.mjs";
|
|
7
|
+
import "./chunk-BSB4EDGR.mjs";
|
|
8
|
+
import "./chunk-CBMFRQ4Y.mjs";
|
|
9
|
+
import "./chunk-XN2UIHBY.mjs";
|
|
10
|
+
import "./chunk-IWXBJD2D.mjs";
|
|
11
|
+
import "./chunk-WDMLPXOD.mjs";
|
|
12
|
+
import "./chunk-VAZ3LJBI.mjs";
|
|
13
|
+
export {
|
|
14
|
+
sprintCreateCommand
|
|
15
|
+
};
|
|
@@ -7,7 +7,7 @@ async function handleCompletionRequest(program) {
|
|
|
7
7
|
return false;
|
|
8
8
|
}
|
|
9
9
|
const tabtab = (await import("tabtab")).default;
|
|
10
|
-
const { resolveCompletions } = await import("./resolver-
|
|
10
|
+
const { resolveCompletions } = await import("./resolver-OVPYVW6Q.mjs");
|
|
11
11
|
const tabEnv = tabtab.parseEnv(env);
|
|
12
12
|
const completions = await resolveCompletions(program, {
|
|
13
13
|
line: tabEnv.line,
|