rafcode 1.0.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 (370) hide show
  1. package/.claude/settings.local.json +32 -0
  2. package/CLAUDE.md +187 -0
  3. package/LICENSE +21 -0
  4. package/RAF/001-raf-task-improvements/input.md +9 -0
  5. package/RAF/001-raf-task-improvements/outcomes/001-add-decisions-folder.md +21 -0
  6. package/RAF/001-raf-task-improvements/outcomes/002-fix-write-error-on-shutdown.md +22 -0
  7. package/RAF/001-raf-task-improvements/outcomes/003-stash-changes-on-failure.md +34 -0
  8. package/RAF/001-raf-task-improvements/outcomes/004-add-project-name-to-commits.md +28 -0
  9. package/RAF/001-raf-task-improvements/outcomes/005-add-running-time-display.md +36 -0
  10. package/RAF/001-raf-task-improvements/outcomes/006-add-task-name-to-logs.md +22 -0
  11. package/RAF/001-raf-task-improvements/outcomes/007-show-model-at-task-start.md +52 -0
  12. package/RAF/001-raf-task-improvements/outcomes/009-remove-editor-placeholder-text.md +20 -0
  13. package/RAF/001-raf-task-improvements/outcomes/SUMMARY.md +83 -0
  14. package/RAF/001-raf-task-improvements/plans/001-add-decisions-folder.md +38 -0
  15. package/RAF/001-raf-task-improvements/plans/002-fix-write-error-on-shutdown.md +33 -0
  16. package/RAF/001-raf-task-improvements/plans/003-stash-changes-on-failure.md +37 -0
  17. package/RAF/001-raf-task-improvements/plans/004-add-project-name-to-commits.md +34 -0
  18. package/RAF/001-raf-task-improvements/plans/005-add-running-time-display.md +39 -0
  19. package/RAF/001-raf-task-improvements/plans/006-add-task-name-to-logs.md +37 -0
  20. package/RAF/001-raf-task-improvements/plans/009-remove-editor-placeholder-text.md +34 -0
  21. package/RAF/002-raf-task-improvements-execution/decisions/DECISIONS.md +13 -0
  22. package/RAF/002-raf-task-improvements-execution/input.md +3 -0
  23. package/RAF/002-raf-task-improvements-execution/outcomes/001-commit-show-model-at-task-start.md +17 -0
  24. package/RAF/002-raf-task-improvements-execution/outcomes/002-delete-skipped-plan.md +23 -0
  25. package/RAF/002-raf-task-improvements-execution/outcomes/SUMMARY.md +32 -0
  26. package/RAF/002-raf-task-improvements-execution/plans/001-commit-show-model-at-task-start.md +37 -0
  27. package/RAF/002-raf-task-improvements-execution/plans/002-delete-skipped-plan.md +23 -0
  28. package/RAF/003-multi-project-execution/decisions/DECISIONS.md +68 -0
  29. package/RAF/003-multi-project-execution/input.md +6 -0
  30. package/RAF/003-multi-project-execution/outcomes/001-remove-state-json.md +52 -0
  31. package/RAF/003-multi-project-execution/outcomes/002-update-raf-status.md +50 -0
  32. package/RAF/003-multi-project-execution/outcomes/003-simplify-git-logic.md +35 -0
  33. package/RAF/003-multi-project-execution/outcomes/004-auto-commit-planning.md +43 -0
  34. package/RAF/003-multi-project-execution/outcomes/005-rerun-failed-tasks.md +43 -0
  35. package/RAF/003-multi-project-execution/outcomes/006-multi-project-execution.md +42 -0
  36. package/RAF/003-multi-project-execution/outcomes/007-verify-timeout.md +54 -0
  37. package/RAF/003-multi-project-execution/outcomes/008-move-decisions-file.md +38 -0
  38. package/RAF/003-multi-project-execution/outcomes/SUMMARY.md +79 -0
  39. package/RAF/003-multi-project-execution/plans/001-remove-state-json.md +71 -0
  40. package/RAF/003-multi-project-execution/plans/002-update-raf-status.md +65 -0
  41. package/RAF/003-multi-project-execution/plans/003-simplify-git-logic.md +74 -0
  42. package/RAF/003-multi-project-execution/plans/004-auto-commit-planning.md +57 -0
  43. package/RAF/003-multi-project-execution/plans/005-rerun-failed-tasks.md +69 -0
  44. package/RAF/003-multi-project-execution/plans/006-multi-project-execution.md +81 -0
  45. package/RAF/003-multi-project-execution/plans/007-verify-timeout.md +63 -0
  46. package/RAF/003-multi-project-execution/plans/008-move-decisions-file.md +78 -0
  47. package/RAF/004-task-naming-optimization/decisions.md +22 -0
  48. package/RAF/004-task-naming-optimization/input.md +6 -0
  49. package/RAF/004-task-naming-optimization/outcomes/001-remove-summary-file.md +17 -0
  50. package/RAF/004-task-naming-optimization/outcomes/002-base36-project-numbering.md +32 -0
  51. package/RAF/004-task-naming-optimization/outcomes/003-improve-haiku-prompt.md +20 -0
  52. package/RAF/004-task-naming-optimization/outcomes/SUMMARY.md +28 -0
  53. package/RAF/004-task-naming-optimization/plans/001-remove-summary-file.md +34 -0
  54. package/RAF/004-task-naming-optimization/plans/002-base36-project-numbering.md +56 -0
  55. package/RAF/004-task-naming-optimization/plans/003-improve-haiku-prompt.md +50 -0
  56. package/RAF/005-task-naming-improvements/decisions.md +60 -0
  57. package/RAF/005-task-naming-improvements/input.md +2 -0
  58. package/RAF/005-task-naming-improvements/outcomes/001-enhance-identifier-resolution.md +42 -0
  59. package/RAF/005-task-naming-improvements/outcomes/002-add-identifier-support-to-status.md +38 -0
  60. package/RAF/005-task-naming-improvements/outcomes/003-update-do-for-full-folder-names.md +44 -0
  61. package/RAF/005-task-naming-improvements/outcomes/004-implement-amend-flag-for-plan.md +55 -0
  62. package/RAF/005-task-naming-improvements/outcomes/005-commit-outcomes-on-complete.md +47 -0
  63. package/RAF/005-task-naming-improvements/outcomes/006-update-execution-prompt-commit-schema.md +40 -0
  64. package/RAF/005-task-naming-improvements/outcomes/007-allow-pending-task-amendments.md +38 -0
  65. package/RAF/005-task-naming-improvements/outcomes/008-fix-timeout-label.md +24 -0
  66. package/RAF/005-task-naming-improvements/plans/001-enhance-identifier-resolution.md +46 -0
  67. package/RAF/005-task-naming-improvements/plans/002-add-identifier-support-to-status.md +36 -0
  68. package/RAF/005-task-naming-improvements/plans/003-update-do-for-full-folder-names.md +38 -0
  69. package/RAF/005-task-naming-improvements/plans/004-implement-amend-flag-for-plan.md +67 -0
  70. package/RAF/005-task-naming-improvements/plans/005-commit-outcomes-on-complete.md +86 -0
  71. package/RAF/005-task-naming-improvements/plans/006-update-execution-prompt-commit-schema.md +60 -0
  72. package/RAF/005-task-naming-improvements/plans/007-allow-pending-task-amendments.md +60 -0
  73. package/RAF/005-task-naming-improvements/plans/008-fix-timeout-label.md +31 -0
  74. package/RAF/006-fix-double-summary-headers/decisions.md +28 -0
  75. package/RAF/006-fix-double-summary-headers/input.md +3 -0
  76. package/RAF/006-fix-double-summary-headers/outcomes/001-fix-double-summary-headers.md +29 -0
  77. package/RAF/006-fix-double-summary-headers/outcomes/002-update-readme-for-npm.md +31 -0
  78. package/RAF/006-fix-double-summary-headers/outcomes/003-npm-publish-instructions.md +30 -0
  79. package/RAF/006-fix-double-summary-headers/outcomes/004-flexible-project-lookup.md +47 -0
  80. package/RAF/006-fix-double-summary-headers/plans/001-fix-double-summary-headers.md +42 -0
  81. package/RAF/006-fix-double-summary-headers/plans/002-update-readme-for-npm.md +44 -0
  82. package/RAF/006-fix-double-summary-headers/plans/003-npm-publish-instructions.md +45 -0
  83. package/RAF/006-fix-double-summary-headers/plans/004-flexible-project-lookup.md +40 -0
  84. package/RAF/007-improve-outcome-format/decisions.md +28 -0
  85. package/RAF/007-improve-outcome-format/input.md +2 -0
  86. package/RAF/007-improve-outcome-format/outcomes/001-update-execution-prompt.md +10 -0
  87. package/RAF/007-improve-outcome-format/outcomes/002-update-state-derivation.md +17 -0
  88. package/RAF/007-improve-outcome-format/outcomes/003-update-do-command-outcome-handling.md +16 -0
  89. package/RAF/007-improve-outcome-format/outcomes/004-implement-failure-analysis.md +16 -0
  90. package/RAF/007-improve-outcome-format/outcomes/005-update-documentation.md +15 -0
  91. package/RAF/007-improve-outcome-format/plans/001-update-execution-prompt.md +36 -0
  92. package/RAF/007-improve-outcome-format/plans/002-update-state-derivation.md +35 -0
  93. package/RAF/007-improve-outcome-format/plans/003-update-do-command-outcome-handling.md +37 -0
  94. package/RAF/007-improve-outcome-format/plans/004-implement-failure-analysis.md +44 -0
  95. package/RAF/007-improve-outcome-format/plans/005-update-documentation.md +33 -0
  96. package/RAF/008-beautiful-do/decisions.md +31 -0
  97. package/RAF/008-beautiful-do/input.md +1 -0
  98. package/RAF/008-beautiful-do/outcomes/001-terminal-symbols.md +55 -0
  99. package/RAF/008-beautiful-do/outcomes/002-refactor-do-output.md +95 -0
  100. package/RAF/008-beautiful-do/outcomes/003-refactor-status-output.md +71 -0
  101. package/RAF/008-beautiful-do/outcomes/004-simplify-logger.md +53 -0
  102. package/RAF/008-beautiful-do/outcomes/005-add-tests.md +41 -0
  103. package/RAF/008-beautiful-do/plans/001-terminal-symbols.md +41 -0
  104. package/RAF/008-beautiful-do/plans/002-refactor-do-output.md +44 -0
  105. package/RAF/008-beautiful-do/plans/003-refactor-status-output.md +37 -0
  106. package/RAF/008-beautiful-do/plans/004-simplify-logger.md +32 -0
  107. package/RAF/008-beautiful-do/plans/005-add-tests.md +40 -0
  108. package/RAF/009-system-promt-ammend/decisions.md +13 -0
  109. package/RAF/009-system-promt-ammend/input.md +9 -0
  110. package/RAF/009-system-promt-ammend/outcomes/001-model-override.md +79 -0
  111. package/RAF/009-system-promt-ammend/outcomes/002-system-prompt-append.md +51 -0
  112. package/RAF/009-system-promt-ammend/outcomes/003-retry-context.md +60 -0
  113. package/RAF/009-system-promt-ammend/plans/001-model-override.md +61 -0
  114. package/RAF/009-system-promt-ammend/plans/002-system-prompt-append.md +56 -0
  115. package/RAF/009-system-promt-ammend/plans/003-retry-context.md +76 -0
  116. package/RAF/010-outcome-marker-fallback/decisions.md +19 -0
  117. package/RAF/010-outcome-marker-fallback/input.md +1 -0
  118. package/RAF/010-outcome-marker-fallback/outcomes/001-outcome-file-marker-fallback.md +35 -0
  119. package/RAF/010-outcome-marker-fallback/outcomes/002-creative-project-naming.md +47 -0
  120. package/RAF/010-outcome-marker-fallback/plans/001-outcome-file-marker-fallback.md +58 -0
  121. package/RAF/010-outcome-marker-fallback/plans/002-creative-project-naming.md +68 -0
  122. package/RAF/011-do-task-in-commit/decisions.md +22 -0
  123. package/RAF/011-do-task-in-commit/input.md +1 -0
  124. package/RAF/011-do-task-in-commit/outcomes/001-update-execution-prompt.md +54 -0
  125. package/RAF/011-do-task-in-commit/outcomes/002-update-tests.md +61 -0
  126. package/RAF/011-do-task-in-commit/outcomes/003-update-documentation.md +51 -0
  127. package/RAF/011-do-task-in-commit/plans/001-update-execution-prompt.md +46 -0
  128. package/RAF/011-do-task-in-commit/plans/002-update-tests.md +51 -0
  129. package/RAF/011-do-task-in-commit/plans/003-update-documentation.md +45 -0
  130. package/RAF/012-name-picker-buffet/decisions.md +40 -0
  131. package/RAF/012-name-picker-buffet/input.md +6 -0
  132. package/RAF/012-name-picker-buffet/outcomes/001-name-picker-for-raf-plan.md +49 -0
  133. package/RAF/012-name-picker-buffet/outcomes/002-interactive-project-picker-for-raf-do.md +49 -0
  134. package/RAF/012-name-picker-buffet/outcomes/003-raf-status-truncation.md +55 -0
  135. package/RAF/012-name-picker-buffet/outcomes/004-failure-reason-details.md +65 -0
  136. package/RAF/012-name-picker-buffet/outcomes/005-remove-raf-commits.md +57 -0
  137. package/RAF/012-name-picker-buffet/outcomes/006-update-execution-prompt-for-commits.md +47 -0
  138. package/RAF/012-name-picker-buffet/outcomes/007-fix-plan-mode-user-prompt.md +83 -0
  139. package/RAF/012-name-picker-buffet/outcomes/008-add-auto-flag-for-plan-mode.md +77 -0
  140. package/RAF/012-name-picker-buffet/plans/001-name-picker-for-raf-plan.md +47 -0
  141. package/RAF/012-name-picker-buffet/plans/002-interactive-project-picker-for-raf-do.md +43 -0
  142. package/RAF/012-name-picker-buffet/plans/003-raf-status-truncation.md +36 -0
  143. package/RAF/012-name-picker-buffet/plans/004-failure-reason-details.md +46 -0
  144. package/RAF/012-name-picker-buffet/plans/005-remove-raf-commits.md +42 -0
  145. package/RAF/012-name-picker-buffet/plans/006-update-execution-prompt-for-commits.md +47 -0
  146. package/RAF/012-name-picker-buffet/plans/007-fix-plan-mode-user-prompt.md +55 -0
  147. package/RAF/012-name-picker-buffet/plans/008-add-auto-flag-for-plan-mode.md +49 -0
  148. package/RAF/013-dependencies-watchdog/decisions.md +37 -0
  149. package/RAF/013-dependencies-watchdog/input.md +1 -0
  150. package/RAF/013-dependencies-watchdog/outcomes/001-define-dependency-syntax.md +56 -0
  151. package/RAF/013-dependencies-watchdog/outcomes/002-update-planning-prompts.md +60 -0
  152. package/RAF/013-dependencies-watchdog/outcomes/003-parse-dependencies-update-state.md +81 -0
  153. package/RAF/013-dependencies-watchdog/outcomes/004-implement-dependency-checking-in-do.md +116 -0
  154. package/RAF/013-dependencies-watchdog/outcomes/005-update-execution-prompts.md +75 -0
  155. package/RAF/013-dependencies-watchdog/outcomes/006-add-tests.md +100 -0
  156. package/RAF/013-dependencies-watchdog/outcomes/007-add-act-alias.md +46 -0
  157. package/RAF/013-dependencies-watchdog/outcomes/008-add-exit-message.md +52 -0
  158. package/RAF/013-dependencies-watchdog/plans/001-define-dependency-syntax.md +32 -0
  159. package/RAF/013-dependencies-watchdog/plans/002-update-planning-prompts.md +38 -0
  160. package/RAF/013-dependencies-watchdog/plans/003-parse-dependencies-update-state.md +46 -0
  161. package/RAF/013-dependencies-watchdog/plans/004-implement-dependency-checking-in-do.md +48 -0
  162. package/RAF/013-dependencies-watchdog/plans/005-update-execution-prompts.md +44 -0
  163. package/RAF/013-dependencies-watchdog/plans/006-add-tests.md +54 -0
  164. package/RAF/013-dependencies-watchdog/plans/007-add-act-alias.md +26 -0
  165. package/RAF/013-dependencies-watchdog/plans/008-add-exit-message.md +31 -0
  166. package/RAF/014-watchdog/decisions.md +16 -0
  167. package/RAF/014-watchdog/input.md +2 -0
  168. package/RAF/014-watchdog/outcomes/001-amend-flag-position.md +50 -0
  169. package/RAF/014-watchdog/outcomes/002-details-only-on-failure.md +58 -0
  170. package/RAF/014-watchdog/plans/001-amend-flag-position.md +34 -0
  171. package/RAF/014-watchdog/plans/002-details-only-on-failure.md +46 -0
  172. package/RAF/015-name-lottery/decisions.md +14 -0
  173. package/RAF/015-name-lottery/input.md +3 -0
  174. package/RAF/015-name-lottery/outcomes/001-auto-pick-project-name.md +31 -0
  175. package/RAF/015-name-lottery/outcomes/002-mention-plan-files-in-commit.md +23 -0
  176. package/RAF/015-name-lottery/outcomes/003-fix-input-md-in-amend-flow.md +44 -0
  177. package/RAF/015-name-lottery/plans/001-auto-pick-project-name.md +38 -0
  178. package/RAF/015-name-lottery/plans/002-mention-plan-files-in-commit.md +32 -0
  179. package/RAF/015-name-lottery/plans/003-fix-input-md-in-amend-flow.md +44 -0
  180. package/README.md +116 -0
  181. package/dist/commands/do.d.ts +12 -0
  182. package/dist/commands/do.d.ts.map +1 -0
  183. package/dist/commands/do.js +684 -0
  184. package/dist/commands/do.js.map +1 -0
  185. package/dist/commands/plan.d.ts +3 -0
  186. package/dist/commands/plan.d.ts.map +1 -0
  187. package/dist/commands/plan.js +345 -0
  188. package/dist/commands/plan.js.map +1 -0
  189. package/dist/commands/status.d.ts +3 -0
  190. package/dist/commands/status.d.ts.map +1 -0
  191. package/dist/commands/status.js +117 -0
  192. package/dist/commands/status.js.map +1 -0
  193. package/dist/core/claude-runner.d.ts +78 -0
  194. package/dist/core/claude-runner.d.ts.map +1 -0
  195. package/dist/core/claude-runner.js +297 -0
  196. package/dist/core/claude-runner.js.map +1 -0
  197. package/dist/core/editor.d.ts +10 -0
  198. package/dist/core/editor.d.ts.map +1 -0
  199. package/dist/core/editor.js +77 -0
  200. package/dist/core/editor.js.map +1 -0
  201. package/dist/core/failure-analyzer.d.ts +28 -0
  202. package/dist/core/failure-analyzer.d.ts.map +1 -0
  203. package/dist/core/failure-analyzer.js +305 -0
  204. package/dist/core/failure-analyzer.js.map +1 -0
  205. package/dist/core/git.d.ts +42 -0
  206. package/dist/core/git.d.ts.map +1 -0
  207. package/dist/core/git.js +148 -0
  208. package/dist/core/git.js.map +1 -0
  209. package/dist/core/project-manager.d.ts +72 -0
  210. package/dist/core/project-manager.d.ts.map +1 -0
  211. package/dist/core/project-manager.js +193 -0
  212. package/dist/core/project-manager.js.map +1 -0
  213. package/dist/core/retry-handler.d.ts +19 -0
  214. package/dist/core/retry-handler.d.ts.map +1 -0
  215. package/dist/core/retry-handler.js +51 -0
  216. package/dist/core/retry-handler.js.map +1 -0
  217. package/dist/core/shutdown-handler.d.ts +30 -0
  218. package/dist/core/shutdown-handler.d.ts.map +1 -0
  219. package/dist/core/shutdown-handler.js +79 -0
  220. package/dist/core/shutdown-handler.js.map +1 -0
  221. package/dist/core/state-derivation.d.ts +82 -0
  222. package/dist/core/state-derivation.d.ts.map +1 -0
  223. package/dist/core/state-derivation.js +271 -0
  224. package/dist/core/state-derivation.js.map +1 -0
  225. package/dist/core/state-manager.d.ts +54 -0
  226. package/dist/core/state-manager.d.ts.map +1 -0
  227. package/dist/core/state-manager.js +198 -0
  228. package/dist/core/state-manager.js.map +1 -0
  229. package/dist/index.d.ts +3 -0
  230. package/dist/index.d.ts.map +1 -0
  231. package/dist/index.js +16 -0
  232. package/dist/index.js.map +1 -0
  233. package/dist/parsers/output-parser.d.ts +19 -0
  234. package/dist/parsers/output-parser.d.ts.map +1 -0
  235. package/dist/parsers/output-parser.js +137 -0
  236. package/dist/parsers/output-parser.js.map +1 -0
  237. package/dist/prompts/amend.d.ts +20 -0
  238. package/dist/prompts/amend.d.ts.map +1 -0
  239. package/dist/prompts/amend.js +166 -0
  240. package/dist/prompts/amend.js.map +1 -0
  241. package/dist/prompts/execution.d.ts +30 -0
  242. package/dist/prompts/execution.d.ts.map +1 -0
  243. package/dist/prompts/execution.js +179 -0
  244. package/dist/prompts/execution.js.map +1 -0
  245. package/dist/prompts/planning.d.ts +15 -0
  246. package/dist/prompts/planning.d.ts.map +1 -0
  247. package/dist/prompts/planning.js +163 -0
  248. package/dist/prompts/planning.js.map +1 -0
  249. package/dist/types/config.d.ts +26 -0
  250. package/dist/types/config.d.ts.map +1 -0
  251. package/dist/types/config.js +7 -0
  252. package/dist/types/config.js.map +1 -0
  253. package/dist/types/state.d.ts +33 -0
  254. package/dist/types/state.d.ts.map +1 -0
  255. package/dist/types/state.js +28 -0
  256. package/dist/types/state.js.map +1 -0
  257. package/dist/ui/name-picker-subprocess.d.ts +11 -0
  258. package/dist/ui/name-picker-subprocess.d.ts.map +1 -0
  259. package/dist/ui/name-picker-subprocess.js +83 -0
  260. package/dist/ui/name-picker-subprocess.js.map +1 -0
  261. package/dist/ui/name-picker.d.ts +19 -0
  262. package/dist/ui/name-picker.d.ts.map +1 -0
  263. package/dist/ui/name-picker.js +173 -0
  264. package/dist/ui/name-picker.js.map +1 -0
  265. package/dist/ui/project-picker.d.ts +27 -0
  266. package/dist/ui/project-picker.d.ts.map +1 -0
  267. package/dist/ui/project-picker.js +58 -0
  268. package/dist/ui/project-picker.js.map +1 -0
  269. package/dist/utils/config.d.ts +24 -0
  270. package/dist/utils/config.d.ts.map +1 -0
  271. package/dist/utils/config.js +63 -0
  272. package/dist/utils/config.js.map +1 -0
  273. package/dist/utils/logger.d.ts +32 -0
  274. package/dist/utils/logger.d.ts.map +1 -0
  275. package/dist/utils/logger.js +60 -0
  276. package/dist/utils/logger.js.map +1 -0
  277. package/dist/utils/name-generator.d.ts +20 -0
  278. package/dist/utils/name-generator.d.ts.map +1 -0
  279. package/dist/utils/name-generator.js +183 -0
  280. package/dist/utils/name-generator.js.map +1 -0
  281. package/dist/utils/paths.d.ts +132 -0
  282. package/dist/utils/paths.d.ts.map +1 -0
  283. package/dist/utils/paths.js +412 -0
  284. package/dist/utils/paths.js.map +1 -0
  285. package/dist/utils/status-line.d.ts +14 -0
  286. package/dist/utils/status-line.d.ts.map +1 -0
  287. package/dist/utils/status-line.js +36 -0
  288. package/dist/utils/status-line.js.map +1 -0
  289. package/dist/utils/terminal-symbols.d.ts +50 -0
  290. package/dist/utils/terminal-symbols.d.ts.map +1 -0
  291. package/dist/utils/terminal-symbols.js +97 -0
  292. package/dist/utils/terminal-symbols.js.map +1 -0
  293. package/dist/utils/timer.d.ts +17 -0
  294. package/dist/utils/timer.d.ts.map +1 -0
  295. package/dist/utils/timer.js +56 -0
  296. package/dist/utils/timer.js.map +1 -0
  297. package/dist/utils/validation.d.ts +17 -0
  298. package/dist/utils/validation.d.ts.map +1 -0
  299. package/dist/utils/validation.js +106 -0
  300. package/dist/utils/validation.js.map +1 -0
  301. package/dist/utils/version.d.ts +2 -0
  302. package/dist/utils/version.d.ts.map +1 -0
  303. package/dist/utils/version.js +12 -0
  304. package/dist/utils/version.js.map +1 -0
  305. package/jest.config.ts +30 -0
  306. package/package.json +55 -0
  307. package/src/commands/do.ts +829 -0
  308. package/src/commands/plan.ts +422 -0
  309. package/src/commands/status.ts +146 -0
  310. package/src/core/claude-runner.ts +374 -0
  311. package/src/core/editor.ts +85 -0
  312. package/src/core/failure-analyzer.ts +372 -0
  313. package/src/core/git.ts +166 -0
  314. package/src/core/project-manager.ts +243 -0
  315. package/src/core/retry-handler.ts +72 -0
  316. package/src/core/shutdown-handler.ts +93 -0
  317. package/src/core/state-derivation.ts +343 -0
  318. package/src/index.ts +20 -0
  319. package/src/parsers/output-parser.ts +164 -0
  320. package/src/prompts/amend.ts +194 -0
  321. package/src/prompts/execution.ts +223 -0
  322. package/src/prompts/planning.ts +175 -0
  323. package/src/types/config.ts +35 -0
  324. package/src/ui/name-picker-subprocess.ts +96 -0
  325. package/src/ui/name-picker.ts +198 -0
  326. package/src/ui/project-picker.ts +80 -0
  327. package/src/utils/config.ts +69 -0
  328. package/src/utils/logger.ts +81 -0
  329. package/src/utils/name-generator.ts +211 -0
  330. package/src/utils/paths.ts +497 -0
  331. package/src/utils/status-line.ts +45 -0
  332. package/src/utils/terminal-symbols.ts +124 -0
  333. package/src/utils/timer.ts +64 -0
  334. package/src/utils/validation.ts +132 -0
  335. package/src/utils/version.ts +12 -0
  336. package/tests/unit/claude-runner-interactive.test.ts +343 -0
  337. package/tests/unit/claude-runner.test.ts +629 -0
  338. package/tests/unit/command-output.test.ts +295 -0
  339. package/tests/unit/config.test.ts +72 -0
  340. package/tests/unit/dependency-integration.test.ts +559 -0
  341. package/tests/unit/do-blocked-tasks.test.ts +323 -0
  342. package/tests/unit/do-command.test.ts +198 -0
  343. package/tests/unit/do-multiproject.test.ts +270 -0
  344. package/tests/unit/do-rerun.test.ts +270 -0
  345. package/tests/unit/execution-prompt.test.ts +406 -0
  346. package/tests/unit/failure-analyzer.test.ts +276 -0
  347. package/tests/unit/failure-history.test.ts +143 -0
  348. package/tests/unit/git-stash.test.ts +138 -0
  349. package/tests/unit/git.test.ts +80 -0
  350. package/tests/unit/logger.test.ts +132 -0
  351. package/tests/unit/name-generator.test.ts +283 -0
  352. package/tests/unit/name-picker.test.ts +179 -0
  353. package/tests/unit/outcome-content.test.ts +166 -0
  354. package/tests/unit/output-parser.test.ts +178 -0
  355. package/tests/unit/paths.test.ts +741 -0
  356. package/tests/unit/plan-command-amend-flag.test.ts +115 -0
  357. package/tests/unit/plan-command-amend-input.test.ts +156 -0
  358. package/tests/unit/plan-command-auto-flag.test.ts +112 -0
  359. package/tests/unit/plan-command.test.ts +580 -0
  360. package/tests/unit/planning-prompt.test.ts +137 -0
  361. package/tests/unit/project-manager.test.ts +265 -0
  362. package/tests/unit/project-picker.test.ts +338 -0
  363. package/tests/unit/retry-handler.test.ts +89 -0
  364. package/tests/unit/state-derivation.test.ts +714 -0
  365. package/tests/unit/status-command.test.ts +271 -0
  366. package/tests/unit/status-line.test.ts +92 -0
  367. package/tests/unit/terminal-symbols.test.ts +214 -0
  368. package/tests/unit/timer.test.ts +102 -0
  369. package/tests/unit/validation.test.ts +118 -0
  370. package/tsconfig.json +26 -0
@@ -0,0 +1,374 @@
1
+ import * as pty from 'node-pty';
2
+ import { execSync, spawn } from 'node:child_process';
3
+ import { logger } from '../utils/logger.js';
4
+
5
+ function getClaudePath(): string {
6
+ try {
7
+ return execSync('which claude', { encoding: 'utf-8' }).trim();
8
+ } catch {
9
+ throw new Error('Claude CLI not found. Please ensure it is installed and in your PATH.');
10
+ }
11
+ }
12
+
13
+ export interface ClaudeRunnerOptions {
14
+ /**
15
+ * Timeout in minutes for this single execution.
16
+ * Default: 60 minutes.
17
+ * Each call to run() or runVerbose() gets its own fresh timeout.
18
+ * Retries get a fresh timeout - elapsed time is NOT accumulated across attempts.
19
+ */
20
+ timeout?: number;
21
+ cwd?: string;
22
+ /**
23
+ * Skip Claude's permission prompts for file operations.
24
+ * Only used in interactive mode (runInteractive).
25
+ * Claude will still ask planning interview questions.
26
+ */
27
+ dangerouslySkipPermissions?: boolean;
28
+ }
29
+
30
+ export interface ClaudeRunnerConfig {
31
+ /**
32
+ * Claude model to use (sonnet, haiku, opus).
33
+ * Default: opus.
34
+ */
35
+ model?: string;
36
+ }
37
+
38
+ export interface RunResult {
39
+ output: string;
40
+ exitCode: number;
41
+ timedOut: boolean;
42
+ contextOverflow: boolean;
43
+ }
44
+
45
+ const CONTEXT_OVERFLOW_PATTERNS = [
46
+ /context length exceeded/i,
47
+ /token limit/i,
48
+ /maximum context/i,
49
+ /context window/i,
50
+ ];
51
+
52
+ export class ClaudeRunner {
53
+ private activeProcess: pty.IPty | null = null;
54
+ private killed = false;
55
+ private model: string;
56
+
57
+ constructor(config: ClaudeRunnerConfig = {}) {
58
+ this.model = config.model ?? 'opus';
59
+ }
60
+
61
+ /**
62
+ * Run Claude interactively with stdin/stdout passthrough.
63
+ * Used for planning phase where user interaction is needed.
64
+ *
65
+ * @param systemPrompt - Instructions appended to Claude's system prompt via --append-system-prompt
66
+ * @param userMessage - User message passed as positional argument to trigger Claude to start
67
+ * @param options - Runner options (cwd, dangerouslySkipPermissions)
68
+ */
69
+ async runInteractive(
70
+ systemPrompt: string,
71
+ userMessage: string,
72
+ options: ClaudeRunnerOptions = {}
73
+ ): Promise<number> {
74
+ const { cwd = process.cwd(), dangerouslySkipPermissions = false } = options;
75
+
76
+ return new Promise((resolve) => {
77
+ const args = ['--model', this.model];
78
+
79
+ // Add --dangerously-skip-permissions if requested (for --auto mode)
80
+ if (dangerouslySkipPermissions) {
81
+ args.push('--dangerously-skip-permissions');
82
+ }
83
+
84
+ // System instructions via --append-system-prompt
85
+ args.push('--append-system-prompt', systemPrompt);
86
+
87
+ // User message as positional argument - Claude starts immediately
88
+ args.push(userMessage);
89
+
90
+ logger.debug(`Starting interactive Claude session with model: ${this.model}`);
91
+
92
+ this.activeProcess = pty.spawn(getClaudePath(), args, {
93
+ name: 'xterm-256color',
94
+ cols: process.stdout.columns ?? 80,
95
+ rows: process.stdout.rows ?? 24,
96
+ cwd,
97
+ env: process.env as Record<string, string>,
98
+ });
99
+
100
+ // Set raw mode to pass through all input
101
+ if (process.stdin.isTTY) {
102
+ process.stdin.setRawMode(true);
103
+ }
104
+ process.stdin.resume();
105
+
106
+ // Pipe input to Claude
107
+ const onData = (data: Buffer): void => {
108
+ if (this.activeProcess && !this.killed) {
109
+ this.activeProcess.write(data.toString());
110
+ }
111
+ };
112
+ process.stdin.on('data', onData);
113
+
114
+ // Pipe output to stdout
115
+ this.activeProcess.onData((data) => {
116
+ process.stdout.write(data);
117
+ });
118
+
119
+ this.activeProcess.onExit(({ exitCode }) => {
120
+ // Cleanup
121
+ process.stdin.off('data', onData);
122
+ if (process.stdin.isTTY) {
123
+ process.stdin.setRawMode(false);
124
+ }
125
+ process.stdin.pause();
126
+ this.activeProcess = null;
127
+
128
+ if (this.killed) {
129
+ resolve(130); // SIGINT exit code
130
+ } else {
131
+ resolve(exitCode);
132
+ }
133
+ });
134
+ });
135
+ }
136
+
137
+ /**
138
+ * Run Claude non-interactively and collect output.
139
+ * Used for execution phase where we parse the results.
140
+ * Uses child_process.spawn with -p flag for prompt (like ralphy).
141
+ *
142
+ * TIMEOUT BEHAVIOR:
143
+ * - The timeout is applied per individual call to this method
144
+ * - Each call gets a fresh timeout - elapsed time is NOT shared between calls
145
+ * - When used with retries (in do.ts), each retry attempt gets its own fresh timeout
146
+ * - Timeout includes all time Claude is running, including context building
147
+ * - Default timeout is 60 minutes if not specified
148
+ */
149
+ async run(prompt: string, options: ClaudeRunnerOptions = {}): Promise<RunResult> {
150
+ const { timeout = 60, cwd = process.cwd() } = options;
151
+ // Ensure timeout is a positive number, fallback to 60 minutes
152
+ const validatedTimeout = Number(timeout) > 0 ? Number(timeout) : 60;
153
+ const timeoutMs = validatedTimeout * 60 * 1000;
154
+
155
+ return new Promise((resolve) => {
156
+ let output = '';
157
+ let stderr = '';
158
+ let timedOut = false;
159
+ let contextOverflow = false;
160
+
161
+ const claudePath = getClaudePath();
162
+
163
+ logger.debug(`Starting Claude execution session with model: ${this.model}`);
164
+ logger.debug(`Claude path: ${claudePath}`);
165
+
166
+ // Use --append-system-prompt to add RAF instructions to system prompt
167
+ // This gives RAF instructions stronger precedence than passing as user message
168
+ // --dangerously-skip-permissions bypasses interactive prompts
169
+ // -p enables print mode (non-interactive)
170
+ const proc = spawn(claudePath, [
171
+ '--dangerously-skip-permissions',
172
+ '--model',
173
+ this.model,
174
+ '--append-system-prompt',
175
+ prompt,
176
+ '-p',
177
+ 'Execute the task as described in the system prompt.',
178
+ ], {
179
+ cwd,
180
+ env: process.env,
181
+ stdio: ['ignore', 'pipe', 'pipe'], // no stdin needed
182
+ });
183
+
184
+ // Track this process
185
+ this.activeProcess = proc as any;
186
+
187
+ // Set up timeout
188
+ const timeoutHandle = setTimeout(() => {
189
+ timedOut = true;
190
+ logger.warn('Claude session timed out');
191
+ proc.kill('SIGTERM');
192
+ }, timeoutMs);
193
+
194
+ // Collect stdout
195
+ proc.stdout.on('data', (data) => {
196
+ const text = data.toString();
197
+ output += text;
198
+
199
+ // Check for context overflow
200
+ for (const pattern of CONTEXT_OVERFLOW_PATTERNS) {
201
+ if (pattern.test(text)) {
202
+ contextOverflow = true;
203
+ logger.warn('Context overflow detected');
204
+ proc.kill('SIGTERM');
205
+ break;
206
+ }
207
+ }
208
+ });
209
+
210
+ // Collect stderr
211
+ proc.stderr.on('data', (data) => {
212
+ stderr += data.toString();
213
+ });
214
+
215
+ proc.on('close', (exitCode) => {
216
+ clearTimeout(timeoutHandle);
217
+ this.activeProcess = null;
218
+
219
+ if (stderr) {
220
+ logger.debug(`Claude stderr: ${stderr}`);
221
+ }
222
+
223
+ resolve({
224
+ output,
225
+ exitCode: exitCode ?? (this.killed ? 130 : 1),
226
+ timedOut,
227
+ contextOverflow,
228
+ });
229
+ });
230
+ });
231
+ }
232
+
233
+ /**
234
+ * Run Claude non-interactively with verbose output to stdout.
235
+ * Uses child_process.spawn with -p flag for prompt (like ralphy).
236
+ *
237
+ * TIMEOUT BEHAVIOR:
238
+ * - The timeout is applied per individual call to this method
239
+ * - Each call gets a fresh timeout - elapsed time is NOT shared between calls
240
+ * - When used with retries (in do.ts), each retry attempt gets its own fresh timeout
241
+ * - Timeout includes all time Claude is running, including context building
242
+ * - Default timeout is 60 minutes if not specified
243
+ */
244
+ async runVerbose(prompt: string, options: ClaudeRunnerOptions = {}): Promise<RunResult> {
245
+ const { timeout = 60, cwd = process.cwd() } = options;
246
+ // Ensure timeout is a positive number, fallback to 60 minutes
247
+ const validatedTimeout = Number(timeout) > 0 ? Number(timeout) : 60;
248
+ const timeoutMs = validatedTimeout * 60 * 1000;
249
+
250
+ return new Promise((resolve) => {
251
+ let output = '';
252
+ let stderr = '';
253
+ let timedOut = false;
254
+ let contextOverflow = false;
255
+
256
+ const claudePath = getClaudePath();
257
+
258
+ logger.debug(`Starting Claude execution session (verbose) with model: ${this.model}`);
259
+ logger.debug(`Prompt length: ${prompt.length}, timeout: ${timeoutMs}ms, cwd: ${cwd}`);
260
+ logger.debug(`Claude path: ${claudePath}`);
261
+
262
+ logger.debug('Spawning process...');
263
+ // Use --append-system-prompt to add RAF instructions to system prompt
264
+ // This gives RAF instructions stronger precedence than passing as user message
265
+ // --dangerously-skip-permissions bypasses interactive prompts
266
+ // -p enables print mode (non-interactive)
267
+ const proc = spawn(claudePath, [
268
+ '--dangerously-skip-permissions',
269
+ '--model',
270
+ this.model,
271
+ '--append-system-prompt',
272
+ prompt,
273
+ '-p',
274
+ 'Execute the task as described in the system prompt.',
275
+ ], {
276
+ cwd,
277
+ env: process.env,
278
+ stdio: ['ignore', 'pipe', 'pipe'], // no stdin needed
279
+ });
280
+
281
+ // Track this process
282
+ this.activeProcess = proc as any;
283
+ logger.debug('Process spawned');
284
+
285
+ // Set up timeout
286
+ const timeoutHandle = setTimeout(() => {
287
+ timedOut = true;
288
+ logger.warn('Claude session timed out');
289
+ proc.kill('SIGTERM');
290
+ }, timeoutMs);
291
+
292
+ // Collect and display stdout
293
+ let dataReceived = false;
294
+ proc.stdout.on('data', (data) => {
295
+ if (!dataReceived) {
296
+ logger.debug('First data chunk received');
297
+ dataReceived = true;
298
+ }
299
+ const text = data.toString();
300
+ output += text;
301
+ process.stdout.write(text);
302
+
303
+ // Check for context overflow
304
+ for (const pattern of CONTEXT_OVERFLOW_PATTERNS) {
305
+ if (pattern.test(text)) {
306
+ contextOverflow = true;
307
+ logger.warn('Context overflow detected');
308
+ proc.kill('SIGTERM');
309
+ break;
310
+ }
311
+ }
312
+ });
313
+
314
+ // Collect stderr
315
+ proc.stderr.on('data', (data) => {
316
+ stderr += data.toString();
317
+ });
318
+
319
+ proc.on('close', (exitCode) => {
320
+ clearTimeout(timeoutHandle);
321
+ this.activeProcess = null;
322
+ logger.debug(`Claude exited with code ${exitCode}, output length: ${output.length}, timedOut: ${timedOut}, contextOverflow: ${contextOverflow}`);
323
+
324
+ if (stderr) {
325
+ logger.debug(`Claude stderr: ${stderr}`);
326
+ }
327
+
328
+ resolve({
329
+ output,
330
+ exitCode: exitCode ?? (this.killed ? 130 : 1),
331
+ timedOut,
332
+ contextOverflow,
333
+ });
334
+ });
335
+ });
336
+ }
337
+
338
+ /**
339
+ * Kill the active Claude process gracefully.
340
+ */
341
+ kill(): void {
342
+ if (this.activeProcess) {
343
+ this.killed = true;
344
+
345
+ // Send Ctrl+C first for graceful shutdown (only for PTY processes)
346
+ // ChildProcess from spawn() doesn't have write(), only PTY does
347
+ try {
348
+ if (typeof this.activeProcess.write === 'function') {
349
+ this.activeProcess.write('\x03');
350
+ }
351
+ } catch {
352
+ // Ignore write errors - process may already be closing
353
+ }
354
+
355
+ // Force kill after 5 seconds if still running
356
+ setTimeout(() => {
357
+ if (this.activeProcess) {
358
+ try {
359
+ this.activeProcess.kill();
360
+ } catch {
361
+ // Ignore kill errors - process may already be dead
362
+ }
363
+ }
364
+ }, 5000);
365
+ }
366
+ }
367
+
368
+ /**
369
+ * Check if a process is currently running.
370
+ */
371
+ isRunning(): boolean {
372
+ return this.activeProcess !== null;
373
+ }
374
+ }
@@ -0,0 +1,85 @@
1
+ import { spawn } from 'node:child_process';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import * as os from 'node:os';
5
+ import { getEditor } from '../utils/config.js';
6
+ import { logger } from '../utils/logger.js';
7
+
8
+ /**
9
+ * Escape a file path for shell usage.
10
+ */
11
+ function escapeShellPath(filePath: string): string {
12
+ // Use single quotes and escape any existing single quotes
13
+ return `'${filePath.replace(/'/g, "'\\''")}'`;
14
+ }
15
+
16
+ /**
17
+ * Open the user's preferred editor and return the content they wrote.
18
+ */
19
+ export async function openEditor(initialContent: string = ''): Promise<string> {
20
+ const editor = getEditor();
21
+ const tempDir = os.tmpdir();
22
+ const tempFile = path.join(tempDir, `raf-input-${Date.now()}.md`);
23
+
24
+ // Write initial content if any
25
+ fs.writeFileSync(tempFile, initialContent);
26
+
27
+ // Build shell command with properly escaped file path
28
+ // This handles editors like "code --wait" or "vim" uniformly
29
+ const shellCommand = `${editor} ${escapeShellPath(tempFile)}`;
30
+ logger.debug(`Opening editor: ${shellCommand}`);
31
+
32
+ return new Promise((resolve, reject) => {
33
+ // Use shell: true with the full command as a single string
34
+ // This correctly handles editors with arguments (e.g., "code --wait")
35
+ const editorProcess = spawn(shellCommand, [], {
36
+ stdio: 'inherit',
37
+ shell: true,
38
+ });
39
+
40
+ editorProcess.on('error', (error) => {
41
+ cleanupTempFile(tempFile);
42
+ reject(new Error(`Failed to open editor: ${error.message}`));
43
+ });
44
+
45
+ editorProcess.on('exit', (code) => {
46
+ // Read the file content regardless of exit code
47
+ // Many editors (vim included) may exit with non-zero for various benign reasons
48
+ try {
49
+ const content = fs.readFileSync(tempFile, 'utf-8');
50
+ cleanupTempFile(tempFile);
51
+
52
+ // Only treat as error if file is empty/unchanged AND exit code is non-zero
53
+ // This distinguishes between "user cancelled" and "editor failed"
54
+ if (code !== 0 && content === initialContent) {
55
+ reject(new Error(`Editor exited with code ${code}`));
56
+ return;
57
+ }
58
+
59
+ resolve(content);
60
+ } catch (error) {
61
+ cleanupTempFile(tempFile);
62
+ reject(new Error(`Failed to read editor content: ${error}`));
63
+ }
64
+ });
65
+ });
66
+ }
67
+
68
+ /**
69
+ * Safely remove temp file, ignoring errors if file doesn't exist.
70
+ */
71
+ function cleanupTempFile(filePath: string): void {
72
+ try {
73
+ fs.unlinkSync(filePath);
74
+ } catch {
75
+ // Ignore errors - file may already be deleted
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Returns initial content for the project description editor.
81
+ * Opens with an empty file for a clean user experience.
82
+ */
83
+ export function getInputTemplate(): string {
84
+ return '';
85
+ }