ralph-research 0.1.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 (174) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -0
  3. package/dist/adapters/extractor/command-extractor.d.ts +9 -0
  4. package/dist/adapters/extractor/command-extractor.js +93 -0
  5. package/dist/adapters/extractor/command-extractor.js.map +1 -0
  6. package/dist/adapters/extractor/llm-judge-extractor.d.ts +9 -0
  7. package/dist/adapters/extractor/llm-judge-extractor.js +12 -0
  8. package/dist/adapters/extractor/llm-judge-extractor.js.map +1 -0
  9. package/dist/adapters/fs/json-file-decision-store.d.ts +10 -0
  10. package/dist/adapters/fs/json-file-decision-store.js +53 -0
  11. package/dist/adapters/fs/json-file-decision-store.js.map +1 -0
  12. package/dist/adapters/fs/json-file-frontier-store.d.ts +8 -0
  13. package/dist/adapters/fs/json-file-frontier-store.js +29 -0
  14. package/dist/adapters/fs/json-file-frontier-store.js.map +1 -0
  15. package/dist/adapters/fs/json-file-run-store.d.ts +10 -0
  16. package/dist/adapters/fs/json-file-run-store.js +53 -0
  17. package/dist/adapters/fs/json-file-run-store.js.map +1 -0
  18. package/dist/adapters/fs/lockfile.d.ts +24 -0
  19. package/dist/adapters/fs/lockfile.js +110 -0
  20. package/dist/adapters/fs/lockfile.js.map +1 -0
  21. package/dist/adapters/fs/manifest-loader.d.ts +10 -0
  22. package/dist/adapters/fs/manifest-loader.js +43 -0
  23. package/dist/adapters/fs/manifest-loader.js.map +1 -0
  24. package/dist/adapters/git/git-client.d.ts +9 -0
  25. package/dist/adapters/git/git-client.js +23 -0
  26. package/dist/adapters/git/git-client.js.map +1 -0
  27. package/dist/adapters/index.d.ts +1 -0
  28. package/dist/adapters/index.js +3 -0
  29. package/dist/adapters/index.js.map +1 -0
  30. package/dist/adapters/judge/llm-judge-provider.d.ts +33 -0
  31. package/dist/adapters/judge/llm-judge-provider.js +90 -0
  32. package/dist/adapters/judge/llm-judge-provider.js.map +1 -0
  33. package/dist/adapters/proposer/command-proposer.d.ts +15 -0
  34. package/dist/adapters/proposer/command-proposer.js +29 -0
  35. package/dist/adapters/proposer/command-proposer.js.map +1 -0
  36. package/dist/app/context.d.ts +5 -0
  37. package/dist/app/context.js +7 -0
  38. package/dist/app/context.js.map +1 -0
  39. package/dist/app/services/manual-decision-service.d.ts +20 -0
  40. package/dist/app/services/manual-decision-service.js +143 -0
  41. package/dist/app/services/manual-decision-service.js.map +1 -0
  42. package/dist/app/services/project-state-service.d.ts +52 -0
  43. package/dist/app/services/project-state-service.js +92 -0
  44. package/dist/app/services/project-state-service.js.map +1 -0
  45. package/dist/app/services/run-cycle-service.d.ts +25 -0
  46. package/dist/app/services/run-cycle-service.js +69 -0
  47. package/dist/app/services/run-cycle-service.js.map +1 -0
  48. package/dist/cli/commands/accept.d.ts +10 -0
  49. package/dist/cli/commands/accept.js +54 -0
  50. package/dist/cli/commands/accept.js.map +1 -0
  51. package/dist/cli/commands/demo.d.ts +9 -0
  52. package/dist/cli/commands/demo.js +108 -0
  53. package/dist/cli/commands/demo.js.map +1 -0
  54. package/dist/cli/commands/frontier.d.ts +8 -0
  55. package/dist/cli/commands/frontier.js +48 -0
  56. package/dist/cli/commands/frontier.js.map +1 -0
  57. package/dist/cli/commands/init.d.ts +10 -0
  58. package/dist/cli/commands/init.js +123 -0
  59. package/dist/cli/commands/init.js.map +1 -0
  60. package/dist/cli/commands/inspect.d.ts +8 -0
  61. package/dist/cli/commands/inspect.js +55 -0
  62. package/dist/cli/commands/inspect.js.map +1 -0
  63. package/dist/cli/commands/reject.d.ts +10 -0
  64. package/dist/cli/commands/reject.js +54 -0
  65. package/dist/cli/commands/reject.js.map +1 -0
  66. package/dist/cli/commands/run.d.ts +13 -0
  67. package/dist/cli/commands/run.js +71 -0
  68. package/dist/cli/commands/run.js.map +1 -0
  69. package/dist/cli/commands/serve-mcp.d.ts +7 -0
  70. package/dist/cli/commands/serve-mcp.js +32 -0
  71. package/dist/cli/commands/serve-mcp.js.map +1 -0
  72. package/dist/cli/commands/status.d.ts +8 -0
  73. package/dist/cli/commands/status.js +53 -0
  74. package/dist/cli/commands/status.js.map +1 -0
  75. package/dist/cli/commands/validate.d.ts +11 -0
  76. package/dist/cli/commands/validate.js +56 -0
  77. package/dist/cli/commands/validate.js.map +1 -0
  78. package/dist/cli/main.d.ts +2 -0
  79. package/dist/cli/main.js +38 -0
  80. package/dist/cli/main.js.map +1 -0
  81. package/dist/core/engine/anchor-checker.d.ts +35 -0
  82. package/dist/core/engine/anchor-checker.js +84 -0
  83. package/dist/core/engine/anchor-checker.js.map +1 -0
  84. package/dist/core/engine/audit-sampler.d.ts +16 -0
  85. package/dist/core/engine/audit-sampler.js +25 -0
  86. package/dist/core/engine/audit-sampler.js.map +1 -0
  87. package/dist/core/engine/change-budget.d.ts +11 -0
  88. package/dist/core/engine/change-budget.js +10 -0
  89. package/dist/core/engine/change-budget.js.map +1 -0
  90. package/dist/core/engine/cycle-runner.d.ts +39 -0
  91. package/dist/core/engine/cycle-runner.js +652 -0
  92. package/dist/core/engine/cycle-runner.js.map +1 -0
  93. package/dist/core/engine/experiment-runner.d.ts +13 -0
  94. package/dist/core/engine/experiment-runner.js +24 -0
  95. package/dist/core/engine/experiment-runner.js.map +1 -0
  96. package/dist/core/engine/history-compactor.d.ts +15 -0
  97. package/dist/core/engine/history-compactor.js +76 -0
  98. package/dist/core/engine/history-compactor.js.map +1 -0
  99. package/dist/core/engine/judge-pack.d.ts +44 -0
  100. package/dist/core/engine/judge-pack.js +111 -0
  101. package/dist/core/engine/judge-pack.js.map +1 -0
  102. package/dist/core/engine/parallel-proposer.d.ts +21 -0
  103. package/dist/core/engine/parallel-proposer.js +58 -0
  104. package/dist/core/engine/parallel-proposer.js.map +1 -0
  105. package/dist/core/engine/scope-checker.d.ts +35 -0
  106. package/dist/core/engine/scope-checker.js +166 -0
  107. package/dist/core/engine/scope-checker.js.map +1 -0
  108. package/dist/core/engine/workspace-manager.d.ts +32 -0
  109. package/dist/core/engine/workspace-manager.js +145 -0
  110. package/dist/core/engine/workspace-manager.js.map +1 -0
  111. package/dist/core/index.d.ts +1 -0
  112. package/dist/core/index.js +3 -0
  113. package/dist/core/index.js.map +1 -0
  114. package/dist/core/manifest/defaults.d.ts +55 -0
  115. package/dist/core/manifest/defaults.js +56 -0
  116. package/dist/core/manifest/defaults.js.map +1 -0
  117. package/dist/core/manifest/schema.d.ts +647 -0
  118. package/dist/core/manifest/schema.js +254 -0
  119. package/dist/core/manifest/schema.js.map +1 -0
  120. package/dist/core/model/decision-record.d.ts +38 -0
  121. package/dist/core/model/decision-record.js +29 -0
  122. package/dist/core/model/decision-record.js.map +1 -0
  123. package/dist/core/model/frontier-entry.d.ts +24 -0
  124. package/dist/core/model/frontier-entry.js +15 -0
  125. package/dist/core/model/frontier-entry.js.map +1 -0
  126. package/dist/core/model/metric.d.ts +13 -0
  127. package/dist/core/model/metric.js +10 -0
  128. package/dist/core/model/metric.js.map +1 -0
  129. package/dist/core/model/run-record.d.ts +110 -0
  130. package/dist/core/model/run-record.js +104 -0
  131. package/dist/core/model/run-record.js.map +1 -0
  132. package/dist/core/ports/decision-store.d.ts +6 -0
  133. package/dist/core/ports/decision-store.js +2 -0
  134. package/dist/core/ports/decision-store.js.map +1 -0
  135. package/dist/core/ports/frontier-store.d.ts +5 -0
  136. package/dist/core/ports/frontier-store.js +2 -0
  137. package/dist/core/ports/frontier-store.js.map +1 -0
  138. package/dist/core/ports/run-store.d.ts +6 -0
  139. package/dist/core/ports/run-store.js +2 -0
  140. package/dist/core/ports/run-store.js.map +1 -0
  141. package/dist/core/state/constraint-engine.d.ts +18 -0
  142. package/dist/core/state/constraint-engine.js +42 -0
  143. package/dist/core/state/constraint-engine.js.map +1 -0
  144. package/dist/core/state/frontier-engine.d.ts +24 -0
  145. package/dist/core/state/frontier-engine.js +178 -0
  146. package/dist/core/state/frontier-engine.js.map +1 -0
  147. package/dist/core/state/ratchet-engine.d.ts +28 -0
  148. package/dist/core/state/ratchet-engine.js +177 -0
  149. package/dist/core/state/ratchet-engine.js.map +1 -0
  150. package/dist/core/state/run-state-machine.d.ts +17 -0
  151. package/dist/core/state/run-state-machine.js +94 -0
  152. package/dist/core/state/run-state-machine.js.map +1 -0
  153. package/dist/mcp/main.d.ts +1 -0
  154. package/dist/mcp/main.js +8 -0
  155. package/dist/mcp/main.js.map +1 -0
  156. package/dist/mcp/server.d.ts +6 -0
  157. package/dist/mcp/server.js +97 -0
  158. package/dist/mcp/server.js.map +1 -0
  159. package/dist/shared/fs-errors.d.ts +1 -0
  160. package/dist/shared/fs-errors.js +4 -0
  161. package/dist/shared/fs-errors.js.map +1 -0
  162. package/dist/shared/logger.d.ts +2 -0
  163. package/dist/shared/logger.js +5 -0
  164. package/dist/shared/logger.js.map +1 -0
  165. package/dist/shared/template-utils.d.ts +9 -0
  166. package/dist/shared/template-utils.js +50 -0
  167. package/dist/shared/template-utils.js.map +1 -0
  168. package/package.json +44 -0
  169. package/templates/writing/docs/draft.md +1 -0
  170. package/templates/writing/prompts/judge.md +15 -0
  171. package/templates/writing/ralph.yaml +63 -0
  172. package/templates/writing/scripts/experiment.mjs +6 -0
  173. package/templates/writing/scripts/metric.mjs +24 -0
  174. package/templates/writing/scripts/propose.mjs +13 -0
@@ -0,0 +1,9 @@
1
+ export interface CommitResult {
2
+ commitSha: string;
3
+ }
4
+ export declare class GitClient {
5
+ private readonly repoRoot;
6
+ constructor(repoRoot: string);
7
+ stageAndCommitPaths(paths: string[], message: string): Promise<CommitResult>;
8
+ getHeadSha(): Promise<string>;
9
+ }
@@ -0,0 +1,23 @@
1
+ import { execa } from "execa";
2
+ export class GitClient {
3
+ repoRoot;
4
+ constructor(repoRoot) {
5
+ this.repoRoot = repoRoot;
6
+ }
7
+ async stageAndCommitPaths(paths, message) {
8
+ const uniquePaths = [...new Set(paths.map((path) => path.trim()).filter(Boolean))];
9
+ if (uniquePaths.length === 0) {
10
+ throw new Error("Refusing to create an acceptance commit with no promoted paths");
11
+ }
12
+ await execa("git", ["-C", this.repoRoot, "add", "-A", "--", ...uniquePaths]);
13
+ await execa("git", ["-C", this.repoRoot, "commit", "-m", message]);
14
+ return {
15
+ commitSha: await this.getHeadSha(),
16
+ };
17
+ }
18
+ async getHeadSha() {
19
+ const { stdout } = await execa("git", ["-C", this.repoRoot, "rev-parse", "HEAD"]);
20
+ return stdout.trim();
21
+ }
22
+ }
23
+ //# sourceMappingURL=git-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-client.js","sourceRoot":"","sources":["../../../src/adapters/git/git-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAM9B,MAAM,OAAO,SAAS;IACH,QAAQ,CAAS;IAElC,YAAmB,QAAgB;QACjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,mBAAmB,CAAC,KAAe,EAAE,OAAe;QAC/D,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACnF,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC;QAC7E,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACnE,OAAO;YACL,SAAS,EAAE,MAAM,IAAI,CAAC,UAAU,EAAE;SACnC,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,UAAU;QACrB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;QAClF,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export {};
2
+ // Adapters — FS stores, git client, proposer/judge providers will be added here.
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":";AAAA,iFAAiF"}
@@ -0,0 +1,33 @@
1
+ export type JudgeMode = "absolute" | "pairwise";
2
+ export type JudgeWinner = "candidate" | "incumbent" | "tie";
3
+ export type JudgeBackend = "codex_exec" | "claude_p";
4
+ export interface JudgeRequest {
5
+ mode: JudgeMode;
6
+ prompt: string;
7
+ model: string;
8
+ }
9
+ export interface PairwiseJudgeResponse {
10
+ mode: "pairwise";
11
+ winner: JudgeWinner;
12
+ confidence?: number;
13
+ rationale: string;
14
+ raw: string;
15
+ }
16
+ export interface AbsoluteJudgeResponse {
17
+ mode: "absolute";
18
+ score: number;
19
+ confidence?: number;
20
+ rationale: string;
21
+ raw: string;
22
+ }
23
+ export type JudgeResponse = PairwiseJudgeResponse | AbsoluteJudgeResponse;
24
+ export interface JudgeProvider {
25
+ evaluate(request: JudgeRequest): Promise<JudgeResponse>;
26
+ }
27
+ export interface CliJudgeProviderOptions {
28
+ backend: JudgeBackend;
29
+ command?: string;
30
+ env?: Record<string, string>;
31
+ timeoutMs?: number;
32
+ }
33
+ export declare function createCliJudgeProvider(options: CliJudgeProviderOptions): JudgeProvider;
@@ -0,0 +1,90 @@
1
+ import { execaCommand } from "execa";
2
+ const DEFAULT_TIMEOUT_MS = 120_000;
3
+ export function createCliJudgeProvider(options) {
4
+ return {
5
+ async evaluate(request) {
6
+ const command = buildCommand(options, request);
7
+ const result = await execaCommand(command, {
8
+ shell: true,
9
+ env: { ...process.env, ...options.env },
10
+ input: request.prompt,
11
+ reject: false,
12
+ timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,
13
+ });
14
+ if (result.exitCode !== 0) {
15
+ throw new Error(`judge provider command failed with exit code ${result.exitCode}: ${result.stderr || result.stdout}`);
16
+ }
17
+ return parseJudgeResponse(request.mode, result.stdout);
18
+ },
19
+ };
20
+ }
21
+ function buildCommand(options, request) {
22
+ if (options.command) {
23
+ return options.command;
24
+ }
25
+ switch (options.backend) {
26
+ case "codex_exec":
27
+ return `codex exec --skip-git-repo-check --quiet ${shellQuote(`You are judging with model ${request.model}. Return JSON only.`)}`;
28
+ case "claude_p":
29
+ return `claude -p ${shellQuote(`You are judging with model ${request.model}. Return JSON only.`)}`;
30
+ }
31
+ }
32
+ function parseJudgeResponse(mode, stdout) {
33
+ const parsed = extractJsonObject(stdout);
34
+ if (mode === "pairwise") {
35
+ const winner = normalizeWinner(parsed.winner);
36
+ const confidence = normalizeConfidence(parsed.confidence);
37
+ return {
38
+ mode,
39
+ winner,
40
+ rationale: String(parsed.rationale ?? ""),
41
+ raw: stdout,
42
+ ...(confidence === undefined ? {} : { confidence }),
43
+ };
44
+ }
45
+ const score = Number(parsed.score);
46
+ if (!Number.isFinite(score)) {
47
+ throw new Error("absolute judge response must include a finite numeric score");
48
+ }
49
+ const confidence = normalizeConfidence(parsed.confidence);
50
+ return {
51
+ mode,
52
+ score,
53
+ rationale: String(parsed.rationale ?? ""),
54
+ raw: stdout,
55
+ ...(confidence === undefined ? {} : { confidence }),
56
+ };
57
+ }
58
+ function extractJsonObject(stdout) {
59
+ const trimmed = stdout.trim();
60
+ try {
61
+ return JSON.parse(trimmed);
62
+ }
63
+ catch {
64
+ const match = trimmed.match(/\{[\s\S]*\}/);
65
+ if (!match) {
66
+ throw new Error("judge provider did not return parseable JSON");
67
+ }
68
+ return JSON.parse(match[0]);
69
+ }
70
+ }
71
+ function normalizeWinner(value) {
72
+ if (value === "candidate" || value === "incumbent" || value === "tie") {
73
+ return value;
74
+ }
75
+ throw new Error(`pairwise judge response must include a valid winner, received ${String(value)}`);
76
+ }
77
+ function normalizeConfidence(value) {
78
+ if (value === undefined || value === null || value === "") {
79
+ return undefined;
80
+ }
81
+ const confidence = Number(value);
82
+ if (!Number.isFinite(confidence) || confidence < 0 || confidence > 1) {
83
+ throw new Error(`judge confidence must be between 0 and 1, received ${String(value)}`);
84
+ }
85
+ return confidence;
86
+ }
87
+ function shellQuote(value) {
88
+ return `'${value.replaceAll("'", `'\\''`)}'`;
89
+ }
90
+ //# sourceMappingURL=llm-judge-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-judge-provider.js","sourceRoot":"","sources":["../../../src/adapters/judge/llm-judge-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { CommandProposerConfig } from "../../core/manifest/schema.js";
2
+ export interface RunCommandProposerInput {
3
+ workspacePath: string;
4
+ env?: Record<string, string>;
5
+ }
6
+ export interface CommandProposalResult {
7
+ proposerType: "command";
8
+ command: string;
9
+ cwd: string;
10
+ stdout: string;
11
+ stderr: string;
12
+ summary: string;
13
+ durationMs: number;
14
+ }
15
+ export declare function runCommandProposer(config: CommandProposerConfig, input: RunCommandProposerInput): Promise<CommandProposalResult>;
@@ -0,0 +1,29 @@
1
+ import { resolve } from "node:path";
2
+ import { execaCommand } from "execa";
3
+ export async function runCommandProposer(config, input) {
4
+ const cwd = resolveConfiguredCwd(input.workspacePath, config.cwd);
5
+ const startedAt = Date.now();
6
+ const result = await execaCommand(config.command, {
7
+ cwd,
8
+ env: { ...process.env, ...config.env, ...input.env },
9
+ reject: false,
10
+ shell: true,
11
+ timeout: config.timeoutSec * 1_000,
12
+ });
13
+ if (result.exitCode !== 0) {
14
+ throw new Error(`command proposer failed with exit code ${result.exitCode}: ${result.stderr || result.stdout || config.command}`);
15
+ }
16
+ return {
17
+ proposerType: "command",
18
+ command: config.command,
19
+ cwd,
20
+ stdout: result.stdout,
21
+ stderr: result.stderr,
22
+ summary: `generated candidate with command proposer in ${Date.now() - startedAt}ms`,
23
+ durationMs: Date.now() - startedAt,
24
+ };
25
+ }
26
+ function resolveConfiguredCwd(workspacePath, configuredCwd) {
27
+ return configuredCwd ? resolve(workspacePath, configuredCwd) : resolve(workspacePath);
28
+ }
29
+ //# sourceMappingURL=command-proposer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-proposer.js","sourceRoot":"","sources":["../../../src/adapters/proposer/command-proposer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAmBrC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAA6B,EAC7B,KAA8B;IAE9B,MAAM,GAAG,GAAG,oBAAoB,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAClE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE;QAChD,GAAG;QACH,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE;QACpD,MAAM,EAAE,KAAK;QACb,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,MAAM,CAAC,UAAU,GAAG,KAAK;KACnC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,0CAA0C,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CACjH,CAAC;IACJ,CAAC;IAED,OAAO;QACL,YAAY,EAAE,SAAS;QACvB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,GAAG;QACH,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,gDAAgD,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI;QACnF,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;KACnC,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,aAAqB,EAAE,aAAsB;IACzE,OAAO,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;AACxF,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface AppContext {
2
+ appName: string;
3
+ phase: "scaffold";
4
+ }
5
+ export declare function createAppContext(): AppContext;
@@ -0,0 +1,7 @@
1
+ export function createAppContext() {
2
+ return {
3
+ appName: "ralph-research",
4
+ phase: "scaffold",
5
+ };
6
+ }
7
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/app/context.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,OAAO,EAAE,gBAAgB;QACzB,KAAK,EAAE,UAAU;KAClB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { DecisionRecord } from "../../core/model/decision-record.js";
2
+ import type { FrontierEntry } from "../../core/model/frontier-entry.js";
3
+ import type { RunRecord } from "../../core/model/run-record.js";
4
+ export interface ManualDecisionInput {
5
+ repoRoot: string;
6
+ runId: string;
7
+ manifestPath?: string;
8
+ note?: string;
9
+ by?: string;
10
+ }
11
+ export interface ManualDecisionResult {
12
+ status: "accepted" | "rejected";
13
+ run: RunRecord;
14
+ decision: DecisionRecord;
15
+ frontier: FrontierEntry[];
16
+ }
17
+ export declare class ManualDecisionService {
18
+ accept(input: ManualDecisionInput): Promise<ManualDecisionResult>;
19
+ reject(input: ManualDecisionInput): Promise<ManualDecisionResult>;
20
+ }
@@ -0,0 +1,143 @@
1
+ import { join, resolve } from "node:path";
2
+ import { JsonFileDecisionStore } from "../../adapters/fs/json-file-decision-store.js";
3
+ import { JsonFileFrontierStore } from "../../adapters/fs/json-file-frontier-store.js";
4
+ import { JsonFileRunStore } from "../../adapters/fs/json-file-run-store.js";
5
+ import { acquireLock, releaseLock } from "../../adapters/fs/lockfile.js";
6
+ import { loadManifestFromFile } from "../../adapters/fs/manifest-loader.js";
7
+ import { GitClient } from "../../adapters/git/git-client.js";
8
+ import { DEFAULT_STORAGE_ROOT } from "../../core/manifest/defaults.js";
9
+ import { DEFAULT_MANIFEST_FILENAME } from "../../core/manifest/schema.js";
10
+ import { advanceRunPhase } from "../../core/state/run-state-machine.js";
11
+ import { GitWorktreeWorkspaceManager } from "../../core/engine/workspace-manager.js";
12
+ export class ManualDecisionService {
13
+ async accept(input) {
14
+ const repoRoot = resolve(input.repoRoot);
15
+ const manifestPath = resolve(repoRoot, input.manifestPath ?? DEFAULT_MANIFEST_FILENAME);
16
+ const lockPath = join(repoRoot, DEFAULT_STORAGE_ROOT, "lock");
17
+ const lock = await acquireLock(lockPath);
18
+ try {
19
+ const { manifest } = await loadManifestFromFile(manifestPath);
20
+ const storageRoot = join(repoRoot, manifest.storage.root);
21
+ const runStore = new JsonFileRunStore(join(storageRoot, "runs"));
22
+ const decisionStore = new JsonFileDecisionStore(join(storageRoot, "decisions"));
23
+ const frontierStore = new JsonFileFrontierStore(join(storageRoot, "frontier.json"));
24
+ const workspaceManager = new GitWorktreeWorkspaceManager(repoRoot, storageRoot);
25
+ const gitClient = new GitClient(repoRoot);
26
+ const run = await requirePendingHumanRun(runStore, input.runId);
27
+ const decision = await requireDecision(decisionStore, run);
28
+ const promoted = await workspaceManager.promoteWorkspace(run.candidateId, {
29
+ excludePaths: manifest.experiment.outputs.map((output) => output.path),
30
+ });
31
+ const commitResult = await gitClient.stageAndCommitPaths([...promoted.copiedPaths, ...promoted.deletedPaths], `rrx: accept ${run.runId}`);
32
+ const acceptedDecision = {
33
+ ...decision,
34
+ outcome: "accepted",
35
+ actorType: "human",
36
+ ...(input.by ? { actorId: input.by } : {}),
37
+ reason: appendHumanDecisionReason(decision.reason, "accepted", input),
38
+ frontierChanged: true,
39
+ afterFrontierIds: [`frontier-${run.runId}`],
40
+ commitSha: commitResult.commitSha,
41
+ };
42
+ await decisionStore.put(acceptedDecision);
43
+ const acceptedFrontier = [
44
+ buildManualFrontierEntry(run, commitResult.commitSha),
45
+ ];
46
+ await frontierStore.save(acceptedFrontier);
47
+ const updatedRun = advanceRunPhase(run, "completed", {
48
+ status: "accepted",
49
+ decisionId: acceptedDecision.decisionId,
50
+ });
51
+ await runStore.put(updatedRun);
52
+ await workspaceManager.cleanupWorkspace(run.candidateId);
53
+ return {
54
+ status: "accepted",
55
+ run: updatedRun,
56
+ decision: acceptedDecision,
57
+ frontier: acceptedFrontier,
58
+ };
59
+ }
60
+ finally {
61
+ await releaseLock(lock.path, lock.metadata.token);
62
+ }
63
+ }
64
+ async reject(input) {
65
+ const repoRoot = resolve(input.repoRoot);
66
+ const manifestPath = resolve(repoRoot, input.manifestPath ?? DEFAULT_MANIFEST_FILENAME);
67
+ const lockPath = join(repoRoot, DEFAULT_STORAGE_ROOT, "lock");
68
+ const lock = await acquireLock(lockPath);
69
+ try {
70
+ const { manifest } = await loadManifestFromFile(manifestPath);
71
+ const storageRoot = join(repoRoot, manifest.storage.root);
72
+ const runStore = new JsonFileRunStore(join(storageRoot, "runs"));
73
+ const decisionStore = new JsonFileDecisionStore(join(storageRoot, "decisions"));
74
+ const frontierStore = new JsonFileFrontierStore(join(storageRoot, "frontier.json"));
75
+ const workspaceManager = new GitWorktreeWorkspaceManager(repoRoot, storageRoot);
76
+ const run = await requirePendingHumanRun(runStore, input.runId);
77
+ const decision = await requireDecision(decisionStore, run);
78
+ const currentFrontier = await frontierStore.load();
79
+ const rejectedDecision = {
80
+ ...decision,
81
+ outcome: "rejected",
82
+ actorType: "human",
83
+ ...(input.by ? { actorId: input.by } : {}),
84
+ reason: appendHumanDecisionReason(decision.reason, "rejected", input),
85
+ frontierChanged: false,
86
+ afterFrontierIds: currentFrontier.map((entry) => entry.frontierId),
87
+ };
88
+ await decisionStore.put(rejectedDecision);
89
+ const updatedRun = advanceRunPhase(run, "completed", {
90
+ status: "rejected",
91
+ decisionId: rejectedDecision.decisionId,
92
+ });
93
+ await runStore.put(updatedRun);
94
+ await workspaceManager.cleanupWorkspace(run.candidateId);
95
+ return {
96
+ status: "rejected",
97
+ run: updatedRun,
98
+ decision: rejectedDecision,
99
+ frontier: currentFrontier,
100
+ };
101
+ }
102
+ finally {
103
+ await releaseLock(lock.path, lock.metadata.token);
104
+ }
105
+ }
106
+ }
107
+ async function requirePendingHumanRun(runStore, runId) {
108
+ const run = await runStore.get(runId);
109
+ if (!run) {
110
+ throw new Error(`Run ${runId} was not found`);
111
+ }
112
+ if (run.status !== "needs_human") {
113
+ throw new Error(`Run ${runId} is not pending human review`);
114
+ }
115
+ return run;
116
+ }
117
+ async function requireDecision(decisionStore, run) {
118
+ if (!run.decisionId) {
119
+ throw new Error(`Run ${run.runId} does not have a decision record`);
120
+ }
121
+ const decision = await decisionStore.get(run.decisionId);
122
+ if (!decision) {
123
+ throw new Error(`Decision ${run.decisionId} was not found`);
124
+ }
125
+ return decision;
126
+ }
127
+ function appendHumanDecisionReason(existingReason, outcome, input) {
128
+ const by = input.by ? ` by ${input.by}` : "";
129
+ const note = input.note ? `; note=${input.note}` : "";
130
+ return `${existingReason}; human ${outcome}${by}${note}`;
131
+ }
132
+ function buildManualFrontierEntry(run, commitSha) {
133
+ return {
134
+ frontierId: `frontier-${run.runId}`,
135
+ runId: run.runId,
136
+ candidateId: run.candidateId,
137
+ acceptedAt: new Date().toISOString(),
138
+ commitSha,
139
+ metrics: run.metrics,
140
+ artifacts: run.artifacts,
141
+ };
142
+ }
143
+ //# sourceMappingURL=manual-decision-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manual-decision-service.js","sourceRoot":"","sources":["../../../src/app/services/manual-decision-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { DecisionRecord } from "../../core/model/decision-record.js";
2
+ import type { FrontierEntry } from "../../core/model/frontier-entry.js";
3
+ import type { RunRecord } from "../../core/model/run-record.js";
4
+ export interface ProjectStateInput {
5
+ repoRoot: string;
6
+ manifestPath?: string;
7
+ }
8
+ export interface ProjectStatus {
9
+ manifestPath: string;
10
+ latestRun: RunRecord | null;
11
+ frontier: FrontierEntry[];
12
+ pendingHumanRuns: RunRecord[];
13
+ decisions: DecisionRecord[];
14
+ }
15
+ export interface InspectRunResult {
16
+ manifestPath: string;
17
+ run: RunRecord;
18
+ decision: DecisionRecord | null;
19
+ frontier: FrontierEntry[];
20
+ explainability: {
21
+ decisionReason: string | null;
22
+ judgeRationales: Array<{
23
+ metricId: string;
24
+ rationale: string;
25
+ judgeTracePath?: string;
26
+ }>;
27
+ metricDeltas: Array<{
28
+ metricId: string;
29
+ value: number;
30
+ delta?: number;
31
+ confidence?: number;
32
+ direction: "maximize" | "minimize";
33
+ }>;
34
+ diffSummary: {
35
+ filesChanged?: number;
36
+ lineDelta?: number;
37
+ changedPaths?: string[];
38
+ withinBudget?: boolean;
39
+ };
40
+ };
41
+ }
42
+ export declare class RunNotFoundError extends Error {
43
+ constructor(runId: string);
44
+ }
45
+ export declare function getProjectStatus(input: ProjectStateInput): Promise<ProjectStatus>;
46
+ export declare function getProjectFrontier(input: ProjectStateInput): Promise<{
47
+ manifestPath: string;
48
+ frontier: FrontierEntry[];
49
+ }>;
50
+ export declare function inspectRun(input: ProjectStateInput & {
51
+ runId: string;
52
+ }): Promise<InspectRunResult>;
@@ -0,0 +1,92 @@
1
+ import { join, resolve } from "node:path";
2
+ import { JsonFileDecisionStore } from "../../adapters/fs/json-file-decision-store.js";
3
+ import { JsonFileFrontierStore } from "../../adapters/fs/json-file-frontier-store.js";
4
+ import { JsonFileRunStore } from "../../adapters/fs/json-file-run-store.js";
5
+ import { loadManifestFromFile } from "../../adapters/fs/manifest-loader.js";
6
+ import { DEFAULT_MANIFEST_FILENAME } from "../../core/manifest/schema.js";
7
+ export class RunNotFoundError extends Error {
8
+ constructor(runId) {
9
+ super(`Run ${runId} was not found`);
10
+ this.name = "RunNotFoundError";
11
+ }
12
+ }
13
+ export async function getProjectStatus(input) {
14
+ const { manifestPath, runStore, decisionStore, frontierStore } = await loadProjectStores(input);
15
+ const runs = await runStore.list();
16
+ const decisions = await decisionStore.list();
17
+ const frontier = await frontierStore.load();
18
+ return {
19
+ manifestPath,
20
+ latestRun: runs.at(-1) ?? null,
21
+ frontier,
22
+ pendingHumanRuns: runs.filter((run) => run.status === "needs_human"),
23
+ decisions,
24
+ };
25
+ }
26
+ export async function getProjectFrontier(input) {
27
+ const { manifestPath, frontierStore } = await loadProjectStores(input);
28
+ return {
29
+ manifestPath,
30
+ frontier: await frontierStore.load(),
31
+ };
32
+ }
33
+ export async function inspectRun(input) {
34
+ const { manifestPath, runStore, decisionStore, frontierStore } = await loadProjectStores(input);
35
+ const run = await runStore.get(input.runId);
36
+ if (!run) {
37
+ throw new RunNotFoundError(input.runId);
38
+ }
39
+ const decision = run.decisionId ? await decisionStore.get(run.decisionId) : null;
40
+ const frontier = await frontierStore.load();
41
+ const judgeRationales = Object.values(run.metrics)
42
+ .flatMap((metric) => {
43
+ const rationale = typeof metric.details.rationale === "string" ? metric.details.rationale : null;
44
+ if (!rationale) {
45
+ return [];
46
+ }
47
+ return [
48
+ {
49
+ metricId: metric.metricId,
50
+ rationale,
51
+ ...(metric.judgeTracePath ? { judgeTracePath: metric.judgeTracePath } : {}),
52
+ },
53
+ ];
54
+ });
55
+ const metricDeltas = Object.values(run.metrics).map((metric) => ({
56
+ metricId: metric.metricId,
57
+ value: metric.value,
58
+ direction: metric.direction,
59
+ ...(metric.confidence === undefined ? {} : { confidence: metric.confidence }),
60
+ ...(decision?.metricId === metric.metricId && decision.delta !== undefined ? { delta: decision.delta } : {}),
61
+ }));
62
+ return {
63
+ manifestPath,
64
+ run,
65
+ decision,
66
+ frontier,
67
+ explainability: {
68
+ decisionReason: decision?.reason ?? null,
69
+ judgeRationales,
70
+ metricDeltas,
71
+ diffSummary: {
72
+ ...(run.proposal.filesChanged === undefined ? {} : { filesChanged: run.proposal.filesChanged }),
73
+ ...(run.proposal.diffLines === undefined ? {} : { lineDelta: run.proposal.diffLines }),
74
+ ...(run.proposal.changedPaths ? { changedPaths: run.proposal.changedPaths } : {}),
75
+ ...(run.proposal.withinBudget === undefined ? {} : { withinBudget: run.proposal.withinBudget }),
76
+ },
77
+ },
78
+ };
79
+ }
80
+ async function loadProjectStores(input) {
81
+ const repoRoot = resolve(input.repoRoot);
82
+ const manifestPath = resolve(repoRoot, input.manifestPath ?? DEFAULT_MANIFEST_FILENAME);
83
+ const loadedManifest = await loadManifestFromFile(manifestPath);
84
+ const storageRoot = join(repoRoot, loadedManifest.manifest.storage.root);
85
+ return {
86
+ manifestPath: loadedManifest.path,
87
+ runStore: new JsonFileRunStore(join(storageRoot, "runs")),
88
+ decisionStore: new JsonFileDecisionStore(join(storageRoot, "decisions")),
89
+ frontierStore: new JsonFileFrontierStore(join(storageRoot, "frontier.json")),
90
+ };
91
+ }
92
+ //# sourceMappingURL=project-state-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-state-service.js","sourceRoot":"","sources":["../../../src/app/services/project-state-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AACtF,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AA8C1E,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAmB,KAAa;QAC9B,KAAK,CAAC,OAAO,KAAK,gBAAgB,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAwB;IAC7D,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAChG,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;IAE5C,OAAO;QACL,YAAY;QACZ,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI;QAC9B,QAAQ;QACR,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,aAAa,CAAC;QACpE,SAAS;KACV,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAAwB;IAI/D,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO;QACL,YAAY;QACZ,QAAQ,EAAE,MAAM,aAAa,CAAC,IAAI,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAA4C;IAC3E,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAChG,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjF,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;IAE5C,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;SAC/C,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QAClB,MAAM,SAAS,GAAG,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QACjG,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO;YACL;gBACE,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,SAAS;gBACT,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC5E;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC/D,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;QAC7E,GAAG,CAAC,QAAQ,EAAE,QAAQ,KAAK,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7G,CAAC,CAAC,CAAC;IAEJ,OAAO;QACL,YAAY;QACZ,GAAG;QACH,QAAQ;QACR,QAAQ;QACR,cAAc,EAAE;YACd,cAAc,EAAE,QAAQ,EAAE,MAAM,IAAI,IAAI;YACxC,eAAe;YACf,YAAY;YACZ,WAAW,EAAE;gBACX,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;gBAC/F,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;gBACtF,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjF,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;aAChG;SACF;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,KAAwB;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,IAAI,yBAAyB,CAAC,CAAC;IACxF,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE,OAAO;QACL,YAAY,EAAE,cAAc,CAAC,IAAI;QACjC,QAAQ,EAAE,IAAI,gBAAgB,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACzD,aAAa,EAAE,IAAI,qBAAqB,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACxE,aAAa,EAAE,IAAI,qBAAqB,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;KAC7E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { JudgeProvider } from "../../adapters/judge/llm-judge-provider.js";
2
+ import { type RecoveryPlan } from "../../core/state/run-state-machine.js";
3
+ import { type CycleRunResult } from "../../core/engine/cycle-runner.js";
4
+ export interface RunCycleServiceInput {
5
+ repoRoot: string;
6
+ manifestPath?: string;
7
+ resume?: boolean;
8
+ }
9
+ export interface RunCycleServiceResult {
10
+ status: CycleRunResult["status"] | "resume_required";
11
+ manifestPath: string;
12
+ lockPath: string;
13
+ runResult?: CycleRunResult;
14
+ recoveryPlan?: RecoveryPlan;
15
+ }
16
+ export interface RunCycleServiceDependencies {
17
+ judgeProvider?: JudgeProvider;
18
+ now?: () => Date;
19
+ }
20
+ export declare class RunCycleService {
21
+ private readonly judgeProvider;
22
+ private readonly now;
23
+ constructor(dependencies?: RunCycleServiceDependencies);
24
+ run(input: RunCycleServiceInput): Promise<RunCycleServiceResult>;
25
+ }