@pasko70/pibo 1.1.0 → 1.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 (439) hide show
  1. package/README.md +106 -254
  2. package/context/codex-base-prompt.md +4 -0
  3. package/context/compute-worker.md +23 -0
  4. package/context/pibo-native-tooling.md +18 -0
  5. package/context/pibo-system-prompt.md +69 -8
  6. package/dist/api/simple-agent-api.js +136 -0
  7. package/dist/app-context.js +4 -0
  8. package/dist/apps/chat/agent-profiles.js +18 -3
  9. package/dist/apps/chat/agent-store.js +113 -16
  10. package/dist/apps/chat/chat-api-routes.js +311 -0
  11. package/dist/apps/chat/chat-capability-routes.js +90 -0
  12. package/dist/apps/chat/chat-files.js +178 -0
  13. package/dist/apps/chat/chat-request-normalizers.js +681 -0
  14. package/dist/apps/chat/chat-settings-routes.js +75 -0
  15. package/dist/apps/chat/chat-trace-helpers.js +94 -0
  16. package/dist/apps/chat/chat-user-skill-routes.js +149 -0
  17. package/dist/apps/chat/cron-api.js +213 -0
  18. package/dist/apps/chat/data/chat-data-mappers.js +74 -0
  19. package/dist/apps/chat/data/event-command-service.js +75 -0
  20. package/dist/apps/chat/data/navigation-query-service.js +11 -0
  21. package/dist/apps/chat/data/project-service.js +844 -0
  22. package/dist/apps/chat/data/read-state-service.js +42 -0
  23. package/dist/apps/chat/data/room-service.js +52 -0
  24. package/dist/apps/chat/data/session-query-service.js +63 -0
  25. package/dist/apps/chat/data/timeline-query-service.js +96 -0
  26. package/dist/apps/chat/event-log.js +1 -307
  27. package/dist/apps/chat/model-catalog.js +7 -2
  28. package/dist/apps/chat/output-compactor.js +126 -0
  29. package/dist/apps/chat/output-event-policy.js +17 -0
  30. package/dist/apps/chat/project-workflow-human-actions.js +347 -0
  31. package/dist/apps/chat/project-workflow-sessions.js +260 -0
  32. package/dist/apps/chat/provider-auth-actions.js +43 -0
  33. package/dist/apps/chat/ralph-api.js +156 -0
  34. package/dist/apps/chat/read-model.js +1 -218
  35. package/dist/apps/chat/rooms.js +1 -321
  36. package/dist/apps/chat/static-assets.js +996 -0
  37. package/dist/apps/chat/stream.js +29 -6
  38. package/dist/apps/chat/trace.js +179 -1003
  39. package/dist/apps/chat/types/event-store.js +1 -0
  40. package/dist/apps/chat/types/read-model.js +1 -0
  41. package/dist/apps/chat/types/rooms.js +36 -0
  42. package/dist/apps/chat/web-app.js +3131 -1959
  43. package/dist/apps/chat/workflow-catalog.js +572 -0
  44. package/dist/apps/chat/workflow-edge-compatibility.js +51 -0
  45. package/dist/apps/chat/workflow-json-schema-validation.js +335 -0
  46. package/dist/apps/chat/workflow-persistence-model.js +140 -0
  47. package/dist/apps/chat/workflow-persistence.js +633 -0
  48. package/dist/apps/chat/workflow-registered-ref-params.js +130 -0
  49. package/dist/apps/chat/workflow-registered-ref-pickers.js +179 -0
  50. package/dist/apps/chat/workflow-registered-ref-validation.js +210 -0
  51. package/dist/apps/chat/workflow-v2-security-validation.js +93 -0
  52. package/dist/apps/chat/workflow-validation-helpers.js +114 -0
  53. package/dist/apps/chat-ui/assets/{dist-CNLWH2qh.js → dist-B4lw9z4F.js} +1 -1
  54. package/dist/apps/chat-ui/assets/{dist-8e4L8ciw.js → dist-BbTaHWON.js} +1 -1
  55. package/dist/apps/chat-ui/assets/{dist-CMZOa5ik.js → dist-BcT_c1EJ.js} +1 -1
  56. package/dist/apps/chat-ui/assets/{dist-DNcnQRPF.js → dist-CGINd7XU.js} +1 -1
  57. package/dist/apps/chat-ui/assets/{dist-CqqUC8Ce.js → dist-CrBzZkUp.js} +1 -1
  58. package/dist/apps/chat-ui/assets/{dist-D2N4-LIc.js → dist-CyyISotB.js} +1 -1
  59. package/dist/apps/chat-ui/assets/{dist-CUqpST5w.js → dist-DFbnFNpX.js} +1 -1
  60. package/dist/apps/chat-ui/assets/{dist-CspjOeBj.js → dist-DGLWQLX8.js} +1 -1
  61. package/dist/apps/chat-ui/assets/{dist-B7bbI3Qz.js → dist-DfcIkFSN.js} +1 -1
  62. package/dist/apps/chat-ui/assets/{dist-v4pjHlB7.js → dist-sKDHTwaT.js} +1 -1
  63. package/dist/apps/chat-ui/assets/{dist-D9L4MSRF.js → dist-y9D6la48.js} +1 -1
  64. package/dist/apps/chat-ui/assets/index-C25VYnyb.css +1 -0
  65. package/dist/apps/chat-ui/assets/index-CUkuvI3v.js +165 -0
  66. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-144x144.png +0 -0
  67. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-192x192.png +0 -0
  68. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-48x48.png +0 -0
  69. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-512x512.png +0 -0
  70. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-72x72.png +0 -0
  71. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-96x96.png +0 -0
  72. package/dist/apps/chat-ui/assets/pwa-images/ios/100.png +0 -0
  73. package/dist/apps/chat-ui/assets/pwa-images/ios/1024.png +0 -0
  74. package/dist/apps/chat-ui/assets/pwa-images/ios/114.png +0 -0
  75. package/dist/apps/chat-ui/assets/pwa-images/ios/120.png +0 -0
  76. package/dist/apps/chat-ui/assets/pwa-images/ios/128.png +0 -0
  77. package/dist/apps/chat-ui/assets/pwa-images/ios/144.png +0 -0
  78. package/dist/apps/chat-ui/assets/pwa-images/ios/152.png +0 -0
  79. package/dist/apps/chat-ui/assets/pwa-images/ios/16.png +0 -0
  80. package/dist/apps/chat-ui/assets/pwa-images/ios/167.png +0 -0
  81. package/dist/apps/chat-ui/assets/pwa-images/ios/180.png +0 -0
  82. package/dist/apps/chat-ui/assets/pwa-images/ios/192.png +0 -0
  83. package/dist/apps/chat-ui/assets/pwa-images/ios/20.png +0 -0
  84. package/dist/apps/chat-ui/assets/pwa-images/ios/256.png +0 -0
  85. package/dist/apps/chat-ui/assets/pwa-images/ios/29.png +0 -0
  86. package/dist/apps/chat-ui/assets/pwa-images/ios/32.png +0 -0
  87. package/dist/apps/chat-ui/assets/pwa-images/ios/40.png +0 -0
  88. package/dist/apps/chat-ui/assets/pwa-images/ios/50.png +0 -0
  89. package/dist/apps/chat-ui/assets/pwa-images/ios/512.png +0 -0
  90. package/dist/apps/chat-ui/assets/pwa-images/ios/57.png +0 -0
  91. package/dist/apps/chat-ui/assets/pwa-images/ios/58.png +0 -0
  92. package/dist/apps/chat-ui/assets/pwa-images/ios/60.png +0 -0
  93. package/dist/apps/chat-ui/assets/pwa-images/ios/64.png +0 -0
  94. package/dist/apps/chat-ui/assets/pwa-images/ios/72.png +0 -0
  95. package/dist/apps/chat-ui/assets/pwa-images/ios/76.png +0 -0
  96. package/dist/apps/chat-ui/assets/pwa-images/ios/80.png +0 -0
  97. package/dist/apps/chat-ui/assets/pwa-images/ios/87.png +0 -0
  98. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-100.png +0 -0
  99. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-125.png +0 -0
  100. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-150.png +0 -0
  101. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-200.png +0 -0
  102. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-400.png +0 -0
  103. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-100.png +0 -0
  104. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-125.png +0 -0
  105. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-150.png +0 -0
  106. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-200.png +0 -0
  107. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-400.png +0 -0
  108. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-100.png +0 -0
  109. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-125.png +0 -0
  110. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-150.png +0 -0
  111. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-200.png +0 -0
  112. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-400.png +0 -0
  113. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-100.png +0 -0
  114. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-125.png +0 -0
  115. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-150.png +0 -0
  116. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-200.png +0 -0
  117. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-400.png +0 -0
  118. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-16.png +0 -0
  119. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-20.png +0 -0
  120. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-24.png +0 -0
  121. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-256.png +0 -0
  122. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-30.png +0 -0
  123. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-32.png +0 -0
  124. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-36.png +0 -0
  125. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-40.png +0 -0
  126. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-44.png +0 -0
  127. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-48.png +0 -0
  128. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-60.png +0 -0
  129. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-64.png +0 -0
  130. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-72.png +0 -0
  131. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-80.png +0 -0
  132. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-96.png +0 -0
  133. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-16.png +0 -0
  134. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-20.png +0 -0
  135. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-24.png +0 -0
  136. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-256.png +0 -0
  137. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-30.png +0 -0
  138. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-32.png +0 -0
  139. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-36.png +0 -0
  140. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-40.png +0 -0
  141. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-44.png +0 -0
  142. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-48.png +0 -0
  143. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-60.png +0 -0
  144. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-64.png +0 -0
  145. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-72.png +0 -0
  146. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-80.png +0 -0
  147. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-96.png +0 -0
  148. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-100.png +0 -0
  149. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-125.png +0 -0
  150. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-150.png +0 -0
  151. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-200.png +0 -0
  152. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-400.png +0 -0
  153. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-16.png +0 -0
  154. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-20.png +0 -0
  155. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-24.png +0 -0
  156. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-256.png +0 -0
  157. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-30.png +0 -0
  158. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-32.png +0 -0
  159. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-36.png +0 -0
  160. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-40.png +0 -0
  161. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-44.png +0 -0
  162. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-48.png +0 -0
  163. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-60.png +0 -0
  164. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-64.png +0 -0
  165. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-72.png +0 -0
  166. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-80.png +0 -0
  167. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-96.png +0 -0
  168. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-100.png +0 -0
  169. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-125.png +0 -0
  170. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-150.png +0 -0
  171. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-200.png +0 -0
  172. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-400.png +0 -0
  173. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-100.png +0 -0
  174. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-125.png +0 -0
  175. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-150.png +0 -0
  176. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-200.png +0 -0
  177. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-400.png +0 -0
  178. package/dist/apps/chat-ui/index.html +8 -3
  179. package/dist/apps/chat-ui/manifest.webmanifest +25 -0
  180. package/dist/apps/chat-ui/sw.js +41 -0
  181. package/dist/apps/chat-vscode-web/assets/index-B5QK07zO.css +2 -0
  182. package/dist/apps/chat-vscode-web/assets/index-C3GTPyDo.js +41 -0
  183. package/dist/apps/chat-vscode-web/index.html +14 -0
  184. package/dist/apps/cli-ui/InkSessionApp.js +1218 -0
  185. package/dist/apps/cli-ui/InkTerminalLine.js +53 -0
  186. package/dist/apps/cli-ui/InkTerminalRow.js +304 -0
  187. package/dist/apps/cli-ui/InkTerminalView.js +25 -0
  188. package/dist/apps/cli-ui/cliSessionsCommand.js +232 -0
  189. package/dist/apps/cli-ui/index.js +8 -0
  190. package/dist/apps/cli-ui/inkColors.js +67 -0
  191. package/dist/apps/cli-ui/inkJson.js +244 -0
  192. package/dist/apps/cli-ui/inkMarkdown.js +122 -0
  193. package/dist/apps/context-files-ui/assets/{dist-DFi2YGux.js → dist-BOiGdrG-.js} +1 -1
  194. package/dist/apps/context-files-ui/assets/{dist-DyfSeBMu.js → dist-DK01b7x4.js} +1 -1
  195. package/dist/apps/context-files-ui/assets/{dist-CwbH_3RN.js → dist-DPG9jOQ-.js} +1 -1
  196. package/dist/apps/context-files-ui/assets/{dist-dTBsFYAl.js → dist-Dp5AH00p.js} +1 -1
  197. package/dist/apps/context-files-ui/assets/{dist-CxRLRmMx.js → dist-DqYw0LH7.js} +1 -1
  198. package/dist/apps/context-files-ui/assets/{dist-MyZgX9K2.js → dist-TF5iO5ML.js} +1 -1
  199. package/dist/apps/context-files-ui/assets/{dist-DQXzt2Ng.js → dist-TbjAhles.js} +1 -1
  200. package/dist/apps/context-files-ui/assets/{dist-YwR9dpb-.js → dist-ZsBbt0uY.js} +1 -1
  201. package/dist/apps/context-files-ui/assets/{dist-CKQF1zEu.js → dist-kmsvtHkH.js} +1 -1
  202. package/dist/apps/context-files-ui/assets/{dist-BJW3917N.js → dist-vnd7PMu3.js} +1 -1
  203. package/dist/apps/context-files-ui/assets/{index-BwRDoHMC.css → index-B92tL3Pp.css} +1 -1
  204. package/dist/apps/context-files-ui/assets/{index-GwvjXytt.js → index-BhAWD3dv.js} +2 -2
  205. package/dist/apps/context-files-ui/index.html +2 -2
  206. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  207. package/dist/apps/vscode-artifacts/pibo-vscode-1.3.0.vsix +0 -0
  208. package/dist/auth/better-auth.js +2 -1
  209. package/dist/auth/login-actions.js +251 -0
  210. package/dist/auth/openai-codex-usage.js +147 -0
  211. package/dist/bin/pibo.js +0 -0
  212. package/dist/bin/rg.js +15 -0
  213. package/dist/cli-session/fakeSessionSource.js +804 -0
  214. package/dist/cli-session/index.js +3 -0
  215. package/dist/cli-session/localSessionSource.js +1144 -0
  216. package/dist/cli-session/sessionSource.js +13 -0
  217. package/dist/cli.js +159 -14
  218. package/dist/compute/cli.js +415 -0
  219. package/dist/compute/docker.js +827 -0
  220. package/dist/compute/resource-health.js +333 -0
  221. package/dist/compute/resource-policy.js +98 -0
  222. package/dist/config/config.js +9 -5
  223. package/dist/core/context-build.js +677 -0
  224. package/dist/core/model-defaults.js +51 -9
  225. package/dist/core/pibo-home.js +8 -0
  226. package/dist/core/profiles.js +48 -0
  227. package/dist/core/provider-telemetry.js +222 -0
  228. package/dist/core/routed-session.js +441 -47
  229. package/dist/core/runtime-telemetry.js +853 -0
  230. package/dist/core/runtime.js +103 -15
  231. package/dist/core/session-errors.js +47 -0
  232. package/dist/core/session-model.js +39 -0
  233. package/dist/core/session-router.js +292 -62
  234. package/dist/core/shared-app.js +17 -0
  235. package/dist/core/skill-expansion.js +43 -0
  236. package/dist/core/system-prompt-template.js +9 -9
  237. package/dist/core/telemetry-staleness.js +128 -0
  238. package/dist/core/test-output-compaction.js +145 -0
  239. package/dist/core/user-settings.js +73 -0
  240. package/dist/cron/channel.js +28 -0
  241. package/dist/cron/cli.js +230 -0
  242. package/dist/cron/plugin.js +11 -0
  243. package/dist/cron/schedule.js +214 -0
  244. package/dist/cron/service.js +177 -0
  245. package/dist/cron/store.js +349 -0
  246. package/dist/cron/types.js +1 -0
  247. package/dist/data/cli.js +184 -0
  248. package/dist/data/event-log.js +106 -0
  249. package/dist/data/final-app-space-cutover-migration.js +728 -0
  250. package/dist/data/ingest-service.js +389 -0
  251. package/dist/data/message-store.js +62 -0
  252. package/dist/data/navigation-store.js +75 -0
  253. package/dist/data/observation-store.js +46 -0
  254. package/dist/data/payload-store.js +144 -0
  255. package/dist/data/pibo-store.js +59 -0
  256. package/dist/data/schema.js +434 -0
  257. package/dist/data/session-store.js +63 -0
  258. package/dist/data/shared-app-migration.js +757 -0
  259. package/dist/data/sqlite-schema.js +12 -0
  260. package/dist/data/telemetry-preview.js +65 -0
  261. package/dist/data/telemetry-queries.js +212 -0
  262. package/dist/data/telemetry-retention.js +50 -0
  263. package/dist/data/telemetry-rows.js +158 -0
  264. package/dist/data/telemetry.js +357 -0
  265. package/dist/debug/delta-compaction.js +99 -0
  266. package/dist/debug/detail-format.js +86 -0
  267. package/dist/debug/events.js +149 -29
  268. package/dist/debug/failures.js +162 -0
  269. package/dist/debug/index.js +655 -30
  270. package/dist/debug/messages.js +185 -0
  271. package/dist/debug/next-commands.js +6 -0
  272. package/dist/debug/payloads.js +123 -0
  273. package/dist/debug/pty.js +924 -0
  274. package/dist/debug/session.js +45 -15
  275. package/dist/debug/sql.js +1 -1
  276. package/dist/debug/stores.js +18 -13
  277. package/dist/debug/summary.js +72 -0
  278. package/dist/debug/telemetry.js +649 -0
  279. package/dist/debug/tools.js +168 -0
  280. package/dist/debug/trace-render-check.js +151 -0
  281. package/dist/debug/trace.js +152 -27
  282. package/dist/debug/web-artifacts.js +63 -0
  283. package/dist/debug/web-options.js +313 -0
  284. package/dist/debug/web-render-analysis.js +310 -0
  285. package/dist/debug/web-snapshot-browser-scripts.js +303 -0
  286. package/dist/debug/web-streaming-benchmark-analysis.js +605 -0
  287. package/dist/debug/web-streaming-browser-library.js +928 -0
  288. package/dist/debug/web-streaming-browser-scripts.js +242 -0
  289. package/dist/debug/web-streaming-provider-telemetry.js +194 -0
  290. package/dist/debug/web-streaming-report.js +493 -0
  291. package/dist/debug/web-streaming-types.js +1 -0
  292. package/dist/debug/web.js +574 -0
  293. package/dist/gateway/backup.js +83 -0
  294. package/dist/gateway/cli.js +511 -0
  295. package/dist/gateway/fallback.js +155 -0
  296. package/dist/gateway/pidfile.js +84 -0
  297. package/dist/gateway/protocol.js +16 -0
  298. package/dist/gateway/server.js +172 -17
  299. package/dist/gateway/tool.js +54 -51
  300. package/dist/gateway/web.js +74 -2
  301. package/dist/index.js +3 -1
  302. package/dist/local/client.js +3 -3
  303. package/dist/local/extension.js +8 -5
  304. package/dist/plugins/builtin.js +251 -49
  305. package/dist/plugins/chat-vscode-web.js +28 -0
  306. package/dist/plugins/codex-compat.js +0 -41
  307. package/dist/plugins/context-files.js +98 -18
  308. package/dist/plugins/dev-auth.js +124 -0
  309. package/dist/plugins/native-tooling.js +15 -0
  310. package/dist/plugins/registry.js +49 -1
  311. package/dist/plugins/web-annotations.js +27 -0
  312. package/dist/providers/minimax.js +70 -0
  313. package/dist/providers/openai-compat.js +48 -0
  314. package/dist/ralph/channel.js +8 -0
  315. package/dist/ralph/cli.js +152 -0
  316. package/dist/ralph/plugin.js +14 -0
  317. package/dist/ralph/service.js +271 -0
  318. package/dist/ralph/stopping.js +151 -0
  319. package/dist/ralph/store.js +450 -0
  320. package/dist/ralph/templates.js +200 -0
  321. package/dist/ralph/types.js +1 -0
  322. package/dist/reliability/store.js +42 -26
  323. package/dist/runs/registry.js +72 -35
  324. package/dist/session-ui/commandCatalog.js +193 -0
  325. package/dist/session-ui/commandResults.js +95 -0
  326. package/dist/session-ui/index.js +7 -0
  327. package/dist/session-ui/ownerViewModel.js +27 -0
  328. package/dist/session-ui/roomSessionViewModel.js +69 -0
  329. package/dist/session-ui/statusViewModel.js +127 -0
  330. package/dist/session-ui/terminalCards.js +210 -0
  331. package/dist/session-ui/terminalRows.js +937 -0
  332. package/dist/session-ui/terminalValue.js +45 -0
  333. package/dist/sessions/pibo-data-store.js +178 -0
  334. package/dist/sessions/sqlite-store.js +78 -12
  335. package/dist/sessions/store.js +11 -4
  336. package/dist/sessions/workflow-session-kind.js +20 -0
  337. package/dist/setup/cli.js +567 -0
  338. package/dist/shared/trace-async-agent-runs.js +127 -0
  339. package/dist/shared/trace-engine.js +96 -0
  340. package/dist/shared/trace-event-projection.js +679 -0
  341. package/dist/shared/trace-live-reducer.js +191 -0
  342. package/dist/shared/trace-nodes.js +76 -0
  343. package/dist/shared/trace-order.js +11 -10
  344. package/dist/shared/trace-patch-nodes.js +83 -0
  345. package/dist/shared/trace-run-notifications.js +69 -0
  346. package/dist/shared/trace-subagent-links.js +46 -0
  347. package/dist/shared/trace-transcript.js +303 -0
  348. package/dist/shared/trace-types.js +1 -0
  349. package/dist/shared-app.js +4 -0
  350. package/dist/signals/aggregate.js +65 -0
  351. package/dist/signals/events.js +1 -0
  352. package/dist/signals/projector.js +158 -0
  353. package/dist/signals/registry.js +513 -0
  354. package/dist/signals/store.js +1 -0
  355. package/dist/signals/types.js +1 -0
  356. package/dist/skills/cli.js +117 -0
  357. package/dist/tools/agent-browser-leases.js +219 -0
  358. package/dist/tools/agent-browser-wrapper.js +99 -0
  359. package/dist/tools/browser-pool.js +623 -0
  360. package/dist/tools/browser-use-cdp.js +56 -4
  361. package/dist/tools/browser-use-leases.js +215 -37
  362. package/dist/tools/browser-use-wrapper.js +508 -65
  363. package/dist/tools/cdp-client.js +189 -0
  364. package/dist/tools/guides.js +203 -4
  365. package/dist/tools/index.js +666 -16
  366. package/dist/tools/npm-runtime.js +136 -0
  367. package/dist/tools/registry.js +107 -8
  368. package/dist/tools/runtime/index.js +3 -0
  369. package/dist/tools/runtime/node-backend.js +225 -0
  370. package/dist/tools/runtime/node-worker-source.js +206 -0
  371. package/dist/tools/runtime/python-backend.js +227 -0
  372. package/dist/tools/runtime/python-worker-source.js +178 -0
  373. package/dist/tools/runtime/registry.js +255 -0
  374. package/dist/tools/runtime/tool.js +168 -0
  375. package/dist/tools/runtime/types.js +1 -0
  376. package/dist/tools/web-search.js +2 -1
  377. package/dist/user-skills/installer.js +39 -36
  378. package/dist/user-skills/store.js +50 -11
  379. package/dist/vscode/cli.js +90 -0
  380. package/dist/vscode/code-cli.js +119 -0
  381. package/dist/vscode/install.js +177 -0
  382. package/dist/vscode/status.js +80 -0
  383. package/dist/vscode/types.js +14 -0
  384. package/dist/vscode/uninstall.js +49 -0
  385. package/dist/vscode/vsix-fetcher.js +131 -0
  386. package/dist/web/auth.js +5 -1
  387. package/dist/web/channel.js +86 -0
  388. package/dist/web/http.js +79 -14
  389. package/dist/web-annotations/api.js +348 -0
  390. package/dist/web-annotations/attachments.js +201 -0
  391. package/dist/web-annotations/cdp.js +1107 -0
  392. package/dist/web-annotations/index.js +7 -0
  393. package/dist/web-annotations/store.js +407 -0
  394. package/dist/web-annotations/tools.js +350 -0
  395. package/dist/web-annotations/types.js +34 -0
  396. package/dist/web-annotations/validation.js +288 -0
  397. package/docs/README.md +23 -0
  398. package/docs/ops/install-developer-host.md +112 -0
  399. package/docs/ops/install-user-host.md +76 -0
  400. package/docs/ops/upgrade-user-to-developer-host.md +69 -0
  401. package/docs/ops/vscode-extension-release.md +138 -0
  402. package/package.json +24 -9
  403. package/skills/builtin/pi-agent-harness/SKILL.md +24 -24
  404. package/skills/builtin/pibo-docker-system/SKILL.md +170 -0
  405. package/skills/builtin/pibo-spec-writing/SKILL.md +330 -0
  406. package/skills/builtin/prd/SKILL.md +143 -0
  407. package/skills/builtin/ralph-loop/SKILL.md +359 -0
  408. package/skills/builtin/ralph-prd-json/SKILL.md +123 -0
  409. package/skills/builtin/skill-creator/LICENSE.txt +202 -0
  410. package/skills/builtin/skill-creator/SKILL.md +513 -0
  411. package/skills/builtin/skill-creator/agents/analyzer.md +274 -0
  412. package/skills/builtin/skill-creator/agents/comparator.md +202 -0
  413. package/skills/builtin/skill-creator/agents/grader.md +223 -0
  414. package/skills/builtin/skill-creator/assets/eval_review.html +146 -0
  415. package/skills/builtin/skill-creator/eval-viewer/generate_review.py +471 -0
  416. package/skills/builtin/skill-creator/eval-viewer/viewer.html +1325 -0
  417. package/skills/builtin/skill-creator/references/schemas.md +430 -0
  418. package/skills/builtin/skill-creator/scripts/__init__.py +0 -0
  419. package/skills/builtin/skill-creator/scripts/aggregate_benchmark.py +401 -0
  420. package/skills/builtin/skill-creator/scripts/generate_report.py +326 -0
  421. package/skills/builtin/skill-creator/scripts/improve_description.py +247 -0
  422. package/skills/builtin/skill-creator/scripts/package_skill.py +136 -0
  423. package/skills/builtin/skill-creator/scripts/quick_validate.py +103 -0
  424. package/skills/builtin/skill-creator/scripts/run_eval.py +310 -0
  425. package/skills/builtin/skill-creator/scripts/run_loop.py +328 -0
  426. package/skills/builtin/skill-creator/scripts/utils.py +47 -0
  427. package/skills/builtin/web-annotations/SKILL.md +93 -0
  428. package/dist/apps/chat-ui/assets/index-D2Qxambd.js +0 -151
  429. package/dist/apps/chat-ui/assets/index-DXx368XK.css +0 -1
  430. package/dist/env.js +0 -32
  431. package/dist/plugins/core-tools.js +0 -94
  432. package/dist/plugins/example.js +0 -67
  433. package/dist/plugins/remote-agent.js +0 -9
  434. package/dist/remote/channel.js +0 -176
  435. package/dist/remote/client.js +0 -92
  436. package/dist/remote/examples/tui-controller.js +0 -263
  437. package/dist/remote/protocol.js +0 -55
  438. package/dist/remote/session-client.js +0 -189
  439. package/dist/sessions/bindings.js +0 -41
@@ -0,0 +1,450 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { mkdirSync } from 'node:fs';
3
+ import { dirname, resolve } from 'node:path';
4
+ import { DatabaseSync } from 'node:sqlite';
5
+ import { piboHomePath } from '../core/pibo-home.js';
6
+ import { isPiboThinkingLevel } from '../core/thinking.js';
7
+ function nowIso(now = new Date()) { return now.toISOString(); }
8
+ function parseJson(json) { return JSON.parse(json); }
9
+ function defaultName(prompt) { const normalized = prompt.replace(/\s+/g, ' ').trim(); return normalized ? normalized.slice(0, 80) : 'Ralph job'; }
10
+ function isJsonObject(value) { return !!value && typeof value === 'object' && !Array.isArray(value); }
11
+ const cleanupStates = new Set(['none', 'active', 'released', 'retained', 'dirty']);
12
+ function normalizeRalphTarget(target) {
13
+ if (target.kind === 'room')
14
+ return { kind: 'room', roomId: String(target.roomId ?? '').trim() };
15
+ return { kind: 'default-chat' };
16
+ }
17
+ function parseRalphTarget(json) { return normalizeRalphTarget(parseJson(json)); }
18
+ function targetJson(target) { return JSON.stringify(normalizeRalphTarget(target)); }
19
+ function optionalString(value, field) {
20
+ if (value === undefined || value === null)
21
+ return undefined;
22
+ if (typeof value !== 'string')
23
+ throw new Error(`${field} must be a string`);
24
+ const trimmed = value.trim();
25
+ return trimmed || undefined;
26
+ }
27
+ function normalizeBrowserLeaseIds(value) {
28
+ if (value === undefined || value === null)
29
+ return undefined;
30
+ if (!Array.isArray(value))
31
+ throw new Error('resources.browserLeaseIds must be an array');
32
+ const ids = [...new Set(value.map((item) => optionalString(item, 'resources.browserLeaseIds[]')).filter((item) => !!item))];
33
+ return ids.length ? ids : undefined;
34
+ }
35
+ export function normalizeRalphResourceMetadata(value) {
36
+ if (value === undefined || value === null)
37
+ return undefined;
38
+ if (!value || typeof value !== 'object' || Array.isArray(value))
39
+ throw new Error('resources must be an object');
40
+ const cleanupState = optionalString(value.cleanupState, 'resources.cleanupState');
41
+ if (cleanupState && !cleanupStates.has(cleanupState))
42
+ throw new Error('resources.cleanupState must be one of none, active, released, retained, dirty');
43
+ const resources = {};
44
+ const workerId = optionalString(value.workerId, 'resources.workerId');
45
+ const browserLeaseIds = normalizeBrowserLeaseIds(value.browserLeaseIds);
46
+ const retainedUntil = optionalString(value.retainedUntil, 'resources.retainedUntil');
47
+ const dirtyReason = optionalString(value.dirtyReason, 'resources.dirtyReason');
48
+ const updatedAt = optionalString(value.updatedAt, 'resources.updatedAt');
49
+ if (workerId)
50
+ resources.workerId = workerId;
51
+ if (browserLeaseIds)
52
+ resources.browserLeaseIds = browserLeaseIds;
53
+ if (cleanupState)
54
+ resources.cleanupState = cleanupState;
55
+ if (retainedUntil)
56
+ resources.retainedUntil = retainedUntil;
57
+ if (dirtyReason)
58
+ resources.dirtyReason = dirtyReason;
59
+ if (updatedAt)
60
+ resources.updatedAt = updatedAt;
61
+ return Object.keys(resources).length ? resources : undefined;
62
+ }
63
+ function parseResourceMetadata(json) {
64
+ if (!json)
65
+ return undefined;
66
+ try {
67
+ return normalizeRalphResourceMetadata(JSON.parse(json));
68
+ }
69
+ catch {
70
+ return undefined;
71
+ }
72
+ }
73
+ function resourceMetadataJson(resources) {
74
+ const normalized = normalizeRalphResourceMetadata(resources);
75
+ return normalized ? JSON.stringify(normalized) : null;
76
+ }
77
+ function jobFromRow(row) {
78
+ const resources = parseResourceMetadata(row.resource_json);
79
+ return { id: row.id, name: row.name, description: row.description ?? undefined, enabled: row.enabled === 1, target: parseRalphTarget(row.target_json), profile: row.profile, prompt: row.prompt, maxIterations: row.max_iterations ?? undefined, stopPolicy: parseStopPolicy(row.stop_policy_json), ...parseRuntimeOptions(row.runtime_options_json), ...(resources ? { resources } : {}), state: parseJson(row.state_json), createdAt: row.created_at, updatedAt: row.updated_at };
80
+ }
81
+ function runFromRow(row) {
82
+ const resources = parseResourceMetadata(row.resource_json);
83
+ return { id: row.id, jobId: row.job_id, piboSessionId: row.pibo_session_id ?? undefined, status: row.status, reason: row.reason ?? undefined, error: row.error ?? undefined, startedAt: row.started_at ?? undefined, completedAt: row.completed_at ?? undefined, ...(resources ? { resources } : {}), createdAt: row.created_at, updatedAt: row.updated_at };
84
+ }
85
+ function mergeResourceMetadata(jobResources, runResources) {
86
+ if (!jobResources && !runResources)
87
+ return undefined;
88
+ const browserLeaseIds = [...new Set([...(jobResources?.browserLeaseIds ?? []), ...(runResources?.browserLeaseIds ?? [])])];
89
+ return { ...(jobResources ?? {}), ...(runResources ?? {}), ...(browserLeaseIds.length ? { browserLeaseIds } : {}) };
90
+ }
91
+ function factFromRow(row) {
92
+ return { id: row.id, jobId: row.job_id, runId: row.run_id ?? undefined, piboSessionId: row.pibo_session_id ?? undefined, type: row.type, source: row.source, payload: parseJson(row.payload_json), createdAt: row.created_at };
93
+ }
94
+ function normalizeMaxIterations(value) {
95
+ if (value === undefined)
96
+ return undefined;
97
+ if (!Number.isInteger(value) || value < 1)
98
+ throw new Error('maxIterations must be a positive integer');
99
+ return value;
100
+ }
101
+ function normalizeModelOverride(value) {
102
+ if (value === undefined || value === null)
103
+ return undefined;
104
+ const provider = value.provider.trim();
105
+ const id = value.id.trim();
106
+ if (!provider || !id)
107
+ throw new Error('modelOverride must include provider and id');
108
+ return { provider, id };
109
+ }
110
+ function normalizeThinkingLevel(value) {
111
+ if (value === undefined || value === null)
112
+ return undefined;
113
+ if (!isPiboThinkingLevel(value))
114
+ throw new Error('thinkingLevel must be one of off, minimal, low, medium, high, xhigh');
115
+ return value;
116
+ }
117
+ function normalizeFastMode(value) {
118
+ if (value === undefined || value === null)
119
+ return undefined;
120
+ if (typeof value !== 'boolean')
121
+ throw new Error('fastMode must be a boolean');
122
+ return value;
123
+ }
124
+ function normalizeRuntimeOptions(input) {
125
+ return { modelOverride: normalizeModelOverride(input.modelOverride), thinkingLevel: normalizeThinkingLevel(input.thinkingLevel), fastMode: normalizeFastMode(input.fastMode) };
126
+ }
127
+ function parseRuntimeOptions(json) {
128
+ if (!json)
129
+ return {};
130
+ try {
131
+ const parsed = JSON.parse(json);
132
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
133
+ return {};
134
+ return normalizeRuntimeOptions(parsed);
135
+ }
136
+ catch {
137
+ return {};
138
+ }
139
+ }
140
+ function runtimeOptionsJson(job) {
141
+ const options = normalizeRuntimeOptions(job);
142
+ const json = {};
143
+ if (options.modelOverride)
144
+ json.modelOverride = options.modelOverride;
145
+ if (options.thinkingLevel)
146
+ json.thinkingLevel = options.thinkingLevel;
147
+ if (options.fastMode !== undefined)
148
+ json.fastMode = options.fastMode;
149
+ return Object.keys(json).length ? JSON.stringify(json) : null;
150
+ }
151
+ function hasOwn(object, key) { return Object.prototype.hasOwnProperty.call(object, key); }
152
+ export function normalizeRalphStopPolicy(value) {
153
+ if (value === undefined || value === null)
154
+ return undefined;
155
+ if (!value || typeof value !== 'object' || Array.isArray(value))
156
+ throw new Error('stopPolicy must be an object');
157
+ if (value.mode !== 'any' && value.mode !== 'all')
158
+ throw new Error('stopPolicy.mode must be any or all');
159
+ if (!Array.isArray(value.conditions))
160
+ throw new Error('stopPolicy.conditions must be an array');
161
+ const ids = new Set();
162
+ return { mode: value.mode, conditions: value.conditions.map((condition, index) => {
163
+ if (!condition || typeof condition !== 'object' || Array.isArray(condition))
164
+ throw new Error(`stopPolicy.conditions[${index}] must be an object`);
165
+ const id = typeof condition.id === 'string' && condition.id.trim() ? condition.id.trim() : `condition-${index + 1}`;
166
+ const type = typeof condition.type === 'string' ? condition.type.trim() : '';
167
+ if (!type)
168
+ throw new Error(`stopPolicy.conditions[${index}].type is required`);
169
+ if (ids.has(id))
170
+ throw new Error(`Duplicate Ralph stop condition id: ${id}`);
171
+ ids.add(id);
172
+ if (condition.options !== undefined && !isJsonObject(condition.options))
173
+ throw new Error(`stopPolicy.conditions[${index}].options must be an object`);
174
+ if (condition.enabled !== undefined && typeof condition.enabled !== 'boolean')
175
+ throw new Error(`stopPolicy.conditions[${index}].enabled must be a boolean`);
176
+ if (condition.failClosed !== undefined && typeof condition.failClosed !== 'boolean')
177
+ throw new Error(`stopPolicy.conditions[${index}].failClosed must be a boolean`);
178
+ if (condition.timeoutMs !== undefined && (!Number.isInteger(condition.timeoutMs) || condition.timeoutMs < 1))
179
+ throw new Error(`stopPolicy.conditions[${index}].timeoutMs must be a positive integer`);
180
+ return { id, type, ...(condition.enabled !== undefined ? { enabled: condition.enabled } : {}), ...(condition.options ? { options: condition.options } : {}), ...(condition.failClosed !== undefined ? { failClosed: condition.failClosed } : {}), ...(condition.timeoutMs !== undefined ? { timeoutMs: condition.timeoutMs } : {}) };
181
+ }) };
182
+ }
183
+ function parseStopPolicy(json) {
184
+ if (!json)
185
+ return undefined;
186
+ try {
187
+ return normalizeRalphStopPolicy(JSON.parse(json));
188
+ }
189
+ catch {
190
+ return undefined;
191
+ }
192
+ }
193
+ function stopPolicyJson(policy) { return policy ? JSON.stringify(normalizeRalphStopPolicy(policy)) : null; }
194
+ function validateJobInput(input) {
195
+ if (!input.profile.trim())
196
+ throw new Error('profile is required');
197
+ if (!input.prompt.trim())
198
+ throw new Error('prompt is required');
199
+ if (input.target.kind === 'room' && !input.target.roomId.trim())
200
+ throw new Error('target.roomId is required');
201
+ normalizeMaxIterations(input.maxIterations);
202
+ normalizeRuntimeOptions(input);
203
+ normalizeRalphStopPolicy(input.stopPolicy);
204
+ normalizeRalphResourceMetadata(input.resources);
205
+ }
206
+ export class PiboRalphStore {
207
+ db;
208
+ constructor(options = {}) {
209
+ const dbPath = options.path ?? piboHomePath('pibo-ralph.sqlite');
210
+ const resolved = dbPath === ':memory:' ? dbPath : resolve(dbPath);
211
+ if (resolved !== ':memory:')
212
+ mkdirSync(dirname(resolved), { recursive: true });
213
+ this.db = new DatabaseSync(resolved);
214
+ this.db.exec('PRAGMA busy_timeout = 5000');
215
+ this.db.exec('PRAGMA foreign_keys = ON');
216
+ if (resolved !== ':memory:')
217
+ this.db.exec('PRAGMA journal_mode = WAL');
218
+ this.applySchema();
219
+ }
220
+ close() { this.db.close(); }
221
+ createJob(input, now = new Date()) {
222
+ const target = normalizeRalphTarget(input.target);
223
+ validateJobInput({ ...input, target });
224
+ const timestamp = nowIso(now);
225
+ const runtimeOptions = normalizeRuntimeOptions(input);
226
+ const resources = normalizeRalphResourceMetadata(input.resources);
227
+ const job = { id: `ralph_${randomUUID()}`, name: (input.name ?? defaultName(input.prompt)).trim(), description: input.description?.trim() || undefined, enabled: input.enabled === true, target, profile: input.profile, prompt: input.prompt, maxIterations: normalizeMaxIterations(input.maxIterations), stopPolicy: normalizeRalphStopPolicy(input.stopPolicy), ...runtimeOptions, ...(resources ? { resources } : {}), state: { completedIterations: 0 }, createdAt: timestamp, updatedAt: timestamp };
228
+ this.insertJob(job);
229
+ return this.getJob(job.id);
230
+ }
231
+ getJob(id) { const row = this.db.prepare('SELECT * FROM pibo_ralph_jobs WHERE id = ?').get(id); return row ? jobFromRow(row) : undefined; }
232
+ listJobs(input = {}) {
233
+ const clauses = [];
234
+ const values = [];
235
+ if (!input.includeDisabled)
236
+ clauses.push('enabled = 1');
237
+ const where = clauses.length ? `WHERE ${clauses.join(' AND ')}` : '';
238
+ return this.db.prepare(`SELECT * FROM pibo_ralph_jobs ${where} ORDER BY updated_at DESC, id ASC`).all(...values).map(jobFromRow);
239
+ }
240
+ updateJob(id, patch, now = new Date()) {
241
+ const existing = this.getJob(id);
242
+ if (!existing)
243
+ return undefined;
244
+ const runtimeOptions = normalizeRuntimeOptions({
245
+ modelOverride: hasOwn(patch, 'modelOverride') ? patch.modelOverride : existing.modelOverride,
246
+ thinkingLevel: hasOwn(patch, 'thinkingLevel') ? patch.thinkingLevel : existing.thinkingLevel,
247
+ fastMode: hasOwn(patch, 'fastMode') ? patch.fastMode : existing.fastMode,
248
+ });
249
+ const stopPolicy = hasOwn(patch, 'stopPolicy') ? normalizeRalphStopPolicy(patch.stopPolicy ?? undefined) : existing.stopPolicy;
250
+ const target = patch.target ? normalizeRalphTarget(patch.target) : existing.target;
251
+ const next = { ...existing, name: patch.name !== undefined ? patch.name.trim() : existing.name, description: patch.description !== undefined ? patch.description?.trim() || undefined : existing.description, enabled: patch.enabled ?? existing.enabled, target, profile: patch.profile ?? existing.profile, prompt: patch.prompt ?? existing.prompt, maxIterations: hasOwn(patch, 'maxIterations') ? normalizeMaxIterations(patch.maxIterations ?? undefined) : existing.maxIterations, stopPolicy, modelOverride: runtimeOptions.modelOverride, thinkingLevel: runtimeOptions.thinkingLevel, fastMode: runtimeOptions.fastMode, updatedAt: nowIso(now) };
252
+ validateJobInput(next);
253
+ this.writeJob(next);
254
+ return this.getJob(id);
255
+ }
256
+ updateJobResources(id, resources, now = new Date()) {
257
+ const existing = this.getJob(id);
258
+ if (!existing)
259
+ return undefined;
260
+ const timestamp = nowIso(now);
261
+ this.db.prepare('UPDATE pibo_ralph_jobs SET resource_json = ?, updated_at = ? WHERE id = ?').run(resourceMetadataJson(resources), timestamp, id);
262
+ return this.getJob(id);
263
+ }
264
+ updateRunResources(input, now = new Date()) {
265
+ const clauses = ['id = ?'];
266
+ const values = [input.runId];
267
+ if (input.jobId) {
268
+ clauses.push('job_id = ?');
269
+ values.push(input.jobId);
270
+ }
271
+ const timestamp = nowIso(now);
272
+ const result = this.db.prepare(`UPDATE pibo_ralph_runs SET resource_json = ?, updated_at = ? WHERE ${clauses.join(' AND ')}`).run(resourceMetadataJson(input.resources), timestamp, ...values);
273
+ if (Number(result.changes ?? 0) === 0)
274
+ return undefined;
275
+ const row = this.db.prepare('SELECT * FROM pibo_ralph_runs WHERE id = ?').get(input.runId);
276
+ return row ? runFromRow(row) : undefined;
277
+ }
278
+ removeJob(id) { const result = this.db.prepare('DELETE FROM pibo_ralph_jobs WHERE id = ?').run(id); return Number(result.changes ?? 0) > 0; }
279
+ listRuns(input = {}) {
280
+ const clauses = [];
281
+ const values = [];
282
+ if (input.jobId) {
283
+ clauses.push('job_id = ?');
284
+ values.push(input.jobId);
285
+ }
286
+ const where = clauses.length ? `WHERE ${clauses.join(' AND ')}` : '';
287
+ return this.db.prepare(`SELECT * FROM pibo_ralph_runs ${where} ORDER BY created_at DESC LIMIT ?`).all(...values, Math.max(1, Math.min(input.limit ?? 100, 500))).map(runFromRow);
288
+ }
289
+ reserveRun(id, now = new Date()) { this.updateJob(id, { enabled: true }, now); return this.reserveJob(id, now); }
290
+ reserveDueRuns(limit, now = new Date()) {
291
+ const rows = this.db.prepare('SELECT * FROM pibo_ralph_jobs WHERE enabled = 1 ORDER BY updated_at ASC').all();
292
+ const result = [];
293
+ for (const row of rows) {
294
+ if (result.length >= limit)
295
+ break;
296
+ const reserved = this.reserveJob(row.id, now);
297
+ if (reserved)
298
+ result.push(reserved);
299
+ }
300
+ return result;
301
+ }
302
+ attachRunSession(jobId, runId, piboSessionId, now = new Date()) {
303
+ const timestamp = nowIso(now);
304
+ const job = this.getJob(jobId);
305
+ if (!job)
306
+ return;
307
+ this.db.prepare('UPDATE pibo_ralph_runs SET pibo_session_id = ?, updated_at = ? WHERE id = ?').run(piboSessionId, timestamp, runId);
308
+ this.updateJobStateLocked(jobId, { ...job.state, lastPiboSessionId: piboSessionId }, timestamp);
309
+ }
310
+ requestStop(id, now = new Date()) {
311
+ const job = this.getJob(id);
312
+ if (!job)
313
+ return undefined;
314
+ const state = { ...job.state, stopRequestedAt: nowIso(now) };
315
+ this.writeJob({ ...job, enabled: false, state, updatedAt: nowIso(now) });
316
+ return this.getJob(id);
317
+ }
318
+ requestCancel(id, now = new Date()) {
319
+ const job = this.getJob(id);
320
+ if (!job)
321
+ return undefined;
322
+ const state = { ...job.state, stopRequestedAt: nowIso(now), cancelRequestedAt: nowIso(now) };
323
+ this.writeJob({ ...job, enabled: false, state, updatedAt: nowIso(now) });
324
+ return this.getJob(id);
325
+ }
326
+ applyStopEvaluation(input, now = new Date()) {
327
+ const job = this.getJob(input.jobId);
328
+ if (!job)
329
+ return;
330
+ const timestamp = nowIso(now);
331
+ const state = { ...job.state, runningAt: undefined, conditionStates: input.conditionStates ?? job.state.conditionStates, lastStopEvaluation: input.evaluation };
332
+ this.db.prepare('UPDATE pibo_ralph_jobs SET enabled = ?, state_json = ?, updated_at = ? WHERE id = ?').run(input.disable ? 0 : job.enabled ? 1 : 0, JSON.stringify(state), timestamp, job.id);
333
+ }
334
+ completeRun(input, now = new Date()) {
335
+ const timestamp = nowIso(now);
336
+ const job = this.getJob(input.jobId);
337
+ if (!job)
338
+ return;
339
+ const completedIterations = (job.state.completedIterations ?? 0) + 1;
340
+ const reachedMaxIterations = job.maxIterations !== undefined && completedIterations >= job.maxIterations;
341
+ const shouldDisable = reachedMaxIterations || input.stopAfterRun === true || input.stopEvaluation?.finalAction === 'stop-after-run' || input.stopEvaluation?.finalAction === 'cancel-current-run';
342
+ const state = { ...job.state, runningAt: undefined, completedIterations, lastRunAt: timestamp, lastRunId: input.runId, lastStatus: input.status === 'error' ? 'error' : input.status === 'cancelled' ? 'cancelled' : 'ok', lastError: input.error, lastPiboSessionId: input.piboSessionId ?? job.state.lastPiboSessionId, consecutiveErrors: input.status === 'error' ? (job.state.consecutiveErrors ?? 0) + 1 : 0, conditionStates: input.conditionStates ?? job.state.conditionStates, lastStopEvaluation: input.stopEvaluation ?? job.state.lastStopEvaluation };
343
+ this.db.prepare('UPDATE pibo_ralph_runs SET status = ?, pibo_session_id = ?, reason = ?, error = ?, completed_at = ?, updated_at = ? WHERE id = ?').run(input.status, input.piboSessionId ?? null, input.reason ?? input.stopEvaluation?.reason ?? null, input.error ?? null, timestamp, timestamp, input.runId);
344
+ this.db.prepare('UPDATE pibo_ralph_jobs SET enabled = ?, state_json = ?, updated_at = ? WHERE id = ?').run(shouldDisable ? 0 : job.enabled ? 1 : 0, JSON.stringify(state), timestamp, job.id);
345
+ }
346
+ appendRunFact(input) {
347
+ if (!input.jobId.trim())
348
+ throw new Error('fact jobId is required');
349
+ if (!input.type.trim())
350
+ throw new Error('fact type is required');
351
+ if (!isJsonObject(input.payload))
352
+ throw new Error('fact payload must be an object');
353
+ const payloadJson = JSON.stringify(input.payload);
354
+ if (payloadJson.length > 16_384)
355
+ throw new Error('fact payload is too large');
356
+ const fact = { id: input.id ?? `rfact_${randomUUID()}`, jobId: input.jobId, runId: input.runId, piboSessionId: input.piboSessionId, type: input.type.trim(), source: input.source, payload: input.payload, createdAt: input.createdAt ?? nowIso() };
357
+ this.db.prepare('INSERT INTO pibo_ralph_run_facts (id, job_id, run_id, pibo_session_id, type, source, payload_json, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)').run(fact.id, fact.jobId, fact.runId ?? null, fact.piboSessionId ?? null, fact.type, fact.source, payloadJson, fact.createdAt);
358
+ return fact;
359
+ }
360
+ listRunFacts(input = {}) {
361
+ const clauses = [];
362
+ const values = [];
363
+ if (input.jobId) {
364
+ clauses.push('job_id = ?');
365
+ values.push(input.jobId);
366
+ }
367
+ if (input.runId) {
368
+ clauses.push('run_id = ?');
369
+ values.push(input.runId);
370
+ }
371
+ if (input.type) {
372
+ clauses.push('type = ?');
373
+ values.push(input.type);
374
+ }
375
+ const where = clauses.length ? `WHERE ${clauses.join(' AND ')}` : '';
376
+ return this.db.prepare(`SELECT * FROM pibo_ralph_run_facts ${where} ORDER BY created_at DESC LIMIT ?`).all(...values, Math.max(1, Math.min(input.limit ?? 100, 500))).map(factFromRow);
377
+ }
378
+ createFactReader(job) {
379
+ return { list: (input = {}) => this.listRunFacts({ jobId: job.id, type: input.type, runId: input.runId, limit: input.limit }), count: (input = {}) => this.listRunFacts({ jobId: job.id, type: input.type, runId: input.runId, limit: 500 }).length };
380
+ }
381
+ recoverInterruptedRuns(cutoff = new Date(Date.now() - 5 * 60_000)) { const cutoffIso = nowIso(cutoff); const rows = this.db.prepare("SELECT * FROM pibo_ralph_jobs WHERE json_extract(state_json, '$.runningAt') IS NOT NULL").all(); let recovered = 0; for (const row of rows) {
382
+ const job = jobFromRow(row);
383
+ if (!job.state.runningAt || job.state.runningAt > cutoffIso)
384
+ continue;
385
+ if (job.state.lastRunId) {
386
+ this.completeRun({ jobId: job.id, runId: job.state.lastRunId, status: 'error', error: 'Ralph run was interrupted by gateway restart', reason: 'interrupted' });
387
+ this.markInterruptedRunResourcesDirty(job, job.state.lastRunId);
388
+ }
389
+ recovered += 1;
390
+ } return recovered; }
391
+ status() { const jobs = this.listJobs({ includeDisabled: false }); return { jobs: jobs.length, running: jobs.filter((job) => job.state.runningAt).length }; }
392
+ markInterruptedRunResourcesDirty(job, runId) {
393
+ const runRow = this.db.prepare('SELECT * FROM pibo_ralph_runs WHERE id = ? AND job_id = ?').get(runId, job.id);
394
+ const resources = mergeResourceMetadata(job.resources, runRow ? runFromRow(runRow).resources : undefined);
395
+ if (!resources || (!resources.workerId && (resources.browserLeaseIds ?? []).length === 0))
396
+ return;
397
+ const nextResources = { ...resources, cleanupState: 'dirty', dirtyReason: 'Ralph run was interrupted before browser resource cleanup could be confirmed', updatedAt: nowIso() };
398
+ this.updateRunResources({ jobId: job.id, runId, resources: nextResources });
399
+ this.updateJobResources(job.id, nextResources);
400
+ }
401
+ reserveJob(id, now = new Date()) {
402
+ const timestamp = nowIso(now);
403
+ this.db.exec('BEGIN IMMEDIATE');
404
+ try {
405
+ const job = this.getJob(id);
406
+ if (!job || !job.enabled || job.state.runningAt) {
407
+ this.db.exec('COMMIT');
408
+ return undefined;
409
+ }
410
+ const run = this.createRunLocked(job, timestamp);
411
+ const state = { ...job.state, runningAt: timestamp, lastRunAt: timestamp, lastRunId: run.id };
412
+ this.updateJobStateLocked(job.id, state, timestamp);
413
+ this.db.exec('COMMIT');
414
+ return { job: { ...job, state, updatedAt: timestamp }, run };
415
+ }
416
+ catch (error) {
417
+ this.db.exec('ROLLBACK');
418
+ throw error;
419
+ }
420
+ }
421
+ applySchema() {
422
+ this.createFreshSchema();
423
+ this.ensureJobColumn('max_iterations', 'INTEGER');
424
+ this.ensureJobColumn('runtime_options_json', 'TEXT');
425
+ this.ensureJobColumn('stop_policy_json', 'TEXT');
426
+ this.ensureJobColumn('resource_json', 'TEXT');
427
+ this.ensureRunColumn('resource_json', 'TEXT');
428
+ }
429
+ createFreshSchema() {
430
+ this.db.exec(`CREATE TABLE IF NOT EXISTS pibo_ralph_jobs (id TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT, enabled INTEGER NOT NULL, target_json TEXT NOT NULL, profile TEXT NOT NULL, prompt TEXT NOT NULL, max_iterations INTEGER, runtime_options_json TEXT, stop_policy_json TEXT, resource_json TEXT, state_json TEXT NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL); CREATE INDEX IF NOT EXISTS idx_pibo_ralph_jobs_enabled ON pibo_ralph_jobs(enabled, updated_at DESC); CREATE TABLE IF NOT EXISTS pibo_ralph_runs (id TEXT PRIMARY KEY, job_id TEXT NOT NULL, pibo_session_id TEXT, status TEXT NOT NULL, reason TEXT, error TEXT, resource_json TEXT, started_at TEXT, completed_at TEXT, created_at TEXT NOT NULL, updated_at TEXT NOT NULL); CREATE INDEX IF NOT EXISTS idx_pibo_ralph_runs_job_created ON pibo_ralph_runs(job_id, created_at DESC); CREATE TABLE IF NOT EXISTS pibo_ralph_run_facts (id TEXT PRIMARY KEY, job_id TEXT NOT NULL, run_id TEXT, pibo_session_id TEXT, type TEXT NOT NULL, source TEXT NOT NULL, payload_json TEXT NOT NULL, created_at TEXT NOT NULL); CREATE INDEX IF NOT EXISTS idx_pibo_ralph_facts_job_created ON pibo_ralph_run_facts(job_id, created_at DESC); CREATE INDEX IF NOT EXISTS idx_pibo_ralph_facts_run_type ON pibo_ralph_run_facts(run_id, type, created_at DESC);`);
431
+ }
432
+ ensureJobColumn(name, definition) {
433
+ const columns = this.tableColumns('pibo_ralph_jobs');
434
+ if (!columns.has(name))
435
+ this.db.exec(`ALTER TABLE pibo_ralph_jobs ADD COLUMN ${name} ${definition}`);
436
+ }
437
+ ensureRunColumn(name, definition) {
438
+ const columns = this.tableColumns('pibo_ralph_runs');
439
+ if (!columns.has(name))
440
+ this.db.exec(`ALTER TABLE pibo_ralph_runs ADD COLUMN ${name} ${definition}`);
441
+ }
442
+ tableColumns(tableName) {
443
+ return new Set(this.db.prepare(`PRAGMA table_info(${tableName})`).all().map((column) => column.name));
444
+ }
445
+ insertJob(job) { this.db.prepare('INSERT INTO pibo_ralph_jobs (id, name, description, enabled, target_json, profile, prompt, max_iterations, runtime_options_json, stop_policy_json, resource_json, state_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').run(job.id, job.name, job.description ?? null, job.enabled ? 1 : 0, targetJson(job.target), job.profile, job.prompt, job.maxIterations ?? null, runtimeOptionsJson(job), stopPolicyJson(job.stopPolicy), resourceMetadataJson(job.resources), JSON.stringify(job.state), job.createdAt, job.updatedAt); }
446
+ writeJob(job) { this.db.prepare('UPDATE pibo_ralph_jobs SET name = ?, description = ?, enabled = ?, target_json = ?, profile = ?, prompt = ?, max_iterations = ?, runtime_options_json = ?, stop_policy_json = ?, resource_json = ?, state_json = ?, updated_at = ? WHERE id = ?').run(job.name, job.description ?? null, job.enabled ? 1 : 0, targetJson(job.target), job.profile, job.prompt, job.maxIterations ?? null, runtimeOptionsJson(job), stopPolicyJson(job.stopPolicy), resourceMetadataJson(job.resources), JSON.stringify(job.state), job.updatedAt, job.id); }
447
+ updateJobStateLocked(id, state, updatedAt) { this.db.prepare('UPDATE pibo_ralph_jobs SET state_json = ?, updated_at = ? WHERE id = ?').run(JSON.stringify(state), updatedAt, id); }
448
+ createRunLocked(job, timestamp) { const run = { id: `rrun_${randomUUID()}`, jobId: job.id, status: 'running', startedAt: timestamp, ...(job.resources ? { resources: job.resources } : {}), createdAt: timestamp, updatedAt: timestamp }; this.db.prepare('INSERT INTO pibo_ralph_runs (id, job_id, pibo_session_id, status, reason, error, resource_json, started_at, completed_at, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').run(run.id, run.jobId, null, run.status, null, null, resourceMetadataJson(run.resources), run.startedAt ?? null, null, run.createdAt, run.updatedAt); return run; }
449
+ }
450
+ export function createDefaultPiboRalphStore(options = {}) { return new PiboRalphStore(options); }
@@ -0,0 +1,200 @@
1
+ const promiseCompletePolicy = {
2
+ mode: 'any',
3
+ conditions: [{ id: 'promise-complete', type: 'pibo.ralph.promise-complete' }],
4
+ };
5
+ const singleRunPolicy = {
6
+ mode: 'any',
7
+ conditions: [{ id: 'max-iterations', type: 'pibo.ralph.max-iterations' }],
8
+ };
9
+ function markdown(strings) {
10
+ return String.raw(strings).replaceAll('\\`', '`');
11
+ }
12
+ export const BUILT_IN_RALPH_JOB_TEMPLATES = [
13
+ {
14
+ id: 'prd-single-story-standard',
15
+ name: 'PRD single story standard',
16
+ description: 'Default Ralph loop: pick the highest-priority failing PRD user story, implement exactly one story, test, commit, update progress, then stop or continue on the next run.',
17
+ category: 'prd',
18
+ job: {
19
+ name: 'Ralph PRD single story',
20
+ description: 'One PRD user story per Ralph iteration.',
21
+ prompt: markdown `# Ralph Auftrag: <Project / Change Name>
22
+
23
+ ## Worktree
24
+
25
+ Work from the host worktree, not from a container copy:
26
+
27
+ \`\`\`bash
28
+ cd <host-worktree>
29
+ \`\`\`
30
+
31
+ Branch: \`<branch-name>\`
32
+ Base: \`<base-branch-or-commit>\`
33
+ PRDs: \`<path-to-prds>/prd_*.json\`
34
+ Progress log: \`<path-to-prds>/progress.txt\`
35
+
36
+ If a container is required for build, gateway, or browser checks, use it only for running commands. Edit files and run git commands in the host worktree. Do not edit \`/app\` inside a container.
37
+
38
+ ## Ralph Agent Instructions
39
+
40
+ You are an autonomous coding agent working on a software project.
41
+
42
+ ### Your Task
43
+
44
+ 1. Work from the host worktree above.
45
+ 2. Read all PRD JSON files matching \`<path-to-prds>/prd_*.json\`.
46
+ 3. Read the progress log. If it does not exist, create it.
47
+ 4. Read the \`## Codebase Patterns\` section at the top of the progress log if present.
48
+ 5. Pick the highest-priority user story where \`passes: false\`.
49
+ 6. Implement that single user story only.
50
+ 7. Run quality checks:
51
+ - Always run \`npm run typecheck\`.
52
+ - Run relevant tests for touched areas.
53
+ - For UI stories, run browser verification in the configured dev container/browser environment.
54
+ 8. If checks pass, update the PRD JSON to set \`passes: true\` for the completed story.
55
+ 9. Commit all changes from the host worktree with message:
56
+ \`feat: [Story ID] - [Story Title]\`
57
+ 10. Append your progress to the progress log.
58
+
59
+ ### Progress Report Format
60
+
61
+ Append to the progress log. Never replace; always append.
62
+
63
+ \`\`\`md
64
+ ## [Date/Time] - [Story ID]
65
+ - What was implemented
66
+ - Files changed
67
+ - Quality checks run
68
+ - Browser verification, if UI changed
69
+ - **Learnings for future iterations:**
70
+ - Patterns discovered
71
+ - Gotchas encountered
72
+ - Useful context
73
+ ---
74
+ \`\`\`
75
+
76
+ ### Consolidate Patterns
77
+
78
+ If you discover a reusable pattern, add it to the \`## Codebase Patterns\` section at the top of the progress log. Only add general reusable patterns, not story-specific notes.
79
+
80
+ ## Quality Requirements
81
+
82
+ - All commits must pass quality checks.
83
+ - Do not commit broken code.
84
+ - Keep changes focused and minimal.
85
+ - Follow existing code patterns.
86
+ - For UI stories, browser verification is mandatory.
87
+
88
+ ## Stop Condition
89
+
90
+ After completing one user story, check whether all stories in all PRD JSON files have \`passes: true\`.
91
+
92
+ If all stories are complete and passing, reply with the XML completion marker on its own line. Compose it from the opening tag \`<promise>\`, the word \`COMPLETE\`, and the closing tag \`</promise>\`.
93
+
94
+ Do not quote, negate, explain, or mention that literal marker unless all stories are complete and you intend to stop the job. If any story remains with \`passes: false\`, end normally so another iteration can pick up the next story and say only that the completion marker was omitted.`,
95
+ stopPolicy: promiseCompletePolicy,
96
+ },
97
+ },
98
+ {
99
+ id: 'prd-batch-stories',
100
+ name: 'PRD batch stories',
101
+ description: 'Batch loop: implement several failing PRD user stories in priority order in one Ralph run, committing after each completed story.',
102
+ category: 'prd',
103
+ job: {
104
+ name: 'Ralph PRD batch',
105
+ description: 'Multiple PRD user stories per Ralph run.',
106
+ prompt: markdown `# Ralph Auftrag: <Project / Change Name> Batch
107
+
108
+ ## Worktree
109
+
110
+ Work from the host worktree:
111
+
112
+ \`\`\`bash
113
+ cd <host-worktree>
114
+ \`\`\`
115
+
116
+ PRDs: \`<path-to-prds>/prd_*.json\`
117
+ Progress log: \`<path-to-prds>/progress.txt\`
118
+ Batch limit: \`<max-stories-this-run>\`
119
+
120
+ ## Task
121
+
122
+ 1. Read the PRD JSON files and progress log.
123
+ 2. Work through failing user stories in priority order.
124
+ 3. Complete up to \`<max-stories-this-run>\` stories in this run.
125
+ 4. Keep each story isolated:
126
+ - implement one story;
127
+ - run relevant checks;
128
+ - set that story's \`passes\` to \`true\` only after checks pass;
129
+ - commit with \`feat: [Story ID] - [Story Title]\`;
130
+ - append a progress-log entry.
131
+ 5. Stop early if a story is blocked, ambiguous, or tests fail. Do not continue with later stories after a failed story.
132
+
133
+ ## Quality Requirements
134
+
135
+ - Always run \`npm run typecheck\` before each story commit unless the repository has a documented narrower check for this batch.
136
+ - Run relevant tests for touched areas.
137
+ - Browser verification is mandatory for UI changes.
138
+ - Keep changes focused; do not bundle unrelated refactors.
139
+
140
+ ## Stop Condition
141
+
142
+ If all stories in all PRD JSON files are complete and passing, reply with the XML completion marker on its own line. Compose it from the opening tag \`<promise>\`, the word \`COMPLETE\`, and the closing tag \`</promise>\`.
143
+
144
+ Do not quote, negate, explain, or mention that literal marker unless all stories are complete and you intend to stop the job. Otherwise report the stories completed and the next remaining failing story, and say only that the completion marker was omitted.`,
145
+ stopPolicy: promiseCompletePolicy,
146
+ },
147
+ },
148
+ {
149
+ id: 'single-run-objective',
150
+ name: 'Single-run objective',
151
+ description: 'Non-PRD template for one focused objective with explicit done criteria. Stops after one completed run attempt by max-iterations.',
152
+ category: 'general',
153
+ job: {
154
+ name: 'Ralph single-run objective',
155
+ description: 'One focused non-PRD objective.',
156
+ maxIterations: 1,
157
+ stopPolicy: singleRunPolicy,
158
+ prompt: markdown `# Ralph Auftrag: <Objective>
159
+
160
+ ## Worktree
161
+
162
+ \`\`\`bash
163
+ cd <host-worktree>
164
+ \`\`\`
165
+
166
+ Branch: \`<branch-name>\`
167
+
168
+ ## Objective
169
+
170
+ <Describe the concrete outcome.>
171
+
172
+ ## Done Criteria
173
+
174
+ - <Pass/fail criterion 1>
175
+ - <Pass/fail criterion 2>
176
+ - <Required verification command or manual check>
177
+
178
+ ## Instructions
179
+
180
+ 1. Inspect the relevant code and docs before editing.
181
+ 2. State assumptions in code comments or docs only when they matter for maintainers.
182
+ 3. Implement the smallest focused change that satisfies the done criteria.
183
+ 4. Run \`npm run typecheck\` and relevant tests.
184
+ 5. Commit with a concise message if checks pass.
185
+ 6. End with a short report listing files changed and verification run.
186
+
187
+ This is not a PRD loop. Do not edit PRD JSON progress unless the objective explicitly asks for it.`,
188
+ },
189
+ },
190
+ ];
191
+ export function listRalphJobTemplates() {
192
+ return BUILT_IN_RALPH_JOB_TEMPLATES.map((template) => cloneTemplate(template));
193
+ }
194
+ export function getRalphJobTemplate(id) {
195
+ const template = BUILT_IN_RALPH_JOB_TEMPLATES.find((item) => item.id === id);
196
+ return template ? cloneTemplate(template) : undefined;
197
+ }
198
+ function cloneTemplate(template) {
199
+ return JSON.parse(JSON.stringify(template));
200
+ }
@@ -0,0 +1 @@
1
+ export {};