@bastani/atomic 0.5.31 → 0.5.32-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/dist/sdk/runtime/tmux.d.ts +13 -0
- package/dist/sdk/runtime/tmux.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts +7 -2
- package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts +7 -2
- package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/ralph/helpers/prompts.d.ts +48 -40
- package/dist/sdk/workflows/builtin/ralph/helpers/prompts.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/ralph/helpers/review.d.ts +9 -5
- package/dist/sdk/workflows/builtin/ralph/helpers/review.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts +7 -2
- package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts.map +1 -1
- package/dist/sdk/workflows/index.d.ts +1 -1
- package/dist/sdk/workflows/index.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/commands/cli/chat/index.ts +7 -0
- package/src/commands/cli/workflow-command.test.ts +12 -0
- package/src/sdk/runtime/tmux.conf +11 -8
- package/src/sdk/runtime/tmux.ts +22 -0
- package/src/sdk/workflows/builtin/ralph/claude/index.ts +13 -35
- package/src/sdk/workflows/builtin/ralph/copilot/index.ts +13 -29
- package/src/sdk/workflows/builtin/ralph/helpers/prompts.ts +224 -205
- package/src/sdk/workflows/builtin/ralph/helpers/review.ts +12 -11
- package/src/sdk/workflows/builtin/ralph/opencode/index.ts +13 -35
- package/src/sdk/workflows/index.ts +1 -0
|
@@ -8,25 +8,26 @@
|
|
|
8
8
|
import type { ReviewResult } from "./prompts.ts";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Check whether the
|
|
11
|
+
* Check whether the loop should iterate again.
|
|
12
12
|
*
|
|
13
13
|
* Returns true when:
|
|
14
|
-
* 1. The parsed
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* 1. The review could not be parsed (null) but the raw response text is
|
|
15
|
+
* non-empty — treat unparseable output as actionable so the loop keeps
|
|
16
|
+
* iterating instead of silently exiting on a missing reviewer.
|
|
17
|
+
* 2. The merged review reports `overall_correctness === "patch is incorrect"`.
|
|
18
|
+
* {@link mergeReviewResults} sets the merged value to "patch is incorrect"
|
|
19
|
+
* if EITHER reviewer flagged it, so "patch is correct" here means BOTH
|
|
20
|
+
* reviewers signed off — the only stop condition.
|
|
17
21
|
*
|
|
18
|
-
* @param review - Parsed ReviewResult, or null if parsing failed.
|
|
22
|
+
* @param review - Parsed (merged) ReviewResult, or null if parsing failed.
|
|
19
23
|
* @param rawText - The raw reviewer response text.
|
|
20
24
|
*/
|
|
21
25
|
export function hasActionableFindings(
|
|
22
26
|
review: ReviewResult | null,
|
|
23
27
|
rawText: string,
|
|
24
28
|
): boolean {
|
|
25
|
-
if (review
|
|
26
|
-
return
|
|
29
|
+
if (review === null) {
|
|
30
|
+
return rawText.trim().length > 0;
|
|
27
31
|
}
|
|
28
|
-
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
return false;
|
|
32
|
+
return review.overall_correctness === "patch is incorrect";
|
|
32
33
|
}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ralph workflow for OpenCode — plan → orchestrate → review
|
|
2
|
+
* Ralph workflow for OpenCode — plan → orchestrate → review loop.
|
|
3
3
|
*
|
|
4
4
|
* Each sub-agent invocation spawns its own visible session in the graph,
|
|
5
5
|
* so users can see each iteration's progress in real time. The loop
|
|
6
6
|
* terminates when:
|
|
7
7
|
* - `max_loops` iterations have completed (defaults to {@link DEFAULT_MAX_LOOPS}), OR
|
|
8
|
-
* -
|
|
8
|
+
* - Both parallel reviewer passes return `overall_correctness === "patch is correct"`.
|
|
9
|
+
*
|
|
10
|
+
* On a failed review the merged findings are formatted into a markdown
|
|
11
|
+
* brief by {@link formatReviewForReplan} and fed into the next iteration's
|
|
12
|
+
* planner, which is responsible for validating, deduping, and clustering
|
|
13
|
+
* them into shared root causes before revising the RFC.
|
|
9
14
|
*
|
|
10
15
|
* The reviewer stages use the OpenCode SDK's structured output
|
|
11
16
|
* (`format: { type: "json_schema" }`) to guarantee the review result
|
|
@@ -21,9 +26,8 @@ import {
|
|
|
21
26
|
buildOrchestratorPrompt,
|
|
22
27
|
buildInfraDiscoveryPrompts,
|
|
23
28
|
buildReviewPrompt,
|
|
24
|
-
buildDebuggerReportPrompt,
|
|
25
|
-
extractMarkdownBlock,
|
|
26
29
|
filterActionable,
|
|
30
|
+
formatReviewForReplan,
|
|
27
31
|
mergeReviewResults,
|
|
28
32
|
REVIEW_RESULT_JSON_SCHEMA,
|
|
29
33
|
type ReviewResult,
|
|
@@ -71,8 +75,7 @@ function extractReview(
|
|
|
71
75
|
|
|
72
76
|
export default defineWorkflow({
|
|
73
77
|
name: "ralph",
|
|
74
|
-
description:
|
|
75
|
-
"Plan → orchestrate → review → debug loop with bounded iteration",
|
|
78
|
+
description: "Plan → orchestrate → review loop with bounded iteration",
|
|
76
79
|
inputs: [
|
|
77
80
|
{ name: "prompt", type: "text", required: true, description: "task prompt" },
|
|
78
81
|
{
|
|
@@ -87,7 +90,7 @@ export default defineWorkflow({
|
|
|
87
90
|
.run(async (ctx) => {
|
|
88
91
|
const prompt = ctx.inputs.prompt ?? "";
|
|
89
92
|
const maxLoops = ctx.inputs.max_loops ?? DEFAULT_MAX_LOOPS;
|
|
90
|
-
let
|
|
93
|
+
let reviewReport = "";
|
|
91
94
|
|
|
92
95
|
for (let iteration = 1; iteration <= maxLoops; iteration++) {
|
|
93
96
|
// ── Plan ────────────────────────────────────────────────────────────
|
|
@@ -103,7 +106,7 @@ export default defineWorkflow({
|
|
|
103
106
|
type: "text",
|
|
104
107
|
text: buildPlannerPrompt(prompt, {
|
|
105
108
|
iteration,
|
|
106
|
-
|
|
109
|
+
reviewReport: reviewReport || undefined,
|
|
107
110
|
}),
|
|
108
111
|
},
|
|
109
112
|
],
|
|
@@ -235,33 +238,8 @@ export default defineWorkflow({
|
|
|
235
238
|
// Both reviewers agree the code is clean → done
|
|
236
239
|
if (!hasActionableFindings(parsed, reviewRaw)) break;
|
|
237
240
|
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
const debugger_ = await ctx.stage(
|
|
241
|
-
{ name: `debugger-${iteration}` },
|
|
242
|
-
{},
|
|
243
|
-
{ title: `debugger-${iteration}` },
|
|
244
|
-
async (s) => {
|
|
245
|
-
const result = await s.client.session.prompt({
|
|
246
|
-
sessionID: s.session.id,
|
|
247
|
-
parts: [
|
|
248
|
-
{
|
|
249
|
-
type: "text",
|
|
250
|
-
text: buildDebuggerReportPrompt(parsed, reviewRaw, {
|
|
251
|
-
iteration,
|
|
252
|
-
changeset,
|
|
253
|
-
}),
|
|
254
|
-
},
|
|
255
|
-
],
|
|
256
|
-
agent: "debugger",
|
|
257
|
-
});
|
|
258
|
-
s.save(result.data!);
|
|
259
|
-
return extractResponseText(result.data!.parts);
|
|
260
|
-
},
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
debuggerReport = extractMarkdownBlock(debugger_.result);
|
|
264
|
-
}
|
|
241
|
+
// Findings exist — format them for the next iteration's planner.
|
|
242
|
+
reviewReport = formatReviewForReplan(parsed, reviewRaw);
|
|
265
243
|
}
|
|
266
244
|
})
|
|
267
245
|
.compile();
|