@herbcaudill/ralph 0.8.3 → 1.0.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.
Files changed (302) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +26 -5
  3. package/dist/cli.js.map +1 -1
  4. package/dist/components/App.d.ts +6 -1
  5. package/dist/components/App.d.ts.map +1 -1
  6. package/dist/components/App.js +7 -3
  7. package/dist/components/App.js.map +1 -1
  8. package/dist/components/EnhancedTextInput.d.ts +8 -8
  9. package/dist/components/EnhancedTextInput.d.ts.map +1 -1
  10. package/dist/components/EnhancedTextInput.js +2 -36
  11. package/dist/components/EnhancedTextInput.js.map +1 -1
  12. package/dist/components/EnhancedTextInput.test.js +2 -10
  13. package/dist/components/EnhancedTextInput.test.js.map +1 -1
  14. package/dist/components/EventDisplay.d.ts +1 -1
  15. package/dist/components/EventDisplay.d.ts.map +1 -1
  16. package/dist/components/EventDisplay.js +3 -94
  17. package/dist/components/EventDisplay.js.map +1 -1
  18. package/dist/components/EventDisplay.replay.test.js +34 -68
  19. package/dist/components/EventDisplay.replay.test.js.map +1 -1
  20. package/dist/components/EventDisplay.test.js +30 -0
  21. package/dist/components/EventDisplay.test.js.map +1 -1
  22. package/dist/components/FullScreenLayout.d.ts +5 -4
  23. package/dist/components/FullScreenLayout.d.ts.map +1 -1
  24. package/dist/components/FullScreenLayout.js +2 -12
  25. package/dist/components/FullScreenLayout.js.map +1 -1
  26. package/dist/components/Header.d.ts +2 -1
  27. package/dist/components/Header.d.ts.map +1 -1
  28. package/dist/components/Header.js +8 -1
  29. package/dist/components/Header.js.map +1 -1
  30. package/dist/components/InitRalph.d.ts +6 -1
  31. package/dist/components/InitRalph.d.ts.map +1 -1
  32. package/dist/components/InitRalph.js +71 -89
  33. package/dist/components/InitRalph.js.map +1 -1
  34. package/dist/components/IterationRunner.d.ts +6 -13
  35. package/dist/components/IterationRunner.d.ts.map +1 -1
  36. package/dist/components/IterationRunner.js +84 -168
  37. package/dist/components/IterationRunner.js.map +1 -1
  38. package/dist/components/IterationRunner.test.d.ts +44 -0
  39. package/dist/components/IterationRunner.test.d.ts.map +1 -1
  40. package/dist/components/IterationRunner.test.js +66 -126
  41. package/dist/components/IterationRunner.test.js.map +1 -1
  42. package/dist/components/IterationRunner.types.d.ts +30 -0
  43. package/dist/components/IterationRunner.types.d.ts.map +1 -0
  44. package/dist/components/IterationRunner.types.js +2 -0
  45. package/dist/components/IterationRunner.types.js.map +1 -0
  46. package/dist/components/JsonOutput.d.ts +5 -6
  47. package/dist/components/JsonOutput.d.ts.map +1 -1
  48. package/dist/components/JsonOutput.js +57 -34
  49. package/dist/components/JsonOutput.js.map +1 -1
  50. package/dist/components/JsonOutput.test.d.ts +2 -0
  51. package/dist/components/JsonOutput.test.d.ts.map +1 -0
  52. package/dist/components/JsonOutput.test.js +39 -0
  53. package/dist/components/JsonOutput.test.js.map +1 -0
  54. package/dist/components/ReplayLog.d.ts +1 -1
  55. package/dist/components/ReplayLog.d.ts.map +1 -1
  56. package/dist/components/ReplayLog.js +9 -2
  57. package/dist/components/ReplayLog.js.map +1 -1
  58. package/dist/components/StreamingText.d.ts +4 -0
  59. package/dist/components/StreamingText.d.ts.map +1 -1
  60. package/dist/components/StreamingText.js +4 -3
  61. package/dist/components/StreamingText.js.map +1 -1
  62. package/dist/components/StreamingText.test.js +39 -0
  63. package/dist/components/StreamingText.test.js.map +1 -1
  64. package/dist/components/ToolUse.d.ts +8 -0
  65. package/dist/components/ToolUse.d.ts.map +1 -1
  66. package/dist/components/ToolUse.js +1 -0
  67. package/dist/components/ToolUse.js.map +1 -1
  68. package/dist/components/blocksToLines.d.ts +6 -0
  69. package/dist/components/blocksToLines.d.ts.map +1 -0
  70. package/dist/components/blocksToLines.js +15 -0
  71. package/dist/components/blocksToLines.js.map +1 -0
  72. package/dist/components/eventToBlocks.d.ts +7 -1
  73. package/dist/components/eventToBlocks.d.ts.map +1 -1
  74. package/dist/components/eventToBlocks.js +7 -1
  75. package/dist/components/eventToBlocks.js.map +1 -1
  76. package/dist/components/findNextWordBoundary.d.ts +10 -0
  77. package/dist/components/findNextWordBoundary.d.ts.map +1 -0
  78. package/dist/components/findNextWordBoundary.js +23 -0
  79. package/dist/components/findNextWordBoundary.js.map +1 -0
  80. package/dist/components/findPreviousWordBoundary.d.ts +10 -0
  81. package/dist/components/findPreviousWordBoundary.d.ts.map +1 -0
  82. package/dist/components/findPreviousWordBoundary.js +23 -0
  83. package/dist/components/findPreviousWordBoundary.js.map +1 -0
  84. package/dist/components/processEvents.d.ts +11 -0
  85. package/dist/components/processEvents.d.ts.map +1 -0
  86. package/dist/components/processEvents.js +87 -0
  87. package/dist/components/processEvents.js.map +1 -0
  88. package/dist/components/renderStaticItem.d.ts +7 -0
  89. package/dist/components/renderStaticItem.d.ts.map +1 -0
  90. package/dist/components/renderStaticItem.js +23 -0
  91. package/dist/components/renderStaticItem.js.map +1 -0
  92. package/dist/components/replay.d.ts +5 -0
  93. package/dist/components/replay.d.ts.map +1 -0
  94. package/dist/components/replay.js +49 -0
  95. package/dist/components/replay.js.map +1 -0
  96. package/dist/components/test-helpers/ControlledInput.d.ts +14 -0
  97. package/dist/components/test-helpers/ControlledInput.d.ts.map +1 -0
  98. package/dist/components/test-helpers/ControlledInput.js +15 -0
  99. package/dist/components/test-helpers/ControlledInput.js.map +1 -0
  100. package/dist/components/useContentHeight.d.ts +9 -0
  101. package/dist/components/useContentHeight.d.ts.map +1 -0
  102. package/dist/components/useContentHeight.js +16 -0
  103. package/dist/components/useContentHeight.js.map +1 -0
  104. package/dist/index.d.ts +1 -0
  105. package/dist/index.d.ts.map +1 -1
  106. package/dist/index.js +2 -1
  107. package/dist/index.js.map +1 -1
  108. package/dist/lib/MessageQueue.d.ts +18 -5
  109. package/dist/lib/MessageQueue.d.ts.map +1 -1
  110. package/dist/lib/MessageQueue.js +21 -14
  111. package/dist/lib/MessageQueue.js.map +1 -1
  112. package/dist/lib/StdinCommandHandler.d.ts +26 -20
  113. package/dist/lib/StdinCommandHandler.js +78 -85
  114. package/dist/lib/StdinCommandHandler.test.d.ts +2 -2
  115. package/dist/lib/StdinCommandHandler.test.js +92 -92
  116. package/dist/lib/WorktreeManager.d.ts +114 -0
  117. package/dist/lib/WorktreeManager.d.ts.map +1 -0
  118. package/dist/lib/WorktreeManager.js +350 -0
  119. package/dist/lib/WorktreeManager.js.map +1 -0
  120. package/dist/lib/WorktreeManager.test.d.ts +2 -0
  121. package/dist/lib/WorktreeManager.test.d.ts.map +1 -0
  122. package/dist/lib/WorktreeManager.test.js +261 -0
  123. package/dist/lib/WorktreeManager.test.js.map +1 -0
  124. package/dist/lib/addTodo.d.ts +5 -5
  125. package/dist/lib/addTodo.d.ts.map +1 -1
  126. package/dist/lib/addTodo.js +6 -20
  127. package/dist/lib/addTodo.js.map +1 -1
  128. package/dist/lib/beadsClient.d.ts +6 -12
  129. package/dist/lib/beadsClient.d.ts.map +1 -1
  130. package/dist/lib/beadsClient.js +3 -2
  131. package/dist/lib/beadsClient.js.map +1 -1
  132. package/dist/lib/captureBeadsSnapshot.d.ts +4 -0
  133. package/dist/lib/captureBeadsSnapshot.d.ts.map +1 -0
  134. package/dist/lib/captureBeadsSnapshot.js +24 -0
  135. package/dist/lib/captureBeadsSnapshot.js.map +1 -0
  136. package/dist/lib/captureStartupSnapshot.d.ts +10 -0
  137. package/dist/lib/captureStartupSnapshot.d.ts.map +1 -0
  138. package/dist/lib/captureStartupSnapshot.js +29 -0
  139. package/dist/lib/captureStartupSnapshot.js.map +1 -0
  140. package/dist/lib/captureTodoSnapshot.d.ts +4 -0
  141. package/dist/lib/captureTodoSnapshot.d.ts.map +1 -0
  142. package/dist/lib/captureTodoSnapshot.js +24 -0
  143. package/dist/lib/captureTodoSnapshot.js.map +1 -0
  144. package/dist/lib/copyTemplates.d.ts +22 -0
  145. package/dist/lib/copyTemplates.d.ts.map +1 -0
  146. package/dist/lib/copyTemplates.js +32 -0
  147. package/dist/lib/copyTemplates.js.map +1 -0
  148. package/dist/lib/createStdinCommandHandler.d.ts +28 -0
  149. package/dist/lib/createStdinCommandHandler.d.ts.map +1 -0
  150. package/dist/lib/createStdinCommandHandler.js +67 -0
  151. package/dist/lib/createStdinCommandHandler.js.map +1 -0
  152. package/dist/lib/createUserMessage.d.ts +6 -0
  153. package/dist/lib/createUserMessage.d.ts.map +1 -0
  154. package/dist/lib/createUserMessage.js +13 -0
  155. package/dist/lib/createUserMessage.js.map +1 -0
  156. package/dist/lib/debug.d.ts +17 -16
  157. package/dist/lib/debug.d.ts.map +1 -1
  158. package/dist/lib/debug.js +25 -15
  159. package/dist/lib/debug.js.map +1 -1
  160. package/dist/lib/findMaxLogNumber.d.ts +6 -0
  161. package/dist/lib/findMaxLogNumber.d.ts.map +1 -0
  162. package/dist/lib/findMaxLogNumber.js +26 -0
  163. package/dist/lib/findMaxLogNumber.js.map +1 -0
  164. package/dist/lib/findMaxLogNumber.test.d.ts +2 -0
  165. package/dist/lib/findMaxLogNumber.test.d.ts.map +1 -0
  166. package/dist/lib/findMaxLogNumber.test.js +39 -0
  167. package/dist/lib/findMaxLogNumber.test.js.map +1 -0
  168. package/dist/lib/formatContentBlock.d.ts +4 -8
  169. package/dist/lib/formatContentBlock.d.ts.map +1 -1
  170. package/dist/lib/formatContentBlock.js +7 -58
  171. package/dist/lib/formatContentBlock.js.map +1 -1
  172. package/dist/lib/formatIterationHeader.d.ts +5 -0
  173. package/dist/lib/formatIterationHeader.d.ts.map +1 -0
  174. package/dist/lib/formatIterationHeader.js +8 -0
  175. package/dist/lib/formatIterationHeader.js.map +1 -0
  176. package/dist/lib/formatText.d.ts +5 -0
  177. package/dist/lib/formatText.d.ts.map +1 -0
  178. package/dist/lib/formatText.js +33 -0
  179. package/dist/lib/formatText.js.map +1 -0
  180. package/dist/lib/formatToolUse.d.ts +7 -0
  181. package/dist/lib/formatToolUse.d.ts.map +1 -0
  182. package/dist/lib/formatToolUse.js +14 -0
  183. package/dist/lib/formatToolUse.js.map +1 -0
  184. package/dist/lib/formatUserMessage.d.ts +5 -0
  185. package/dist/lib/formatUserMessage.d.ts.map +1 -0
  186. package/dist/lib/formatUserMessage.js +8 -0
  187. package/dist/lib/formatUserMessage.js.map +1 -0
  188. package/dist/lib/getBaseCwd.d.ts +6 -0
  189. package/dist/lib/getBaseCwd.d.ts.map +1 -0
  190. package/dist/lib/getBaseCwd.js +6 -0
  191. package/dist/lib/getBaseCwd.js.map +1 -0
  192. package/dist/lib/getBeadsProgress.d.ts +8 -0
  193. package/dist/lib/getBeadsProgress.d.ts.map +1 -0
  194. package/dist/lib/getBeadsProgress.js +35 -0
  195. package/dist/lib/getBeadsProgress.js.map +1 -0
  196. package/dist/lib/getClaudeVersion.d.ts +4 -0
  197. package/dist/lib/getClaudeVersion.d.ts.map +1 -1
  198. package/dist/lib/getClaudeVersion.js +4 -0
  199. package/dist/lib/getClaudeVersion.js.map +1 -1
  200. package/dist/lib/getDefaultIterations.d.ts +6 -0
  201. package/dist/lib/getDefaultIterations.d.ts.map +1 -0
  202. package/dist/lib/getDefaultIterations.js +14 -0
  203. package/dist/lib/getDefaultIterations.js.map +1 -0
  204. package/dist/lib/getDefaultIterations.test.d.ts +2 -0
  205. package/dist/lib/getDefaultIterations.test.d.ts.map +1 -0
  206. package/dist/lib/getDefaultIterations.test.js +39 -0
  207. package/dist/lib/getDefaultIterations.test.js.map +1 -0
  208. package/dist/lib/getLatestLogFile.d.ts +6 -0
  209. package/dist/lib/getLatestLogFile.d.ts.map +1 -0
  210. package/dist/lib/getLatestLogFile.js +15 -0
  211. package/dist/lib/getLatestLogFile.js.map +1 -0
  212. package/dist/lib/getNextLogFile.d.ts +0 -5
  213. package/dist/lib/getNextLogFile.d.ts.map +1 -1
  214. package/dist/lib/getNextLogFile.js +2 -36
  215. package/dist/lib/getNextLogFile.js.map +1 -1
  216. package/dist/lib/getNextLogFile.test.js +2 -1
  217. package/dist/lib/getNextLogFile.test.js.map +1 -1
  218. package/dist/lib/getOpenIssueCount.d.ts +0 -5
  219. package/dist/lib/getOpenIssueCount.d.ts.map +1 -1
  220. package/dist/lib/getOpenIssueCount.js +0 -12
  221. package/dist/lib/getOpenIssueCount.js.map +1 -1
  222. package/dist/lib/getOpenIssueCount.test.js +1 -35
  223. package/dist/lib/getOpenIssueCount.test.js.map +1 -1
  224. package/dist/lib/getProgress.d.ts +6 -26
  225. package/dist/lib/getProgress.d.ts.map +1 -1
  226. package/dist/lib/getProgress.js +8 -109
  227. package/dist/lib/getProgress.js.map +1 -1
  228. package/dist/lib/getProgress.test.js +2 -1
  229. package/dist/lib/getProgress.test.js.map +1 -1
  230. package/dist/lib/getPromptContent.d.ts +8 -0
  231. package/dist/lib/getPromptContent.d.ts.map +1 -0
  232. package/dist/lib/getPromptContent.js +31 -0
  233. package/dist/lib/getPromptContent.js.map +1 -0
  234. package/dist/lib/getTerminalSize.d.ts +8 -0
  235. package/dist/lib/getTerminalSize.d.ts.map +1 -0
  236. package/dist/lib/getTerminalSize.js +10 -0
  237. package/dist/lib/getTerminalSize.js.map +1 -0
  238. package/dist/lib/getTodoProgress.d.ts +4 -0
  239. package/dist/lib/getTodoProgress.d.ts.map +1 -0
  240. package/dist/lib/getTodoProgress.js +22 -0
  241. package/dist/lib/getTodoProgress.js.map +1 -0
  242. package/dist/lib/insertTodo.d.ts +7 -0
  243. package/dist/lib/insertTodo.d.ts.map +1 -0
  244. package/dist/lib/insertTodo.js +22 -0
  245. package/dist/lib/insertTodo.js.map +1 -0
  246. package/dist/lib/outputEvent.d.ts +5 -0
  247. package/dist/lib/outputEvent.d.ts.map +1 -0
  248. package/dist/lib/outputEvent.js +7 -0
  249. package/dist/lib/outputEvent.js.map +1 -0
  250. package/dist/lib/parseStdinCommand.d.ts +25 -0
  251. package/dist/lib/parseStdinCommand.d.ts.map +1 -0
  252. package/dist/lib/parseStdinCommand.js +43 -0
  253. package/dist/lib/parseStdinCommand.js.map +1 -0
  254. package/dist/lib/parseStdinCommand.test.d.ts +2 -0
  255. package/dist/lib/parseStdinCommand.test.d.ts.map +1 -0
  256. package/dist/lib/parseStdinCommand.test.js +93 -0
  257. package/dist/lib/parseStdinCommand.test.js.map +1 -0
  258. package/dist/lib/parseTaskLifecycle.d.ts +18 -0
  259. package/dist/lib/parseTaskLifecycle.d.ts.map +1 -0
  260. package/dist/lib/parseTaskLifecycle.js +30 -0
  261. package/dist/lib/parseTaskLifecycle.js.map +1 -0
  262. package/dist/lib/parseTaskLifecycle.test.d.ts +2 -0
  263. package/dist/lib/parseTaskLifecycle.test.d.ts.map +1 -0
  264. package/dist/lib/parseTaskLifecycle.test.js +122 -0
  265. package/dist/lib/parseTaskLifecycle.test.js.map +1 -0
  266. package/dist/lib/parseWorktreeFromBranch.d.ts +13 -0
  267. package/dist/lib/parseWorktreeFromBranch.d.ts.map +1 -0
  268. package/dist/lib/parseWorktreeFromBranch.js +19 -0
  269. package/dist/lib/parseWorktreeFromBranch.js.map +1 -0
  270. package/dist/lib/processEvents.d.ts +12 -0
  271. package/dist/lib/processEvents.d.ts.map +1 -0
  272. package/dist/lib/processEvents.js +113 -0
  273. package/dist/lib/processEvents.js.map +1 -0
  274. package/dist/lib/rel.d.ts +7 -1
  275. package/dist/lib/rel.d.ts.map +1 -1
  276. package/dist/lib/rel.js +13 -4
  277. package/dist/lib/rel.js.map +1 -1
  278. package/dist/lib/rel.test.js +16 -1
  279. package/dist/lib/rel.test.js.map +1 -1
  280. package/dist/lib/sdkMessageToEvent.d.ts +6 -0
  281. package/dist/lib/sdkMessageToEvent.d.ts.map +1 -0
  282. package/dist/lib/sdkMessageToEvent.js +12 -0
  283. package/dist/lib/sdkMessageToEvent.js.map +1 -0
  284. package/dist/lib/shortenTempPaths.d.ts +7 -1
  285. package/dist/lib/shortenTempPaths.d.ts.map +1 -1
  286. package/dist/lib/shortenTempPaths.js +7 -2
  287. package/dist/lib/shortenTempPaths.js.map +1 -1
  288. package/dist/lib/types.d.ts +19 -0
  289. package/dist/lib/types.d.ts.map +1 -0
  290. package/dist/lib/types.js +2 -0
  291. package/dist/lib/types.js.map +1 -0
  292. package/dist/lib/useTerminalSize.d.ts +3 -2
  293. package/dist/lib/useTerminalSize.d.ts.map +1 -1
  294. package/dist/lib/useTerminalSize.js +4 -6
  295. package/dist/lib/useTerminalSize.js.map +1 -1
  296. package/package.json +4 -3
  297. package/templates/core-prompt.md +77 -0
  298. package/templates/skills/manage-tasks/SKILL.md +113 -0
  299. package/templates/workflow.md +46 -0
  300. package/templates/prompt-beads.md +0 -44
  301. package/templates/prompt-todos.md +0 -17
  302. package/templates/todo.md +0 -9
@@ -1,58 +1,60 @@
1
1
  import { Text, Box } from "ink";
2
- import SelectInput from "ink-select-input";
3
2
  import React, { useEffect, useState } from "react";
4
- import { existsSync, mkdirSync, copyFileSync, readFileSync, appendFileSync, writeFileSync, } from "fs";
3
+ import { existsSync, readFileSync, appendFileSync, writeFileSync } from "fs";
5
4
  import { join, dirname } from "path";
6
5
  import { fileURLToPath } from "url";
7
- const __dirname = dirname(fileURLToPath(import.meta.url));
8
- export const InitRalph = () => {
6
+ import { copyTemplates } from "../lib/copyTemplates.js";
7
+ /**
8
+ * Initializes Ralph by copying workflow templates and agent configurations to the project.
9
+ * Creates .ralph/workflow.md, .claude/skills/, and .claude/agents/ directories with default files.
10
+ * Also adds .ralph/events-*.jsonl to .gitignore.
11
+ */
12
+ export function InitRalph() {
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
14
  const [status, setStatus] = useState("checking");
10
- const [taskMode, setTaskMode] = useState(null);
11
15
  const [createdFiles, setCreatedFiles] = useState([]);
16
+ const [skippedFiles, setSkippedFiles] = useState([]);
12
17
  const [errors, setErrors] = useState([]);
13
- // Check if .ralph already exists
18
+ // Check if .ralph already exists and run initialization
14
19
  useEffect(() => {
15
20
  const ralphDir = join(process.cwd(), ".ralph");
16
- if (existsSync(ralphDir) && existsSync(join(ralphDir, "prompt.md"))) {
21
+ const claudeDir = join(process.cwd(), ".claude");
22
+ // Check if already initialized
23
+ if (existsSync(join(ralphDir, "workflow.md"))) {
17
24
  setStatus("exists");
18
- }
19
- else {
20
- setStatus("selecting");
21
- }
22
- }, []);
23
- // Run initialization when task mode is selected
24
- useEffect(() => {
25
- if (!taskMode)
26
25
  return;
26
+ }
27
+ // Run initialization
27
28
  const initialize = async () => {
28
- const ralphDir = join(process.cwd(), ".ralph");
29
29
  const templatesDir = join(__dirname, "..", "..", "templates");
30
- // Select templates based on task mode
31
- const templates = taskMode === "beads" ?
32
- [{ src: "prompt-beads.md", dest: "prompt.md" }]
33
- : [
34
- { src: "prompt-todos.md", dest: "prompt.md" },
35
- { src: "todo.md", dest: "todo.md" },
36
- ];
37
30
  setStatus("creating");
38
31
  try {
39
- mkdirSync(ralphDir, { recursive: true });
40
- const created = [];
41
- const failed = [];
42
- for (const template of templates) {
43
- const src = join(templatesDir, template.src);
44
- const dest = join(ralphDir, template.dest);
45
- // Only copy if the destination doesn't exist
46
- if (!existsSync(dest)) {
47
- if (existsSync(src)) {
48
- copyFileSync(src, dest);
49
- created.push(template.dest);
50
- }
51
- else {
52
- failed.push(`Template not found: ${template.src}`);
53
- }
54
- }
55
- }
32
+ const allCreated = [];
33
+ const allSkipped = [];
34
+ const allErrors = [];
35
+ // Copy workflow to .ralph/
36
+ const ralphResult = copyTemplates(templatesDir, ralphDir, [
37
+ { src: "workflow.md", dest: "workflow.md" },
38
+ ]);
39
+ allCreated.push(...ralphResult.created.map(f => `.ralph/${f}`));
40
+ allSkipped.push(...ralphResult.skipped.map(f => `.ralph/${f}`));
41
+ allErrors.push(...ralphResult.errors);
42
+ // Copy skills to .claude/skills/
43
+ const skillsResult = copyTemplates(templatesDir, claudeDir, [
44
+ { src: "skills/manage-tasks/SKILL.md", dest: "skills/manage-tasks/SKILL.md" },
45
+ ]);
46
+ allCreated.push(...skillsResult.created.map(f => `.claude/${f}`));
47
+ allSkipped.push(...skillsResult.skipped.map(f => `.claude/${f}`));
48
+ allErrors.push(...skillsResult.errors);
49
+ // Copy agents to .claude/agents/
50
+ const agentsResult = copyTemplates(templatesDir, claudeDir, [
51
+ { src: "agents/make-tests.md", dest: "agents/make-tests.md" },
52
+ { src: "agents/write-docs.md", dest: "agents/write-docs.md" },
53
+ { src: "agents/run-tests.md", dest: "agents/run-tests.md" },
54
+ ]);
55
+ allCreated.push(...agentsResult.created.map(f => `.claude/${f}`));
56
+ allSkipped.push(...agentsResult.skipped.map(f => `.claude/${f}`));
57
+ allErrors.push(...agentsResult.errors);
56
58
  // Add events log pattern to .gitignore
57
59
  const gitignorePath = join(process.cwd(), ".gitignore");
58
60
  const eventsLogEntry = ".ralph/events-*.jsonl";
@@ -61,15 +63,16 @@ export const InitRalph = () => {
61
63
  if (!content.includes(eventsLogEntry)) {
62
64
  const newline = content.endsWith("\n") ? "" : "\n";
63
65
  appendFileSync(gitignorePath, `${newline}${eventsLogEntry}\n`);
64
- created.push("(added .ralph/events-*.jsonl to .gitignore)");
66
+ allCreated.push("(added .ralph/events-*.jsonl to .gitignore)");
65
67
  }
66
68
  }
67
69
  else {
68
70
  writeFileSync(gitignorePath, `${eventsLogEntry}\n`);
69
- created.push("(created .gitignore with .ralph/events-*.jsonl)");
71
+ allCreated.push("(created .gitignore with .ralph/events-*.jsonl)");
70
72
  }
71
- setCreatedFiles(created);
72
- setErrors(failed);
73
+ setCreatedFiles(allCreated);
74
+ setSkippedFiles(allSkipped);
75
+ setErrors(allErrors);
73
76
  setStatus("done");
74
77
  // Exit after a brief delay so user can see success message
75
78
  setTimeout(() => process.exit(0), 100);
@@ -81,26 +84,14 @@ export const InitRalph = () => {
81
84
  }
82
85
  };
83
86
  initialize();
84
- }, [taskMode]);
85
- const handleModeSelect = (item) => {
86
- setTaskMode(item.value);
87
- };
87
+ }, []);
88
88
  if (status === "checking") {
89
- return React.createElement(Text, null, "Checking .ralph directory...");
89
+ return React.createElement(Text, null, "Checking directories...");
90
90
  }
91
91
  if (status === "exists") {
92
92
  return (React.createElement(Box, { flexDirection: "column" },
93
- React.createElement(Text, { color: "yellow" }, "\u26A0\uFE0F .ralph directory already exists"),
94
- React.createElement(Text, { dimColor: true }, "To reinitialize, remove the directory first: rm -rf .ralph")));
95
- }
96
- if (status === "selecting") {
97
- return (React.createElement(Box, { flexDirection: "column" },
98
- React.createElement(Text, { bold: true }, "How will you manage tasks?"),
99
- React.createElement(Box, { marginTop: 1 },
100
- React.createElement(SelectInput, { items: [
101
- { label: "todo.md - Simple markdown checklist", value: "todo" },
102
- { label: "beads - Git-backed issue tracker", value: "beads" },
103
- ], onSelect: handleModeSelect }))));
93
+ React.createElement(Text, { color: "yellow" }, "Ralph is already initialized"),
94
+ React.createElement(Text, { dimColor: true }, "To reinitialize, remove the workflow first: rm .ralph/workflow.md")));
104
95
  }
105
96
  if (status === "creating") {
106
97
  return React.createElement(Text, { color: "cyan" }, "Initializing ralph...");
@@ -109,9 +100,12 @@ export const InitRalph = () => {
109
100
  createdFiles.map(file => (React.createElement(Text, { key: file },
110
101
  React.createElement(Text, { color: "green" }, "\u2713"),
111
102
  " Created ",
112
- React.createElement(Text, { dimColor: true },
113
- ".ralph/",
114
- file)))),
103
+ React.createElement(Text, { dimColor: true }, file)))),
104
+ skippedFiles.map(file => (React.createElement(Text, { key: file },
105
+ React.createElement(Text, { color: "yellow" }, "\u25CB"),
106
+ " Skipped ",
107
+ React.createElement(Text, { dimColor: true }, file),
108
+ React.createElement(Text, { dimColor: true }, " (already exists)")))),
115
109
  errors.map((error, i) => (React.createElement(Text, { key: i },
116
110
  React.createElement(Text, { color: "red" }, "\u2717"),
117
111
  " ",
@@ -119,36 +113,24 @@ export const InitRalph = () => {
119
113
  errors.length === 0 && (React.createElement(React.Fragment, null,
120
114
  React.createElement(Text, { color: "green" },
121
115
  "\n",
122
- "\u2713 Ralph initialized successfully!"),
123
- taskMode === "todo" ?
124
- React.createElement(React.Fragment, null,
125
- React.createElement(Text, { bold: true },
126
- "\n",
127
- "Before running ralph, you need to:"),
128
- React.createElement(Text, null,
129
- React.createElement(Text, { color: "cyan" }, " 1. Edit .ralph/prompt.md"),
130
- React.createElement(Text, { dimColor: true }, " - Add your project context and workflow instructions")),
131
- React.createElement(Text, null,
132
- React.createElement(Text, { color: "cyan" }, " 2. Edit .ralph/todo.md"),
133
- React.createElement(Text, { dimColor: true }, " - Add the tasks you want Ralph to work on")))
134
- : React.createElement(React.Fragment, null,
135
- React.createElement(Text, { bold: true },
136
- "\n",
137
- "Before running ralph, you need to:"),
138
- React.createElement(Text, null,
139
- React.createElement(Text, { color: "cyan" }, " 1. Edit .ralph/prompt.md"),
140
- React.createElement(Text, { dimColor: true }, " - Customize build commands and workflow for your project")),
141
- React.createElement(Text, null,
142
- React.createElement(Text, { color: "cyan" }, " 2. Initialize beads"),
143
- React.createElement(Text, { dimColor: true }, " - Run `bd init` to set up the issue tracker")),
144
- React.createElement(Text, null,
145
- React.createElement(Text, { color: "cyan" }, " 3. Create issues"),
146
- React.createElement(Text, { dimColor: true }, " - Run `bd create --title=\"...\" --type=task` to add work"))),
116
+ "Ralph initialized successfully!"),
117
+ React.createElement(Text, { bold: true },
118
+ "\n",
119
+ "Next steps:"),
120
+ React.createElement(Text, null,
121
+ React.createElement(Text, { color: "cyan" }, " 1. Edit .ralph/workflow.md"),
122
+ React.createElement(Text, { dimColor: true }, " - Customize build commands for your project")),
123
+ React.createElement(Text, null,
124
+ React.createElement(Text, { color: "cyan" }, " 2. Initialize beads"),
125
+ React.createElement(Text, { dimColor: true }, " - Run `bd init` to set up the issue tracker")),
126
+ React.createElement(Text, null,
127
+ React.createElement(Text, { color: "cyan" }, " 3. Create issues"),
128
+ React.createElement(Text, { dimColor: true }, " - Run `bd create --title=\"...\" --type=task` to add work")),
147
129
  React.createElement(Text, null,
148
130
  React.createElement(Text, { bold: true },
149
131
  "\n",
150
132
  "Then run: "),
151
133
  React.createElement(Text, { color: "cyan" }, "ralph"),
152
134
  "\n")))));
153
- };
135
+ }
154
136
  //# sourceMappingURL=InitRalph.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InitRalph.js","sourceRoot":"","sources":["../../src/components/InitRalph.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"InitRalph.js","sourceRoot":"","sources":["../../src/components/InitRalph.tsx"],"names":[],"mappings":"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"}
@@ -1,17 +1,10 @@
1
1
  import React from "react";
2
+ import { type IterationRunnerProps } from "./IterationRunner.types.js";
2
3
  /**
3
- * Get the prompt content, falling back to templates if .ralph/prompt.md doesn't exist.
4
- * Uses the appropriate template based on the project setup:
5
- * - If .beads directory exists OR no .ralph/todo.md: use prompt-beads.md
6
- * - If .ralph/todo.md exists: use prompt-todos.md (todo-based workflow)
4
+ * Orchestrates the iterative execution of Claude AI iterations.
5
+ *
6
+ * Spawns Claude CLI with prompts, captures streaming output, displays formatted UI,
7
+ * and handles user input during iteration execution.
7
8
  */
8
- export declare const getPromptContent: () => string;
9
- export declare const IterationRunner: ({ totalIterations, claudeVersion, ralphVersion, watch }: Props) => React.JSX.Element;
10
- type Props = {
11
- totalIterations: number;
12
- claudeVersion: string;
13
- ralphVersion: string;
14
- watch?: boolean;
15
- };
16
- export {};
9
+ export declare const IterationRunner: ({ totalIterations, claudeVersion, ralphVersion, watch, agent, }: IterationRunnerProps) => React.JSX.Element;
17
10
  //# sourceMappingURL=IterationRunner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IterationRunner.d.ts","sourceRoot":"","sources":["../../src/components/IterationRunner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAsC1D;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAAO,MAiBnC,CAAA;AA0ID,eAAO,MAAM,eAAe,GAAI,yDAAyD,KAAK,sBAgjB7F,CAAA;AAED,KAAK,KAAK,GAAG;IACX,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA"}
1
+ {"version":3,"file":"IterationRunner.d.ts","sourceRoot":"","sources":["../../src/components/IterationRunner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAuB1D,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAcvF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,iEAM7B,oBAAoB,sBA0lBtB,CAAA"}
@@ -1,169 +1,39 @@
1
1
  import React, { useState, useEffect, useRef } from "react";
2
2
  import { Box, Text, useApp, Static, useInput } from "ink";
3
3
  import Spinner from "ink-spinner";
4
- import BigText from "ink-big-text";
5
- import Gradient from "ink-gradient";
6
4
  import { EnhancedTextInput } from "./EnhancedTextInput.js";
7
5
  import { appendFileSync, writeFileSync, readFileSync, existsSync } from "fs";
8
- import { join, dirname, basename } from "path";
9
- import { fileURLToPath } from "url";
10
- const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ import { join, basename } from "path";
11
7
  import { query } from "@anthropic-ai/claude-agent-sdk";
12
- import { Header } from "./Header.js";
13
- import { eventToBlocks } from "./eventToBlocks.js";
14
- import { formatContentBlock } from "../lib/formatContentBlock.js";
15
8
  import { addTodo } from "../lib/addTodo.js";
16
- import { getProgress, captureStartupSnapshot, } from "../lib/getProgress.js";
9
+ import { getProgress } from "../lib/getProgress.js";
10
+ import { captureStartupSnapshot } from "../lib/captureStartupSnapshot.js";
17
11
  import { ProgressBar } from "./ProgressBar.js";
18
12
  import { watchForNewIssues } from "../lib/beadsClient.js";
19
13
  import { MessageQueue, createUserMessage } from "../lib/MessageQueue.js";
20
14
  import { createDebugLogger } from "../lib/debug.js";
21
15
  import { useTerminalSize } from "../lib/useTerminalSize.js";
22
16
  import { getNextLogFile } from "../lib/getNextLogFile.js";
17
+ import { parseTaskLifecycleEvent } from "../lib/parseTaskLifecycle.js";
18
+ import { getPromptContent } from "../lib/getPromptContent.js";
19
+ import { sdkMessageToEvent } from "../lib/sdkMessageToEvent.js";
20
+ import { processEvents } from "../lib/processEvents.js";
21
+ import { renderStaticItem } from "./renderStaticItem.js";
22
+ /** Debug logger for iteration lifecycle events */
23
23
  const log = createDebugLogger("iteration");
24
+ /** The .ralph directory path in the current working directory */
24
25
  const ralphDir = join(process.cwd(), ".ralph");
25
- const promptFile = join(ralphDir, "prompt.md");
26
+ /** Path to the todo.md file in the .ralph directory */
26
27
  const todoFile = join(ralphDir, "todo.md");
27
- const beadsDir = join(process.cwd(), ".beads");
28
- const templatesDir = join(__dirname, "..", "..", "templates");
28
+ /** The name of the current repository (basename of cwd) */
29
29
  const repoName = basename(process.cwd());
30
30
  /**
31
- * Get the prompt content, falling back to templates if .ralph/prompt.md doesn't exist.
32
- * Uses the appropriate template based on the project setup:
33
- * - If .beads directory exists OR no .ralph/todo.md: use prompt-beads.md
34
- * - If .ralph/todo.md exists: use prompt-todos.md (todo-based workflow)
31
+ * Orchestrates the iterative execution of Claude AI iterations.
32
+ *
33
+ * Spawns Claude CLI with prompts, captures streaming output, displays formatted UI,
34
+ * and handles user input during iteration execution.
35
35
  */
36
- export const getPromptContent = () => {
37
- // First, try to read from .ralph/prompt.md
38
- if (existsSync(promptFile)) {
39
- return readFileSync(promptFile, "utf-8");
40
- }
41
- // Fall back to templates based on project setup
42
- const useBeadsTemplate = existsSync(beadsDir) || !existsSync(todoFile);
43
- const templateFile = useBeadsTemplate ? "prompt-beads.md" : "prompt-todos.md";
44
- const templatePath = join(templatesDir, templateFile);
45
- if (existsSync(templatePath)) {
46
- return readFileSync(templatePath, "utf-8");
47
- }
48
- // Last resort: return a minimal prompt
49
- return "Work on the highest-priority task.";
50
- };
51
- // Convert SDK message to event format for display
52
- const sdkMessageToEvent = (message) => {
53
- // Pass through messages that have the structure we expect
54
- if (message.type === "assistant" || message.type === "user" || message.type === "result") {
55
- return message;
56
- }
57
- // Skip system and stream_event messages for display
58
- return null;
59
- };
60
- // Process raw events into content blocks (moved from EventDisplay)
61
- // With includePartialMessages: true, we receive multiple snapshots of the same message
62
- // as it builds up. Each snapshot may contain different parts of the message content,
63
- // so we need to merge them and deduplicate.
64
- const processEvents = (events) => {
65
- const blocks = [];
66
- // First pass: collect all assistant message content and track message order
67
- const assistantEvents = events.filter(event => event.type === "assistant");
68
- // Collect all content blocks from all snapshots of the same message
69
- const messageMap = new Map();
70
- for (const event of assistantEvents) {
71
- const message = event.message;
72
- const messageId = message?.id;
73
- const content = message?.content;
74
- if (messageId && content) {
75
- if (!messageMap.has(messageId)) {
76
- messageMap.set(messageId, []);
77
- }
78
- messageMap.get(messageId).push(...content);
79
- }
80
- }
81
- // Create merged events with deduplicated content
82
- const mergedEvents = Array.from(messageMap.entries()).map(([messageId, allContent]) => {
83
- // Deduplicate content blocks by their ID (for tool_use) or text (for text blocks)
84
- const seenBlocks = new Set();
85
- const uniqueContent = [];
86
- for (const block of allContent) {
87
- const blockType = block.type;
88
- let blockKey;
89
- if (blockType === "tool_use") {
90
- // Tool use blocks are unique by their ID
91
- blockKey = `tool:${block.id}`;
92
- }
93
- else if (blockType === "text") {
94
- // For text blocks, check if this is a prefix of or prefixed by existing text
95
- // This handles incremental text updates where each snapshot has more content
96
- const text = block.text;
97
- let isDuplicate = false;
98
- for (const seenKey of seenBlocks) {
99
- if (seenKey.startsWith("text:")) {
100
- const seenText = seenKey.substring(5);
101
- // If existing text starts with this text, or this text starts with existing,
102
- // keep only the longer one
103
- if (seenText.startsWith(text)) {
104
- // Existing is longer, this is a duplicate
105
- isDuplicate = true;
106
- break;
107
- }
108
- else if (text.startsWith(seenText)) {
109
- // This is longer, remove the old one and add this
110
- seenBlocks.delete(seenKey);
111
- // Also remove from uniqueContent
112
- const idx = uniqueContent.findIndex(b => b.type === "text" && b.text === seenText);
113
- if (idx >= 0)
114
- uniqueContent.splice(idx, 1);
115
- break;
116
- }
117
- }
118
- }
119
- if (isDuplicate)
120
- continue;
121
- blockKey = `text:${text}`;
122
- }
123
- else {
124
- blockKey = JSON.stringify(block);
125
- }
126
- if (!seenBlocks.has(blockKey)) {
127
- seenBlocks.add(blockKey);
128
- uniqueContent.push(block);
129
- }
130
- }
131
- return {
132
- type: "assistant",
133
- message: {
134
- id: messageId,
135
- content: uniqueContent,
136
- },
137
- };
138
- });
139
- const assistantBlocks = mergedEvents.flatMap(event => eventToBlocks(event));
140
- // Second pass: process events in order, including user messages
141
- // Track which user messages and assistant messages we've already seen
142
- const processedUserIds = new Set();
143
- const processedAssistantIds = new Set();
144
- for (const event of events) {
145
- if (event.type === "user") {
146
- const message = event.message;
147
- const messageId = message?.id ?? `user-${Date.now()}`;
148
- if (!processedUserIds.has(messageId)) {
149
- processedUserIds.add(messageId);
150
- blocks.push(...eventToBlocks(event));
151
- }
152
- }
153
- else if (event.type === "assistant") {
154
- const message = event.message;
155
- const messageId = message?.id;
156
- if (messageId && !processedAssistantIds.has(messageId)) {
157
- processedAssistantIds.add(messageId);
158
- // Find the merged version of this message
159
- const merged = assistantBlocks.filter(b => b.id.startsWith(messageId));
160
- blocks.push(...merged);
161
- }
162
- }
163
- }
164
- return blocks;
165
- };
166
- export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion, watch }) => {
36
+ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion, watch, agent, }) => {
167
37
  const { exit } = useApp();
168
38
  const { columns } = useTerminalSize();
169
39
  const [currentIteration, setCurrentIteration] = useState(1);
@@ -192,6 +62,8 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
192
62
  const stopAfterCurrentRef = useRef(false); // Ref to access in async callbacks
193
63
  const [isPaused, setIsPaused] = useState(false); // Pause after current iteration completes
194
64
  const isPausedRef = useRef(false); // Ref to access in async callbacks
65
+ const [currentTaskId, setCurrentTaskId] = useState(null);
66
+ const [currentTaskTitle, setCurrentTaskTitle] = useState(null);
195
67
  // Track static items that have been rendered (for Ink's Static component)
196
68
  const [staticItems, setStaticItems] = useState([
197
69
  { type: "header", claudeVersion, ralphVersion, key: "header" },
@@ -202,10 +74,14 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
202
74
  const messageQueueRef = useRef(null);
203
75
  // Log file path for this run (set once at startup, persisted across iterations)
204
76
  const logFileRef = useRef(null);
205
- // Only use input handling if stdin supports raw mode
77
+ /** Whether stdin supports raw mode (required for keyboard input handling) */
206
78
  const stdinSupportsRawMode = process.stdin.isTTY === true;
207
- // Handle Ctrl-T to add a new todo
208
- const handleTodoSubmit = (text) => {
79
+ /**
80
+ * Handle adding a new todo when Ctrl-T is pressed.
81
+ */
82
+ const handleTodoSubmit = (
83
+ /** The todo text to add */
84
+ text) => {
209
85
  const trimmed = text.trim();
210
86
  if (!trimmed) {
211
87
  setIsAddingTodo(false);
@@ -231,8 +107,12 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
231
107
  setTimeout(() => setTodoMessage(null), 5000);
232
108
  }
233
109
  };
234
- // Handle submitting a user message to Claude
235
- const handleUserMessageSubmit = (text) => {
110
+ /**
111
+ * Handle submitting a user message to Claude during iteration.
112
+ */
113
+ const handleUserMessageSubmit = (
114
+ /** The message text from the user */
115
+ text) => {
236
116
  const trimmed = text.trim();
237
117
  if (!trimmed) {
238
118
  setUserMessageText("");
@@ -264,8 +144,14 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
264
144
  // Clear status message after 3 seconds
265
145
  setTimeout(() => setUserMessageStatus(null), 3000);
266
146
  };
267
- // Handle keyboard input for Ctrl-T (todo), Ctrl-S (stop), and Escape (cancel todo input)
268
- useInput((input, key) => {
147
+ /**
148
+ * Handle keyboard input for Ctrl-T (todo), Ctrl-S (stop), Ctrl-P (pause), and Escape (cancel).
149
+ */
150
+ useInput((
151
+ /** The input character */
152
+ input,
153
+ /** The key information including modifiers */
154
+ key) => {
269
155
  // Ctrl-T to start adding a todo (only if todo.md exists)
270
156
  if (key.ctrl && input === "t" && hasTodoFile) {
271
157
  setIsAddingTodo(true);
@@ -430,6 +316,9 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
430
316
  messageQueueRef.current = messageQueue;
431
317
  // Push the initial prompt as the first message
432
318
  messageQueue.push(createUserMessage(fullPrompt));
319
+ /**
320
+ * Execute a query to Claude and handle the streaming response.
321
+ */
433
322
  const runQuery = async () => {
434
323
  let finalResult = "";
435
324
  log(`Starting iteration ${currentIteration}`);
@@ -446,6 +335,8 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
446
335
  ...process.env,
447
336
  // Disable LSP plugins to avoid crashes when TypeScript LSP server errors
448
337
  ENABLE_LSP_TOOL: "0",
338
+ // Signal that tests should use minimal reporters (dots)
339
+ RALPH_QUIET: "1",
449
340
  },
450
341
  },
451
342
  })) {
@@ -457,6 +348,45 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
457
348
  if (event) {
458
349
  setEvents(prev => [...prev, event]);
459
350
  }
351
+ // Check for task lifecycle events in assistant messages
352
+ if (message.type === "assistant") {
353
+ const assistantMessage = message.message;
354
+ const content = assistantMessage?.content;
355
+ if (content) {
356
+ for (const block of content) {
357
+ if (block.type === "text" && typeof block.text === "string") {
358
+ const taskInfo = parseTaskLifecycleEvent(block.text);
359
+ if (taskInfo) {
360
+ if (taskInfo.action === "starting") {
361
+ setCurrentTaskId(taskInfo.taskId ?? null);
362
+ setCurrentTaskTitle(taskInfo.taskTitle ?? null);
363
+ log(`Task started: ${taskInfo.taskId}${taskInfo.taskTitle ? ` - ${taskInfo.taskTitle}` : ""}`);
364
+ // Emit ralph_task_started event to log file
365
+ const taskStartedEvent = {
366
+ type: "ralph_task_started",
367
+ taskId: taskInfo.taskId,
368
+ taskTitle: taskInfo.taskTitle,
369
+ iteration: currentIteration,
370
+ };
371
+ appendFileSync(logFile, JSON.stringify(taskStartedEvent) + "\n");
372
+ }
373
+ else if (taskInfo.action === "completed") {
374
+ log(`Task completed: ${taskInfo.taskId}${taskInfo.taskTitle ? ` - ${taskInfo.taskTitle}` : ""}`);
375
+ // Emit ralph_task_completed event to log file
376
+ const taskCompletedEvent = {
377
+ type: "ralph_task_completed",
378
+ taskId: taskInfo.taskId,
379
+ taskTitle: taskInfo.taskTitle,
380
+ iteration: currentIteration,
381
+ };
382
+ appendFileSync(logFile, JSON.stringify(taskCompletedEvent) + "\n");
383
+ // Keep tracking the same task until a new one starts
384
+ }
385
+ }
386
+ }
387
+ }
388
+ }
389
+ }
460
390
  // Capture the final result message
461
391
  if (message.type === "result" &&
462
392
  "result" in message &&
@@ -536,20 +466,6 @@ export const IterationRunner = ({ totalIterations, claudeVersion, ralphVersion,
536
466
  return (React.createElement(Box, { flexDirection: "column" },
537
467
  React.createElement(Text, { color: "red" }, error)));
538
468
  }
539
- // Render a static item (header, iteration header, or content block)
540
- const renderStaticItem = (item) => {
541
- if (item.type === "header") {
542
- return React.createElement(Header, { claudeVersion: item.claudeVersion, ralphVersion: item.ralphVersion });
543
- }
544
- if (item.type === "iteration") {
545
- return (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
546
- React.createElement(Gradient, { colors: ["#30A6E4", "#EBC635"] },
547
- React.createElement(BigText, { text: `R${item.iteration}`, font: "tiny" }))));
548
- }
549
- // Content block
550
- const lines = formatContentBlock(item.block);
551
- return (React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, lines.map((line, i) => (React.createElement(Text, { key: i }, line || " ")))));
552
- };
553
469
  return (React.createElement(Box, { flexDirection: "column" },
554
470
  React.createElement(Static, { items: staticItems }, item => (React.createElement(Box, { key: item.key, flexDirection: "column" }, renderStaticItem(item)))),
555
471
  isAddingTodo && (React.createElement(Box, { flexDirection: "column", marginTop: 1 },