minimal-agent 0.2.0 → 0.3.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 (107) hide show
  1. package/README.md +50 -72
  2. package/package.json +18 -13
  3. package/plugins/ralph-wiggum/plugin.js +205 -0
  4. package/plugins/ralph-wiggum/src/goalState.js +260 -0
  5. package/plugins/ralph-wiggum/src/{sentinels.ts → sentinels.js} +4 -7
  6. package/plugins/ralph-wiggum/src/stopHookRunner.js +104 -0
  7. package/plugins/ralph-wiggum/src/verificationGate.js +202 -0
  8. package/plugins/workflow-runner/{plugin.ts → plugin.js} +20 -26
  9. package/plugins/workflow-runner/src/expressions.js +369 -0
  10. package/plugins/workflow-runner/src/index.js +174 -0
  11. package/plugins/workflow-runner/src/loader.js +183 -0
  12. package/plugins/workflow-runner/src/runner.js +290 -0
  13. package/plugins/workflow-runner/src/stepExecutors/assert.js +28 -0
  14. package/plugins/workflow-runner/src/stepExecutors/llm.js +44 -0
  15. package/plugins/workflow-runner/src/stepExecutors/skill.js +103 -0
  16. package/plugins/workflow-runner/src/stepExecutors/{tool.ts → tool.js} +19 -25
  17. package/plugins/workflow-runner/src/types.js +59 -0
  18. package/plugins/workflow-runner/src/{workflowState.ts → workflowState.js} +21 -40
  19. package/src/bootstrap/cwdArg.js +22 -0
  20. package/src/bootstrap/workingDir.js +31 -0
  21. package/src/cli/configWizard.js +272 -0
  22. package/src/cli/print.js +192 -0
  23. package/src/config/configFile.js +78 -0
  24. package/src/config.js +118 -0
  25. package/src/context/compact.js +357 -0
  26. package/src/context/microCompactLite.js +151 -0
  27. package/src/context/persistContext.js +109 -0
  28. package/src/context/reactiveCompact.js +121 -0
  29. package/src/context/sessionPath.js +58 -0
  30. package/src/context/snipCompact.js +112 -0
  31. package/src/context/tokenCounter.js +66 -0
  32. package/src/llm/client.js +182 -0
  33. package/src/loop.js +230 -0
  34. package/src/main.js +116 -0
  35. package/src/plugin-sdk.js +24 -0
  36. package/src/plugins/commandRouter.js +169 -0
  37. package/src/plugins/hookEngine.js +258 -0
  38. package/src/plugins/pluginApi.js +23 -0
  39. package/src/plugins/pluginLoader.js +71 -0
  40. package/src/plugins/pluginRunner.js +65 -0
  41. package/src/plugins/transcript.js +171 -0
  42. package/src/prompts/projectInstructions.js +48 -0
  43. package/src/prompts/skillList.js +126 -0
  44. package/src/prompts/system.js +155 -0
  45. package/src/session/runTurn.js +41 -0
  46. package/src/session/sessionState.js +19 -0
  47. package/src/tools/bash/bash.js +352 -0
  48. package/src/tools/bash/semantics.js +85 -0
  49. package/src/tools/bash/warnings.js +98 -0
  50. package/src/tools/edit/edit.js +253 -0
  51. package/src/tools/edit/multi-edit.js +155 -0
  52. package/src/tools/glob/glob.js +97 -0
  53. package/src/tools/grep/grep.js +185 -0
  54. package/src/tools/grep/rgPath.js +173 -0
  55. package/src/tools/index.js +94 -0
  56. package/src/tools/read/read.js +209 -0
  57. package/src/tools/shared/fileState.js +61 -0
  58. package/src/tools/shared/fileUtils.js +281 -0
  59. package/src/tools/shared/schemas.js +16 -0
  60. package/src/tools/types.js +21 -0
  61. package/src/tools/webbrowser/browser.js +55 -0
  62. package/src/tools/webbrowser/webbrowser.js +194 -0
  63. package/src/tools/webfetch/preapproved.js +267 -0
  64. package/src/tools/webfetch/webfetch.js +317 -0
  65. package/src/tools/websearch/websearch.js +161 -0
  66. package/src/tools/write/write.js +125 -0
  67. package/src/types/turndown.d.ts +23 -0
  68. package/src/types.js +16 -0
  69. package/src/ui/App.js +37 -0
  70. package/src/ui/InputBox.js +240 -0
  71. package/src/ui/MessageList.js +28 -0
  72. package/src/ui/Root.js +70 -0
  73. package/src/ui/StatusLine.js +41 -0
  74. package/src/ui/ToolStatus.js +11 -0
  75. package/src/ui/hooks/useChat.js +234 -0
  76. package/src/ui/hooks/usePasteHandler.js +137 -0
  77. package/src/ui/hooks/useTextBuffer.js +55 -0
  78. package/src/ui/hooks/useTokenUsage.js +30 -0
  79. package/src/ui/textBuffer.js +217 -0
  80. package/src/utils/packageRoot.js +37 -0
  81. package/src/utils/resourcePaths.js +49 -0
  82. package/src/utils/zodToJson.js +29 -0
  83. package/dist/main.js +0 -5315
  84. package/plugins/ralph-wiggum/plugin.ts +0 -275
  85. package/plugins/ralph-wiggum/scripts/setup-ralph-loop.sh +0 -203
  86. package/plugins/ralph-wiggum/src/goalState.ts +0 -310
  87. package/plugins/ralph-wiggum/src/stopHookRunner.ts +0 -136
  88. package/plugins/ralph-wiggum/src/verificationGate.ts +0 -252
  89. package/plugins/ralph-wiggum/test/goalState.test.ts +0 -410
  90. package/plugins/ralph-wiggum/test/verificationGate.test.ts +0 -122
  91. package/plugins/workflow-runner/src/expressions.ts +0 -371
  92. package/plugins/workflow-runner/src/index.ts +0 -194
  93. package/plugins/workflow-runner/src/loader.ts +0 -193
  94. package/plugins/workflow-runner/src/runner.ts +0 -313
  95. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -30
  96. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -54
  97. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -115
  98. package/plugins/workflow-runner/src/types.ts +0 -183
  99. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -114
  100. package/plugins/workflow-runner/test/e2e.test.ts +0 -268
  101. package/plugins/workflow-runner/test/expressions.test.ts +0 -140
  102. package/plugins/workflow-runner/test/fixtures/cli-e2e.yaml +0 -27
  103. package/plugins/workflow-runner/test/fixtures/hello-workflow.yaml +0 -49
  104. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  105. package/plugins/workflow-runner/test/loader.test.ts +0 -216
  106. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -230
  107. package/plugins/workflow-runner/test/runner.test.ts +0 -511
@@ -1,275 +0,0 @@
1
- /**
2
- * ============================================================
3
- * plugins/ralph-wiggum/plugin.ts —— ralph-wiggum 真·插件入口
4
- * ------------------------------------------------------------
5
- * 把原 src/plugins/pluginRunner.ts 的 do-while 循环驱动整段搬来。
6
- * 对外通过 PluginApi.runCommand 暴露 /ralph-loop。
7
- *
8
- * 循环契约:
9
- * - 每轮把 history 重置成进入循环前的快照(fresh context)
10
- * - 用 GoalState.composeContext() 拼 PLAN/BUILD/VERIFY/HEAL 阶段信息
11
- * - 跑 runQuery
12
- * - 检测 <promise>DONE</promise> → runVerification → 通过则退出
13
- * - 检测 <PROMISE>NEED_REPLAN</PROMISE> → forceSetPhase(PLAN)
14
- * - executeStopHook 是咨询式:block 才把 reason 注入下一轮,pass 不退出
15
- *
16
- * 终止(独占):sentinel + verify 通过 / 达 max-iterations / abort / 安全天花板
17
- *
18
- * Windows 上 hooks/stop-hook.sh 不可用,但循环不依赖 hook,功能完整,
19
- * 只是 hook 的咨询通道失效。
20
- * ============================================================
21
- */
22
-
23
- import { fileURLToPath } from 'node:url';
24
- import { dirname } from 'node:path';
25
-
26
- import {
27
- runQuery,
28
- getWorkingDir,
29
- type PluginApi,
30
- type PluginContext,
31
- type LoopEvent,
32
- type Message,
33
- } from '../../src/plugin-sdk.ts';
34
-
35
- import { GoalState, Phase } from './src/goalState.ts';
36
- import { parseVerifyArgs, runVerification } from './src/verificationGate.ts';
37
- import {
38
- hasCompleteSentinel,
39
- hasNeedReplanSentinel,
40
- } from './src/sentinels.ts';
41
- import { executeStopHook } from './src/stopHookRunner.ts';
42
-
43
- const PLUGIN_NAME = 'ralph-wiggum';
44
- const DEFAULT_MAX_ITERATIONS = 50;
45
- const SAFETY_CEILING = 200;
46
-
47
- const PLUGIN_ROOT = dirname(fileURLToPath(import.meta.url));
48
-
49
- function extractMaxIterations(args: string): number | undefined {
50
- const match = args.match(/--max-iterations\s+(\d+)/i);
51
- return match ? parseInt(match[1], 10) : undefined;
52
- }
53
-
54
- async function* runRalphLoop(
55
- args: string,
56
- ctx: PluginContext,
57
- ): AsyncGenerator<LoopEvent, void, void> {
58
- const { provider, history, signal } = ctx;
59
-
60
- const maxIter = Math.min(
61
- extractMaxIterations(args) ?? DEFAULT_MAX_ITERATIONS,
62
- SAFETY_CEILING,
63
- );
64
-
65
- // 没有 args(用户只敲 /ralph-loop)→ 留个最小 goal placeholder,避免 GoalState.init 拒空串
66
- const userGoal = args.trim() || '(未提供目标)';
67
-
68
- yield {
69
- type: 'plugin_progress',
70
- pluginId: PLUGIN_NAME,
71
- current: 0,
72
- max: maxIter,
73
- message: 'Ralph Wiggum copy-task loop 启动',
74
- };
75
-
76
- const checks = parseVerifyArgs(args);
77
-
78
- // sessionTag = 插件名 → 多插件可并发不打架,/new 也能扫到清掉
79
- const goalState = new GoalState(getWorkingDir(), PLUGIN_NAME);
80
- await goalState.reset();
81
- await goalState.init(userGoal, checks);
82
- await goalState.appendProgress(
83
- `=== Loop 启动 === 目标: ${userGoal.slice(0, 120)}...`,
84
- );
85
-
86
- // 进循环前快照 history —— 每轮 runQuery 前用它重置,保证 fresh context
87
- const baseHistory = history.slice();
88
-
89
- let iterationCount = 0;
90
- let consecutiveFailures = 0;
91
- let currentInput = userGoal;
92
- let finalAssistantMsg: Message | null = null;
93
-
94
- try {
95
- do {
96
- iterationCount++;
97
- if (iterationCount > maxIter) {
98
- await goalState.forceSetPhase(Phase.DONE, `达到迭代上限 ${maxIter}`);
99
- await goalState.appendLearning(
100
- `[迭代上限] 循环在 ${iterationCount - 1} 轮后强制终止,可能目标过大或陷入死循环`,
101
- );
102
- yield {
103
- type: 'error',
104
- error: `Loop 已达迭代上限 ${maxIter},自动停止`,
105
- };
106
- return;
107
- }
108
-
109
- if (signal?.aborted) {
110
- yield { type: 'interrupted' };
111
- return;
112
- }
113
-
114
- yield {
115
- type: 'plugin_progress',
116
- pluginId: PLUGIN_NAME,
117
- current: iterationCount,
118
- max: maxIter,
119
- };
120
-
121
- // fresh context:清空 history,重置为入循环前的快照
122
- history.length = 0;
123
- history.push(...baseHistory);
124
-
125
- const freshContext = goalState.composeContext(iterationCount);
126
- const enhancedInput = `${freshContext}\n\n${currentInput}`;
127
-
128
- yield* runQuery(enhancedInput, {
129
- provider,
130
- history,
131
- signal,
132
- maxTurns: ctx.maxTurns,
133
- sessionState: ctx.sessionState,
134
- });
135
-
136
- if (signal?.aborted) {
137
- yield { type: 'interrupted' };
138
- return;
139
- }
140
-
141
- // 从本轮 history 抓最后一个 assistant 消息(runQuery 已 push 进去)
142
- const lastAssistantIdx = (() => {
143
- for (let i = history.length - 1; i >= 0; i--) {
144
- if (history[i].role === 'assistant') return i;
145
- }
146
- return -1;
147
- })();
148
- finalAssistantMsg =
149
- lastAssistantIdx >= 0 ? history[lastAssistantIdx] : null;
150
- const lastAssistantText = finalAssistantMsg
151
- ? typeof finalAssistantMsg.content === 'string'
152
- ? finalAssistantMsg.content
153
- : JSON.stringify(finalAssistantMsg.content)
154
- : '';
155
-
156
- if (hasCompleteSentinel(lastAssistantText)) {
157
- // 哨兵:可能来自任意阶段(包括 iter 1 的 PLAN),用 force 跳到 VERIFY
158
- await goalState.forceSetPhase(Phase.VERIFY, '检测到完成哨兵,进入验证');
159
- await goalState.appendProgress(
160
- `迭代 ${iterationCount}: 检测到完成哨兵,运行验证门...`,
161
- );
162
-
163
- if (checks.length > 0) {
164
- const vResult = await runVerification(checks);
165
-
166
- if (!vResult.passed) {
167
- consecutiveFailures++;
168
- await goalState.appendLearning(
169
- `[迭代 ${iterationCount}] 声称完成但验证未通过: ${vResult.summary}`,
170
- );
171
- yield {
172
- type: 'error',
173
- error: `⚠️ 验证未通过: ${vResult.summary}。继续尝试...`,
174
- };
175
-
176
- if (consecutiveFailures >= 3) {
177
- await goalState.forceSetPhase(
178
- Phase.HEAL,
179
- `连续 ${consecutiveFailures} 次验证失败`,
180
- );
181
- } else {
182
- await goalState.setPhase(Phase.BUILD, '验证未通过,返回构建');
183
- }
184
- continue;
185
- }
186
-
187
- await goalState.appendProgress(`✅ 验证通过: ${vResult.summary}`);
188
- }
189
-
190
- await goalState.setPhase(Phase.DONE, 'goal complete & verified');
191
- yield {
192
- type: 'plugin_iteration',
193
- pluginName: PLUGIN_NAME,
194
- current: iterationCount,
195
- max: maxIter,
196
- };
197
- return;
198
- }
199
-
200
- if (hasNeedReplanSentinel(lastAssistantText)) {
201
- await goalState.forceSetPhase(Phase.PLAN, 'agent 请求重新规划');
202
- await goalState.appendLearning(
203
- '[NEED_REPLAN] Agent 认为当前方案不可行,需要重新规划',
204
- );
205
- await goalState.appendProgress(
206
- 'Agent 请求 NEED_REPLAN,回 PLAN 阶段',
207
- );
208
- consecutiveFailures = 0;
209
- continue;
210
- }
211
-
212
- // PLAN 阶段跑过一轮还没哨兵,认为规划已完成,自动推进 BUILD
213
- if (goalState.currentPhase === Phase.PLAN && iterationCount >= 2) {
214
- await goalState.setPhase(Phase.BUILD, '规划阶段已完成,进入构建');
215
- }
216
-
217
- // Stop-hook 咨询式调用:block 才把 reason 注入下一轮 prompt
218
- // pass / 报错都不再终止循环;终止由 sentinel/maxIter/abort/NEED_REPLAN 独占
219
- const hookResult = await executeStopHook(PLUGIN_ROOT, lastAssistantText);
220
-
221
- if (hookResult.decision === 'block' && hookResult.reason) {
222
- currentInput = hookResult.reason;
223
- consecutiveFailures = 0;
224
- await goalState.recordDecision(
225
- {
226
- iteration: iterationCount,
227
- phase: goalState.currentPhase,
228
- summary: 'stop-hook 反馈',
229
- },
230
- ['继续循环', '终止'],
231
- '继续循环',
232
- hookResult.reason.slice(0, 200),
233
- );
234
- if (hookResult.systemMessage) {
235
- baseHistory.push({
236
- role: 'user',
237
- content: `[Plugin Stop Hook] ${hookResult.systemMessage}`,
238
- });
239
- }
240
- await goalState.appendProgress(
241
- `迭代 ${iterationCount}: Stop hook block,注入反馈继续`,
242
- );
243
- } else {
244
- await goalState.appendProgress(
245
- `迭代 ${iterationCount}: 无哨兵 / hook pass,继续下一轮`,
246
- );
247
- }
248
- } while (true);
249
- } finally {
250
- // 收尾:把循环里临时累积的 history 还原成 baseHistory + 最后一轮 assistant
251
- // 这样 TUI 上看到的就是"一次问答",而不是 N 轮重复
252
- history.length = 0;
253
- history.push(...baseHistory);
254
- if (finalAssistantMsg) {
255
- history.push(finalAssistantMsg);
256
- }
257
- await goalState.cleanup();
258
- }
259
- }
260
-
261
- const api: PluginApi = {
262
- async *runCommand(commandName, args, ctx) {
263
- if (commandName === 'ralph-loop') {
264
- yield* runRalphLoop(args, ctx);
265
- return;
266
- }
267
- // 其它命令(help / cancel-ralph)→ 不接管,让框架走声明式 fallback
268
- yield {
269
- type: 'error',
270
- error: `ralph-wiggum: 命令 /${commandName} 未由 plugin.ts 接管`,
271
- };
272
- },
273
- };
274
-
275
- export default api;
@@ -1,203 +0,0 @@
1
- #!/bin/bash
2
-
3
- # Ralph Loop Setup Script
4
- # Creates state file for in-session Ralph loop
5
-
6
- set -euo pipefail
7
-
8
- # Parse arguments
9
- PROMPT_PARTS=()
10
- MAX_ITERATIONS=0
11
- COMPLETION_PROMISE="null"
12
-
13
- # Parse options and positional arguments
14
- while [[ $# -gt 0 ]]; do
15
- case $1 in
16
- -h|--help)
17
- cat << 'HELP_EOF'
18
- Ralph Loop - Interactive self-referential development loop
19
-
20
- USAGE:
21
- /ralph-loop [PROMPT...] [OPTIONS]
22
-
23
- ARGUMENTS:
24
- PROMPT... Initial prompt to start the loop (can be multiple words without quotes)
25
-
26
- OPTIONS:
27
- --max-iterations <n> Maximum iterations before auto-stop (default: unlimited)
28
- --completion-promise '<text>' Promise phrase (USE QUOTES for multi-word)
29
- -h, --help Show this help message
30
-
31
- DESCRIPTION:
32
- Starts a Ralph Wiggum loop in your CURRENT session. The stop hook prevents
33
- exit and feeds your output back as input until completion or iteration limit.
34
-
35
- To signal completion, you must output: <promise>YOUR_PHRASE</promise>
36
-
37
- Use this for:
38
- - Interactive iteration where you want to see progress
39
- - Tasks requiring self-correction and refinement
40
- - Learning how Ralph works
41
-
42
- EXAMPLES:
43
- /ralph-loop Build a todo API --completion-promise 'DONE' --max-iterations 20
44
- /ralph-loop --max-iterations 10 Fix the auth bug
45
- /ralph-loop Refactor cache layer (runs forever)
46
- /ralph-loop --completion-promise 'TASK COMPLETE' Create a REST API
47
-
48
- STOPPING:
49
- Only by reaching --max-iterations or detecting --completion-promise
50
- No manual stop - Ralph runs infinitely by default!
51
-
52
- MONITORING:
53
- # View current iteration:
54
- grep '^iteration:' .minimal-agent/ralph-loop.local.md
55
-
56
- # View full state:
57
- head -10 .minimal-agent/ralph-loop.local.md
58
- HELP_EOF
59
- exit 0
60
- ;;
61
- --max-iterations)
62
- if [[ -z "${2:-}" ]]; then
63
- echo "❌ Error: --max-iterations requires a number argument" >&2
64
- echo "" >&2
65
- echo " Valid examples:" >&2
66
- echo " --max-iterations 10" >&2
67
- echo " --max-iterations 50" >&2
68
- echo " --max-iterations 0 (unlimited)" >&2
69
- echo "" >&2
70
- echo " You provided: --max-iterations (with no number)" >&2
71
- exit 1
72
- fi
73
- if ! [[ "$2" =~ ^[0-9]+$ ]]; then
74
- echo "❌ Error: --max-iterations must be a positive integer or 0, got: $2" >&2
75
- echo "" >&2
76
- echo " Valid examples:" >&2
77
- echo " --max-iterations 10" >&2
78
- echo " --max-iterations 50" >&2
79
- echo " --max-iterations 0 (unlimited)" >&2
80
- echo "" >&2
81
- echo " Invalid: decimals (10.5), negative numbers (-5), text" >&2
82
- exit 1
83
- fi
84
- MAX_ITERATIONS="$2"
85
- shift 2
86
- ;;
87
- --completion-promise)
88
- if [[ -z "${2:-}" ]]; then
89
- echo "❌ Error: --completion-promise requires a text argument" >&2
90
- echo "" >&2
91
- echo " Valid examples:" >&2
92
- echo " --completion-promise 'DONE'" >&2
93
- echo " --completion-promise 'TASK COMPLETE'" >&2
94
- echo " --completion-promise 'All tests passing'" >&2
95
- echo "" >&2
96
- echo " You provided: --completion-promise (with no text)" >&2
97
- echo "" >&2
98
- echo " Note: Multi-word promises must be quoted!" >&2
99
- exit 1
100
- fi
101
- COMPLETION_PROMISE="$2"
102
- shift 2
103
- ;;
104
- *)
105
- # Non-option argument - collect all as prompt parts
106
- PROMPT_PARTS+=("$1")
107
- shift
108
- ;;
109
- esac
110
- done
111
-
112
- # Join all prompt parts with spaces
113
- PROMPT="${PROMPT_PARTS[*]}"
114
-
115
- # Validate prompt is non-empty
116
- if [[ -z "$PROMPT" ]]; then
117
- echo "❌ Error: No prompt provided" >&2
118
- echo "" >&2
119
- echo " Ralph needs a task description to work on." >&2
120
- echo "" >&2
121
- echo " Examples:" >&2
122
- echo " /ralph-loop Build a REST API for todos" >&2
123
- echo " /ralph-loop Fix the auth bug --max-iterations 20" >&2
124
- echo " /ralph-loop --completion-promise 'DONE' Refactor code" >&2
125
- echo "" >&2
126
- echo " For all options: /ralph-loop --help" >&2
127
- exit 1
128
- fi
129
-
130
- # Create state file for stop hook (markdown with YAML frontmatter)
131
- mkdir -p .minimal-agent
132
-
133
- # Quote completion promise for YAML if it contains special chars or is not null
134
- if [[ -n "$COMPLETION_PROMISE" ]] && [[ "$COMPLETION_PROMISE" != "null" ]]; then
135
- COMPLETION_PROMISE_YAML="\"$COMPLETION_PROMISE\""
136
- else
137
- COMPLETION_PROMISE_YAML="null"
138
- fi
139
-
140
- cat > .minimal-agent/ralph-loop.local.md <<EOF
141
- ---
142
- active: true
143
- iteration: 1
144
- max_iterations: $MAX_ITERATIONS
145
- completion_promise: $COMPLETION_PROMISE_YAML
146
- started_at: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
147
- ---
148
-
149
- $PROMPT
150
- EOF
151
-
152
- # Output setup message
153
- cat <<EOF
154
- 🔄 Ralph loop activated in this session!
155
-
156
- Iteration: 1
157
- Max iterations: $(if [[ $MAX_ITERATIONS -gt 0 ]]; then echo $MAX_ITERATIONS; else echo "unlimited"; fi)
158
- Completion promise: $(if [[ "$COMPLETION_PROMISE" != "null" ]]; then echo "${COMPLETION_PROMISE//\"/} (ONLY output when TRUE - do not lie!)"; else echo "none (runs forever)"; fi)
159
-
160
- The stop hook is now active. When you try to exit, the SAME PROMPT will be
161
- fed back to you. You'll see your previous work in files, creating a
162
- self-referential loop where you iteratively improve on the same task.
163
-
164
- To monitor: head -10 .minimal-agent/ralph-loop.local.md
165
-
166
- ⚠️ WARNING: This loop cannot be stopped manually! It will run infinitely
167
- unless you set --max-iterations or --completion-promise.
168
-
169
- 🔄
170
- EOF
171
-
172
- # Output the initial prompt if provided
173
- if [[ -n "$PROMPT" ]]; then
174
- echo ""
175
- echo "$PROMPT"
176
- fi
177
-
178
- # Display completion promise requirements if set
179
- if [[ "$COMPLETION_PROMISE" != "null" ]]; then
180
- echo ""
181
- echo "═══════════════════════════════════════════════════════════"
182
- echo "CRITICAL - Ralph Loop Completion Promise"
183
- echo "═══════════════════════════════════════════════════════════"
184
- echo ""
185
- echo "To complete this loop, output this EXACT text:"
186
- echo " <promise>$COMPLETION_PROMISE</promise>"
187
- echo ""
188
- echo "STRICT REQUIREMENTS (DO NOT VIOLATE):"
189
- echo " ✓ Use <promise> XML tags EXACTLY as shown above"
190
- echo " ✓ The statement MUST be completely and unequivocally TRUE"
191
- echo " ✓ Do NOT output false statements to exit the loop"
192
- echo " ✓ Do NOT lie even if you think you should exit"
193
- echo ""
194
- echo "IMPORTANT - Do not circumvent the loop:"
195
- echo " Even if you believe you're stuck, the task is impossible,"
196
- echo " or you've been running too long - you MUST NOT output a"
197
- echo " false promise statement. The loop is designed to continue"
198
- echo " until the promise is GENUINELY TRUE. Trust the process."
199
- echo ""
200
- echo " If the loop should stop, the promise statement will become"
201
- echo " true naturally. Do not force it by lying."
202
- echo "═══════════════════════════════════════════════════════════"
203
- fi