@unimatrix27/ralph-harness 1.0.0

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.
Files changed (103) hide show
  1. package/CONTRIBUTING.md +89 -0
  2. package/README.md +401 -0
  3. package/dist/bin/ralph-bootstrap-aws.d.ts +3 -0
  4. package/dist/bin/ralph-bootstrap-aws.d.ts.map +1 -0
  5. package/dist/bin/ralph-bootstrap-aws.js +43 -0
  6. package/dist/bin/ralph-bootstrap-aws.js.map +1 -0
  7. package/dist/bin/ralph-fire.d.ts +3 -0
  8. package/dist/bin/ralph-fire.d.ts.map +1 -0
  9. package/dist/bin/ralph-fire.js +59 -0
  10. package/dist/bin/ralph-fire.js.map +1 -0
  11. package/dist/bin/ralph-gsm.d.ts +3 -0
  12. package/dist/bin/ralph-gsm.d.ts.map +1 -0
  13. package/dist/bin/ralph-gsm.js +93 -0
  14. package/dist/bin/ralph-gsm.js.map +1 -0
  15. package/dist/bin/ralph-orchestrate.d.ts +3 -0
  16. package/dist/bin/ralph-orchestrate.d.ts.map +1 -0
  17. package/dist/bin/ralph-orchestrate.js +20 -0
  18. package/dist/bin/ralph-orchestrate.js.map +1 -0
  19. package/dist/bin/ralph-sync-credential.d.ts +3 -0
  20. package/dist/bin/ralph-sync-credential.d.ts.map +1 -0
  21. package/dist/bin/ralph-sync-credential.js +44 -0
  22. package/dist/bin/ralph-sync-credential.js.map +1 -0
  23. package/dist/bin/ralph-sync-github-pat.d.ts +3 -0
  24. package/dist/bin/ralph-sync-github-pat.d.ts.map +1 -0
  25. package/dist/bin/ralph-sync-github-pat.js +93 -0
  26. package/dist/bin/ralph-sync-github-pat.js.map +1 -0
  27. package/dist/bin/ralph-tail-logs.d.ts +3 -0
  28. package/dist/bin/ralph-tail-logs.d.ts.map +1 -0
  29. package/dist/bin/ralph-tail-logs.js +72 -0
  30. package/dist/bin/ralph-tail-logs.js.map +1 -0
  31. package/dist/bin/ralph-validate-config.d.ts +3 -0
  32. package/dist/bin/ralph-validate-config.d.ts.map +1 -0
  33. package/dist/bin/ralph-validate-config.js +41 -0
  34. package/dist/bin/ralph-validate-config.js.map +1 -0
  35. package/dist/lib/aws-bootstrap.d.ts +53 -0
  36. package/dist/lib/aws-bootstrap.d.ts.map +1 -0
  37. package/dist/lib/aws-bootstrap.js +438 -0
  38. package/dist/lib/aws-bootstrap.js.map +1 -0
  39. package/dist/lib/aws-clients.d.ts +17 -0
  40. package/dist/lib/aws-clients.d.ts.map +1 -0
  41. package/dist/lib/aws-clients.js +25 -0
  42. package/dist/lib/aws-clients.js.map +1 -0
  43. package/dist/lib/claude-runner.d.ts +21 -0
  44. package/dist/lib/claude-runner.d.ts.map +1 -0
  45. package/dist/lib/claude-runner.js +101 -0
  46. package/dist/lib/claude-runner.js.map +1 -0
  47. package/dist/lib/credential-syncer.d.ts +27 -0
  48. package/dist/lib/credential-syncer.d.ts.map +1 -0
  49. package/dist/lib/credential-syncer.js +116 -0
  50. package/dist/lib/credential-syncer.js.map +1 -0
  51. package/dist/lib/ec2-orchestrator.d.ts +38 -0
  52. package/dist/lib/ec2-orchestrator.d.ts.map +1 -0
  53. package/dist/lib/ec2-orchestrator.js +469 -0
  54. package/dist/lib/ec2-orchestrator.js.map +1 -0
  55. package/dist/lib/env-loader.d.ts +18 -0
  56. package/dist/lib/env-loader.d.ts.map +1 -0
  57. package/dist/lib/env-loader.js +120 -0
  58. package/dist/lib/env-loader.js.map +1 -0
  59. package/dist/lib/fire-launcher.d.ts +59 -0
  60. package/dist/lib/fire-launcher.d.ts.map +1 -0
  61. package/dist/lib/fire-launcher.js +320 -0
  62. package/dist/lib/fire-launcher.js.map +1 -0
  63. package/dist/lib/gh-runner.d.ts +13 -0
  64. package/dist/lib/gh-runner.d.ts.map +1 -0
  65. package/dist/lib/gh-runner.js +50 -0
  66. package/dist/lib/gh-runner.js.map +1 -0
  67. package/dist/lib/github-state-mutator.d.ts +11 -0
  68. package/dist/lib/github-state-mutator.d.ts.map +1 -0
  69. package/dist/lib/github-state-mutator.js +179 -0
  70. package/dist/lib/github-state-mutator.js.map +1 -0
  71. package/dist/lib/phase-result-schemas.d.ts +88 -0
  72. package/dist/lib/phase-result-schemas.d.ts.map +1 -0
  73. package/dist/lib/phase-result-schemas.js +180 -0
  74. package/dist/lib/phase-result-schemas.js.map +1 -0
  75. package/dist/lib/post-hoc-agent-stuck-checker.d.ts +26 -0
  76. package/dist/lib/post-hoc-agent-stuck-checker.d.ts.map +1 -0
  77. package/dist/lib/post-hoc-agent-stuck-checker.js +142 -0
  78. package/dist/lib/post-hoc-agent-stuck-checker.js.map +1 -0
  79. package/dist/lib/prompt-renderer.d.ts +4 -0
  80. package/dist/lib/prompt-renderer.d.ts.map +1 -0
  81. package/dist/lib/prompt-renderer.js +30 -0
  82. package/dist/lib/prompt-renderer.js.map +1 -0
  83. package/dist/lib/security-runner.d.ts +7 -0
  84. package/dist/lib/security-runner.d.ts.map +1 -0
  85. package/dist/lib/security-runner.js +53 -0
  86. package/dist/lib/security-runner.js.map +1 -0
  87. package/dist/lib/structured-log-emitter.d.ts +53 -0
  88. package/dist/lib/structured-log-emitter.d.ts.map +1 -0
  89. package/dist/lib/structured-log-emitter.js +122 -0
  90. package/dist/lib/structured-log-emitter.js.map +1 -0
  91. package/dist/lib/target-config-schema.d.ts +28 -0
  92. package/dist/lib/target-config-schema.d.ts.map +1 -0
  93. package/dist/lib/target-config-schema.js +157 -0
  94. package/dist/lib/target-config-schema.js.map +1 -0
  95. package/dist/lib/user-data-renderer.d.ts +20 -0
  96. package/dist/lib/user-data-renderer.d.ts.map +1 -0
  97. package/dist/lib/user-data-renderer.js +75 -0
  98. package/dist/lib/user-data-renderer.js.map +1 -0
  99. package/lib/cloud-init/system-setup.sh +338 -0
  100. package/package.json +55 -0
  101. package/prompts/discovery.md +182 -0
  102. package/prompts/implementation.md +161 -0
  103. package/prompts/review.md +135 -0
@@ -0,0 +1,50 @@
1
+ // gh-runner — thin subprocess wrapper around the `gh` CLI.
2
+ //
3
+ // Exists so github-state-mutator (and any future caller) can be unit-tested
4
+ // by mocking exactly one module instead of stubbing a binary on PATH.
5
+ //
6
+ // Contract:
7
+ // runGh(args) — spawn `gh <args...>`, return { stdout, stderr, exitCode }.
8
+ // runGhJson(args) — same, but JSON.parse the stdout (caller still passes
9
+ // `--json` to gh; this just parses the result).
10
+ //
11
+ // Both functions throw GhRunnerError on non-zero exit. Callers that need to
12
+ // branch on a non-zero exit (none today) can catch and inspect .exitCode.
13
+ import { spawnSync } from "node:child_process";
14
+ const MODULE_PREFIX = "gh-runner";
15
+ export class GhRunnerError extends Error {
16
+ exitCode;
17
+ stderr;
18
+ constructor(exitCode, stderr, message) {
19
+ super(message);
20
+ this.exitCode = exitCode;
21
+ this.stderr = stderr;
22
+ this.name = "GhRunnerError";
23
+ }
24
+ }
25
+ export function runGh(args) {
26
+ const r = spawnSync("gh", args, { encoding: "utf8" });
27
+ if (r.error) {
28
+ throw new GhRunnerError(-1, "", `${MODULE_PREFIX}: failed to spawn gh: ${r.error.message}`);
29
+ }
30
+ const result = {
31
+ stdout: r.stdout ?? "",
32
+ stderr: r.stderr ?? "",
33
+ exitCode: r.status ?? -1,
34
+ };
35
+ if (result.exitCode !== 0) {
36
+ throw new GhRunnerError(result.exitCode, result.stderr, `${MODULE_PREFIX}: gh ${args.join(" ")} failed (exit ${result.exitCode}): ${result.stderr.trim()}`);
37
+ }
38
+ return result;
39
+ }
40
+ export function runGhJson(args) {
41
+ const { stdout } = runGh(args);
42
+ try {
43
+ return JSON.parse(stdout);
44
+ }
45
+ catch (err) {
46
+ const detail = err instanceof Error ? err.message : String(err);
47
+ throw new GhRunnerError(0, "", `${MODULE_PREFIX}: could not parse gh stdout as JSON: ${detail}`);
48
+ }
49
+ }
50
+ //# sourceMappingURL=gh-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gh-runner.js","sourceRoot":"","sources":["../../src/lib/gh-runner.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,EAAE;AACF,4EAA4E;AAC5E,sEAAsE;AACtE,EAAE;AACF,YAAY;AACZ,8EAA8E;AAC9E,2EAA2E;AAC3E,oEAAoE;AACpE,EAAE;AACF,4EAA4E;AAC5E,0EAA0E;AAE1E,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,aAAa,GAAG,WAAW,CAAC;AAQlC,MAAM,OAAO,aAAc,SAAQ,KAAK;IAEpB;IACA;IAFlB,YACkB,QAAgB,EAChB,MAAc,EAC9B,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAQ;QAI9B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,UAAU,KAAK,CAAC,IAAuB;IAC3C,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAEtD,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,IAAI,aAAa,CACrB,CAAC,CAAC,EACF,EAAE,EACF,GAAG,aAAa,yBAAyB,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAC3D,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAa;QACvB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;QACtB,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE;QACtB,QAAQ,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;KACzB,CAAC;IAEF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,aAAa,CACrB,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,MAAM,EACb,GAAG,aAAa,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,QAAQ,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CACnG,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,SAAS,CAAc,IAAuB;IAC5D,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAM,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,MAAM,IAAI,aAAa,CACrB,CAAC,EACD,EAAE,EACF,GAAG,aAAa,wCAAwC,MAAM,EAAE,CACjE,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { GhRunnerError, runGh, type GhResult } from "./gh-runner.js";
2
+ export declare const MODULE_PREFIX = "github-state-mutator";
3
+ export declare function moduleErr(message: string): string;
4
+ export declare function swapLabel(repo: string, num: number, from: string, to: string): void;
5
+ export declare function commentIssue(repo: string, num: number, body: string): void;
6
+ export declare function findOrCreateMilestoneLogIssue(repo: string, milestone: string): number;
7
+ export declare function appendCavemanLog(repo: string, logNum: number, issueNum: number, summary: string, gotcha?: string): void;
8
+ export declare function milestoneLogBody(milestone: string): string;
9
+ export { GhRunnerError, runGh };
10
+ export type { GhResult };
11
+ //# sourceMappingURL=github-state-mutator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-state-mutator.d.ts","sourceRoot":"","sources":["../../src/lib/github-state-mutator.ts"],"names":[],"mappings":"AA4BA,OAAO,EACL,aAAa,EACb,KAAK,EACL,KAAK,QAAQ,EACd,MAAM,gBAAgB,CAAC;AAExB,eAAO,MAAM,aAAa,yBAAyB,CAAC;AAEpD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAaD,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,IAAI,CAuBN;AAGD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE1E;AAKD,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,MAAM,CAqCR;AAID,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAIN;AAID,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ1D;AA0FD,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;AAChC,YAAY,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,179 @@
1
+ // github-state-mutator — idempotent wrappers around `gh` for the four state
2
+ // mutations the orchestrator needs:
3
+ //
4
+ // swapLabel(repo, num, from, to)
5
+ // commentIssue(repo, num, body)
6
+ // findOrCreateMilestoneLogIssue(repo, milestone) — returns issue number
7
+ // appendCavemanLog(repo, logNum, issueNum, summary, gotcha?)
8
+ //
9
+ // Idempotency contract (must match lib/github-state-mutator.sh — bash module
10
+ // is still sourced by the EC2 orchestrator until slice 5 cuts it over):
11
+ //
12
+ // - swapLabel: when the issue already has `to` and not `from`, no `gh issue
13
+ // edit` call is made (verified by the test matrix).
14
+ // - findOrCreateMilestoneLogIssue: a second call with the same milestone
15
+ // name returns the existing issue number without invoking `gh issue
16
+ // create`.
17
+ // - commentIssue / appendCavemanLog are append-only by design — every call
18
+ // posts. The milestone-log workflow relies on this (one comment per
19
+ // iteration). This matches the bash contract; deduping would be a
20
+ // regression for the consumer.
21
+ //
22
+ // Errors go to stderr via moduleErr() so callers can grep on the prefix.
23
+ //
24
+ // Exit codes are surfaced by the CLI (ralph-gsm), not this module:
25
+ // 0 success
26
+ // 2 usage / missing required argument (CLI only)
27
+ // non-zero propagated from gh via GhRunnerError (CLI only)
28
+ import { GhRunnerError, runGh, } from "./gh-runner.js";
29
+ export const MODULE_PREFIX = "github-state-mutator";
30
+ export function moduleErr(message) {
31
+ return `${MODULE_PREFIX}: error: ${message}`;
32
+ }
33
+ // swapLabel — remove `from` if present, add `to` if missing. No gh-edit call
34
+ // at all when the target state already matches.
35
+ export function swapLabel(repo, num, from, to) {
36
+ const view = runGh([
37
+ "issue",
38
+ "view",
39
+ String(num),
40
+ "--repo",
41
+ repo,
42
+ "--json",
43
+ "labels",
44
+ ]);
45
+ const parsed = parseLabelsJson(view.stdout, repo, num);
46
+ const names = new Set(parsed.labels.map((l) => l.name));
47
+ const hasFrom = names.has(from);
48
+ const hasTo = names.has(to);
49
+ if (!hasFrom && hasTo)
50
+ return;
51
+ const args = ["issue", "edit", String(num), "--repo", repo];
52
+ if (hasFrom)
53
+ args.push("--remove-label", from);
54
+ if (!hasTo)
55
+ args.push("--add-label", to);
56
+ runGh(args);
57
+ }
58
+ // commentIssue — post a comment. Append-only (see contract above).
59
+ export function commentIssue(repo, num, body) {
60
+ runGh(["issue", "comment", String(num), "--repo", repo, "--body", body]);
61
+ }
62
+ // findOrCreateMilestoneLogIssue — find by exact title `[log] <milestone>`
63
+ // (filtered to the meta:milestone-log label). Create if missing. Echo the
64
+ // issue number.
65
+ export function findOrCreateMilestoneLogIssue(repo, milestone) {
66
+ const title = `[log] ${milestone}`;
67
+ const list = runGh([
68
+ "issue",
69
+ "list",
70
+ "--repo",
71
+ repo,
72
+ "--label",
73
+ "meta:milestone-log",
74
+ "--state",
75
+ "all",
76
+ "--json",
77
+ "number,title",
78
+ "--limit",
79
+ "100",
80
+ ]);
81
+ const items = parseIssueList(list.stdout, repo);
82
+ const existing = items.find((i) => i.title === title);
83
+ if (existing)
84
+ return existing.number;
85
+ const body = milestoneLogBody(milestone);
86
+ const create = runGh([
87
+ "issue",
88
+ "create",
89
+ "--repo",
90
+ repo,
91
+ "--title",
92
+ title,
93
+ "--label",
94
+ "meta:milestone-log",
95
+ "--body",
96
+ body,
97
+ ]);
98
+ return parseIssueNumberFromUrl(create.stdout);
99
+ }
100
+ // appendCavemanLog — post one caveman-format comment on the milestone-log
101
+ // issue. Empty/missing gotcha renders as `-`.
102
+ export function appendCavemanLog(repo, logNum, issueNum, summary, gotcha) {
103
+ const g = gotcha && gotcha.length > 0 ? gotcha : "-";
104
+ const line = `#${issueNum} | ${summary} | ${g}`;
105
+ commentIssue(repo, logNum, line);
106
+ }
107
+ // ---- internals ----
108
+ export function milestoneLogBody(milestone) {
109
+ return `This issue is the cross-iteration learnings log for milestone '${milestone}'.
110
+
111
+ Each ralph-harness implementation iteration appends one comment in caveman format:
112
+
113
+ #<issue> | <one-line summary> | <gotcha or '-'>
114
+
115
+ Do not close manually — the harness reads recent comments here for prior-iteration context.`;
116
+ }
117
+ function parseLabelsJson(stdout, repo, num) {
118
+ let parsed;
119
+ try {
120
+ parsed = JSON.parse(stdout);
121
+ }
122
+ catch (err) {
123
+ const detail = err instanceof Error ? err.message : String(err);
124
+ throw new Error(moduleErr(`swap_label: could not parse labels for ${repo}#${num}: ${detail}`));
125
+ }
126
+ if (!parsed ||
127
+ typeof parsed !== "object" ||
128
+ !Array.isArray(parsed.labels)) {
129
+ throw new Error(moduleErr(`swap_label: unexpected labels payload for ${repo}#${num}`));
130
+ }
131
+ const rawLabels = parsed.labels;
132
+ const labels = [];
133
+ for (const l of rawLabels) {
134
+ if (l && typeof l === "object" && typeof l.name === "string") {
135
+ labels.push({ name: l.name });
136
+ }
137
+ }
138
+ return { labels };
139
+ }
140
+ function parseIssueList(stdout, repo) {
141
+ let parsed;
142
+ try {
143
+ parsed = JSON.parse(stdout);
144
+ }
145
+ catch (err) {
146
+ const detail = err instanceof Error ? err.message : String(err);
147
+ throw new Error(moduleErr(`find_or_create_milestone_log_issue: could not parse issue list for ${repo}: ${detail}`));
148
+ }
149
+ if (!Array.isArray(parsed)) {
150
+ throw new Error(moduleErr(`find_or_create_milestone_log_issue: expected array from gh issue list, got ${typeof parsed}`));
151
+ }
152
+ const out = [];
153
+ for (const i of parsed) {
154
+ if (i &&
155
+ typeof i === "object" &&
156
+ typeof i.number === "number" &&
157
+ typeof i.title === "string") {
158
+ out.push({
159
+ number: i.number,
160
+ title: i.title,
161
+ });
162
+ }
163
+ }
164
+ return out;
165
+ }
166
+ function parseIssueNumberFromUrl(stdout) {
167
+ // `gh issue create` prints the new issue URL on stdout — last path segment
168
+ // is the issue number.
169
+ const trimmed = stdout.trim();
170
+ const tail = trimmed.split("/").pop() ?? "";
171
+ const n = Number.parseInt(tail, 10);
172
+ if (!Number.isFinite(n) || n <= 0) {
173
+ throw new Error(moduleErr(`find_or_create_milestone_log_issue: could not parse issue number from gh stdout: ${trimmed}`));
174
+ }
175
+ return n;
176
+ }
177
+ // Re-export so the CLI can use a single import surface.
178
+ export { GhRunnerError, runGh };
179
+ //# sourceMappingURL=github-state-mutator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-state-mutator.js","sourceRoot":"","sources":["../../src/lib/github-state-mutator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { z } from "zod";
2
+ export declare const MODULE_PREFIX = "phase-result-schemas";
3
+ export declare class SchemaError extends Error {
4
+ readonly path?: string | undefined;
5
+ readonly cause?: unknown | undefined;
6
+ constructor(message: string, path?: string | undefined, cause?: unknown | undefined);
7
+ }
8
+ export declare const DecisionPickedSchema: z.ZodObject<{
9
+ status: z.ZodLiteral<"PICKED">;
10
+ issue: z.ZodNumber;
11
+ reasoning: z.ZodString;
12
+ }, z.core.$strip>;
13
+ export declare const DecisionNoneSchema: z.ZodObject<{
14
+ status: z.ZodLiteral<"NONE">;
15
+ reasoning: z.ZodString;
16
+ }, z.core.$strip>;
17
+ export declare const DecisionAllBlockedSchema: z.ZodObject<{
18
+ status: z.ZodLiteral<"ALL_BLOCKED">;
19
+ reasoning: z.ZodString;
20
+ }, z.core.$strip>;
21
+ export declare const DecisionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
22
+ status: z.ZodLiteral<"PICKED">;
23
+ issue: z.ZodNumber;
24
+ reasoning: z.ZodString;
25
+ }, z.core.$strip>, z.ZodObject<{
26
+ status: z.ZodLiteral<"NONE">;
27
+ reasoning: z.ZodString;
28
+ }, z.core.$strip>, z.ZodObject<{
29
+ status: z.ZodLiteral<"ALL_BLOCKED">;
30
+ reasoning: z.ZodString;
31
+ }, z.core.$strip>], "status">;
32
+ export type Decision = z.infer<typeof DecisionSchema>;
33
+ export declare const ImplPrOpenedSchema: z.ZodObject<{
34
+ status: z.ZodLiteral<"PR_OPENED">;
35
+ issue: z.ZodNumber;
36
+ pr_number: z.ZodNumber;
37
+ pr_url: z.ZodString;
38
+ branch: z.ZodString;
39
+ }, z.core.$strip>;
40
+ export declare const ImplAgentStuckSchema: z.ZodObject<{
41
+ status: z.ZodLiteral<"AGENT_STUCK">;
42
+ issue: z.ZodNumber;
43
+ reason: z.ZodString;
44
+ }, z.core.$strip>;
45
+ export declare const ImplResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
46
+ status: z.ZodLiteral<"PR_OPENED">;
47
+ issue: z.ZodNumber;
48
+ pr_number: z.ZodNumber;
49
+ pr_url: z.ZodString;
50
+ branch: z.ZodString;
51
+ }, z.core.$strip>, z.ZodObject<{
52
+ status: z.ZodLiteral<"AGENT_STUCK">;
53
+ issue: z.ZodNumber;
54
+ reason: z.ZodString;
55
+ }, z.core.$strip>], "status">;
56
+ export type ImplResult = z.infer<typeof ImplResultSchema>;
57
+ export declare const ReviewNoReviewSchema: z.ZodObject<{
58
+ status: z.ZodLiteral<"NO_REVIEW">;
59
+ reason: z.ZodOptional<z.ZodString>;
60
+ }, z.core.$strip>;
61
+ export declare const ReviewRevisionAppliedSchema: z.ZodObject<{
62
+ status: z.ZodLiteral<"REVISION_APPLIED">;
63
+ summary: z.ZodString;
64
+ gotcha: z.ZodOptional<z.ZodString>;
65
+ }, z.core.$strip>;
66
+ export declare const ReviewResultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
67
+ status: z.ZodLiteral<"NO_REVIEW">;
68
+ reason: z.ZodOptional<z.ZodString>;
69
+ }, z.core.$strip>, z.ZodObject<{
70
+ status: z.ZodLiteral<"REVISION_APPLIED">;
71
+ summary: z.ZodString;
72
+ gotcha: z.ZodOptional<z.ZodString>;
73
+ }, z.core.$strip>], "status">;
74
+ export type ReviewResult = z.infer<typeof ReviewResultSchema>;
75
+ export declare const MilestoneLogSchema: z.ZodUnion<readonly [z.ZodObject<{
76
+ milestone: z.ZodString;
77
+ log_issue: z.ZodNullable<z.ZodNumber>;
78
+ }, z.core.$strip>, z.ZodObject<{}, z.core.$strict>]>;
79
+ export type MilestoneLog = z.infer<typeof MilestoneLogSchema>;
80
+ export declare function parseDecision(raw: string): Decision;
81
+ export declare function parseImplResult(raw: string): ImplResult;
82
+ export declare function parseReviewResult(raw: string): ReviewResult;
83
+ export declare function parseMilestoneLog(raw: string): MilestoneLog;
84
+ export declare function readDecision(path: string): Decision;
85
+ export declare function readImplResult(path: string): ImplResult;
86
+ export declare function readReviewResult(path: string): ReviewResult;
87
+ export declare function readMilestoneLog(path: string): MilestoneLog;
88
+ //# sourceMappingURL=phase-result-schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phase-result-schemas.d.ts","sourceRoot":"","sources":["../../src/lib/phase-result-schemas.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,aAAa,yBAAyB,CAAC;AAEpD,qBAAa,WAAY,SAAQ,KAAK;aAGlB,IAAI,CAAC,EAAE,MAAM;aACb,KAAK,CAAC,EAAE,OAAO;gBAF/B,OAAO,EAAE,MAAM,EACC,IAAI,CAAC,EAAE,MAAM,YAAA,EACb,KAAK,CAAC,EAAE,OAAO,YAAA;CAKlC;AAID,eAAO,MAAM,oBAAoB;;;;iBAI/B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;iBAG7B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;iBAGnC,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;6BAIzB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAItD,eAAO,MAAM,kBAAkB;;;;;;iBAM7B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;iBAI/B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;6BAG3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAI1D,eAAO,MAAM,oBAAoB;;;iBAG/B,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;iBAItC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;6BAG7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAmB9D,eAAO,MAAM,kBAAkB;;;oDAG7B,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAwC9D,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAEnD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAEvD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAE3D;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAE3D;AAiCD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAEnD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEvD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAE3D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAE3D"}
@@ -0,0 +1,180 @@
1
+ // phase-result-schemas — Zod schemas + parser helpers for the four contract
2
+ // JSON files the harness writes during a single iteration:
3
+ //
4
+ // /tmp/ralph/decision.json (discovery output)
5
+ // /tmp/ralph/issue.json (full gh payload of the picked issue)
6
+ // /tmp/ralph/milestone-log.json (cross-iteration log pointer)
7
+ // /tmp/ralph/impl-result.json (implementation output)
8
+ // /tmp/ralph/review-result.json (review output)
9
+ // /tmp/ralph/crafted-prompt.md (the impl call's input — text, not JSON)
10
+ //
11
+ // The orchestrator branches on the discriminated `status` field of each
12
+ // JSON output. Validation here exists so an off-by-one in claude's output
13
+ // surfaces as a typed error in the orchestrator (exit 3, missing/invalid
14
+ // contract file) rather than an opaque later crash.
15
+ //
16
+ // Public surface:
17
+ // DecisionSchema (PICKED | NONE | ALL_BLOCKED)
18
+ // ImplResultSchema (PR_OPENED | AGENT_STUCK)
19
+ // ReviewResultSchema (NO_REVIEW | REVISION_APPLIED)
20
+ // MilestoneLogSchema ({} | {milestone, log_issue})
21
+ // parseDecision / parseImplResult / parseReviewResult / parseMilestoneLog
22
+ // readDecision / readImplResult / readReviewResult / readMilestoneLog
23
+ //
24
+ // Parsers throw `SchemaError` on a parse failure with a human-readable
25
+ // summary; readers add the file path to the message so a CloudWatch grep
26
+ // shows which contract file misbehaved.
27
+ import { readFileSync } from "node:fs";
28
+ import { z } from "zod";
29
+ export const MODULE_PREFIX = "phase-result-schemas";
30
+ export class SchemaError extends Error {
31
+ path;
32
+ cause;
33
+ constructor(message, path, cause) {
34
+ super(message);
35
+ this.path = path;
36
+ this.cause = cause;
37
+ this.name = "SchemaError";
38
+ }
39
+ }
40
+ // ---- Decision -------------------------------------------------------
41
+ export const DecisionPickedSchema = z.object({
42
+ status: z.literal("PICKED"),
43
+ issue: z.number().int().positive(),
44
+ reasoning: z.string(),
45
+ });
46
+ export const DecisionNoneSchema = z.object({
47
+ status: z.literal("NONE"),
48
+ reasoning: z.string(),
49
+ });
50
+ export const DecisionAllBlockedSchema = z.object({
51
+ status: z.literal("ALL_BLOCKED"),
52
+ reasoning: z.string(),
53
+ });
54
+ export const DecisionSchema = z.discriminatedUnion("status", [
55
+ DecisionPickedSchema,
56
+ DecisionNoneSchema,
57
+ DecisionAllBlockedSchema,
58
+ ]);
59
+ // ---- Implementation result -----------------------------------------
60
+ export const ImplPrOpenedSchema = z.object({
61
+ status: z.literal("PR_OPENED"),
62
+ issue: z.number().int().positive(),
63
+ pr_number: z.number().int().positive(),
64
+ pr_url: z.string().url(),
65
+ branch: z.string().min(1),
66
+ });
67
+ export const ImplAgentStuckSchema = z.object({
68
+ status: z.literal("AGENT_STUCK"),
69
+ issue: z.number().int().positive(),
70
+ reason: z.string(),
71
+ });
72
+ export const ImplResultSchema = z.discriminatedUnion("status", [
73
+ ImplPrOpenedSchema,
74
+ ImplAgentStuckSchema,
75
+ ]);
76
+ // ---- Review result -------------------------------------------------
77
+ export const ReviewNoReviewSchema = z.object({
78
+ status: z.literal("NO_REVIEW"),
79
+ reason: z.string().optional(),
80
+ });
81
+ export const ReviewRevisionAppliedSchema = z.object({
82
+ status: z.literal("REVISION_APPLIED"),
83
+ summary: z.string(),
84
+ gotcha: z.string().optional(),
85
+ });
86
+ export const ReviewResultSchema = z.discriminatedUnion("status", [
87
+ ReviewNoReviewSchema,
88
+ ReviewRevisionAppliedSchema,
89
+ ]);
90
+ // ---- Milestone log -------------------------------------------------
91
+ //
92
+ // Two valid shapes:
93
+ // {} — discovery returned NONE/ALL_BLOCKED
94
+ // OR the picked issue had no milestone
95
+ // {milestone: string, log_issue: int|null}
96
+ //
97
+ // `log_issue` may be `null` when discovery picked an issue without a
98
+ // milestone (the bash port emitted that explicitly).
99
+ const MilestoneLogPresentSchema = z.object({
100
+ milestone: z.string(),
101
+ log_issue: z.number().int().positive().nullable(),
102
+ });
103
+ const MilestoneLogEmptySchema = z.object({}).strict();
104
+ export const MilestoneLogSchema = z.union([
105
+ MilestoneLogPresentSchema,
106
+ MilestoneLogEmptySchema,
107
+ ]);
108
+ // ---- parser helpers -----------------------------------------------
109
+ function parseWith(schema, raw, what) {
110
+ let parsed;
111
+ try {
112
+ parsed = JSON.parse(raw);
113
+ }
114
+ catch (err) {
115
+ const detail = err instanceof Error ? err.message : String(err);
116
+ throw new SchemaError(`${MODULE_PREFIX}: ${what} is not valid JSON: ${detail}`, undefined, err);
117
+ }
118
+ const result = schema.safeParse(parsed);
119
+ if (!result.success) {
120
+ throw new SchemaError(`${MODULE_PREFIX}: ${what} failed schema validation: ${formatZodError(result.error)}`, undefined, result.error);
121
+ }
122
+ return result.data;
123
+ }
124
+ function formatZodError(err) {
125
+ return err.issues
126
+ .map((i) => {
127
+ const path = i.path.length === 0 ? "<root>" : i.path.join(".");
128
+ return `${path}: ${i.message}`;
129
+ })
130
+ .join("; ");
131
+ }
132
+ export function parseDecision(raw) {
133
+ return parseWith(DecisionSchema, raw, "decision.json");
134
+ }
135
+ export function parseImplResult(raw) {
136
+ return parseWith(ImplResultSchema, raw, "impl-result.json");
137
+ }
138
+ export function parseReviewResult(raw) {
139
+ return parseWith(ReviewResultSchema, raw, "review-result.json");
140
+ }
141
+ export function parseMilestoneLog(raw) {
142
+ return parseWith(MilestoneLogSchema, raw, "milestone-log.json");
143
+ }
144
+ // ---- readers --------------------------------------------------------
145
+ //
146
+ // readers wrap parsers with a file-read step. They re-throw SchemaError
147
+ // with the path attached so a CloudWatch grep tells the operator which
148
+ // contract file misbehaved.
149
+ function readContractFile(path, parse) {
150
+ let raw;
151
+ try {
152
+ raw = readFileSync(path, "utf8");
153
+ }
154
+ catch (err) {
155
+ const detail = err instanceof Error ? err.message : String(err);
156
+ throw new SchemaError(`${MODULE_PREFIX}: could not read ${path}: ${detail}`, path, err);
157
+ }
158
+ try {
159
+ return parse(raw);
160
+ }
161
+ catch (err) {
162
+ if (err instanceof SchemaError) {
163
+ throw new SchemaError(`${err.message} (path: ${path})`, path, err.cause);
164
+ }
165
+ throw err;
166
+ }
167
+ }
168
+ export function readDecision(path) {
169
+ return readContractFile(path, parseDecision);
170
+ }
171
+ export function readImplResult(path) {
172
+ return readContractFile(path, parseImplResult);
173
+ }
174
+ export function readReviewResult(path) {
175
+ return readContractFile(path, parseReviewResult);
176
+ }
177
+ export function readMilestoneLog(path) {
178
+ return readContractFile(path, parseMilestoneLog);
179
+ }
180
+ //# sourceMappingURL=phase-result-schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phase-result-schemas.js","sourceRoot":"","sources":["../../src/lib/phase-result-schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { AwsClients } from "./aws-clients.js";
2
+ import type { Sink } from "./structured-log-emitter.js";
3
+ export declare const MODULE_PREFIX = "post-hoc-agent-stuck-checker";
4
+ export type CheckResult = {
5
+ kind: "ClearTermination";
6
+ prNumber?: number;
7
+ } | {
8
+ kind: "NoPickedIssueRecoverable";
9
+ } | {
10
+ kind: "AgentStuckLabelApplied";
11
+ issue: number;
12
+ };
13
+ export interface CheckOptions {
14
+ clients: AwsClients;
15
+ targetRepo: string;
16
+ launchTag: string;
17
+ instanceId: string;
18
+ logGroup: string;
19
+ agentStuckLabel: string;
20
+ info?: Sink;
21
+ }
22
+ export declare function findPrWithLaunchTag(repo: string, launchTag: string): Promise<number | null>;
23
+ export declare function fetchPickedIssue(clients: AwsClients, logGroup: string, instanceId: string): Promise<number | null>;
24
+ export declare function applyAgentStuckLabel(repo: string, issue: number, label: string, info: Sink): boolean;
25
+ export declare function postHocCheck(opts: CheckOptions): Promise<CheckResult>;
26
+ //# sourceMappingURL=post-hoc-agent-stuck-checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-hoc-agent-stuck-checker.d.ts","sourceRoot":"","sources":["../../src/lib/post-hoc-agent-stuck-checker.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAExD,eAAO,MAAM,aAAa,iCAAiC,CAAC;AAE5D,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,0BAA0B,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,UAAU,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAYD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuCxB;AAKD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqBxB;AAMD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,IAAI,GACT,OAAO,CAqBT;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,WAAW,CAAC,CAgCtB"}