@daonhan/ralph-core 0.1.0 → 0.1.1

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/Dockerfile CHANGED
@@ -15,7 +15,7 @@ RUN wget -qO /tmp/ms.deb https://packages.microsoft.com/config/debian/12/package
15
15
  && dpkg -i /tmp/ms.deb \
16
16
  && rm /tmp/ms.deb \
17
17
  && apt-get update \
18
- && apt-get install -y dotnet-sdk-9.0 \
18
+ && apt-get install -y dotnet-sdk-10.0 \
19
19
  && rm -rf /var/lib/apt/lists/*
20
20
 
21
21
  # GitHub CLI
@@ -34,6 +34,10 @@ RUN corepack enable
34
34
  RUN usermod -d /home/agent -m -l agent node
35
35
  USER agent
36
36
 
37
+ # Bind-mounted host workspace may show foreign UID inside container.
38
+ # Tell git to trust any path so `git ...` works against the mount.
39
+ RUN git config --global --add safe.directory '*'
40
+
37
41
  # Claude Code CLI
38
42
  RUN curl -fsSL https://claude.ai/install.sh | bash
39
43
 
@@ -0,0 +1,9 @@
1
+ export type CliFlags = {
2
+ help: boolean;
3
+ printConfig: boolean;
4
+ rest: string[];
5
+ };
6
+ export declare function parseFlags(argv: string[]): CliFlags;
7
+ export declare function printHelp(bin: string, usage: string, description: string): void;
8
+ export declare function printConfig(bin: string, workspaceDir: string, ralphDir: string, sandcastleDir: string): void;
9
+ //# sourceMappingURL=cli-help.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE/E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,CAUnD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,CAqB/E;AAED,wBAAgB,WAAW,CACzB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GACpB,IAAI,CAUN"}
@@ -0,0 +1,51 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { IMAGE_REF } from "./runner.js";
4
+ export function parseFlags(argv) {
5
+ let help = false;
6
+ let printConfig = false;
7
+ const rest = [];
8
+ for (const a of argv) {
9
+ if (a === "-h" || a === "--help")
10
+ help = true;
11
+ else if (a === "--print-config")
12
+ printConfig = true;
13
+ else
14
+ rest.push(a);
15
+ }
16
+ return { help, printConfig, rest };
17
+ }
18
+ export function printHelp(bin, usage, description) {
19
+ process.stdout.write(`${bin} — ${description}
20
+
21
+ Usage:
22
+ ${bin} ${usage}
23
+ ${bin} --help | -h
24
+ ${bin} --print-config [args...]
25
+
26
+ Flags:
27
+ -h, --help show this help and exit
28
+ --print-config resolve workspace / docker context / image, print, exit without launching docker
29
+
30
+ Environment variables:
31
+ RALPH_WORKSPACE host dir bind-mounted at /home/agent/workspace (default: cwd)
32
+ RALPH_DOCKER_CONTEXT docker build fallback context (default: bundled @daonhan/ralph-core dir)
33
+ RALPH_IMAGE image ref (default: docker.io/daonhan/ralph-sandbox:latest)
34
+ RALPH_IMAGE_TAG legacy alias for RALPH_IMAGE
35
+
36
+ Image resolution: docker image inspect → docker pull → docker build (fallback).
37
+ Build fallback runs only if pull fails AND $RALPH_DOCKER_CONTEXT/Dockerfile exists; expect ~5min.
38
+ `);
39
+ }
40
+ export function printConfig(bin, workspaceDir, ralphDir, sandcastleDir) {
41
+ const dockerfile = join(ralphDir, "Dockerfile");
42
+ const dfPresent = existsSync(dockerfile);
43
+ process.stdout.write(`[${bin}] resolved config
44
+ RALPH_WORKSPACE ${workspaceDir}${process.env.RALPH_WORKSPACE ? "" : " (default: cwd)"}
45
+ RALPH_DOCKER_CONTEXT ${ralphDir}${process.env.RALPH_DOCKER_CONTEXT ? "" : " (default: bundled core dir)"}
46
+ RALPH_IMAGE ${IMAGE_REF}${process.env.RALPH_IMAGE || process.env.RALPH_IMAGE_TAG ? "" : " (default)"}
47
+ Dockerfile at ctx ${dfPresent ? "present" : "MISSING"} (${dockerfile})
48
+ sandcastleDir ${sandcastleDir}
49
+ `);
50
+ }
51
+ //# sourceMappingURL=cli-help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC,MAAM,UAAU,UAAU,CAAC,IAAc;IACvC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,QAAQ;YAAE,IAAI,GAAG,IAAI,CAAC;aACzC,IAAI,CAAC,KAAK,gBAAgB;YAAE,WAAW,GAAG,IAAI,CAAC;;YAC/C,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,KAAa,EAAE,WAAmB;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,WAAW;;;IAG1C,GAAG,IAAI,KAAK;IACZ,GAAG;IACH,GAAG;;;;;;;;;;;;;;CAcN,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,GAAW,EACX,YAAoB,EACpB,QAAgB,EAChB,aAAqB;IAErB,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG;0BACJ,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB;0BACpE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,+BAA+B;0BAClF,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa;0BACvF,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,KAAK,UAAU;0BAChD,aAAa;CACtC,CAAC,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runGhAfk(argv: string[]): Promise<void>;
2
+ //# sourceMappingURL=gh-main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh-main.d.ts","sourceRoot":"","sources":["../src/gh-main.ts"],"names":[],"mappings":"AAWA,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsC5D"}
@@ -0,0 +1,43 @@
1
+ import { dirname, resolve } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { parseFlags, printConfig, printHelp } from "./cli-help.js";
4
+ import { runLoop } from "./loop.js";
5
+ import { STAGES } from "./stages.js";
6
+ const BIN = "ralph-ghafk";
7
+ const USAGE = "<iterations>";
8
+ const DESC = "GitHub-issue-driven Claude Code AFK loop";
9
+ export async function runGhAfk(argv) {
10
+ const flags = parseFlags(argv);
11
+ if (flags.help) {
12
+ printHelp(BIN, USAGE, DESC);
13
+ return;
14
+ }
15
+ const here = dirname(fileURLToPath(import.meta.url));
16
+ const sandcastleDir = resolve(here, "..");
17
+ const workspaceDir = resolve(process.env.RALPH_WORKSPACE ?? process.cwd());
18
+ const ralphDir = resolve(process.env.RALPH_DOCKER_CONTEXT ?? sandcastleDir);
19
+ if (flags.printConfig) {
20
+ printConfig(BIN, workspaceDir, ralphDir, sandcastleDir);
21
+ return;
22
+ }
23
+ const [iterationsArg] = flags.rest;
24
+ if (!iterationsArg) {
25
+ console.error(`Usage: ${BIN} ${USAGE}`);
26
+ console.error(` ${BIN} --help`);
27
+ process.exit(1);
28
+ }
29
+ const iterations = Number.parseInt(iterationsArg, 10);
30
+ if (!Number.isFinite(iterations) || iterations < 1) {
31
+ console.error(`Invalid iterations: ${iterationsArg}`);
32
+ process.exit(1);
33
+ }
34
+ await runLoop({
35
+ stages: [STAGES.ghafkImplementer, STAGES.reviewer],
36
+ inputs: "",
37
+ iterations,
38
+ ralphDir,
39
+ workspaceDir,
40
+ sandcastleDir,
41
+ });
42
+ }
43
+ //# sourceMappingURL=gh-main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh-main.js","sourceRoot":"","sources":["../src/gh-main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,GAAG,GAAG,aAAa,CAAC;AAC1B,MAAM,KAAK,GAAG,cAAc,CAAC;AAC7B,MAAM,IAAI,GAAG,0CAA0C,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAc;IAC3C,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,aAAa,CAAC,CAAC;IAE5E,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,WAAW,CAAC,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QACxD,OAAO;IACT,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC;IACnC,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,KAAK,CAAC,uBAAuB,aAAa,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,CAAC;QACZ,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,QAAQ,CAAC;QAClD,MAAM,EAAE,EAAE;QACV,UAAU;QACV,QAAQ;QACR,YAAY;QACZ,aAAa;KACd,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { runAfk } from "./main.js";
2
+ export { runGhAfk } from "./gh-main.js";
3
+ export { runLoop, type LoopOptions } from "./loop.js";
4
+ export { STAGES, type Stage } from "./stages.js";
5
+ export { renderTemplate, type RenderOptions, type RenderVars } from "./render.js";
6
+ export { ensureImage, runStage } from "./runner.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { runAfk } from "./main.js";
2
+ export { runGhAfk } from "./gh-main.js";
3
+ export { runLoop } from "./loop.js";
4
+ export { STAGES } from "./stages.js";
5
+ export { renderTemplate } from "./render.js";
6
+ export { ensureImage, runStage } from "./runner.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,OAAO,EAAoB,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,MAAM,EAAc,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,cAAc,EAAuC,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC"}
package/dist/loop.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ import type { Stage } from "./stages.js";
2
+ export type LoopOptions = {
3
+ stages: [Stage, ...Stage[]];
4
+ inputs: string;
5
+ iterations: number;
6
+ ralphDir: string;
7
+ workspaceDir: string;
8
+ sandcastleDir: string;
9
+ };
10
+ export declare function runLoop(opts: LoopOptions): Promise<void>;
11
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAIzC,MAAM,MAAM,WAAW,GAAG;IAGxB,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB9D"}
package/dist/loop.js ADDED
@@ -0,0 +1,26 @@
1
+ import { join } from "node:path";
2
+ import { renderTemplate } from "./render.js";
3
+ import { ensureImage, runStage } from "./runner.js";
4
+ const SENTINEL = "<promise>NO MORE TASKS</promise>";
5
+ export async function runLoop(opts) {
6
+ const { stages, inputs, iterations, ralphDir, workspaceDir, sandcastleDir } = opts;
7
+ ensureImage(ralphDir);
8
+ for (let i = 1; i <= iterations; i++) {
9
+ let gateResult = "";
10
+ for (let s = 0; s < stages.length; s++) {
11
+ const stage = stages[s];
12
+ process.stderr.write(`\n[sandcastle] iteration ${i}/${iterations} stage ${s + 1}/${stages.length} (${stage.name})\n`);
13
+ const templatePath = join(sandcastleDir, "templates", stage.template);
14
+ const prompt = renderTemplate(templatePath, { INPUTS: inputs }, { cwd: workspaceDir });
15
+ const result = await runStage(stage, prompt, workspaceDir, i);
16
+ if (s === 0) {
17
+ gateResult = result;
18
+ if (gateResult.includes(SENTINEL)) {
19
+ console.log(`Ralph complete after ${i} iterations.`);
20
+ return;
21
+ }
22
+ }
23
+ }
24
+ }
25
+ }
26
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGpD,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AAapD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAiB;IAC7C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAEnF,WAAW,CAAC,QAAQ,CAAC,CAAC;IAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,UAAU,GAAG,EAAE,CAAC;QACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,4BAA4B,CAAC,IAAI,UAAU,UAAU,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,CAAC,IAAI,KAAK,CAChG,CAAC;YACF,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;YACtE,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;YACvF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;YAC9D,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACZ,UAAU,GAAG,MAAM,CAAC;gBACpB,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAClC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;oBACrD,OAAO;gBACT,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function runAfk(argv: string[]): Promise<void>;
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAWA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsC1D"}
package/dist/main.js ADDED
@@ -0,0 +1,43 @@
1
+ import { dirname, resolve } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { parseFlags, printConfig, printHelp } from "./cli-help.js";
4
+ import { runLoop } from "./loop.js";
5
+ import { STAGES } from "./stages.js";
6
+ const BIN = "ralph-afk";
7
+ const USAGE = "<plan-and-prd> <iterations>";
8
+ const DESC = "plan/PRD-driven Claude Code AFK loop";
9
+ export async function runAfk(argv) {
10
+ const flags = parseFlags(argv);
11
+ if (flags.help) {
12
+ printHelp(BIN, USAGE, DESC);
13
+ return;
14
+ }
15
+ const here = dirname(fileURLToPath(import.meta.url));
16
+ const sandcastleDir = resolve(here, "..");
17
+ const workspaceDir = resolve(process.env.RALPH_WORKSPACE ?? process.cwd());
18
+ const ralphDir = resolve(process.env.RALPH_DOCKER_CONTEXT ?? sandcastleDir);
19
+ if (flags.printConfig) {
20
+ printConfig(BIN, workspaceDir, ralphDir, sandcastleDir);
21
+ return;
22
+ }
23
+ const [planAndPrd, iterationsArg] = flags.rest;
24
+ if (!planAndPrd || !iterationsArg) {
25
+ console.error(`Usage: ${BIN} ${USAGE}`);
26
+ console.error(` ${BIN} --help`);
27
+ process.exit(1);
28
+ }
29
+ const iterations = Number.parseInt(iterationsArg, 10);
30
+ if (!Number.isFinite(iterations) || iterations < 1) {
31
+ console.error(`Invalid iterations: ${iterationsArg}`);
32
+ process.exit(1);
33
+ }
34
+ await runLoop({
35
+ stages: [STAGES.implementer, STAGES.reviewer],
36
+ inputs: planAndPrd,
37
+ iterations,
38
+ ralphDir,
39
+ workspaceDir,
40
+ sandcastleDir,
41
+ });
42
+ }
43
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,GAAG,GAAG,WAAW,CAAC;AACxB,MAAM,KAAK,GAAG,6BAA6B,CAAC;AAC5C,MAAM,IAAI,GAAG,sCAAsC,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,aAAa,CAAC,CAAC;IAE5E,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QACtB,WAAW,CAAC,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QACxD,OAAO;IACT,CAAC;IAED,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC;IAC/C,IAAI,CAAC,UAAU,IAAI,CAAC,aAAa,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,KAAK,CAAC,uBAAuB,aAAa,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,CAAC;QACZ,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC;QAC7C,MAAM,EAAE,UAAU;QAClB,UAAU;QACV,QAAQ;QACR,YAAY;QACZ,aAAa;KACd,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type RenderVars = {
2
+ INPUTS: string;
3
+ };
4
+ export type RenderOptions = {
5
+ cwd?: string;
6
+ };
7
+ export declare function renderTemplate(templatePath: string, vars: RenderVars, opts?: RenderOptions): string;
8
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAcF,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,UAAU,EAChB,IAAI,GAAE,aAAkB,GACvB,MAAM,CAsCR"}
package/dist/render.js ADDED
@@ -0,0 +1,61 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { dirname, isAbsolute, resolve } from "node:path";
4
+ // Order matters: !?`...` (try-shell w/ ||| fallback) must match before plain !`...`.
5
+ const SHELL_TRY_TAG = /!\?`([^`]+)`/g;
6
+ const SHELL_TAG = /!`([^`]+)`/g;
7
+ const INCLUDE_TAG = /@include:([^\s`)]+)/g;
8
+ const INPUTS_TAG = /\{\{\s*INPUTS\s*\}\}/g;
9
+ const TRY_SEP = "|||";
10
+ function resolveShell() {
11
+ if (process.platform !== "win32")
12
+ return "/bin/bash";
13
+ // Prefer bash.exe (git-for-windows / WSL passthrough) for POSIX redirects + utils.
14
+ const pathDirs = (process.env.PATH ?? "").split(";");
15
+ for (const d of pathDirs) {
16
+ if (!d)
17
+ continue;
18
+ const candidate = resolve(d, "bash.exe");
19
+ if (existsSync(candidate))
20
+ return candidate;
21
+ }
22
+ return "cmd.exe";
23
+ }
24
+ export function renderTemplate(templatePath, vars, opts = {}) {
25
+ const raw = readFileSync(templatePath, "utf8");
26
+ const templateDir = dirname(templatePath);
27
+ const shell = resolveShell();
28
+ const afterInclude = raw.replace(INCLUDE_TAG, (_match, rel) => {
29
+ const target = isAbsolute(rel) ? rel : resolve(templateDir, rel);
30
+ return readFileSync(target, "utf8").replace(/\r?\n$/, "");
31
+ });
32
+ const afterShellTry = afterInclude.replace(SHELL_TRY_TAG, (_match, body) => {
33
+ const sep = body.lastIndexOf(TRY_SEP);
34
+ const cmd = sep >= 0 ? body.slice(0, sep) : body;
35
+ const fallback = sep >= 0 ? body.slice(sep + TRY_SEP.length) : "";
36
+ try {
37
+ const out = execSync(cmd, {
38
+ shell,
39
+ encoding: "utf8",
40
+ maxBuffer: 64 * 1024 * 1024,
41
+ cwd: opts.cwd,
42
+ stdio: ["ignore", "pipe", "ignore"],
43
+ });
44
+ return out.replace(/\r?\n$/, "");
45
+ }
46
+ catch {
47
+ return fallback;
48
+ }
49
+ });
50
+ const afterShell = afterShellTry.replace(SHELL_TAG, (_match, cmd) => {
51
+ const out = execSync(cmd, {
52
+ shell,
53
+ encoding: "utf8",
54
+ maxBuffer: 64 * 1024 * 1024,
55
+ cwd: opts.cwd,
56
+ });
57
+ return out.replace(/\r?\n$/, "");
58
+ });
59
+ return afterShell.replace(INPUTS_TAG, vars.INPUTS);
60
+ }
61
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Stage } from "./stages.js";
2
+ export declare const IMAGE_REF: string;
3
+ export declare function ensureImage(buildContext?: string): void;
4
+ export declare function runStage(stage: Stage, renderedPrompt: string, workspaceDir: string, iteration: number): Promise<string>;
5
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,eAAO,MAAM,SAAS,QAGoB,CAAC;AAyB3C,wBAAgB,WAAW,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAgCvD;AAED,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,KAAK,EACZ,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAqEjB"}
package/dist/runner.js ADDED
@@ -0,0 +1,242 @@
1
+ import { spawn, spawnSync } from "node:child_process";
2
+ import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, rmSync, writeFileSync, } from "node:fs";
3
+ import { createInterface } from "node:readline";
4
+ import { join, posix } from "node:path";
5
+ export const IMAGE_REF = process.env.RALPH_IMAGE ??
6
+ process.env.RALPH_IMAGE_TAG ?? // legacy
7
+ "docker.io/daonhan/ralph-sandbox:latest";
8
+ const STDERR_TAIL_LINES = 40;
9
+ const TOOL_INPUT_PREVIEW = 200;
10
+ const TOOL_RESULT_PREVIEW = 400;
11
+ export function ensureImage(buildContext) {
12
+ const inspect = spawnSync("docker", ["image", "inspect", IMAGE_REF], {
13
+ stdio: "ignore",
14
+ });
15
+ if (inspect.status === 0)
16
+ return;
17
+ process.stderr.write(`[sandcastle] Pulling image ${IMAGE_REF}\n`);
18
+ const pull = spawnSync("docker", ["pull", IMAGE_REF], { stdio: "inherit" });
19
+ if (pull.status === 0)
20
+ return;
21
+ if (!buildContext) {
22
+ throw new Error(`docker pull failed for ${IMAGE_REF} and no build context provided. ` +
23
+ `Set RALPH_DOCKER_CONTEXT to a directory containing a Dockerfile, ` +
24
+ `or override RALPH_IMAGE to an image you can pull.`);
25
+ }
26
+ const dockerfile = join(buildContext, "Dockerfile");
27
+ if (!existsSync(dockerfile)) {
28
+ throw new Error(`docker pull failed for ${IMAGE_REF} and no Dockerfile at ${dockerfile}`);
29
+ }
30
+ process.stderr.write(`[sandcastle] pull failed; building ${IMAGE_REF} from ${buildContext}\n`);
31
+ const build = spawnSync("docker", ["build", "-t", IMAGE_REF, buildContext], {
32
+ stdio: "inherit",
33
+ });
34
+ if (build.status !== 0) {
35
+ throw new Error(`docker build failed (exit ${build.status})`);
36
+ }
37
+ }
38
+ export async function runStage(stage, renderedPrompt, workspaceDir, iteration) {
39
+ const tmpHostDir = join(workspaceDir, ".ralph-tmp");
40
+ mkdirSync(tmpHostDir, { recursive: true });
41
+ const logsDir = join(tmpHostDir, "logs");
42
+ mkdirSync(logsDir, { recursive: true });
43
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
44
+ const logPath = join(logsDir, `${timestamp}-iter${iteration}-${stage.name}.ndjson`);
45
+ const promptName = `.run-${process.pid}-${iteration}-${Date.now()}.md`;
46
+ const promptHostPath = join(tmpHostDir, promptName);
47
+ const promptContainerPath = posix.join(".ralph-tmp", promptName);
48
+ writeFileSync(promptHostPath, renderedPrompt, "utf8");
49
+ process.stderr.write(`[sandcastle] log → ${logPath}\n`);
50
+ try {
51
+ const args = [
52
+ "run",
53
+ "--rm",
54
+ "-i",
55
+ "-v",
56
+ `${workspaceDir}:/home/agent/workspace`,
57
+ "-w",
58
+ "/home/agent/workspace",
59
+ "-e",
60
+ "GIT_CONFIG_COUNT=1",
61
+ "-e",
62
+ "GIT_CONFIG_KEY_0=safe.directory",
63
+ "-e",
64
+ "GIT_CONFIG_VALUE_0=*",
65
+ ];
66
+ const home = process.env.HOME || process.env.USERPROFILE || "";
67
+ if (home) {
68
+ const claudeDir = join(home, ".claude");
69
+ const claudeJson = join(home, ".claude.json");
70
+ const ghConfigDir = join(home, ".config", "gh");
71
+ if (existsSync(claudeDir)) {
72
+ args.push("-v", `${claudeDir}:/home/agent/.claude`);
73
+ }
74
+ if (existsSync(claudeJson)) {
75
+ args.push("-v", `${claudeJson}:/home/agent/.claude.json`);
76
+ }
77
+ if (existsSync(ghConfigDir)) {
78
+ args.push("-v", `${ghConfigDir}:/home/agent/.config/gh:ro`);
79
+ }
80
+ }
81
+ args.push(IMAGE_REF, "claude", "--verbose", "--print", "--output-format", "stream-json");
82
+ if (stage.permissionMode) {
83
+ args.push("--permission-mode", stage.permissionMode);
84
+ }
85
+ args.push(`Read the full instructions from the file ./${promptContainerPath} in the current workspace and execute them.`);
86
+ return await streamDocker(args, logPath);
87
+ }
88
+ finally {
89
+ rmSync(promptHostPath, { force: true });
90
+ }
91
+ }
92
+ function streamDocker(args, logPath) {
93
+ return new Promise((resolve, reject) => {
94
+ const logFd = openSync(logPath, "a");
95
+ const child = spawn("docker", args, {
96
+ stdio: ["ignore", "pipe", "pipe"],
97
+ });
98
+ let finalResult = "";
99
+ const stderrTail = [];
100
+ const rl = createInterface({ input: child.stdout });
101
+ rl.on("line", (line) => {
102
+ if (!line.startsWith("{"))
103
+ return;
104
+ appendFileSync(logFd, line + "\n");
105
+ let parsed;
106
+ try {
107
+ parsed = JSON.parse(line);
108
+ }
109
+ catch {
110
+ return;
111
+ }
112
+ renderEvent(parsed);
113
+ if (parsed.type === "result") {
114
+ const r = parsed.result;
115
+ if (typeof r === "string")
116
+ finalResult = r;
117
+ }
118
+ });
119
+ const rlErr = createInterface({ input: child.stderr });
120
+ rlErr.on("line", (line) => {
121
+ stderrTail.push(line);
122
+ if (stderrTail.length > STDERR_TAIL_LINES)
123
+ stderrTail.shift();
124
+ process.stderr.write(`[docker] ${line}\n`);
125
+ });
126
+ child.on("error", (err) => {
127
+ closeSync(logFd);
128
+ reject(err);
129
+ });
130
+ child.on("close", (code) => {
131
+ closeSync(logFd);
132
+ if (code !== 0) {
133
+ reject(new Error(`docker run exited with ${code}\n${stderrTail.join("\n")}`));
134
+ return;
135
+ }
136
+ resolve(finalResult);
137
+ });
138
+ });
139
+ }
140
+ function renderEvent(ev) {
141
+ switch (ev.type) {
142
+ case "system": {
143
+ const sub = ev.subtype;
144
+ if (sub === "init") {
145
+ const model = ev.model ?? "?";
146
+ const cwd = ev.cwd ?? "?";
147
+ process.stderr.write(`[init] model=${model} cwd=${cwd}\n`);
148
+ }
149
+ return;
150
+ }
151
+ case "assistant": {
152
+ const content = ev.message?.content ?? [];
153
+ for (const block of content) {
154
+ if (block.type === "text" && typeof block.text === "string") {
155
+ process.stdout.write(block.text.replace(/\n/g, "\r\n") + "\r\n\n");
156
+ }
157
+ else if (block.type === "thinking") {
158
+ // Thinking blocks are usually long; show one marker line, not full text.
159
+ process.stderr.write(`[thinking]\n`);
160
+ }
161
+ else if (block.type === "tool_use") {
162
+ const name = block.name ?? "?";
163
+ const preview = previewInput(name, block.input);
164
+ process.stderr.write(`[tool] ${name} ${preview}\n`);
165
+ }
166
+ }
167
+ return;
168
+ }
169
+ case "user": {
170
+ const content = ev.message?.content ?? [];
171
+ for (const block of content) {
172
+ if (block.type !== "tool_result")
173
+ continue;
174
+ const text = stringifyToolResult(block.content);
175
+ if (block.is_error) {
176
+ const snippet = text.slice(0, TOOL_RESULT_PREVIEW * 2);
177
+ process.stderr.write(`[tool:error] ${snippet}${text.length > snippet.length ? " …" : ""}\n`);
178
+ }
179
+ else {
180
+ const snippet = text.replace(/\s+/g, " ").trim().slice(0, TOOL_RESULT_PREVIEW);
181
+ process.stderr.write(`[tool:ok] ${snippet}${text.length > snippet.length ? " …" : ""}\n`);
182
+ }
183
+ }
184
+ return;
185
+ }
186
+ case "result": {
187
+ const isError = ev.is_error;
188
+ if (isError)
189
+ process.stderr.write(`[result] is_error=true\n`);
190
+ return;
191
+ }
192
+ default:
193
+ return;
194
+ }
195
+ }
196
+ function previewInput(toolName, input) {
197
+ if (input == null || typeof input !== "object")
198
+ return "";
199
+ const obj = input;
200
+ // Pick the most informative field per tool.
201
+ const keyOrder = {
202
+ Bash: ["command"],
203
+ Edit: ["file_path"],
204
+ Write: ["file_path"],
205
+ Read: ["file_path"],
206
+ Glob: ["pattern", "path"],
207
+ Grep: ["pattern", "path"],
208
+ TodoWrite: [],
209
+ };
210
+ const keys = keyOrder[toolName] ?? Object.keys(obj).slice(0, 2);
211
+ const parts = [];
212
+ for (const k of keys) {
213
+ const v = obj[k];
214
+ if (v == null)
215
+ continue;
216
+ const s = typeof v === "string" ? v : JSON.stringify(v);
217
+ parts.push(`${k}=${truncate(s, TOOL_INPUT_PREVIEW)}`);
218
+ }
219
+ return parts.join(" ");
220
+ }
221
+ function stringifyToolResult(content) {
222
+ if (typeof content === "string")
223
+ return content;
224
+ if (Array.isArray(content)) {
225
+ return content
226
+ .map((c) => {
227
+ if (typeof c === "string")
228
+ return c;
229
+ if (c && typeof c === "object" && "text" in c)
230
+ return String(c.text ?? "");
231
+ return JSON.stringify(c);
232
+ })
233
+ .join("\n");
234
+ }
235
+ return JSON.stringify(content ?? "");
236
+ }
237
+ function truncate(s, max) {
238
+ if (s.length <= max)
239
+ return s;
240
+ return s.slice(0, max - 1) + "…";
241
+ }
242
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export type Stage = {
2
+ name: string;
3
+ template: string;
4
+ permissionMode?: string;
5
+ };
6
+ export declare const STAGES: {
7
+ implementer: {
8
+ name: string;
9
+ template: string;
10
+ permissionMode: string;
11
+ };
12
+ ghafkImplementer: {
13
+ name: string;
14
+ template: string;
15
+ permissionMode: string;
16
+ };
17
+ reviewer: {
18
+ name: string;
19
+ template: string;
20
+ permissionMode: string;
21
+ };
22
+ };
23
+ //# sourceMappingURL=stages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stages.d.ts","sourceRoot":"","sources":["../src/stages.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAMF,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;CAgBlB,CAAC"}
package/dist/stages.js ADDED
@@ -0,0 +1,22 @@
1
+ // All stages run inside the ephemeral ralph-sandbox container (--rm,
2
+ // bind-mounted workspace only). Bash + edits must auto-approve for AFK to
3
+ // work non-interactively, so every stage uses bypassPermissions. Worst-case
4
+ // blast radius is the workspace tree, recoverable via git.
5
+ export const STAGES = {
6
+ implementer: {
7
+ name: "implementer",
8
+ template: "afk.md",
9
+ permissionMode: "bypassPermissions",
10
+ },
11
+ ghafkImplementer: {
12
+ name: "ghafk-implementer",
13
+ template: "ghafk.md",
14
+ permissionMode: "bypassPermissions",
15
+ },
16
+ reviewer: {
17
+ name: "reviewer",
18
+ template: "review.md",
19
+ permissionMode: "bypassPermissions",
20
+ },
21
+ };
22
+ //# sourceMappingURL=stages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stages.js","sourceRoot":"","sources":["../src/stages.ts"],"names":[],"mappings":"AAMA,qEAAqE;AACrE,0EAA0E;AAC1E,4EAA4E;AAC5E,2DAA2D;AAC3D,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,QAAQ;QAClB,cAAc,EAAE,mBAAmB;KACpB;IACjB,gBAAgB,EAAE;QAChB,IAAI,EAAE,mBAAmB;QACzB,QAAQ,EAAE,UAAU;QACpB,cAAc,EAAE,mBAAmB;KACpB;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,WAAW;QACrB,cAAc,EAAE,mBAAmB;KACpB;CAClB,CAAC"}
package/package.json CHANGED
@@ -1,43 +1,23 @@
1
1
  {
2
2
  "name": "@daonhan/ralph-core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Claude Code AFK orchestration: iteration loop, docker runner, template renderer.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
12
- },
13
- "./loop": {
14
- "types": "./dist/loop.d.ts",
15
- "import": "./dist/loop.js"
16
- },
17
- "./runner": {
18
- "types": "./dist/runner.d.ts",
19
- "import": "./dist/runner.js"
20
- },
21
- "./stages": {
22
- "types": "./dist/stages.d.ts",
23
- "import": "./dist/stages.js"
24
- }
25
- },
26
- "files": [
27
- "dist",
28
- "templates",
29
- "Dockerfile",
30
- "README.md"
31
- ],
32
- "engines": {
33
- "node": ">=20"
34
- },
35
- "publishConfig": {
36
- "access": "public"
9
+ ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
10
+ "./loop": { "types": "./dist/loop.d.ts", "import": "./dist/loop.js" },
11
+ "./runner": { "types": "./dist/runner.d.ts", "import": "./dist/runner.js" },
12
+ "./stages": { "types": "./dist/stages.d.ts", "import": "./dist/stages.js" }
37
13
  },
14
+ "files": ["dist", "templates", "Dockerfile", "README.md"],
38
15
  "scripts": {
39
16
  "build": "tsc -p tsconfig.json",
40
17
  "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
41
- "typecheck": "tsc -p tsconfig.json --noEmit"
42
- }
43
- }
18
+ "typecheck": "tsc -p tsconfig.json --noEmit",
19
+ "prepublishOnly": "pnpm run clean && pnpm run build"
20
+ },
21
+ "engines": { "node": ">=20" },
22
+ "publishConfig": { "access": "public" }
23
+ }
@@ -1,67 +1,67 @@
1
- # ISSUES
2
-
3
- GitHub issues are provided at start of context. Parse it to get open issues with their bodies and comments.
4
-
5
- You will work on the AFK issues only, not the HITL ones.
6
-
7
- You've also been passed a file containing the last few commits. Review these to understand what work has been done.
8
-
9
- If all AFK tasks are complete, output <promise>NO MORE TASKS</promise>.
10
-
11
- # TASK SELECTION
12
-
13
- Pick the next task. Prioritize tasks in this order:
14
-
15
- 1. Critical bugfixes
16
- 2. Development infrastructure
17
-
18
- Getting development infrastructure like tests and types and dev scripts ready is an important precursor to building features.
19
-
20
- 3. Tracer bullets for new features
21
-
22
- Tracer bullets are small slices of functionality that go through all layers of the system, allowing you to test and validate your approach early. This helps in identifying potential issues and ensures that the overall architecture is sound before investing significant time in development.
23
-
24
- TL;DR - build a tiny, end-to-end slice of the feature first, then expand it out.
25
-
26
- 4. Polish and quick wins
27
- 5. Refactors
28
-
29
- # EXPLORATION
30
-
31
- Explore the repo.
32
-
33
- # IMPLEMENTATION
34
-
35
- Complete the task.
36
-
37
- # FEEDBACK LOOPS
38
-
39
- Before committing, run the feedback loops:
40
-
41
- ### Frontend / Node
42
-
43
- - `pnpm run test` to run the tests
44
- - `pnpm run typecheck` to run the type checker
45
-
46
- ### Backend / Dotnet
47
-
48
- - `dotnet test` to run the tests
49
- - `dotnet build` to type-check
50
-
51
- # COMMIT
52
-
53
- Make a single `git commit -am` with a short message:
54
-
55
- - Subject line (≤72 chars): what changed
56
- - Optional body (≤3 bullets): key decision, blocker for next iteration
57
- - No file lists (git tracks them), no `Co-Authored-By`
58
-
59
- # THE ISSUE
60
-
61
- If the task is complete, close the original GitHub issue.
62
-
63
- If the task is not complete, leave a comment on the GitHub issue with what was done.
64
-
65
- # FINAL RULES
66
-
67
- ONLY WORK ON A SINGLE TASK.
1
+ # ISSUES
2
+
3
+ GitHub issues are provided at start of context. Parse it to get open issues with their bodies and comments.
4
+
5
+ You will work on the AFK issues only, not the HITL ones.
6
+
7
+ You've also been passed a file containing the last few commits. Review these to understand what work has been done.
8
+
9
+ If all AFK tasks are complete, output <promise>NO MORE TASKS</promise>.
10
+
11
+ # TASK SELECTION
12
+
13
+ Pick the next task. Prioritize tasks in this order:
14
+
15
+ 1. Critical bugfixes
16
+ 2. Development infrastructure
17
+
18
+ Getting development infrastructure like tests and types and dev scripts ready is an important precursor to building features.
19
+
20
+ 3. Tracer bullets for new features
21
+
22
+ Tracer bullets are small slices of functionality that go through all layers of the system, allowing you to test and validate your approach early. This helps in identifying potential issues and ensures that the overall architecture is sound before investing significant time in development.
23
+
24
+ TL;DR - build a tiny, end-to-end slice of the feature first, then expand it out.
25
+
26
+ 4. Polish and quick wins
27
+ 5. Refactors
28
+
29
+ # EXPLORATION
30
+
31
+ Explore the repo.
32
+
33
+ # IMPLEMENTATION
34
+
35
+ Complete the task.
36
+
37
+ # FEEDBACK LOOPS
38
+
39
+ Before committing, run the feedback loops:
40
+
41
+ ### Frontend / Node
42
+
43
+ - `pnpm run test` to run the tests
44
+ - `pnpm run typecheck` to run the type checker
45
+
46
+ ### Backend / Dotnet
47
+
48
+ - `dotnet test` to run the tests
49
+ - `dotnet build` to type-check
50
+
51
+ # COMMIT
52
+
53
+ Make a single `git commit -am` with a short message:
54
+
55
+ - Subject line (≤72 chars): what changed
56
+ - Optional body (≤3 bullets): key decision, blocker for next iteration
57
+ - No file lists (git tracks them), no `Co-Authored-By`
58
+
59
+ # THE ISSUE
60
+
61
+ If the task is complete, close the original GitHub issue.
62
+
63
+ If the task is not complete, leave a comment on the GitHub issue with what was done.
64
+
65
+ # FINAL RULES
66
+
67
+ ONLY WORK ON A SINGLE TASK.
@@ -1,80 +1,80 @@
1
- # ISSUES
2
-
3
- GitHub issues are provided at start of context. Parse it to get open issues with their bodies and comments.
4
-
5
- You will work on the AFK issues only, not the HITL ones.
6
-
7
- You've also been passed a file containing the last few commits. Review these to understand what work has been done.
8
-
9
- If all AFK tasks are complete, output <promise>NO MORE TASKS</promise>.
10
-
11
- # TASK SELECTION
12
-
13
- Pick the next task. Prioritize tasks in this order:
14
-
15
- 1. Critical bugfixes
16
- 2. Development infrastructure
17
-
18
- Getting development infrastructure like tests and types and dev scripts ready is an important precursor to building features.
19
-
20
- 3. Tracer bullets for new features
21
-
22
- Tracer bullets are small slices of functionality that go through all layers of the system, allowing you to test and validate your approach early. This helps in identifying potential issues and ensures that the overall architecture is sound before investing significant time in development.
23
-
24
- TL;DR - build a tiny, end-to-end slice of the feature first, then expand it out.
25
-
26
- 4. Polish and quick wins
27
- 5. Refactors
28
-
29
- # EXPLORATION
30
-
31
- Explore the repo.
32
-
33
- # IMPLEMENTATION
34
-
35
- Complete the task.
36
-
37
- # FEEDBACK LOOPS
38
-
39
- Before committing, run the feedback loops:
40
-
41
- ### Frontend / Node
42
-
43
- - `pnpm run test` to run the tests
44
- - `pnpm run typecheck` to run the type checker
45
-
46
- ### Backend / Dotnet
47
-
48
- - `dotnet test` to run the tests
49
- - `dotnet build` to type-check
50
-
51
- **If `dotnet test` or `dotnet build` fails with MSB3248** ("Could not resolve assembly reference" / "file is corrupt") — this is a known virtiofs/9p I/O quirk when the repo is mounted from the Windows host. It is NOT a code defect. Do not defer verification. Re-run with build outputs redirected to `/tmp` and parallelism disabled:
52
-
53
- ```bash
54
- dotnet test <path-to-test-csproj> \
55
- -m:1 \
56
- /p:UseSharedCompilation=false \
57
- /p:BuildInParallel=false \
58
- /p:BaseIntermediateOutputPath=/tmp/ralph-obj/$(basename <path-to-test-csproj> .csproj)/ \
59
- /p:BaseOutputPath=/tmp/ralph-bin/$(basename <path-to-test-csproj> .csproj)/
60
- ```
61
-
62
- Only if that second attempt also fails may you defer and record the blocker in the commit message.
63
-
64
- # COMMIT
65
-
66
- Make a single `git commit -am` with a short message:
67
-
68
- - Subject line (≤72 chars): what changed
69
- - Optional body (≤3 bullets): key decision, blocker for next iteration
70
- - No file lists (git tracks them), no `Co-Authored-By`
71
-
72
- # THE ISSUE
73
-
74
- If the task is complete, close the original GitHub issue.
75
-
76
- If the task is not complete, leave a comment on the GitHub issue with what was done.
77
-
78
- # FINAL RULES
79
-
80
- ONLY WORK ON A SINGLE TASK.
1
+ # ISSUES
2
+
3
+ GitHub issues are provided at start of context. Parse it to get open issues with their bodies and comments.
4
+
5
+ You will work on the AFK issues only, not the HITL ones.
6
+
7
+ You've also been passed a file containing the last few commits. Review these to understand what work has been done.
8
+
9
+ If all AFK tasks are complete, output <promise>NO MORE TASKS</promise>.
10
+
11
+ # TASK SELECTION
12
+
13
+ Pick the next task. Prioritize tasks in this order:
14
+
15
+ 1. Critical bugfixes
16
+ 2. Development infrastructure
17
+
18
+ Getting development infrastructure like tests and types and dev scripts ready is an important precursor to building features.
19
+
20
+ 3. Tracer bullets for new features
21
+
22
+ Tracer bullets are small slices of functionality that go through all layers of the system, allowing you to test and validate your approach early. This helps in identifying potential issues and ensures that the overall architecture is sound before investing significant time in development.
23
+
24
+ TL;DR - build a tiny, end-to-end slice of the feature first, then expand it out.
25
+
26
+ 4. Polish and quick wins
27
+ 5. Refactors
28
+
29
+ # EXPLORATION
30
+
31
+ Explore the repo.
32
+
33
+ # IMPLEMENTATION
34
+
35
+ Complete the task.
36
+
37
+ # FEEDBACK LOOPS
38
+
39
+ Before committing, run the feedback loops:
40
+
41
+ ### Frontend / Node
42
+
43
+ - `pnpm run test` to run the tests
44
+ - `pnpm run typecheck` to run the type checker
45
+
46
+ ### Backend / Dotnet
47
+
48
+ - `dotnet test` to run the tests
49
+ - `dotnet build` to type-check
50
+
51
+ **If `dotnet test` or `dotnet build` fails with MSB3248** ("Could not resolve assembly reference" / "file is corrupt") — this is a known virtiofs/9p I/O quirk when the repo is mounted from the Windows host. It is NOT a code defect. Do not defer verification. Re-run with build outputs redirected to `/tmp` and parallelism disabled:
52
+
53
+ ```bash
54
+ dotnet test <path-to-test-csproj> \
55
+ -m:1 \
56
+ /p:UseSharedCompilation=false \
57
+ /p:BuildInParallel=false \
58
+ /p:BaseIntermediateOutputPath=/tmp/ralph-obj/$(basename <path-to-test-csproj> .csproj)/ \
59
+ /p:BaseOutputPath=/tmp/ralph-bin/$(basename <path-to-test-csproj> .csproj)/
60
+ ```
61
+
62
+ Only if that second attempt also fails may you defer and record the blocker in the commit message.
63
+
64
+ # COMMIT
65
+
66
+ Make a single `git commit -am` with a short message:
67
+
68
+ - Subject line (≤72 chars): what changed
69
+ - Optional body (≤3 bullets): key decision, blocker for next iteration
70
+ - No file lists (git tracks them), no `Co-Authored-By`
71
+
72
+ # THE ISSUE
73
+
74
+ If the task is complete, close the original GitHub issue.
75
+
76
+ If the task is not complete, leave a comment on the GitHub issue with what was done.
77
+
78
+ # FINAL RULES
79
+
80
+ ONLY WORK ON A SINGLE TASK.