ralph-flow-pi 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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +428 -0
  3. package/dist/cli.d.ts +9 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +56 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/prompts.d.ts +25 -0
  8. package/dist/commands/prompts.d.ts.map +1 -0
  9. package/dist/commands/prompts.js +249 -0
  10. package/dist/commands/prompts.js.map +1 -0
  11. package/dist/commands/tools.d.ts +47 -0
  12. package/dist/commands/tools.d.ts.map +1 -0
  13. package/dist/commands/tools.js +633 -0
  14. package/dist/commands/tools.js.map +1 -0
  15. package/dist/engine/check-bash.d.ts +121 -0
  16. package/dist/engine/check-bash.d.ts.map +1 -0
  17. package/dist/engine/check-bash.js +373 -0
  18. package/dist/engine/check-bash.js.map +1 -0
  19. package/dist/engine/check.d.ts +47 -0
  20. package/dist/engine/check.d.ts.map +1 -0
  21. package/dist/engine/check.js +298 -0
  22. package/dist/engine/check.js.map +1 -0
  23. package/dist/engine/core.d.ts +153 -0
  24. package/dist/engine/core.d.ts.map +1 -0
  25. package/dist/engine/core.js +1984 -0
  26. package/dist/engine/core.js.map +1 -0
  27. package/dist/engine/lock.d.ts +27 -0
  28. package/dist/engine/lock.d.ts.map +1 -0
  29. package/dist/engine/lock.js +121 -0
  30. package/dist/engine/lock.js.map +1 -0
  31. package/dist/engine/runner.d.ts +108 -0
  32. package/dist/engine/runner.d.ts.map +1 -0
  33. package/dist/engine/runner.js +510 -0
  34. package/dist/engine/runner.js.map +1 -0
  35. package/dist/engine/skills.d.ts +53 -0
  36. package/dist/engine/skills.d.ts.map +1 -0
  37. package/dist/engine/skills.js +109 -0
  38. package/dist/engine/skills.js.map +1 -0
  39. package/dist/engine/step-tools.d.ts +22 -0
  40. package/dist/engine/step-tools.d.ts.map +1 -0
  41. package/dist/engine/step-tools.js +45 -0
  42. package/dist/engine/step-tools.js.map +1 -0
  43. package/dist/engine/types.d.ts +136 -0
  44. package/dist/engine/types.d.ts.map +1 -0
  45. package/dist/engine/types.js +20 -0
  46. package/dist/engine/types.js.map +1 -0
  47. package/dist/headless.d.ts +57 -0
  48. package/dist/headless.d.ts.map +1 -0
  49. package/dist/headless.js +318 -0
  50. package/dist/headless.js.map +1 -0
  51. package/dist/pi/adapter.d.ts +135 -0
  52. package/dist/pi/adapter.d.ts.map +1 -0
  53. package/dist/pi/adapter.js +231 -0
  54. package/dist/pi/adapter.js.map +1 -0
  55. package/dist/pi/interactive.d.ts +28 -0
  56. package/dist/pi/interactive.d.ts.map +1 -0
  57. package/dist/pi/interactive.js +58 -0
  58. package/dist/pi/interactive.js.map +1 -0
  59. package/dist/pi/tui.d.ts +12 -0
  60. package/dist/pi/tui.d.ts.map +1 -0
  61. package/dist/pi/tui.js +12 -0
  62. package/dist/pi/tui.js.map +1 -0
  63. package/dist/tui/app.d.ts +25 -0
  64. package/dist/tui/app.d.ts.map +1 -0
  65. package/dist/tui/app.js +47 -0
  66. package/dist/tui/app.js.map +1 -0
  67. package/dist/tui/embed.d.ts +42 -0
  68. package/dist/tui/embed.d.ts.map +1 -0
  69. package/dist/tui/embed.js +38 -0
  70. package/dist/tui/embed.js.map +1 -0
  71. package/dist/tui/extension.d.ts +88 -0
  72. package/dist/tui/extension.d.ts.map +1 -0
  73. package/dist/tui/extension.js +114 -0
  74. package/dist/tui/extension.js.map +1 -0
  75. package/dist/tui/history-editor.d.ts +38 -0
  76. package/dist/tui/history-editor.d.ts.map +1 -0
  77. package/dist/tui/history-editor.js +55 -0
  78. package/dist/tui/history-editor.js.map +1 -0
  79. package/dist/tui/launcher.d.ts +24 -0
  80. package/dist/tui/launcher.d.ts.map +1 -0
  81. package/dist/tui/launcher.js +97 -0
  82. package/dist/tui/launcher.js.map +1 -0
  83. package/dist/tui/render.d.ts +87 -0
  84. package/dist/tui/render.d.ts.map +1 -0
  85. package/dist/tui/render.js +266 -0
  86. package/dist/tui/render.js.map +1 -0
  87. package/dist/tui/run-app.d.ts +49 -0
  88. package/dist/tui/run-app.d.ts.map +1 -0
  89. package/dist/tui/run-app.js +317 -0
  90. package/dist/tui/run-app.js.map +1 -0
  91. package/dist/tui/run-model.d.ts +162 -0
  92. package/dist/tui/run-model.d.ts.map +1 -0
  93. package/dist/tui/run-model.js +280 -0
  94. package/dist/tui/run-model.js.map +1 -0
  95. package/dist/tui/run-view.d.ts +71 -0
  96. package/dist/tui/run-view.d.ts.map +1 -0
  97. package/dist/tui/run-view.js +167 -0
  98. package/dist/tui/run-view.js.map +1 -0
  99. package/dist/tui/welcome-header.d.ts +40 -0
  100. package/dist/tui/welcome-header.d.ts.map +1 -0
  101. package/dist/tui/welcome-header.js +90 -0
  102. package/dist/tui/welcome-header.js.map +1 -0
  103. package/package.json +55 -0
  104. package/skills/c-to-rust-audit/SKILL.md +67 -0
  105. package/skills/c-to-rust-implement/SKILL.md +151 -0
  106. package/skills/c-to-rust-implement/references/c-to-rust-patterns.md +86 -0
  107. package/skills/c-to-rust-implement/references/conditional-compilation.md +47 -0
  108. package/skills/c-to-rust-implement/references/crate-reference.md +15 -0
  109. package/skills/c-to-rust-implement/references/error-strategies.md +80 -0
  110. package/skills/c-to-rust-implement/references/inline-asm.md +37 -0
  111. package/skills/c-to-rust-plan/SKILL.md +166 -0
  112. package/skills/c-to-rust-plan/references/detection-commands.md +66 -0
  113. package/skills/c-to-rust-test-gen/SKILL.md +130 -0
  114. package/skills/c-to-rust-test-gen/references/proptest-patterns.md +81 -0
  115. package/skills/c-to-rust-test-gen/references/test-porting.md +56 -0
  116. package/skills/c-to-rust-validate/SKILL.md +121 -0
  117. package/skills/everything2rust-audit/SKILL.md +69 -0
  118. package/skills/everything2rust-design/SKILL.md +121 -0
  119. package/skills/everything2rust-design/references/domain-playbooks.md +68 -0
  120. package/skills/everything2rust-design/references/paradigm-map.md +99 -0
  121. package/skills/everything2rust-implement/SKILL.md +101 -0
  122. package/skills/everything2rust-spec/SKILL.md +86 -0
  123. package/skills/everything2rust-spec/references/oracle-strategies.md +96 -0
  124. package/skills/everything2rust-survey/SKILL.md +99 -0
  125. package/skills/everything2rust-test-gen/SKILL.md +68 -0
  126. package/skills/everything2rust-test-gen/references/harness-patterns.md +186 -0
  127. package/skills/everything2rust-validate/SKILL.md +85 -0
  128. package/workflows/c-to-rust.yaml +202 -0
  129. package/workflows/everything2rust.yaml +259 -0
  130. package/workflows/loop.yaml +68 -0
  131. package/workflows/spec.yaml +183 -0
@@ -0,0 +1,510 @@
1
+ /**
2
+ * The instance runner — one loop per active workflow instance.
3
+ *
4
+ * This file replaces driver.ts, and it is the place where ralph-flow-pi stops
5
+ * being a port and becomes a different thing. The opencode plugin could not own
6
+ * the DO session: it lived in the user's chat, so the plugin waited for a
7
+ * `session.idle` event, scraped the last assistant message, regex'd it for
8
+ * `<promise>done</promise>`, and poked the session with `promptAsync`. Every one
9
+ * of those steps was a guess about someone else's session.
10
+ *
11
+ * Here the engine creates the session, so the loop just awaits it:
12
+ *
13
+ * while (instance is live and unpaused):
14
+ * DO → fresh session per step, keep-alive until report_done
15
+ * gate → stop and let the user review (manual steps only)
16
+ * CHECK → fresh read-only session, verdict tool
17
+ * route → handleCheckPassed/Failed (verbatim engine logic)
18
+ *
19
+ * What the DO session gets is the point of the whole project: a brand-new
20
+ * context per step. Steps hand off through artifacts + the input/output fields,
21
+ * never through accumulated chat history — so step 7 cannot be poisoned by the
22
+ * debris of steps 1-6. The one exception is a check-failed retry of the SAME
23
+ * step, which resumes the same session because "here's what you just tried and
24
+ * why it failed" is exactly the context a fix needs, and max_fail_count bounds
25
+ * how far it can grow.
26
+ *
27
+ * Behaviors carried over verbatim from driver.ts (each was load-bearing):
28
+ * - keep-alive budget MAX_DO_REINJECT=5, keyed per step:phase, NOT burned while
29
+ * the model is making tool calls (it's working, not stuck); on exhaustion the
30
+ * loop stops driving and hands control to the user WITHOUT pausing the state.
31
+ * - the manual review gate sits BEFORE the check, not after.
32
+ * - a check verdict is DISCARDED if the state moved while the check ran.
33
+ * - infra failures pause with check_error and never burn a fail count.
34
+ */
35
+ import fs from "fs";
36
+ import path from "path";
37
+ import { MANUAL_GATE_MARKER, MANUAL_STEP_MARKER } from "./core.js";
38
+ import { adversarialCheck } from "./check.js";
39
+ import { isSubWorkflowStep } from "./types.js";
40
+ import { createStepSession } from "../pi/adapter.js";
41
+ import { makeReportDoneTool } from "./step-tools.js";
42
+ /** Keep-alive nudges before the loop gives up and hands control to the user. */
43
+ export const MAX_DO_REINJECT = 5;
44
+ export function createRunner(engine, initialEvents = {}, deps = {}) {
45
+ const createSession = deps.createSession ?? createStepSession;
46
+ /**
47
+ * The runner has exactly one caller of these callbacks internally (`events.
48
+ * onXxx?.(...)`, unchanged below), but now potentially several consumers:
49
+ * the chat session's "post into the transcript" listener lives for the
50
+ * whole process, and a run-view's listener is added only while a human is
51
+ * actively attached (see attachRunView in tui/embed.ts) and removed on
52
+ * detach. `events` stays a single object with the same shape so every
53
+ * existing call site below is untouched — it just fans out to whichever
54
+ * listeners are currently registered instead of being one fixed sink.
55
+ */
56
+ const listeners = new Set([initialEvents]);
57
+ const events = {
58
+ onStepStart: (instId, stepId, phase, attempt) => { for (const l of listeners)
59
+ l.onStepStart?.(instId, stepId, phase, attempt); },
60
+ onStepEvent: (instId, stepId, phase, event) => { for (const l of listeners)
61
+ l.onStepEvent?.(instId, stepId, phase, event); },
62
+ onVerdict: (instId, stepId, result) => { for (const l of listeners)
63
+ l.onVerdict?.(instId, stepId, result); },
64
+ onMessage: (instId, text) => { for (const l of listeners)
65
+ l.onMessage?.(instId, text); },
66
+ onGate: (instId, stepId) => { for (const l of listeners)
67
+ l.onGate?.(instId, stepId); },
68
+ onPaused: (instId, state) => { for (const l of listeners)
69
+ l.onPaused?.(instId, state); },
70
+ onStalled: (instId, stepId, attempts) => { for (const l of listeners)
71
+ l.onStalled?.(instId, stepId, attempts); },
72
+ onCompleted: (instId, reportPath) => { for (const l of listeners)
73
+ l.onCompleted?.(instId, reportPath); },
74
+ };
75
+ /** Attach an additional listener; call the returned function to detach it. */
76
+ function addEventListener(l) {
77
+ listeners.add(l);
78
+ return () => { listeners.delete(l); };
79
+ }
80
+ /** In-process guard: one loop per instance. Also the abort registry. */
81
+ const loops = new Map();
82
+ const activeStepSessions = new Map();
83
+ /** Pending "revise this gated step" instructions, consumed by the next DO turn. */
84
+ const pendingRevisions = new Map();
85
+ /**
86
+ * instIds that got a live human message since the loop last checked. A human
87
+ * talking to the session is not the model going silent, so that cycle must not
88
+ * burn the keep-alive budget — see sendUserMessage and its use in runDoPhase.
89
+ */
90
+ const humanSteered = new Set();
91
+ /** Platform seam: destroyInstance aborts a DO session running in this process. */
92
+ function abortActiveStep(instId) {
93
+ const session = activeStepSessions.get(instId);
94
+ if (!session)
95
+ return;
96
+ activeStepSessions.delete(instId);
97
+ Promise.resolve().then(() => session.abort()).catch(() => { }).then(() => session.dispose()).catch(() => { });
98
+ }
99
+ function isRunning(instId) {
100
+ return loops.has(instId);
101
+ }
102
+ /** Start the loop for an instance unless one is already running for it. */
103
+ function ensureRunning(instId) {
104
+ if (loops.has(instId))
105
+ return;
106
+ const loop = runLoop(instId)
107
+ .catch((e) => {
108
+ engine.diag(`[runner] loop crashed for ${instId}:`, e?.stack || e?.message || String(e));
109
+ engine.logEvent(instId, "error", "runner_loop_crashed", { error: e?.message });
110
+ })
111
+ .finally(() => {
112
+ loops.delete(instId);
113
+ engine.clearRunnerPid(instId);
114
+ });
115
+ loops.set(instId, loop);
116
+ }
117
+ /**
118
+ * The user reviewed a manual step and wants changes before verification.
119
+ * Re-open that step's DO session with their instruction and re-arm the gate —
120
+ * the opposite of approving it. The instruction is consumed by the next DO turn.
121
+ */
122
+ function reviseGate(instId, instruction) {
123
+ if (!engine.instanceExists(instId))
124
+ return;
125
+ const text = String(instruction || "").trim();
126
+ if (!text)
127
+ return;
128
+ pendingRevisions.set(instId, text);
129
+ engine.clearManualGate(instId);
130
+ engine.clearDoneReported(instId); // must re-run DO, not go to CHECK
131
+ engine.logEvent(instId, "info", "manual_gate_revise", { instruction: text.slice(0, 200) });
132
+ ensureRunning(instId);
133
+ }
134
+ /**
135
+ * Steer the live DO session with a human-typed message. Only meaningful while
136
+ * a DO turn is actually running — CHECK is independent and read-only by
137
+ * design, and there's nothing to steer once the step has moved on. Returns
138
+ * whether the message actually had somewhere to go.
139
+ */
140
+ function sendUserMessage(instId, text) {
141
+ const value = String(text || "").trim();
142
+ if (!value)
143
+ return false;
144
+ const session = activeStepSessions.get(instId);
145
+ if (!session)
146
+ return false;
147
+ const state = engine.readState(instId);
148
+ if (!state || !state.active || state.paused || state.current_phase !== "do")
149
+ return false;
150
+ humanSteered.add(instId);
151
+ void session.steer(value).catch((e) => engine.logEvent(instId, "warn", "steer_failed", { error: e?.message }));
152
+ return true;
153
+ }
154
+ /** Await every in-flight loop (tests; shutdown). */
155
+ async function idle() {
156
+ while (loops.size > 0)
157
+ await Promise.all([...loops.values()]);
158
+ }
159
+ /**
160
+ * Pause every instance this process is driving. Called on SIGINT/exit: the
161
+ * step transcripts are already on disk, so `ralphflow_continue` resumes the
162
+ * very session that was interrupted rather than restarting the step.
163
+ */
164
+ function pauseAllForShutdown() {
165
+ for (const instId of loops.keys()) {
166
+ const state = engine.readState(instId);
167
+ if (state && state.active && !state.paused) {
168
+ engine.writeState({ ...state, paused: true, pause_reason: "session_aborted" }, instId);
169
+ engine.logEvent(instId, "warn", "session_aborted", { instance: instId, step: state.current_step, phase: state.current_phase });
170
+ }
171
+ abortActiveStep(instId);
172
+ engine.clearRunnerPid(instId);
173
+ }
174
+ }
175
+ // ─── The loop ───────────────────────────────────────────────────────────────
176
+ async function runLoop(instId) {
177
+ engine.writeRunnerPid(instId);
178
+ for (;;) {
179
+ const state = engine.readState(instId);
180
+ // Gone: completed (destroyInstance) or cancelled by anyone.
181
+ if (!state || !state.active)
182
+ return;
183
+ if (state.paused) {
184
+ events.onPaused?.(instId, state);
185
+ return;
186
+ }
187
+ const workflow = engine.loadWorkflow(state.workflow_name);
188
+ if (!workflow) {
189
+ // Workflow YAML deleted after the instance was created — pause instead
190
+ // of stalling silently (driver.ts did the same).
191
+ pause(instId, state, "config_error", `工作流 "${state.workflow_name}" 未找到。`);
192
+ continue;
193
+ }
194
+ const step = engine.getStep(workflow, state.current_step);
195
+ if (!step) {
196
+ pause(instId, state, "config_error", `步骤 "${state.current_step}" 在工作流 "${state.workflow_name}" 中未找到。`);
197
+ continue;
198
+ }
199
+ if (isSubWorkflowStep(step)) {
200
+ // Normal flow enters sub-workflows inline through the transition logic;
201
+ // landing here means a resume found the state parked on one. Resolve it.
202
+ const entry = engine.resolveSubWorkflowEntry(instId, step.workflow, state.user_task, step);
203
+ if (entry.error) {
204
+ pause(instId, state, "config_error", entry.text);
205
+ }
206
+ else {
207
+ events.onMessage?.(instId, entry.text);
208
+ }
209
+ continue;
210
+ }
211
+ // ── CHECK re-entry ──
212
+ // A state already in "check" means either a continue cleared a check_error
213
+ // pause, or a crash landed here. Either way: verify, don't re-run DO.
214
+ if (state.current_phase === "check") {
215
+ const finished = await runCheckAndAdvance(instId, workflow, step, state);
216
+ if (finished)
217
+ return;
218
+ continue;
219
+ }
220
+ // ── DO ──
221
+ const outcome = await runDoPhase(instId, workflow, step, state);
222
+ if (outcome === "gone")
223
+ return;
224
+ if (outcome === "stalled")
225
+ return; // user's turn; state deliberately NOT paused
226
+ // ── Manual review gate: BEFORE the check, never after ──
227
+ // The user's ralphflow_continue is the approval that starts verification.
228
+ if (engine.markerExists(MANUAL_STEP_MARKER, instId)) {
229
+ if (outcome === "done") {
230
+ // Just finished a manual step → stop for review.
231
+ engine.writeManualGate(instId);
232
+ engine.logEvent(instId, "info", "manual_gate_armed", { step: step.id });
233
+ events.onGate?.(instId, step.id);
234
+ events.onMessage?.(instId, `📋 手动步骤 \`${step.id}\` 已完成,等待你的审查。\n\n- 满意后运行 /ralphflow-continue 进入独立验证\n- 需要修改直接在对话里说明,修改完成后会再次提示审查\n- 放弃可运行 /ralphflow-cancel`);
235
+ return; // ralphflow_continue re-enters the loop
236
+ }
237
+ // Re-entered on a step that had already reported done. If the gate is
238
+ // still armed the user hasn't approved yet — stay out of their way.
239
+ // If it's gone, ralphflow_continue cleared it: that IS the approval.
240
+ if (engine.markerExists(MANUAL_GATE_MARKER, instId))
241
+ return;
242
+ }
243
+ const fresh = engine.readState(instId);
244
+ if (!fresh || !fresh.active)
245
+ return;
246
+ const finished = await runCheckAndAdvance(instId, workflow, step, fresh);
247
+ if (finished)
248
+ return;
249
+ }
250
+ }
251
+ function pause(instId, state, reason, failure) {
252
+ engine.writeState({ ...state, paused: true, pause_reason: reason, last_failure_reason: failure }, instId);
253
+ engine.logEvent(instId, "warn", "workflow_paused", { workflow: state.workflow_name, step: state.current_step, reason });
254
+ }
255
+ // ─── DO phase ───────────────────────────────────────────────────────────────
256
+ /**
257
+ * Drive one step's DO phase to `report_done`.
258
+ *
259
+ * Session identity is the interesting part. `resumeSession` is true only when
260
+ * this step is being retried after its own check failed (state carries a
261
+ * last_failure_reason and the attempt dir already exists) — then the model
262
+ * keeps the context of what it just tried. Any other entry (a new step, a
263
+ * route from elsewhere) opens a fresh attempt dir, and therefore a fresh
264
+ * context window.
265
+ */
266
+ async function runDoPhase(instId, workflow, step, state) {
267
+ // A DO that already reported done (a gate the user just approved, or a crash
268
+ // between report_done and the check) must not be re-run — the work exists.
269
+ if (engine.doneReported(instId))
270
+ return "already-done";
271
+ // A gate revision resumes the SAME session (so the model keeps what it built)
272
+ // and leads with the user's requested change.
273
+ const revision = pendingRevisions.get(instId);
274
+ const attemptDir = revision !== undefined
275
+ ? (engine.listStepSessionDirs(instId, step.id, "do").slice(-1)[0] ?? pickAttemptDir(instId, step.id, state))
276
+ : pickAttemptDir(instId, step.id, state);
277
+ const model = deps.currentModel?.() ?? {};
278
+ let session;
279
+ try {
280
+ session = await createSession({
281
+ cwd: engine.projectDir,
282
+ model: model.model,
283
+ thinkingLevel: model.thinkingLevel,
284
+ sessionDir: attemptDir,
285
+ customTools: [makeReportDoneTool(engine, instId), ...(deps.stepTools?.(instId) ?? [])],
286
+ appendSystemPrompt: deps.stepSystemPromptSuffix?.(),
287
+ skillPaths: deps.skillPaths?.(),
288
+ });
289
+ }
290
+ catch (e) {
291
+ pause(instId, state, "config_error", `无法创建步骤会话:${e.message}`);
292
+ events.onMessage?.(instId, `## ⚠️ 无法创建步骤会话\n\n${e.message}\n\n工作流已暂停。解决后运行 \`/ralphflow-continue\` 恢复。`);
293
+ return "gone";
294
+ }
295
+ activeStepSessions.set(instId, session);
296
+ const attempt = (state.fail_count || 0) + 1;
297
+ events.onStepStart?.(instId, step.id, "do", attempt);
298
+ // Track tool activity per turn: a model that is calling tools is working,
299
+ // not stuck, so its keep-alive budget must not be burned.
300
+ let turnHadToolCalls = false;
301
+ let compacted = false;
302
+ const unsubscribe = session.subscribe((event) => {
303
+ if (event.type === "tool_start")
304
+ turnHadToolCalls = true;
305
+ if (event.type === "compaction_end")
306
+ compacted = true;
307
+ events.onStepEvent?.(instId, step.id, "do", event);
308
+ });
309
+ try {
310
+ const reinjectKey = `${step.id}:do`;
311
+ // First turn: a gate revision leads with the user's change (resuming the
312
+ // same session); otherwise the DO prompt itself (already cached).
313
+ let message;
314
+ if (revision !== undefined) {
315
+ pendingRevisions.delete(instId);
316
+ message = `用户审查了这一步的成果,要求如下修改:\n\n${revision}\n\n请据此调整,完成后再次调用 report_done 工具。`;
317
+ }
318
+ else {
319
+ message = engine.readDoPromptCache(instId)
320
+ ?? engine.buildDoPrompt(instId, step, state.user_task, state.last_failure_reason, state.fail_count || undefined);
321
+ }
322
+ await session.prompt(message);
323
+ for (;;) {
324
+ if (engine.doneReported(instId)) {
325
+ engine.clearReinjectCounter(instId);
326
+ return "done";
327
+ }
328
+ const cur = engine.readState(instId);
329
+ if (!cur || !cur.active || cur.paused)
330
+ return "gone"; // cancelled / paused underneath us
331
+ // A human just steered this session — that is engagement, not the model
332
+ // going silent, so this cycle must not burn the keep-alive budget.
333
+ const steered = humanSteered.delete(instId);
334
+ const attempts = turnHadToolCalls || steered
335
+ ? engine.readReinjectCount(instId, reinjectKey)
336
+ : engine.incrementReinjectCount(instId, reinjectKey);
337
+ if (attempts > MAX_DO_REINJECT && !turnHadToolCalls && !steered) {
338
+ // Stop driving, but do NOT pause: the workflow is fine, the model is
339
+ // just stuck. Driving resumes the moment the user says something.
340
+ engine.logEvent(instId, "warn", "do_reinject_exhausted", { step: step.id, attempts });
341
+ events.onStalled?.(instId, step.id, attempts);
342
+ events.onMessage?.(instId, `## ⚠️ Ralph Flow 已停止自动驱动\n\n步骤 \`${step.id}\` 的 DO 阶段已连续 ${attempts} 次收到继续提示但未调用 report_done,请人工介入:\n1. 查看任务卡在哪里,补充信息后让模型继续\n2. 若任务实际已完成,运行 /ralphflow-continue 进入验证\n3. 运行 /ralphflow-cancel 取消工作流`);
343
+ return "stalled";
344
+ }
345
+ // A compaction just dropped the task out of context — re-inject the full
346
+ // DO prompt rather than a bare "continue" (driver.ts did this on the
347
+ // session.compacted event). A human message was already steered into the
348
+ // turn directly, so the generic nudge would just be noise stacked right
349
+ // after real feedback — use a short acknowledgement instead.
350
+ const nudge = steered
351
+ ? "(已收到你的补充说明,请据此继续;完成后调用 report_done 工具。)"
352
+ : compacted
353
+ ? `继续执行步骤 \`${step.id}\` 的任务。\n\n${engine.readDoPromptCache(instId) ?? ""}\n\n所有要求满足后调用 \`report_done\` 工具。`
354
+ : `继续执行步骤 \`${step.id}\` 的任务。当所有要求满足后,调用 \`report_done\` 工具。`;
355
+ compacted = false;
356
+ turnHadToolCalls = false;
357
+ await session.followUp(nudge);
358
+ }
359
+ }
360
+ catch (e) {
361
+ if (!engine.instanceExists(instId))
362
+ return "gone"; // cancelled mid-turn
363
+ engine.logEvent(instId, "error", "do_session_error", { step: step.id, error: e.message });
364
+ const cur = engine.readState(instId);
365
+ if (cur && cur.active && !cur.paused) {
366
+ pause(instId, cur, "check_error", `步骤会话执行失败:${e.message}`);
367
+ events.onMessage?.(instId, `## ⚠️ 步骤会话执行失败\n\n${e.message}\n\n工作流已暂停(不计入失败次数)。解决后运行 \`/ralphflow-continue\` 恢复。`);
368
+ }
369
+ return "gone";
370
+ }
371
+ finally {
372
+ unsubscribe();
373
+ if (activeStepSessions.get(instId) === session)
374
+ activeStepSessions.delete(instId);
375
+ session.dispose();
376
+ }
377
+ }
378
+ /**
379
+ * Where this step attempt's transcript lives.
380
+ *
381
+ * Retrying the same step after ITS check failed resumes the newest attempt dir
382
+ * (fail_count > 0 and a dir exists). Everything else gets a new one — which is
383
+ * what makes "fresh context per step" true rather than aspirational.
384
+ */
385
+ /**
386
+ * Where this step attempt's transcript lives.
387
+ *
388
+ * Two conditions must BOTH hold to resume an existing session:
389
+ * 1. The state carries failure context (a check just rejected something, and
390
+ * we are here to fix it — fail_count > 0, last_failure_reason present).
391
+ * 2. THIS specific step has been attempted before (its session dir exists).
392
+ *
393
+ * Together they mean "we came back to a step that already ran, with a reason
394
+ * to fix it." The second condition is the important guard: if on_fail routes
395
+ * to a DIFFERENT step that has never been tried, existing is empty → a new
396
+ * session is created (fresh context per step, even during failure routing).
397
+ *
398
+ * The common cases:
399
+ * - Self-retry (on_fail == this step): resumes, model sees what it just tried.
400
+ * - Loop-back (test fails → on_fail: implement): resumes implement's own
401
+ * session so the model has its prior implementation context + the failure.
402
+ * - Route to a recovery step never run before: fresh session.
403
+ */
404
+ function pickAttemptDir(instId, stepId, state) {
405
+ const hasFailureContext = (state.fail_count || 0) > 0 && !!state.last_failure_reason;
406
+ const existing = engine.listStepSessionDirs(instId, stepId, "do");
407
+ if (hasFailureContext && existing.length > 0)
408
+ return existing[existing.length - 1];
409
+ return engine.getStepSessionDir(instId, stepId, "do", existing.length + 1);
410
+ }
411
+ // ─── CHECK phase ────────────────────────────────────────────────────────────
412
+ /** @returns true when the loop should stop (completed, paused, or gone). */
413
+ async function runCheckAndAdvance(instId, workflow, step, state) {
414
+ // The DO-completion record belongs to the real do→check edge only. This
415
+ // function is re-entered with the state already in "check" (an infra retry
416
+ // after continue, or the crashed-check path), where re-recording would
417
+ // double the report rows.
418
+ if (state.current_phase === "do") {
419
+ engine.logEvent(instId, "info", "done_detected", { step: state.current_step });
420
+ engine.addStepRecord(instId, state.current_step, "do", "passed", state.fail_count || 0);
421
+ }
422
+ engine.clearManualStepMarker(instId);
423
+ engine.clearManualGate(instId);
424
+ engine.clearReinjectCounter(instId);
425
+ engine.clearDoPromptCache(instId);
426
+ engine.clearDoneReported(instId);
427
+ engine.writeState({ ...state, current_phase: "check" }, instId);
428
+ engine.recordStepStart(instId, state.current_step, "check");
429
+ engine.logEvent(instId, "info", "step_start", { step: state.current_step, phase: "check" });
430
+ events.onStepStart?.(instId, step.id, "check", (state.fail_count || 0) + 1);
431
+ const checkPrompt = engine.buildCheckPrompt(instId, step, state.user_task);
432
+ let checkResult;
433
+ try {
434
+ checkResult = await adversarialCheck(engine, instId, step, checkPrompt, state.user_task, workflow.adversarial_check, undefined, // onBashEvent: superseded by the live event stream below
435
+ deps.checkDeps, (event) => events.onStepEvent?.(instId, step.id, "check", event));
436
+ }
437
+ catch (err) {
438
+ engine.logEvent(instId, "error", "adversarial_check_uncaught", { stepId: step.id, error: err.message });
439
+ const st = engine.readState(instId);
440
+ if (st && st.active && st.current_phase === "check" && st.current_step === state.current_step && st.workflow_name === state.workflow_name) {
441
+ engine.writeState({ ...st, paused: true, pause_reason: "check_error", last_failure_reason: `对抗性检查崩溃:${err.message}` }, instId);
442
+ }
443
+ events.onMessage?.(instId, `## ⚠️ 验证未能运行\n\n对抗性检查崩溃:${err.message}\n\n工作流已暂停(不计入失败次数,已完成的工作保持原样)。问题解决后运行 \`/ralphflow-continue\` 重新验证。`);
444
+ return true;
445
+ }
446
+ // The state may have moved while the check ran (a cancel, a continue from
447
+ // another process, a shutdown pause). Applying a stale verdict would clear
448
+ // someone else's pause and drive a workflow that has moved on — discard it.
449
+ const cur = engine.readState(instId);
450
+ if (!cur || !cur.active || cur.paused || cur.current_phase !== "check"
451
+ || cur.workflow_name !== state.workflow_name || cur.current_step !== state.current_step) {
452
+ engine.logEvent(instId, "warn", "check_result_discarded", { reason: cur?.paused ? "instance paused during check" : "state changed during check" });
453
+ return true;
454
+ }
455
+ events.onVerdict?.(instId, step.id, { passed: checkResult.passed, infra: checkResult.infra, reason: checkResult.reason });
456
+ // Infra failure: no verdict was produced. Pause in check WITHOUT burning a
457
+ // fail count — the work is fine, the verifier isn't.
458
+ if (checkResult.infra) {
459
+ engine.writeState({ ...cur, paused: true, pause_reason: "check_error", last_failure_reason: checkResult.reason }, instId);
460
+ engine.logEvent(instId, "warn", "workflow_paused", { workflow: cur.workflow_name, step: cur.current_step, reason: "check_infra_error" });
461
+ events.onMessage?.(instId, `## ⚠️ 验证未能运行\n\n${checkResult.reason}\n\n这是验证进程自身的问题(额度/API/超时),**不是**工作成果的问题:本次不计入失败次数,已完成的工作无需重做。问题解决后运行 \`/ralphflow-continue\` 直接重新验证。`);
462
+ const p = engine.readState(instId);
463
+ if (p)
464
+ events.onPaused?.(instId, p);
465
+ return true;
466
+ }
467
+ engine.addStepRecord(instId, cur.current_step, "check", checkResult.passed ? "passed" : "failed", cur.fail_count || 0, checkResult.reason);
468
+ const result = checkResult.passed
469
+ ? engine.handleCheckPassed(instId, cur, workflow, step, checkResult)
470
+ : engine.handleCheckFailed(instId, cur, workflow, step, checkResult);
471
+ // Arm the next DO phase's markers before emitting the transition text
472
+ // (handleCheckPassed/Failed already wrote the state and cached the prompt).
473
+ if (!result.completed && !result.paused) {
474
+ const next = engine.readState(instId);
475
+ if (next && next.active && next.current_phase === "do") {
476
+ engine.clearDoneReported(instId);
477
+ engine.clearManualGate(instId);
478
+ const nextWf = next.workflow_name === workflow.name ? workflow : engine.loadWorkflow(next.workflow_name);
479
+ if (nextWf?.manual_step?.includes(next.current_step))
480
+ engine.writeManualStepMarker(instId);
481
+ else
482
+ engine.clearManualStepMarker(instId);
483
+ }
484
+ }
485
+ // Only a transition that needs the user (paused/completed) reaches the
486
+ // permanent chat listener — an ordinary silent pass-and-advance or
487
+ // fail-and-retry is exactly what "runs in the background, tells you when
488
+ // it needs you" promises NOT to surface unprompted. The run view (if
489
+ // attached) already shows every attempt live via onStepStart/onStepEvent/
490
+ // onVerdict, independent of onMessage, so nothing here is lost by staying
491
+ // quiet — only who gets told, and when.
492
+ if (result.completed || result.paused)
493
+ events.onMessage?.(instId, result.text);
494
+ if (result.completed) {
495
+ // The instance dir is gone now, but the archived report survives here.
496
+ const reportPath = path.join(engine.getReportsDir(), `${instId}-final-report.md`);
497
+ events.onCompleted?.(instId, fs.existsSync(reportPath) ? reportPath : undefined);
498
+ return true;
499
+ }
500
+ if (result.paused) {
501
+ const paused = engine.readState(instId);
502
+ if (paused)
503
+ events.onPaused?.(instId, paused);
504
+ return true;
505
+ }
506
+ return false; // keep looping into the next step's DO
507
+ }
508
+ return { ensureRunning, reviseGate, sendUserMessage, addEventListener, abortActiveStep, isRunning, idle, pauseAllForShutdown };
509
+ }
510
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/engine/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Skill discovery, in the same three tiers as workflows: project → global → built-in.
3
+ *
4
+ * The engine deliberately knows almost nothing about skills. A workflow step's
5
+ * `do:` text just says "use the c-to-rust-plan skill"; the model reads that,
6
+ * finds the skill in its system prompt catalog, and loads it. That decoupling is
7
+ * inherited from both plugin versions and is why the 12 domain skills could move
8
+ * here as plain text.
9
+ *
10
+ * What changed from the plan: pi already ships this. `loadSkillsFromDir` parses
11
+ * SKILL.md frontmatter, and the default system prompt appends a catalog (name,
12
+ * description, ABSOLUTE location) plus the instruction to resolve a skill's
13
+ * relative references against its own directory — as long as the session has the
14
+ * `read` tool. So there is no `use_skill` tool here: writing one would have
15
+ * duplicated pi's mechanism and fought its prompt.
16
+ *
17
+ * All this file adds is the tier resolution pi doesn't do: same-named skills
18
+ * shadow, nearest tier wins, and only the winners are handed to the session.
19
+ */
20
+ export type SkillSource = "project" | "global" | "builtin";
21
+ export interface ResolvedSkill {
22
+ name: string;
23
+ description: string;
24
+ /** Absolute path to SKILL.md — what goes in the model's catalog. */
25
+ filePath: string;
26
+ source: SkillSource;
27
+ /** Same-named skills this one shadows, nearest-tier-first. */
28
+ shadowed: Array<{
29
+ source: SkillSource;
30
+ filePath: string;
31
+ }>;
32
+ }
33
+ export interface SkillIndex {
34
+ skills: ResolvedSkill[];
35
+ /** Absolute SKILL.md paths for the winners — pass to a session's skillPaths. */
36
+ paths: string[];
37
+ /** Human-readable problems (unparseable SKILL.md, etc). */
38
+ diagnostics: string[];
39
+ }
40
+ /** Skills shipped inside the package. */
41
+ export declare function getBuiltinSkillsDir(): string;
42
+ export declare function getProjectSkillsDir(ralphFlowDir: string): string;
43
+ export declare function getGlobalSkillsDir(globalConfigHome: string | null): string | null;
44
+ /**
45
+ * Resolve the skills available to a DO session.
46
+ *
47
+ * @param ralphFlowDir the project's .ralph-flow dir
48
+ * @param globalConfigHome ~/.config/ralph-flow-pi, or null when there's no home
49
+ */
50
+ export declare function loadSkillIndex(ralphFlowDir: string, globalConfigHome: string | null): SkillIndex;
51
+ /** Doctor section: which skills are available, and what shadows what. */
52
+ export declare function formatSkillReport(index: SkillIndex): string;
53
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/engine/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,8DAA8D;IAC9D,QAAQ,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,gFAAgF;IAChF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,yCAAyC;AACzC,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAEjF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,CA2ChG;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAoB3D"}