@mobrienv/autoloop 0.4.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (441) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -14
  3. package/bin/autoloop +1 -1
  4. package/dist/index.d.ts +6 -0
  5. package/dist/index.js +19 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/testing/mock-backend.js +3 -5
  8. package/dist/testing/mock-backend.js.map +1 -1
  9. package/package.json +32 -23
  10. package/plugins/autoloop/.claude-plugin/plugin.json +1 -1
  11. package/dist/agent-map.d.ts +0 -10
  12. package/dist/agent-map.js +0 -58
  13. package/dist/agent-map.js.map +0 -1
  14. package/dist/backend/acp-client.d.ts +0 -38
  15. package/dist/backend/acp-client.js +0 -293
  16. package/dist/backend/acp-client.js.map +0 -1
  17. package/dist/backend/index.d.ts +0 -10
  18. package/dist/backend/index.js +0 -71
  19. package/dist/backend/index.js.map +0 -1
  20. package/dist/backend/kiro-bridge.d.ts +0 -19
  21. package/dist/backend/kiro-bridge.js +0 -114
  22. package/dist/backend/kiro-bridge.js.map +0 -1
  23. package/dist/backend/kiro-worker.d.ts +0 -1
  24. package/dist/backend/kiro-worker.js +0 -96
  25. package/dist/backend/kiro-worker.js.map +0 -1
  26. package/dist/backend/run-command.d.ts +0 -7
  27. package/dist/backend/run-command.js +0 -50
  28. package/dist/backend/run-command.js.map +0 -1
  29. package/dist/backend/run-kiro.d.ts +0 -3
  30. package/dist/backend/run-kiro.js +0 -16
  31. package/dist/backend/run-kiro.js.map +0 -1
  32. package/dist/backend/run-mock.d.ts +0 -1
  33. package/dist/backend/run-mock.js +0 -6
  34. package/dist/backend/run-mock.js.map +0 -1
  35. package/dist/backend/run-pi.d.ts +0 -5
  36. package/dist/backend/run-pi.js +0 -5
  37. package/dist/backend/run-pi.js.map +0 -1
  38. package/dist/backend/types.d.ts +0 -21
  39. package/dist/backend/types.js +0 -2
  40. package/dist/backend/types.js.map +0 -1
  41. package/dist/chains/budget.d.ts +0 -7
  42. package/dist/chains/budget.js +0 -54
  43. package/dist/chains/budget.js.map +0 -1
  44. package/dist/chains/load.d.ts +0 -18
  45. package/dist/chains/load.js +0 -129
  46. package/dist/chains/load.js.map +0 -1
  47. package/dist/chains/render.d.ts +0 -2
  48. package/dist/chains/render.js +0 -74
  49. package/dist/chains/render.js.map +0 -1
  50. package/dist/chains/run.d.ts +0 -17
  51. package/dist/chains/run.js +0 -260
  52. package/dist/chains/run.js.map +0 -1
  53. package/dist/chains/types.d.ts +0 -38
  54. package/dist/chains/types.js +0 -2
  55. package/dist/chains/types.js.map +0 -1
  56. package/dist/chains.d.ts +0 -6
  57. package/dist/chains.js +0 -5
  58. package/dist/chains.js.map +0 -1
  59. package/dist/cli/color.d.ts +0 -6
  60. package/dist/cli/color.js +0 -40
  61. package/dist/cli/color.js.map +0 -1
  62. package/dist/commands/chain.d.ts +0 -1
  63. package/dist/commands/chain.js +0 -53
  64. package/dist/commands/chain.js.map +0 -1
  65. package/dist/commands/config.d.ts +0 -1
  66. package/dist/commands/config.js +0 -74
  67. package/dist/commands/config.js.map +0 -1
  68. package/dist/commands/dashboard.d.ts +0 -1
  69. package/dist/commands/dashboard.js +0 -68
  70. package/dist/commands/dashboard.js.map +0 -1
  71. package/dist/commands/guide.d.ts +0 -1
  72. package/dist/commands/guide.js +0 -33
  73. package/dist/commands/guide.js.map +0 -1
  74. package/dist/commands/inspect.d.ts +0 -1
  75. package/dist/commands/inspect.js +0 -243
  76. package/dist/commands/inspect.js.map +0 -1
  77. package/dist/commands/list.d.ts +0 -1
  78. package/dist/commands/list.js +0 -15
  79. package/dist/commands/list.js.map +0 -1
  80. package/dist/commands/loops.d.ts +0 -1
  81. package/dist/commands/loops.js +0 -72
  82. package/dist/commands/loops.js.map +0 -1
  83. package/dist/commands/memory.d.ts +0 -1
  84. package/dist/commands/memory.js +0 -65
  85. package/dist/commands/memory.js.map +0 -1
  86. package/dist/commands/pi-adapter.d.ts +0 -1
  87. package/dist/commands/pi-adapter.js +0 -6
  88. package/dist/commands/pi-adapter.js.map +0 -1
  89. package/dist/commands/run.d.ts +0 -1
  90. package/dist/commands/run.js +0 -292
  91. package/dist/commands/run.js.map +0 -1
  92. package/dist/commands/runs.d.ts +0 -1
  93. package/dist/commands/runs.js +0 -50
  94. package/dist/commands/runs.js.map +0 -1
  95. package/dist/commands/task.d.ts +0 -1
  96. package/dist/commands/task.js +0 -74
  97. package/dist/commands/task.js.map +0 -1
  98. package/dist/commands/worktree.d.ts +0 -1
  99. package/dist/commands/worktree.js +0 -162
  100. package/dist/commands/worktree.js.map +0 -1
  101. package/dist/config.d.ts +0 -31
  102. package/dist/config.js +0 -261
  103. package/dist/config.js.map +0 -1
  104. package/dist/dashboard/app.d.ts +0 -12
  105. package/dist/dashboard/app.js +0 -23
  106. package/dist/dashboard/app.js.map +0 -1
  107. package/dist/dashboard/routes/api.d.ts +0 -3
  108. package/dist/dashboard/routes/api.js +0 -186
  109. package/dist/dashboard/routes/api.js.map +0 -1
  110. package/dist/dashboard/routes/pages.d.ts +0 -2
  111. package/dist/dashboard/routes/pages.js +0 -16
  112. package/dist/dashboard/routes/pages.js.map +0 -1
  113. package/dist/dashboard/views/alpine-vendor.d.ts +0 -1
  114. package/dist/dashboard/views/alpine-vendor.js +0 -10
  115. package/dist/dashboard/views/alpine-vendor.js.map +0 -1
  116. package/dist/dashboard/views/shell.d.ts +0 -1
  117. package/dist/dashboard/views/shell.js +0 -1062
  118. package/dist/dashboard/views/shell.js.map +0 -1
  119. package/dist/events/decode.d.ts +0 -2
  120. package/dist/events/decode.js +0 -45
  121. package/dist/events/decode.js.map +0 -1
  122. package/dist/events/encode.d.ts +0 -2
  123. package/dist/events/encode.js +0 -33
  124. package/dist/events/encode.js.map +0 -1
  125. package/dist/events/guards.d.ts +0 -5
  126. package/dist/events/guards.js +0 -42
  127. package/dist/events/guards.js.map +0 -1
  128. package/dist/events/types.d.ts +0 -27
  129. package/dist/events/types.js +0 -2
  130. package/dist/events/types.js.map +0 -1
  131. package/dist/harness/artifacts.d.ts +0 -50
  132. package/dist/harness/artifacts.js +0 -333
  133. package/dist/harness/artifacts.js.map +0 -1
  134. package/dist/harness/config-helpers.d.ts +0 -35
  135. package/dist/harness/config-helpers.js +0 -409
  136. package/dist/harness/config-helpers.js.map +0 -1
  137. package/dist/harness/coordination.d.ts +0 -1
  138. package/dist/harness/coordination.js +0 -127
  139. package/dist/harness/coordination.js.map +0 -1
  140. package/dist/harness/display.d.ts +0 -21
  141. package/dist/harness/display.js +0 -176
  142. package/dist/harness/display.js.map +0 -1
  143. package/dist/harness/emit.d.ts +0 -15
  144. package/dist/harness/emit.js +0 -240
  145. package/dist/harness/emit.js.map +0 -1
  146. package/dist/harness/index.d.ts +0 -20
  147. package/dist/harness/index.js +0 -311
  148. package/dist/harness/index.js.map +0 -1
  149. package/dist/harness/iteration.d.ts +0 -16
  150. package/dist/harness/iteration.js +0 -131
  151. package/dist/harness/iteration.js.map +0 -1
  152. package/dist/harness/journal-format.d.ts +0 -25
  153. package/dist/harness/journal-format.js +0 -153
  154. package/dist/harness/journal-format.js.map +0 -1
  155. package/dist/harness/journal.d.ts +0 -31
  156. package/dist/harness/journal.js +0 -178
  157. package/dist/harness/journal.js.map +0 -1
  158. package/dist/harness/metareview.d.ts +0 -4
  159. package/dist/harness/metareview.js +0 -48
  160. package/dist/harness/metareview.js.map +0 -1
  161. package/dist/harness/metrics.d.ts +0 -12
  162. package/dist/harness/metrics.js +0 -180
  163. package/dist/harness/metrics.js.map +0 -1
  164. package/dist/harness/parallel.d.ts +0 -37
  165. package/dist/harness/parallel.js +0 -237
  166. package/dist/harness/parallel.js.map +0 -1
  167. package/dist/harness/prompt.d.ts +0 -46
  168. package/dist/harness/prompt.js +0 -403
  169. package/dist/harness/prompt.js.map +0 -1
  170. package/dist/harness/scratchpad.d.ts +0 -2
  171. package/dist/harness/scratchpad.js +0 -67
  172. package/dist/harness/scratchpad.js.map +0 -1
  173. package/dist/harness/stop.d.ts +0 -5
  174. package/dist/harness/stop.js +0 -70
  175. package/dist/harness/stop.js.map +0 -1
  176. package/dist/harness/tools.d.ts +0 -3
  177. package/dist/harness/tools.js +0 -65
  178. package/dist/harness/tools.js.map +0 -1
  179. package/dist/harness/types.d.ts +0 -110
  180. package/dist/harness/types.js +0 -2
  181. package/dist/harness/types.js.map +0 -1
  182. package/dist/harness/wave/finalize-wave.d.ts +0 -9
  183. package/dist/harness/wave/finalize-wave.js +0 -87
  184. package/dist/harness/wave/finalize-wave.js.map +0 -1
  185. package/dist/harness/wave/launch-branches.d.ts +0 -6
  186. package/dist/harness/wave/launch-branches.js +0 -314
  187. package/dist/harness/wave/launch-branches.js.map +0 -1
  188. package/dist/harness/wave/parse-objectives.d.ts +0 -3
  189. package/dist/harness/wave/parse-objectives.js +0 -32
  190. package/dist/harness/wave/parse-objectives.js.map +0 -1
  191. package/dist/harness/wave/types.d.ts +0 -43
  192. package/dist/harness/wave/types.js +0 -2
  193. package/dist/harness/wave/types.js.map +0 -1
  194. package/dist/harness/wave.d.ts +0 -6
  195. package/dist/harness/wave.js +0 -159
  196. package/dist/harness/wave.js.map +0 -1
  197. package/dist/isolation/index.d.ts +0 -4
  198. package/dist/isolation/index.js +0 -3
  199. package/dist/isolation/index.js.map +0 -1
  200. package/dist/isolation/resolve.d.ts +0 -39
  201. package/dist/isolation/resolve.js +0 -118
  202. package/dist/isolation/resolve.js.map +0 -1
  203. package/dist/isolation/run-scope.d.ts +0 -21
  204. package/dist/isolation/run-scope.js +0 -50
  205. package/dist/isolation/run-scope.js.map +0 -1
  206. package/dist/json.d.ts +0 -8
  207. package/dist/json.js +0 -82
  208. package/dist/json.js.map +0 -1
  209. package/dist/loops/health.d.ts +0 -17
  210. package/dist/loops/health.js +0 -152
  211. package/dist/loops/health.js.map +0 -1
  212. package/dist/loops/list.d.ts +0 -6
  213. package/dist/loops/list.js +0 -21
  214. package/dist/loops/list.js.map +0 -1
  215. package/dist/loops/policy.d.ts +0 -6
  216. package/dist/loops/policy.js +0 -41
  217. package/dist/loops/policy.js.map +0 -1
  218. package/dist/loops/render.d.ts +0 -19
  219. package/dist/loops/render.js +0 -100
  220. package/dist/loops/render.js.map +0 -1
  221. package/dist/loops/show.d.ts +0 -8
  222. package/dist/loops/show.js +0 -31
  223. package/dist/loops/show.js.map +0 -1
  224. package/dist/loops/watch.d.ts +0 -14
  225. package/dist/loops/watch.js +0 -143
  226. package/dist/loops/watch.js.map +0 -1
  227. package/dist/main.d.ts +0 -1
  228. package/dist/main.js +0 -148
  229. package/dist/main.js.map +0 -1
  230. package/dist/markdown.d.ts +0 -10
  231. package/dist/markdown.js +0 -66
  232. package/dist/markdown.js.map +0 -1
  233. package/dist/memory-render.d.ts +0 -6
  234. package/dist/memory-render.js +0 -81
  235. package/dist/memory-render.js.map +0 -1
  236. package/dist/memory.d.ts +0 -22
  237. package/dist/memory.js +0 -318
  238. package/dist/memory.js.map +0 -1
  239. package/dist/pi-adapter.d.ts +0 -1
  240. package/dist/pi-adapter.js +0 -220
  241. package/dist/pi-adapter.js.map +0 -1
  242. package/dist/profiles.d.ts +0 -12
  243. package/dist/profiles.js +0 -71
  244. package/dist/profiles.js.map +0 -1
  245. package/dist/registry/derive.d.ts +0 -8
  246. package/dist/registry/derive.js +0 -88
  247. package/dist/registry/derive.js.map +0 -1
  248. package/dist/registry/discover.d.ts +0 -20
  249. package/dist/registry/discover.js +0 -98
  250. package/dist/registry/discover.js.map +0 -1
  251. package/dist/registry/harness.d.ts +0 -7
  252. package/dist/registry/harness.js +0 -63
  253. package/dist/registry/harness.js.map +0 -1
  254. package/dist/registry/index.d.ts +0 -6
  255. package/dist/registry/index.js +0 -6
  256. package/dist/registry/index.js.map +0 -1
  257. package/dist/registry/read.d.ts +0 -11
  258. package/dist/registry/read.js +0 -50
  259. package/dist/registry/read.js.map +0 -1
  260. package/dist/registry/rebuild.d.ts +0 -5
  261. package/dist/registry/rebuild.js +0 -22
  262. package/dist/registry/rebuild.js.map +0 -1
  263. package/dist/registry/types.d.ts +0 -28
  264. package/dist/registry/types.js +0 -2
  265. package/dist/registry/types.js.map +0 -1
  266. package/dist/registry/update.d.ts +0 -2
  267. package/dist/registry/update.js +0 -7
  268. package/dist/registry/update.js.map +0 -1
  269. package/dist/tasks-render.d.ts +0 -2
  270. package/dist/tasks-render.js +0 -44
  271. package/dist/tasks-render.js.map +0 -1
  272. package/dist/tasks.d.ts +0 -24
  273. package/dist/tasks.js +0 -184
  274. package/dist/tasks.js.map +0 -1
  275. package/dist/topology.d.ts +0 -31
  276. package/dist/topology.js +0 -309
  277. package/dist/topology.js.map +0 -1
  278. package/dist/usage.d.ts +0 -9
  279. package/dist/usage.js +0 -160
  280. package/dist/usage.js.map +0 -1
  281. package/dist/utils.d.ts +0 -21
  282. package/dist/utils.js +0 -349
  283. package/dist/utils.js.map +0 -1
  284. package/dist/worktree/clean.d.ts +0 -12
  285. package/dist/worktree/clean.js +0 -113
  286. package/dist/worktree/clean.js.map +0 -1
  287. package/dist/worktree/create.d.ts +0 -14
  288. package/dist/worktree/create.js +0 -71
  289. package/dist/worktree/create.js.map +0 -1
  290. package/dist/worktree/index.d.ts +0 -10
  291. package/dist/worktree/index.js +0 -6
  292. package/dist/worktree/index.js.map +0 -1
  293. package/dist/worktree/list.d.ts +0 -9
  294. package/dist/worktree/list.js +0 -24
  295. package/dist/worktree/list.js.map +0 -1
  296. package/dist/worktree/merge.d.ts +0 -11
  297. package/dist/worktree/merge.js +0 -129
  298. package/dist/worktree/merge.js.map +0 -1
  299. package/dist/worktree/meta.d.ts +0 -17
  300. package/dist/worktree/meta.js +0 -34
  301. package/dist/worktree/meta.js.map +0 -1
  302. package/presets/autocode/README.md +0 -81
  303. package/presets/autocode/autoloops.toml +0 -30
  304. package/presets/autocode/harness.md +0 -26
  305. package/presets/autocode/miniloops.toml +0 -22
  306. package/presets/autocode/roles/build.md +0 -34
  307. package/presets/autocode/roles/critic.md +0 -40
  308. package/presets/autocode/roles/finalizer.md +0 -43
  309. package/presets/autocode/roles/planner.md +0 -40
  310. package/presets/autocode/topology.toml +0 -32
  311. package/presets/autodebug/README.md +0 -50
  312. package/presets/autodebug/autoloops.toml +0 -18
  313. package/presets/autodebug/harness.md +0 -31
  314. package/presets/autodebug/roles/fixer.md +0 -58
  315. package/presets/autodebug/roles/investigator.md +0 -52
  316. package/presets/autodebug/roles/strategist.md +0 -45
  317. package/presets/autodebug/roles/verifier.md +0 -66
  318. package/presets/autodebug/topology.toml +0 -34
  319. package/presets/autodoc/README.md +0 -42
  320. package/presets/autodoc/autoloops.toml +0 -21
  321. package/presets/autodoc/harness.md +0 -19
  322. package/presets/autodoc/miniloops.toml +0 -21
  323. package/presets/autodoc/roles/auditor.md +0 -39
  324. package/presets/autodoc/roles/checker.md +0 -43
  325. package/presets/autodoc/roles/publisher.md +0 -51
  326. package/presets/autodoc/roles/writer.md +0 -37
  327. package/presets/autodoc/topology.toml +0 -31
  328. package/presets/autofix/README.md +0 -56
  329. package/presets/autofix/autoloops.toml +0 -24
  330. package/presets/autofix/harness.md +0 -25
  331. package/presets/autofix/miniloops.toml +0 -21
  332. package/presets/autofix/roles/closer.md +0 -48
  333. package/presets/autofix/roles/diagnoser.md +0 -43
  334. package/presets/autofix/roles/fixer.md +0 -28
  335. package/presets/autofix/roles/verifier.md +0 -31
  336. package/presets/autofix/topology.toml +0 -33
  337. package/presets/autoideas/README.md +0 -73
  338. package/presets/autoideas/autoloops.toml +0 -18
  339. package/presets/autoideas/harness.md +0 -31
  340. package/presets/autoideas/miniloops.toml +0 -18
  341. package/presets/autoideas/roles/analyst.md +0 -32
  342. package/presets/autoideas/roles/reviewer.md +0 -36
  343. package/presets/autoideas/roles/scanner.md +0 -26
  344. package/presets/autoideas/roles/synthesizer.md +0 -61
  345. package/presets/autoideas/topology.toml +0 -32
  346. package/presets/automerge/README.md +0 -3
  347. package/presets/automerge/autoloops.toml +0 -12
  348. package/presets/automerge/harness.md +0 -10
  349. package/presets/automerge/miniloops.toml +0 -12
  350. package/presets/automerge/roles/merge.md +0 -10
  351. package/presets/automerge/topology.toml +0 -10
  352. package/presets/autoperf/README.md +0 -56
  353. package/presets/autoperf/autoloops.toml +0 -21
  354. package/presets/autoperf/harness.md +0 -21
  355. package/presets/autoperf/miniloops.toml +0 -21
  356. package/presets/autoperf/roles/judge.md +0 -38
  357. package/presets/autoperf/roles/measurer.md +0 -36
  358. package/presets/autoperf/roles/optimizer.md +0 -35
  359. package/presets/autoperf/roles/profiler.md +0 -38
  360. package/presets/autoperf/topology.toml +0 -32
  361. package/presets/autopr/README.md +0 -99
  362. package/presets/autopr/autoloops.toml +0 -22
  363. package/presets/autopr/harness.md +0 -27
  364. package/presets/autopr/miniloops.toml +0 -22
  365. package/presets/autopr/roles/collector.md +0 -55
  366. package/presets/autopr/roles/drafter.md +0 -38
  367. package/presets/autopr/roles/publisher.md +0 -28
  368. package/presets/autopr/roles/validator.md +0 -31
  369. package/presets/autopr/topology.toml +0 -32
  370. package/presets/autopreset/README.md +0 -35
  371. package/presets/autopreset/autoloops.toml +0 -18
  372. package/presets/autopreset/harness.md +0 -38
  373. package/presets/autopreset/roles/designer.md +0 -33
  374. package/presets/autopreset/roles/finalizer.md +0 -23
  375. package/presets/autopreset/roles/generator.md +0 -34
  376. package/presets/autopreset/roles/validator.md +0 -31
  377. package/presets/autopreset/topology.toml +0 -32
  378. package/presets/autoqa/README.md +0 -105
  379. package/presets/autoqa/autoloops.toml +0 -21
  380. package/presets/autoqa/harness.md +0 -52
  381. package/presets/autoqa/miniloops.toml +0 -21
  382. package/presets/autoqa/roles/executor.md +0 -96
  383. package/presets/autoqa/roles/inspector.md +0 -100
  384. package/presets/autoqa/roles/planner.md +0 -87
  385. package/presets/autoqa/roles/reporter.md +0 -117
  386. package/presets/autoqa/topology.toml +0 -31
  387. package/presets/autoresearch/README.md +0 -63
  388. package/presets/autoresearch/autoloops.toml +0 -18
  389. package/presets/autoresearch/harness.md +0 -28
  390. package/presets/autoresearch/miniloops.toml +0 -18
  391. package/presets/autoresearch/roles/benchmarker.md +0 -34
  392. package/presets/autoresearch/roles/evaluator.md +0 -33
  393. package/presets/autoresearch/roles/implementer.md +0 -26
  394. package/presets/autoresearch/roles/strategist.md +0 -43
  395. package/presets/autoresearch/topology.toml +0 -31
  396. package/presets/autoreview/README.md +0 -51
  397. package/presets/autoreview/autoloops.toml +0 -21
  398. package/presets/autoreview/harness.md +0 -20
  399. package/presets/autoreview/miniloops.toml +0 -21
  400. package/presets/autoreview/roles/checker.md +0 -36
  401. package/presets/autoreview/roles/reader.md +0 -33
  402. package/presets/autoreview/roles/suggester.md +0 -26
  403. package/presets/autoreview/roles/summarizer.md +0 -57
  404. package/presets/autoreview/topology.toml +0 -31
  405. package/presets/autosec/README.md +0 -51
  406. package/presets/autosec/autoloops.toml +0 -21
  407. package/presets/autosec/harness.md +0 -20
  408. package/presets/autosec/miniloops.toml +0 -21
  409. package/presets/autosec/roles/analyst.md +0 -38
  410. package/presets/autosec/roles/hardener.md +0 -36
  411. package/presets/autosec/roles/reporter.md +0 -63
  412. package/presets/autosec/roles/scanner.md +0 -38
  413. package/presets/autosec/topology.toml +0 -31
  414. package/presets/autosimplify/README.md +0 -83
  415. package/presets/autosimplify/autoloops.toml +0 -26
  416. package/presets/autosimplify/harness.md +0 -25
  417. package/presets/autosimplify/miniloops.toml +0 -22
  418. package/presets/autosimplify/roles/reviewer.md +0 -38
  419. package/presets/autosimplify/roles/scoper.md +0 -42
  420. package/presets/autosimplify/roles/simplifier.md +0 -51
  421. package/presets/autosimplify/roles/verifier.md +0 -40
  422. package/presets/autosimplify/topology.toml +0 -32
  423. package/presets/autospec/README.md +0 -84
  424. package/presets/autospec/autoloops.toml +0 -21
  425. package/presets/autospec/harness.md +0 -23
  426. package/presets/autospec/miniloops.toml +0 -21
  427. package/presets/autospec/roles/clarifier.md +0 -39
  428. package/presets/autospec/roles/critic.md +0 -41
  429. package/presets/autospec/roles/designer.md +0 -37
  430. package/presets/autospec/roles/planner.md +0 -38
  431. package/presets/autospec/roles/researcher.md +0 -33
  432. package/presets/autospec/topology.toml +0 -38
  433. package/presets/autotest/README.md +0 -55
  434. package/presets/autotest/autoloops.toml +0 -21
  435. package/presets/autotest/harness.md +0 -21
  436. package/presets/autotest/miniloops.toml +0 -21
  437. package/presets/autotest/roles/assessor.md +0 -57
  438. package/presets/autotest/roles/runner.md +0 -31
  439. package/presets/autotest/roles/surveyor.md +0 -39
  440. package/presets/autotest/roles/writer.md +0 -37
  441. package/presets/autotest/topology.toml +0 -32
@@ -1,1062 +0,0 @@
1
- export function htmlShell(projectName) {
2
- const displayName = projectName || "autoloop";
3
- return `<!DOCTYPE html>
4
- <html lang="en">
5
- <head>
6
- <meta charset="utf-8">
7
- <meta name="viewport" content="width=device-width, initial-scale=1">
8
- <title>autoloop / ${displayName}</title>
9
- <style>
10
- :root {
11
- --bg: #fff; --fg: #1a1a1a; --muted: #666; --border: #e0e0e0;
12
- --card-bg: #fafafa; --badge-bg: #eee;
13
- --active: #2563eb; --watching: #d97706; --stuck: #dc2626;
14
- --failed: #dc2626; --completed: #16a34a;
15
- --cat-loop: #06b6d4; --cat-iteration: #d97706; --cat-backend: #666;
16
- --cat-review: #c026d3; --cat-coordination: #2563eb; --cat-error: #dc2626;
17
- --cat-operator: #ef4444; --cat-completion: #16a34a;
18
- }
19
- @media (prefers-color-scheme: dark) {
20
- :root {
21
- --bg: #111; --fg: #e0e0e0; --muted: #999; --border: #333;
22
- --card-bg: #1a1a1a; --badge-bg: #2a2a2a;
23
- }
24
- }
25
- * { box-sizing: border-box; margin: 0; padding: 0; }
26
- body { font-family: system-ui, -apple-system, sans-serif; background: var(--bg); color: var(--fg); max-width: 900px; margin: 0 auto; padding: 1rem; }
27
- h1 { font-size: 1.25rem; font-weight: 600; }
28
- header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 1rem; border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; }
29
- header .updated { font-size: 0.75rem; color: var(--muted); font-family: monospace; }
30
-
31
- .chatbox { background: var(--card-bg); border: 1px solid var(--border); border-radius: 6px; padding: 0.75rem; margin-bottom: 1rem; display: flex; gap: 0.5rem; align-items: flex-end; }
32
- .chatbox select { padding: 0.4rem; border: 1px solid var(--border); border-radius: 4px; background: var(--bg); color: var(--fg); font-size: 0.8rem; }
33
- .chatbox textarea { flex: 1; resize: vertical; min-height: 2.5rem; max-height: 8rem; padding: 0.4rem; border: 1px solid var(--border); border-radius: 4px; font-family: inherit; font-size: 0.85rem; background: var(--bg); color: var(--fg); }
34
- .chatbox button { padding: 0.4rem 1rem; border: none; border-radius: 4px; background: var(--active); color: #fff; cursor: pointer; font-size: 0.85rem; white-space: nowrap; }
35
- .chatbox button:hover { opacity: 0.9; }
36
-
37
- .section summary { cursor: pointer; font-weight: 600; font-size: 0.9rem; padding: 0.4rem 0; list-style: none; }
38
- .section summary::-webkit-details-marker { display: none; }
39
- .section summary::before { content: "\\25b6 "; font-size: 0.7rem; }
40
- .section[open] summary::before { content: "\\25bc "; }
41
- .badge { display: inline-block; font-size: 0.7rem; padding: 0.1rem 0.4rem; border-radius: 8px; background: var(--badge-bg); margin-left: 0.3rem; font-weight: normal; }
42
- .badge[data-status="active"] { background: var(--active); color: #fff; }
43
- .badge[data-status="watching"] { background: var(--watching); color: #fff; }
44
- .badge[data-status="stuck"] { background: var(--stuck); color: #fff; }
45
- .badge[data-status="failed"] { background: var(--failed); color: #fff; }
46
- .badge[data-status="completed"] { background: var(--completed); color: #fff; }
47
- .wt-badge { background: var(--badge-bg); color: var(--muted); font-weight: 600; letter-spacing: 0.03em; }
48
-
49
- .run-list { list-style: none; padding: 0; }
50
- .run-item { display: grid; grid-template-columns: 1fr auto; gap: 0.5rem; padding: 0.4rem 0.5rem; border-bottom: 1px solid var(--border); cursor: pointer; font-size: 0.8rem; font-family: monospace; }
51
- .run-item:hover { background: var(--card-bg); }
52
- .run-item .meta { color: var(--muted); text-align: right; white-space: nowrap; }
53
-
54
- .detail-pane { background: var(--card-bg); border: 1px solid var(--border); border-radius: 6px; padding: 1rem; margin-top: 1rem; }
55
- .detail-pane h3 { font-size: 0.95rem; margin-bottom: 0.5rem; }
56
- .detail-pane .field { font-size: 0.8rem; font-family: monospace; margin-bottom: 0.25rem; }
57
- .detail-pane .field label { color: var(--muted); }
58
- .events-list { margin-top: 0.75rem; max-height: 400px; overflow-y: auto; }
59
- .event-item { font-size: 0.75rem; font-family: monospace; padding: 0.2rem 0; border-bottom: 1px solid var(--border); word-break: break-all; }
60
- .event-item summary { cursor: pointer; }
61
- .event-item.ev-system { border-left: 3px solid var(--muted); padding-left: 0.4rem; }
62
- .event-item.ev-backend { border-left: 3px solid var(--muted); padding-left: 0.4rem; }
63
- .event-item.ev-review { border-left: 3px solid var(--watching); padding-left: 0.4rem; background: rgba(217,119,6,0.03); }
64
- .event-item.ev-error { border-left: 3px solid var(--failed); padding-left: 0.4rem; background: rgba(220,38,38,0.05); }
65
- .event-item.ev-coordination { border-left: 3px solid var(--active); padding-left: 0.4rem; }
66
- .event-item.ev-completion { border-left: 3px solid var(--completed); padding-left: 0.4rem; }
67
- .event-item.ev-highlight { border-left-color: var(--active); }
68
- .event-item.ev-backend summary { opacity: 0.6; }
69
- .event-item.ev-highlight summary { opacity: 1; }
70
- .event-item.ev-backend:hover summary { opacity: 1; }
71
- .event-field { margin: 0.15rem 0; font-size: 0.7rem; }
72
- .event-field strong { color: var(--muted); margin-right: 0.3rem; }
73
- .event-field pre { display: inline; white-space: pre-wrap; }
74
- .event-field details summary { cursor: pointer; color: var(--muted); font-style: italic; }
75
-
76
- .md-content { font-family: system-ui, -apple-system, sans-serif; font-size: 0.75rem; line-height: 1.5; white-space: normal; }
77
- .md-content h1, .md-content h2, .md-content h3, .md-content h4, .md-content h5, .md-content h6 { margin: 0.5em 0 0.25em; font-weight: 600; }
78
- .md-content h1 { font-size: 1.1em; } .md-content h2 { font-size: 1em; } .md-content h3 { font-size: 0.95em; }
79
- .md-content p { margin: 0.3em 0; }
80
- .md-content code { background: var(--badge-bg); padding: 0.1em 0.3em; border-radius: 3px; font-size: 0.9em; }
81
- .md-content pre { background: var(--badge-bg); padding: 0.5em; border-radius: 4px; overflow-x: auto; margin: 0.4em 0; }
82
- .md-content pre code { background: none; padding: 0; }
83
- .md-content ul, .md-content ol { margin: 0.3em 0; padding-left: 1.5em; }
84
- .md-content li { margin: 0.15em 0; }
85
- .md-content strong { font-weight: 600; }
86
- .md-content em { font-style: italic; }
87
-
88
- .empty { color: var(--muted); font-size: 0.8rem; padding: 0.5rem 0; }
89
-
90
- /* Structured prompt styles */
91
- .prompt-structured { font-size: 0.75rem; line-height: 1.5; }
92
- .prompt-section { border-bottom: 1px solid var(--border); padding: 0.5rem 0; }
93
- .prompt-section:last-child { border-bottom: none; }
94
- .prompt-objective { background: color-mix(in srgb, var(--active) 10%, transparent); border: 1px solid color-mix(in srgb, var(--active) 30%, transparent); border-radius: 6px; padding: 0.6rem 0.8rem; margin-bottom: 0.5rem; }
95
- .prompt-objective h4 { font-size: 0.8rem; color: var(--active); margin-bottom: 0.25rem; }
96
- .prompt-topology { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; padding: 0.4rem 0; font-size: 0.7rem; font-family: monospace; }
97
- .prompt-topology .topo-label { color: var(--muted); margin-right: 0.15rem; }
98
- .prompt-topology .topo-badge { display: inline-block; padding: 0.1rem 0.4rem; border-radius: 8px; background: var(--badge-bg); font-size: 0.7rem; }
99
- .prompt-scratchpad-entries { margin-top: 0.3rem; }
100
- .prompt-show-more { background: none; border: 1px solid var(--border); border-radius: 4px; padding: 0.2rem 0.5rem; font-size: 0.7rem; color: var(--muted); cursor: pointer; margin-bottom: 0.3rem; }
101
- .prompt-show-more:hover { background: var(--card-bg); color: var(--fg); }
102
- .prompt-raw-toggle { margin-top: 0.5rem; }
103
- .prompt-raw-toggle button { background: none; border: 1px solid var(--border); border-radius: 4px; padding: 0.2rem 0.6rem; font-size: 0.7rem; color: var(--muted); cursor: pointer; }
104
- .prompt-raw-toggle button:hover { background: var(--card-bg); color: var(--fg); }
105
- .prompt-raw-toggle pre { white-space: pre-wrap; font-size: 0.65rem; margin-top: 0.3rem; max-height: 400px; overflow-y: auto; background: var(--badge-bg); padding: 0.5rem; border-radius: 4px; }
106
-
107
- /* Routing badges and backpressure */
108
- .routing-badge { display: inline-block; font-size: 0.65rem; padding: 0.1rem 0.35rem; border-radius: 6px; background: var(--badge-bg); margin: 0.1rem 0.15rem; font-family: monospace; }
109
- .bp-none { color: var(--muted); font-style: italic; font-size: 0.7rem; }
110
- .bp-warning { display: inline-block; font-size: 0.7rem; padding: 0.15rem 0.4rem; border-radius: 6px; background: color-mix(in srgb, var(--watching) 15%, transparent); border: 1px solid color-mix(in srgb, var(--watching) 40%, transparent); color: var(--watching); font-family: monospace; }
111
-
112
- /* Merged indicator */
113
- .merged-badge { color: var(--completed); font-weight: 600; }
114
- .merge-detail { margin-top: 0.5rem; padding: 0.5rem; background: color-mix(in srgb, var(--completed) 8%, transparent); border: 1px solid color-mix(in srgb, var(--completed) 25%, transparent); border-radius: 4px; }
115
- .merge-detail .field label { color: var(--completed); }
116
-
117
- .detail-tabs { display: flex; gap: 0; border-bottom: 2px solid var(--border); margin-top: 0.75rem; margin-bottom: 0; }
118
- .detail-tab { background: none; border: none; padding: 0.4rem 0.8rem; font-size: 0.8rem; font-family: monospace; cursor: pointer; color: var(--muted); border-bottom: 2px solid transparent; margin-bottom: -2px; }
119
- .detail-tab:hover { color: var(--fg); }
120
- .detail-tab.active { color: var(--active); border-bottom-color: var(--active); font-weight: 600; }
121
-
122
- .topic-chip { display: inline-flex; align-items: center; gap: 0.2rem; padding: 0.15rem 0.4rem; border: 1px solid var(--border); border-left-width: 3px; border-radius: 4px; background: none; font-size: 0.7rem; font-family: monospace; cursor: pointer; color: var(--muted); }
123
- .topic-chip.active { color: var(--fg); background: var(--card-bg); }
124
- .topic-chip .badge { font-size: 0.6rem; padding: 0 0.25rem; }
125
-
126
- .journal-search { width: 100%; padding: 0.35rem 0.5rem; border: 1px solid var(--border); border-radius: 4px; font-size: 0.8rem; font-family: inherit; background: var(--bg); color: var(--fg); }
127
-
128
- .iter-group { border: 1px solid var(--border); border-radius: 4px; margin-bottom: 0.4rem; }
129
- .iter-group > summary { cursor: pointer; padding: 0.3rem 0.5rem; font-size: 0.75rem; font-family: monospace; color: var(--muted); background: var(--card-bg); list-style: none; }
130
- .iter-group > summary::-webkit-details-marker { display: none; }
131
- .iter-group > summary::before { content: "\\25b6 "; font-size: 0.6rem; }
132
- .iter-group[open] > summary::before { content: "\\25bc "; }
133
-
134
- .artifacts-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; margin-bottom: 0.75rem; }
135
- .artifact-stat-card { background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 0.5rem; text-align: center; }
136
- .artifact-stat-value { font-size: 1.2rem; font-weight: 700; font-family: monospace; }
137
- .artifact-stat-label { font-size: 0.7rem; color: var(--muted); }
138
- .artifacts-bar-chart { margin: 0.5rem 0; }
139
- .bar-row { display: grid; grid-template-columns: 80px 1fr 40px; gap: 0.4rem; align-items: center; font-size: 0.75rem; margin-bottom: 0.2rem; }
140
- .bar-label { text-align: right; color: var(--muted); font-family: monospace; }
141
- .bar-track { height: 14px; background: var(--badge-bg); border-radius: 3px; overflow: hidden; }
142
- .bar-fill { height: 100%; border-radius: 3px; min-width: 2px; }
143
- .bar-count { font-family: monospace; text-align: right; }
144
- .artifact-doc-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.3rem 0; border-bottom: 1px solid var(--border); font-size: 0.8rem; }
145
- .artifact-view-btn { padding: 0.15rem 0.5rem; border: 1px solid var(--border); border-radius: 3px; background: var(--bg); color: var(--fg); cursor: pointer; font-size: 0.7rem; }
146
- .artifact-view-btn:hover { background: var(--badge-bg); }
147
- </style>
148
- </head>
149
- <body x-data="dashboard()" x-init="startPolling()">
150
-
151
- <header>
152
- <h1>autoloop <span style="color:var(--muted);font-weight:400">/ ${displayName}</span></h1>
153
- <span class="updated" x-text="lastUpdated ? 'updated ' + lastUpdated : 'loading...'"></span>
154
- </header>
155
-
156
- <div class="chatbox">
157
- <select x-model="selectedPreset">
158
- <template x-for="p in presets" :key="p.name">
159
- <option :value="p.name" x-text="p.name"></option>
160
- </template>
161
- </select>
162
- <textarea x-model="newPrompt" placeholder="Describe what you want to do..." @keydown.meta.enter="startLoop()" @keydown.ctrl.enter="startLoop()"></textarea>
163
- <button @click="startLoop()">Start</button>
164
- </div>
165
-
166
- <template x-for="cat in categories" :key="cat.key">
167
- <details class="section" :open="sectionOpen[cat.key]" @toggle="sectionUserToggled[cat.key] = true; sectionOpen[cat.key] = $el.open">
168
- <summary>
169
- <span x-text="cat.label"></span>
170
- <span class="badge" :data-status="cat.key" x-text="cat.total"></span>
171
- </summary>
172
- <ul class="run-list">
173
- <template x-for="run in cat.items" :key="run.run_id">
174
- <li class="run-item" @click="selectRun(run.run_id)">
175
- <span>
176
- <span x-text="run.run_id.slice(0, 16)"></span>
177
- <span style="color:var(--muted)"> &middot; </span>
178
- <span x-text="run.preset"></span>
179
- <span style="color:var(--muted)"> &middot; iter </span>
180
- <span x-text="run.iteration + '/' + (run.max_iterations || '?')"></span>
181
- <template x-if="run.isolation_mode === 'worktree'">
182
- <span>
183
- <span class="badge wt-badge" :title="run.worktree_name || ''">WT</span>
184
- <template x-if="run.worktree_merged">
185
- <span class="merged-badge" title="merged"> &#x2713;</span>
186
- </template>
187
- </span>
188
- </template>
189
- </span>
190
- <span class="meta">
191
- <span x-text="run.latest_event || '-'"></span>
192
- <span style="color:var(--muted)"> &middot; </span>
193
- <span x-text="timeAgo(run.created_at)"></span>
194
- </span>
195
- </li>
196
- </template>
197
- <li class="empty" x-show="cat.items.length === 0">None</li>
198
- <li x-show="cat.capped" style="text-align:center;padding:0.3rem;list-style:none">
199
- <button @click="sectionShowAll[cat.key] = true" style="background:none;border:1px solid var(--border);border-radius:4px;padding:0.25rem 0.6rem;color:var(--muted);cursor:pointer;font-size:0.75rem" x-text="'Show all ' + cat.total + ' runs'"></button>
200
- </li>
201
- <li x-show="sectionShowAll[cat.key] && cat.total > 10" style="text-align:center;padding:0.3rem;list-style:none">
202
- <button @click="sectionShowAll[cat.key] = false" style="background:none;border:1px solid var(--border);border-radius:4px;padding:0.25rem 0.6rem;color:var(--muted);cursor:pointer;font-size:0.75rem">Show fewer</button>
203
- </li>
204
- </ul>
205
- </details>
206
- </template>
207
-
208
- <div class="detail-pane" x-show="selectedRun" x-cloak>
209
- <h3 x-text="'Run: ' + (selectedRun || '')"></h3>
210
- <template x-if="selectedRunDetail">
211
- <div>
212
- <div class="field"><label>Status: </label><span x-text="selectedRunDetail.status"></span></div>
213
- <div class="field"><label>Preset: </label><span x-text="selectedRunDetail.preset"></span></div>
214
- <div class="field"><label>Objective: </label><div class="md-content" style="display:inline" x-html="renderMarkdown(selectedRunDetail.objective)"></div></div>
215
- <div class="field"><label>Iteration: </label><span x-text="selectedRunDetail.iteration + '/' + (selectedRunDetail.max_iterations || '?')"></span></div>
216
- <div class="field"><label>Workspace: </label><span :title="workspacePath(selectedRunDetail)" x-text="workspaceLabel(selectedRunDetail)"></span></div>
217
- <div class="field"><label>Created: </label><span :title="selectedRunDetail.created_at" x-text="timeAgo(selectedRunDetail.created_at) + ' ago'"></span></div>
218
- <div class="field"><label>Updated: </label><span :title="selectedRunDetail.updated_at" x-text="timeAgo(selectedRunDetail.updated_at) + ' ago'"></span></div>
219
- <div class="field"><label>Duration: </label><span x-text="runDuration()"></span></div>
220
- <div class="field"><label>Latest event: </label><span x-text="'[iter ' + selectedRunDetail.iteration + '] ' + selectedRunDetail.latest_event"></span></div>
221
- <div class="field"><label>Events: </label><span x-text="selectedRunEvents.length"></span></div>
222
- <template x-if="selectedRunDetail.worktree_merged">
223
- <div class="merge-detail">
224
- <div class="field"><label>Merge status: </label><span>merged</span></div>
225
- <div class="field" x-show="selectedRunDetail.worktree_merged_at"><label>Merged at: </label><span x-text="selectedRunDetail.worktree_merged_at"></span></div>
226
- <div class="field" x-show="selectedRunDetail.worktree_merge_strategy"><label>Merge strategy: </label><span x-text="selectedRunDetail.worktree_merge_strategy"></span></div>
227
- </div>
228
- </template>
229
- </div>
230
- </template>
231
- <div x-show="selectedRunDetail && selectedRunDetail.status === 'running'" style="display:grid;grid-template-columns:1fr auto;gap:0.4rem;align-items:center;margin:0.75rem 0;padding:0.6rem;border:1px solid var(--border);border-radius:6px;background:var(--bg)">
232
- <input type="text" x-model="guideMessage" placeholder="Send guidance to this run..." @keydown.enter="sendGuide()"
233
- style="width:100%;box-sizing:border-box;padding:0.4rem 0.6rem;border:1px solid var(--border);border-radius:4px;font-size:0.8rem;font-family:inherit;background:var(--bg);color:var(--fg)">
234
- <div style="display:flex;gap:0.4rem;align-items:center">
235
- <button @click="sendGuide()" style="padding:0.4rem 0.8rem;border:none;border-radius:4px;background:var(--active);color:#fff;cursor:pointer;font-size:0.8rem;white-space:nowrap">Send</button>
236
- <span x-show="guideFlash" x-text="guideFlash" x-transition.opacity style="font-size:0.75rem;color:var(--completed)"></span>
237
- </div>
238
- </div>
239
- <div class="detail-tabs" x-show="selectedRunDetail">
240
- <button class="detail-tab" :class="{ active: detailTab === 'events' }" @click="detailTab = 'events'">Events</button>
241
- <button class="detail-tab" :class="{ active: detailTab === 'journal' }" @click="detailTab = 'journal'">Journal</button>
242
- <button class="detail-tab" :class="{ active: detailTab === 'artifacts' }" @click="detailTab = 'artifacts'">Artifacts</button>
243
- </div>
244
- <div x-show="detailTab === 'events'" class="events-list">
245
- <div style="display:flex;justify-content:space-between;align-items:center">
246
- <h3>Events</h3>
247
- <label style="font-size:0.75rem;cursor:pointer"><input type="checkbox" x-model="showVerbose" style="margin-right:0.3rem">Show backend events</label>
248
- </div>
249
- <template x-for="(ev, idx) in visibleRunEvents()" :key="idx">
250
- <details :class="eventClasses(ev)">
251
- <summary x-text="eventSummary(ev)"></summary>
252
- <div style="padding:0.3rem">
253
- <template x-for="[k,v] in eventDisplayEntries(ev)" :key="k">
254
- <div class="event-field">
255
- <strong x-text="k + ':'"></strong>
256
- <template x-if="isPromptField(ev.topic, k)">
257
- <div x-data="{ showRaw: false, showAllScratchpad: false }" class="prompt-structured">
258
- <template x-if="parsePromptSections(String(v))">
259
- <div>
260
- <template x-if="parsePromptSections(String(v)).objective">
261
- <div class="prompt-section prompt-objective">
262
- <h4>Objective</h4>
263
- <div class="md-content" x-html="renderMarkdown(parsePromptSections(String(v)).objective)"></div>
264
- </div>
265
- </template>
266
- <template x-if="parsePromptSections(String(v)).topology">
267
- <div class="prompt-section">
268
- <strong style="font-size:0.75rem">Topology</strong>
269
- <div class="prompt-topology" x-html="renderTopologyBlock(parsePromptSections(String(v)).topology)"></div>
270
- </div>
271
- </template>
272
- <template x-if="parsePromptSections(String(v)).scratchpad">
273
- <div class="prompt-section">
274
- <strong style="font-size:0.75rem">Scratchpad</strong>
275
- <div class="prompt-scratchpad-entries">
276
- <template x-if="getScratchpadEntries(parsePromptSections(String(v)).scratchpad).length > 3">
277
- <div>
278
- <button class="prompt-show-more" x-show="!showAllScratchpad" @click="showAllScratchpad = true"
279
- x-text="'Show ' + (getScratchpadEntries(parsePromptSections(String(v)).scratchpad).length - 3) + ' older entries'"></button>
280
- <template x-if="showAllScratchpad">
281
- <div class="md-content" x-html="renderMarkdown(getScratchpadEntries(parsePromptSections(String(v)).scratchpad).slice(0, -3).join('\\n\\n'))"></div>
282
- </template>
283
- </div>
284
- </template>
285
- <div class="md-content" x-html="renderMarkdown(getScratchpadEntries(parsePromptSections(String(v)).scratchpad).slice(-3).join('\\n\\n'))"></div>
286
- </div>
287
- </div>
288
- </template>
289
- <template x-if="parsePromptSections(String(v)).memory">
290
- <details class="prompt-section">
291
- <summary style="cursor:pointer;font-size:0.75rem;font-weight:600">Loop Memory</summary>
292
- <div class="md-content" style="margin-top:0.3rem" x-html="renderMarkdown(parsePromptSections(String(v)).memory)"></div>
293
- </details>
294
- </template>
295
- <template x-if="parsePromptSections(String(v)).rules">
296
- <details class="prompt-section">
297
- <summary style="cursor:pointer;font-size:0.75rem;font-weight:600">Rules &amp; Event Tool</summary>
298
- <div class="md-content" style="margin-top:0.3rem" x-html="renderMarkdown(parsePromptSections(String(v)).rules)"></div>
299
- </details>
300
- </template>
301
- <template x-if="parsePromptSections(String(v)).config">
302
- <details class="prompt-section">
303
- <summary style="cursor:pointer;font-size:0.75rem;font-weight:600">Config</summary>
304
- <div class="md-content" style="margin-top:0.3rem" x-html="renderMarkdown(parsePromptSections(String(v)).config)"></div>
305
- </details>
306
- </template>
307
- <template x-if="parsePromptSections(String(v)).harness">
308
- <details class="prompt-section">
309
- <summary style="cursor:pointer;font-size:0.75rem;font-weight:600">Harness Instructions</summary>
310
- <div class="md-content" style="margin-top:0.3rem" x-html="renderMarkdown(parsePromptSections(String(v)).harness)"></div>
311
- </details>
312
- </template>
313
- <div class="prompt-raw-toggle">
314
- <button @click="showRaw = !showRaw" x-text="showRaw ? 'Hide raw prompt' : 'Show raw prompt'"></button>
315
- <template x-if="showRaw">
316
- <pre x-text="String(v)"></pre>
317
- </template>
318
- </div>
319
- </div>
320
- </template>
321
- </div>
322
- </template>
323
- <template x-if="!isPromptField(ev.topic, k) && isRoutingBadgeField(k)">
324
- <span x-html="renderRoutingValue(k, v)"></span>
325
- </template>
326
- <template x-if="!isPromptField(ev.topic, k) && !isRoutingBadgeField(k) && isMarkdownField(ev.topic, k)">
327
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length <= 200">
328
- <div class="md-content" x-html="renderMarkdown(typeof v === 'object' ? JSON.stringify(v,null,2) : String(v))"></div>
329
- </template>
330
- </template>
331
- <template x-if="!isPromptField(ev.topic, k) && !isRoutingBadgeField(k) && isMarkdownField(ev.topic, k)">
332
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length > 200">
333
- <details>
334
- <summary x-text="k + ' (' + String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length + ' chars)'"></summary>
335
- <div class="md-content" style="font-size:0.7rem;margin-top:0.2rem" x-html="renderMarkdown(typeof v === 'object' ? JSON.stringify(v,null,2) : String(v))"></div>
336
- </details>
337
- </template>
338
- </template>
339
- <template x-if="!isPromptField(ev.topic, k) && !isRoutingBadgeField(k) && !isMarkdownField(ev.topic, k)">
340
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length <= 200">
341
- <pre x-text="typeof v === 'object' ? JSON.stringify(v,null,2) : String(v)"></pre>
342
- </template>
343
- </template>
344
- <template x-if="!isPromptField(ev.topic, k) && !isRoutingBadgeField(k) && !isMarkdownField(ev.topic, k)">
345
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length > 200">
346
- <details>
347
- <summary x-text="k + ' (' + String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length + ' chars)'"></summary>
348
- <pre style="white-space:pre-wrap;font-size:0.7rem;margin-top:0.2rem" x-text="typeof v === 'object' ? JSON.stringify(v,null,2) : String(v)"></pre>
349
- </details>
350
- </template>
351
- </template>
352
- </div>
353
- </template>
354
- </div>
355
- </details>
356
- </template>
357
- <p class="empty" x-show="visibleRunEvents().length === 0">No events</p>
358
- </div>
359
- <div x-show="detailTab === 'journal'" class="events-list">
360
- <div style="margin-bottom:0.5rem">
361
- <input type="text" class="journal-search" x-model="journalSearch" placeholder="Search events...">
362
- </div>
363
- <div style="display:flex;flex-wrap:wrap;gap:0.3rem;margin-bottom:0.5rem">
364
- <template x-for="cat in journalCategoryChips()" :key="cat.key">
365
- <button class="topic-chip" :class="{ active: journalCategoryFilter[cat.key] }" :style="'border-color:' + cat.color" @click="journalCategoryFilter[cat.key] = !journalCategoryFilter[cat.key]">
366
- <span x-text="cat.label"></span>
367
- <span class="badge" x-text="cat.count"></span>
368
- </button>
369
- </template>
370
- </div>
371
- <template x-for="group in journalGroups()" :key="group.key">
372
- <details class="iter-group" open>
373
- <summary x-text="group.label + ' (' + group.events.length + ' events)'"></summary>
374
- <template x-for="(ev, idx) in group.events" :key="idx">
375
- <details :class="eventClasses(ev)">
376
- <summary x-text="eventSummary(ev)"></summary>
377
- <div style="padding:0.3rem">
378
- <template x-for="[k,v] in eventDisplayEntries(ev)" :key="k">
379
- <div class="event-field">
380
- <strong x-text="k + ':'"></strong>
381
- <template x-if="isRoutingBadgeField(k)">
382
- <span x-html="renderRoutingValue(k, v)"></span>
383
- </template>
384
- <template x-if="!isRoutingBadgeField(k) && isMarkdownField(ev.topic, k)">
385
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length <= 200">
386
- <div class="md-content" x-html="renderMarkdown(typeof v === 'object' ? JSON.stringify(v,null,2) : String(v))"></div>
387
- </template>
388
- </template>
389
- <template x-if="!isRoutingBadgeField(k) && isMarkdownField(ev.topic, k)">
390
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length > 200">
391
- <details>
392
- <summary x-text="k + ' (' + String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length + ' chars)'"></summary>
393
- <div class="md-content" style="font-size:0.7rem;margin-top:0.2rem" x-html="renderMarkdown(typeof v === 'object' ? JSON.stringify(v,null,2) : String(v))"></div>
394
- </details>
395
- </template>
396
- </template>
397
- <template x-if="!isRoutingBadgeField(k) && !isMarkdownField(ev.topic, k)">
398
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length <= 200">
399
- <pre x-text="typeof v === 'object' ? JSON.stringify(v,null,2) : String(v)"></pre>
400
- </template>
401
- </template>
402
- <template x-if="!isRoutingBadgeField(k) && !isMarkdownField(ev.topic, k)">
403
- <template x-if="String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length > 200">
404
- <details>
405
- <summary x-text="k + ' (' + String(typeof v === 'object' ? JSON.stringify(v,null,2) : v).length + ' chars)'"></summary>
406
- <pre style="white-space:pre-wrap;font-size:0.7rem;margin-top:0.2rem" x-text="typeof v === 'object' ? JSON.stringify(v,null,2) : String(v)"></pre>
407
- </details>
408
- </template>
409
- </template>
410
- </div>
411
- </template>
412
- </div>
413
- </details>
414
- </template>
415
- </details>
416
- </template>
417
- <p class="empty" x-show="journalGroups().length === 0">No matching events</p>
418
- </div>
419
- <div x-show="detailTab === 'artifacts'" class="events-list">
420
- <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:0.75rem">
421
- <h3 style="font-size:0.95rem">Artifacts</h3>
422
- <button @click="fetchArtifacts()" style="padding:0.2rem 0.6rem;border:1px solid var(--border);border-radius:4px;background:var(--bg);color:var(--fg);cursor:pointer;font-size:0.75rem">Refresh</button>
423
- </div>
424
-
425
- <div x-show="artifactsData" class="artifacts-grid">
426
- <div class="artifact-stat-card">
427
- <div class="artifact-stat-value" x-text="artifactsData?.events?.total || 0"></div>
428
- <div class="artifact-stat-label">Events</div>
429
- </div>
430
- <div class="artifact-stat-card">
431
- <div class="artifact-stat-value" x-text="artifactsData?.iterations || 0"></div>
432
- <div class="artifact-stat-label">Iterations</div>
433
- </div>
434
- <div class="artifact-stat-card">
435
- <div class="artifact-stat-value" x-text="(artifactsData?.artifacts?.memoryLearnings || 0) + (artifactsData?.artifacts?.memoryMeta || 0)"></div>
436
- <div class="artifact-stat-label">Memory</div>
437
- </div>
438
- <div class="artifact-stat-card">
439
- <div class="artifact-stat-value" x-text="artifactsData?.artifacts?.guidanceSent || 0"></div>
440
- <div class="artifact-stat-label">Guidance</div>
441
- </div>
442
- </div>
443
-
444
- <div x-show="artifactsData" class="artifacts-bar-chart">
445
- <template x-for="cat in artifactsCategoryBars()" :key="cat.key">
446
- <div class="bar-row">
447
- <span class="bar-label" x-text="cat.label"></span>
448
- <div class="bar-track">
449
- <div class="bar-fill" :style="'width:' + cat.pct + '%;background:' + cat.color"></div>
450
- </div>
451
- <span class="bar-count" x-text="cat.count"></span>
452
- </div>
453
- </template>
454
- </div>
455
-
456
- <div x-show="artifactsData" style="font-size:0.8rem;font-family:monospace;margin:0.75rem 0">
457
- <div>commits: <span x-text="artifactsData?.output?.commits || 0"></span></div>
458
- <div>files changed: <span x-text="artifactsData?.output?.filesChanged < 0 ? '-' : artifactsData?.output?.filesChanged"></span></div>
459
- <div>journal size: <span x-text="formatBytes(artifactsData?.output?.journalSizeBytes || 0)"></span></div>
460
- <div>backpressure: <span x-text="artifactsData?.artifacts?.backpressure || 0"></span> rejected</div>
461
- </div>
462
-
463
- <div x-show="artifactsData && artifactsData.documents && artifactsData.documents.length > 0">
464
- <h4 style="font-size:0.85rem;margin:0.75rem 0 0.5rem">Documents</h4>
465
- <template x-for="doc in artifactsData?.documents || []" :key="doc.path">
466
- <div class="artifact-doc-row">
467
- <span x-text="doc.title || doc.path"></span>
468
- <span class="badge" x-text="doc.kind"></span>
469
- <template x-if="doc.missing">
470
- <span style="color:var(--failed);font-size:0.7rem">(missing)</span>
471
- </template>
472
- <template x-if="!doc.missing">
473
- <button class="artifact-view-btn" @click="viewArtifactDoc(doc.path)">View</button>
474
- </template>
475
- </div>
476
- </template>
477
- </div>
478
-
479
- <div x-show="artifactDocContent !== null" style="margin-top:0.75rem">
480
- <button @click="artifactDocContent = null; artifactDocPath = ''" style="padding:0.2rem 0.6rem;border:1px solid var(--border);border-radius:4px;background:var(--bg);color:var(--fg);cursor:pointer;font-size:0.75rem;margin-bottom:0.5rem">\u2190 Back</button>
481
- <div class="md-content" x-html="renderMarkdown(artifactDocContent || '')"></div>
482
- </div>
483
-
484
- <p class="empty" x-show="!artifactsData">Click Refresh to load artifacts</p>
485
- </div>
486
- </div>
487
-
488
- <script defer src="/static/alpine.min.js"></script>
489
- <script>
490
- function dashboard() {
491
- return {
492
- runs: { active: [], watching: [], stuck: [], recentFailed: [], recentCompleted: [] },
493
- presets: [],
494
- selectedRun: null,
495
- selectedRunDetail: null,
496
- selectedRunEvents: [],
497
- newPrompt: "",
498
- selectedPreset: "",
499
- pollInterval: null,
500
- lastUpdated: null,
501
- sectionOpen: { active: false, watching: false, stuck: false, failed: false, completed: false },
502
- sectionUserToggled: {},
503
- sectionShowAll: {},
504
- showVerbose: false,
505
- guideMessage: "",
506
- guideFlash: "",
507
- artifactsData: null,
508
- artifactDocContent: null,
509
- artifactDocPath: '',
510
- detailTab: 'events',
511
- journalSearch: '',
512
- journalCategoryFilter: {
513
- loop: true,
514
- iteration: true,
515
- backend: false,
516
- review: true,
517
- coordination: true,
518
- error: true,
519
- operator: true,
520
- completion: true,
521
- },
522
- categoryColors: {
523
- loop: '#06b6d4',
524
- iteration: '#d97706',
525
- backend: '#666',
526
- review: '#c026d3',
527
- coordination: '#2563eb',
528
- error: '#dc2626',
529
- operator: '#ef4444',
530
- completion: '#16a34a',
531
- },
532
-
533
- get categories() {
534
- const CAP = 10;
535
- const cap = (key, items) => {
536
- const total = items.length;
537
- const show = this.sectionShowAll[key] ? items : items.slice(0, CAP);
538
- return { items: show, total, capped: total > CAP && !this.sectionShowAll[key] };
539
- };
540
- const fc = cap("failed", this.runs.recentFailed);
541
- const cc = cap("completed", this.runs.recentCompleted);
542
- return [
543
- { key: "active", label: "Active", items: this.runs.active, total: this.runs.active.length, capped: false },
544
- { key: "watching", label: "Watching", items: this.runs.watching, total: this.runs.watching.length, capped: false },
545
- { key: "stuck", label: "Stuck", items: this.runs.stuck, total: this.runs.stuck.length, capped: false },
546
- { key: "failed", label: "Failed", items: fc.items, total: fc.total, capped: fc.capped },
547
- { key: "completed", label: "Completed", items: cc.items, total: cc.total, capped: cc.capped },
548
- ];
549
- },
550
-
551
- async startPolling() {
552
- await this.fetchPresets();
553
- await this.fetchRuns();
554
- this.pollInterval = setInterval(() => this.fetchRuns(), 3000);
555
- },
556
-
557
- async fetchRuns() {
558
- try {
559
- const res = await fetch("/api/runs");
560
- const data = await res.json();
561
- const byRecent = (a, b) => new Date(b.updated_at || 0) - new Date(a.updated_at || 0);
562
- for (const key of ['active', 'watching', 'stuck', 'recentFailed', 'recentCompleted']) {
563
- if (data[key]) data[key].sort(byRecent);
564
- }
565
- this.runs = data;
566
- this.lastUpdated = new Date().toLocaleTimeString();
567
- const defaultOpen = ['active', 'watching', 'stuck'];
568
- for (const cat of this.categories) {
569
- if (!this.sectionUserToggled[cat.key]) {
570
- this.sectionOpen[cat.key] = cat.items.length > 0 && defaultOpen.includes(cat.key);
571
- }
572
- }
573
- if (this.selectedRun) this.fetchEvents(this.selectedRun);
574
- } catch (e) { /* retry on next poll */ }
575
- },
576
-
577
- async fetchPresets() {
578
- try {
579
- const res = await fetch("/api/presets");
580
- const data = await res.json();
581
- this.presets = data.presets;
582
- if (this.presets.length && !this.selectedPreset) {
583
- this.selectedPreset = this.presets[0].name;
584
- }
585
- } catch (e) { /* ignore */ }
586
- },
587
-
588
- async selectRun(runId) {
589
- this.selectedRun = runId;
590
- this.artifactsData = null;
591
- this.artifactDocContent = null;
592
- this.artifactDocPath = '';
593
- try {
594
- const detailRes = await fetch("/api/runs/" + runId);
595
- if (detailRes.ok) this.selectedRunDetail = await detailRes.json();
596
- } catch (e) { /* ignore */ }
597
- await this.fetchEvents(runId);
598
- },
599
-
600
- async fetchEvents(runId) {
601
- try {
602
- const res = await fetch("/api/runs/" + runId + "/events");
603
- const data = await res.json();
604
- this.selectedRunEvents = data.events;
605
- } catch (e) { /* ignore */ }
606
- },
607
-
608
- async sendGuide() {
609
- if (!this.guideMessage.trim() || !this.selectedRun) return;
610
- try {
611
- const res = await fetch("/api/runs/" + this.selectedRun + "/guide", {
612
- method: "POST",
613
- headers: { "Content-Type": "application/json" },
614
- body: JSON.stringify({ message: this.guideMessage }),
615
- });
616
- if (res.ok) {
617
- this.guideMessage = "";
618
- this.guideFlash = "Sent";
619
- setTimeout(() => { this.guideFlash = ""; }, 2000);
620
- await this.fetchEvents(this.selectedRun);
621
- } else {
622
- const data = await res.json().catch(() => ({}));
623
- this.guideFlash = data.error || "Failed";
624
- setTimeout(() => { this.guideFlash = ""; }, 3000);
625
- }
626
- } catch (e) {
627
- this.guideFlash = "Error";
628
- setTimeout(() => { this.guideFlash = ""; }, 3000);
629
- }
630
- },
631
-
632
- async startLoop() {
633
- if (!this.newPrompt.trim()) return;
634
- await fetch("/api/runs", {
635
- method: "POST",
636
- headers: { "Content-Type": "application/json" },
637
- body: JSON.stringify({ prompt: this.newPrompt, preset: this.selectedPreset }),
638
- });
639
- this.newPrompt = "";
640
- setTimeout(() => this.fetchRuns(), 1000);
641
- },
642
-
643
- timeAgo(iso) {
644
- if (!iso) return "-";
645
- const s = Math.floor((Date.now() - new Date(iso)) / 1000);
646
- if (s < 0) return "0s";
647
- if (s < 60) return s + "s";
648
- if (s < 3600) return Math.floor(s / 60) + "m";
649
- return Math.floor(s / 3600) + "h";
650
- },
651
-
652
- runDuration() {
653
- const d = this.selectedRunDetail;
654
- if (!d || !d.created_at || !d.updated_at) return "-";
655
- const ms = new Date(d.updated_at) - new Date(d.created_at);
656
- if (ms < 0) return "-";
657
- const s = Math.floor(ms / 1000);
658
- if (s < 60) return s + "s";
659
- if (s < 3600) return Math.floor(s / 60) + "m " + (s % 60) + "s";
660
- return Math.floor(s / 3600) + "h " + Math.floor((s % 3600) / 60) + "m";
661
- },
662
-
663
- workspaceLabel(run) {
664
- if (!run) return "-";
665
- if (run.isolation_mode === "worktree") {
666
- return run.worktree_name || "worktree";
667
- }
668
- return "shared checkout";
669
- },
670
-
671
- workspacePath(run) {
672
- if (!run) return "";
673
- if (run.isolation_mode === "worktree") {
674
- return run.worktree_path || run.work_dir || "";
675
- }
676
- return run.work_dir || run.project_dir || "";
677
- },
678
-
679
- isMarkdownField(topic, key) {
680
- if (!topic || !key) return false;
681
- const t = String(topic);
682
- const k = String(key);
683
- if ((t === 'backend.finish' || t === 'iteration.finish') && k === 'output') return true;
684
- if (t === 'iteration.start' && k === 'prompt') return true;
685
- return false;
686
- },
687
-
688
- renderMarkdown(text) {
689
- if (!text) return '';
690
- let html = String(text);
691
- // Escape HTML
692
- html = html.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
693
- // Fenced code blocks
694
- html = html.replace(/^\\\`\\\`\\\`(\\w*)\\n([\\s\\S]*?)^\\\`\\\`\\\`/gm, function(_, lang, code) {
695
- return '<pre><code>' + code.trim() + '</code></pre>';
696
- });
697
- // Split into lines for block-level processing
698
- const lines = html.split('\\n');
699
- const out = [];
700
- let inList = false;
701
- let listType = '';
702
- for (let i = 0; i < lines.length; i++) {
703
- const line = lines[i];
704
- // Headings
705
- const hMatch = line.match(/^(#{1,6})\\s+(.+)$/);
706
- if (hMatch) {
707
- if (inList) { out.push('</' + listType + '>'); inList = false; }
708
- const lvl = hMatch[1].length;
709
- out.push('<h' + lvl + '>' + this._inlineMd(hMatch[2]) + '</h' + lvl + '>');
710
- continue;
711
- }
712
- // Unordered list
713
- const ulMatch = line.match(/^[\\-\\*]\\s+(.+)$/);
714
- if (ulMatch) {
715
- if (!inList || listType !== 'ul') {
716
- if (inList) out.push('</' + listType + '>');
717
- out.push('<ul>'); inList = true; listType = 'ul';
718
- }
719
- out.push('<li>' + this._inlineMd(ulMatch[1]) + '</li>');
720
- continue;
721
- }
722
- // Ordered list
723
- const olMatch = line.match(/^\\d+\\.\\s+(.+)$/);
724
- if (olMatch) {
725
- if (!inList || listType !== 'ol') {
726
- if (inList) out.push('</' + listType + '>');
727
- out.push('<ol>'); inList = true; listType = 'ol';
728
- }
729
- out.push('<li>' + this._inlineMd(olMatch[1]) + '</li>');
730
- continue;
731
- }
732
- // Close list if we hit non-list line
733
- if (inList) { out.push('</' + listType + '>'); inList = false; }
734
- // Empty line = paragraph break
735
- if (line.trim() === '') {
736
- out.push('');
737
- continue;
738
- }
739
- // Normal paragraph line
740
- out.push('<p>' + this._inlineMd(line) + '</p>');
741
- }
742
- if (inList) out.push('</' + listType + '>');
743
- return out.join('\\n');
744
- },
745
-
746
- _inlineMd(text) {
747
- // Inline code
748
- text = text.replace(/\\\`([^\\\`]+)\\\`/g, '<code>$1</code>');
749
- // Bold
750
- text = text.replace(/\\*\\*(.+?)\\*\\*/g, '<strong>$1</strong>');
751
- text = text.replace(/__(.+?)__/g, '<strong>$1</strong>');
752
- // Italic
753
- text = text.replace(/\\*(.+?)\\*/g, '<em>$1</em>');
754
- text = text.replace(/_(.+?)_/g, '<em>$1</em>');
755
- return text;
756
- },
757
-
758
- eventDisplayEntries(ev) {
759
- if (ev.fields && typeof ev.fields === 'object') {
760
- const entries = [];
761
- for (const [k, v] of Object.entries(ev)) {
762
- if (k === 'fields') continue;
763
- entries.push([k, v]);
764
- }
765
- for (const [fk, fv] of Object.entries(ev.fields)) {
766
- entries.push([fk, fv]);
767
- }
768
- return entries;
769
- }
770
- return Object.entries(ev);
771
- },
772
-
773
- isRoutingBadgeField(key) {
774
- return ['suggested_roles', 'allowed_events', 'backpressure', 'recent_event'].includes(String(key));
775
- },
776
-
777
- renderRoutingValue(key, value) {
778
- const k = String(key);
779
- const v = String(value || '');
780
- if (k === 'backpressure') {
781
- if (!v || v === 'none' || v === '') {
782
- return '<span class="bp-none">none</span>';
783
- }
784
- return '<span class="bp-warning">' + this._escHtml(v) + '</span>';
785
- }
786
- if (k === 'suggested_roles' || k === 'allowed_events') {
787
- const items = v.split(',').map(s => s.trim()).filter(Boolean);
788
- if (items.length === 0) return '<span class="bp-none">-</span>';
789
- return items.map(i => '<span class="routing-badge">' + this._escHtml(i) + '</span>').join(' ');
790
- }
791
- return '<span class="routing-badge">' + this._escHtml(v) + '</span>';
792
- },
793
-
794
- isPromptField(topic, key) {
795
- return String(topic) === 'iteration.start' && String(key) === 'prompt';
796
- },
797
-
798
- parsePromptSections(text) {
799
- if (!text) return null;
800
- const s = String(text);
801
- const sections = {};
802
-
803
- // Objective
804
- const objMatch = s.match(/Objective:\\n([\\s\\S]*?)(?=\\n(?:Loop memory:|Topology \\(advisory\\):|Current scratchpad:|Use the event tool|Iteration:|$))/);
805
- if (objMatch) sections.objective = objMatch[1].trim();
806
-
807
- // Topology
808
- const topoMatch = s.match(/Topology \\(advisory\\):\\n([\\s\\S]*?)(?=\\n(?:Iteration:|Current scratchpad:|Use the event tool|Loop memory:|Objective:|$))/);
809
- if (topoMatch) sections.topology = topoMatch[1].trim();
810
-
811
- // Scratchpad
812
- const scratchMatch = s.match(/Current scratchpad:\\n([\\s\\S]*?)(?=\\n(?:Use the event tool|Backpressure rule:|Plain text alone|$))/);
813
- if (scratchMatch) sections.scratchpad = scratchMatch[1].trim();
814
-
815
- // Rules (event tool usage + examples + backpressure)
816
- const rulesMatch = s.match(/(Use the event tool[\\s\\S]*?)$/);
817
- if (rulesMatch) sections.rules = rulesMatch[1].trim();
818
-
819
- // Loop memory
820
- const memMatch = s.match(/Loop memory:\\n([\\s\\S]*?)(?=\\n(?:Topology \\(advisory\\):|Current scratchpad:|Objective:|Iteration:|$))/);
821
- if (memMatch) sections.memory = memMatch[1].trim();
822
-
823
- // Config (Iteration, Log level, Completion event, etc.)
824
- const cfgMatch = s.match(/(Iteration:[\\s\\S]*?)(?=\\n(?:Current scratchpad:|Use the event tool|$))/);
825
- if (cfgMatch) sections.config = cfgMatch[1].trim();
826
-
827
- // Harness instructions
828
- const harnessMatch = s.match(/Live harness instructions:\\n([\\s\\S]*?)(?=\\n(?:Context pressure:|Objective:|Loop memory:|Topology|$))/);
829
- if (harnessMatch) sections.harness = harnessMatch[1].trim();
830
-
831
- return Object.keys(sections).length > 0 ? sections : null;
832
- },
833
-
834
- renderTopologyBlock(text) {
835
- if (!text) return '';
836
- let html = '';
837
- const lines = String(text).split('\\n');
838
- for (const line of lines) {
839
- const kv = line.match(/^([^:]+):\\s*(.+)$/);
840
- if (kv) {
841
- const label = kv[1].trim();
842
- const val = kv[2].trim();
843
- if (label === 'Suggested next roles' || label === 'Allowed next events' || label === 'Recent routing event') {
844
- html += '<span class="topo-label">' + this._escHtml(label) + ':</span> ';
845
- const items = val.split(',').map(s => s.trim()).filter(Boolean);
846
- for (const item of items) {
847
- html += '<span class="topo-badge">' + this._escHtml(item) + '</span> ';
848
- }
849
- } else {
850
- html += '<span class="topo-label">' + this._escHtml(label) + ':</span> <span>' + this._escHtml(val) + '</span> ';
851
- }
852
- }
853
- }
854
- // Role deck
855
- const deckMatch = text.match(/Role deck:\\n([\\s\\S]*?)$/);
856
- if (deckMatch) {
857
- const roles = deckMatch[1].match(/- role \`([^\`]+)\`/g);
858
- if (roles) {
859
- html += '<span class="topo-label">Roles:</span> ';
860
- for (const r of roles) {
861
- const name = r.match(/\`([^\`]+)\`/);
862
- if (name) html += '<span class="topo-badge">' + this._escHtml(name[1]) + '</span> ';
863
- }
864
- }
865
- }
866
- return html;
867
- },
868
-
869
- getScratchpadEntries(text) {
870
- if (!text) return [];
871
- // Split by "## Iteration N" headers
872
- const parts = String(text).split(/(?=## Iteration \\d+)/);
873
- return parts.filter(p => p.trim().length > 0);
874
- },
875
-
876
- _escHtml(s) {
877
- return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
878
- },
879
-
880
- async fetchArtifacts() {
881
- if (!this.selectedRun) return;
882
- try {
883
- const res = await fetch('/api/runs/' + this.selectedRun + '/artifacts');
884
- if (res.ok) this.artifactsData = await res.json();
885
- } catch (e) { /* ignore */ }
886
- },
887
-
888
- async viewArtifactDoc(path) {
889
- if (!this.selectedRun) return;
890
- try {
891
- const res = await fetch('/api/runs/' + this.selectedRun + '/artifact?path=' + encodeURIComponent(path));
892
- if (res.ok) {
893
- this.artifactDocContent = await res.text();
894
- this.artifactDocPath = path;
895
- }
896
- } catch (e) { /* ignore */ }
897
- },
898
-
899
- artifactsCategoryBars() {
900
- if (!this.artifactsData) return [];
901
- const ev = this.artifactsData.events;
902
- const max = Math.max(ev.loop, ev.iteration, ev.backend, ev.review, ev.coordination, ev.operator, ev.routing, ev.errors, 1);
903
- return [
904
- { key: 'loop', label: 'loop', count: ev.loop, pct: (ev.loop / max) * 100, color: 'var(--cat-loop)' },
905
- { key: 'iteration', label: 'iteration', count: ev.iteration, pct: (ev.iteration / max) * 100, color: 'var(--cat-iteration)' },
906
- { key: 'backend', label: 'backend', count: ev.backend, pct: (ev.backend / max) * 100, color: 'var(--cat-backend)' },
907
- { key: 'review', label: 'review', count: ev.review, pct: (ev.review / max) * 100, color: 'var(--cat-review)' },
908
- { key: 'coordination', label: 'coord', count: ev.coordination, pct: (ev.coordination / max) * 100, color: 'var(--cat-coordination)' },
909
- { key: 'operator', label: 'operator', count: ev.operator, pct: (ev.operator / max) * 100, color: 'var(--cat-operator)' },
910
- { key: 'routing', label: 'routing', count: ev.routing, pct: (ev.routing / max) * 100, color: 'var(--cat-routing, #6366f1)' },
911
- { key: 'errors', label: 'errors', count: ev.errors, pct: (ev.errors / max) * 100, color: 'var(--cat-error)' },
912
- ];
913
- },
914
-
915
- formatBytes(bytes) {
916
- if (!bytes || bytes === 0) return '0 B';
917
- if (bytes < 1024) return bytes + ' B';
918
- const kb = bytes / 1024;
919
- if (kb < 1024) return kb.toFixed(1) + ' KB';
920
- return (kb / 1024).toFixed(1) + ' MB';
921
- },
922
-
923
- visibleRunEvents() {
924
- return this.selectedRunEvents.filter(ev => this.showVerbose || !this.isBackendEvent(ev));
925
- },
926
-
927
- isBackendEvent(ev) {
928
- const t = String(ev?.topic || '');
929
- return t.startsWith('backend.');
930
- },
931
-
932
- eventCategory(ev) {
933
- const t = ev.topic || '';
934
- if (['event.invalid','wave.timeout','wave.failed','loop.stop'].includes(t)) return 'ev-error';
935
- if (t === 'task.complete' || t === 'loop.complete') return 'ev-completion';
936
- if (t.startsWith('review.')) return 'ev-review';
937
- if (t.startsWith('backend.')) return 'ev-backend';
938
- if (t.startsWith('iteration.')) return 'ev-system';
939
- return 'ev-coordination';
940
- },
941
-
942
- eventClasses(ev) {
943
- const classes = ['event-item', this.eventCategory(ev)];
944
- if ((ev.topic || '') === 'iteration.start') classes.push('ev-highlight');
945
- return classes.join(' ');
946
- },
947
-
948
- topicCategoryKey(ev) {
949
- const t = String(ev?.topic || '');
950
- if (['event.invalid','wave.timeout','wave.failed','loop.stop'].includes(t)) return 'error';
951
- if (t === 'task.complete' || t === 'loop.complete') return 'completion';
952
- if (t.startsWith('loop.')) return 'loop';
953
- if (t.startsWith('iteration.')) return 'iteration';
954
- if (t.startsWith('backend.')) return 'backend';
955
- if (t.startsWith('review.')) return 'review';
956
- if (t.startsWith('operator.')) return 'operator';
957
- return 'coordination';
958
- },
959
-
960
- journalCategoryChips() {
961
- const counts = {};
962
- for (const k of Object.keys(this.journalCategoryFilter)) counts[k] = 0;
963
- for (const ev of this.selectedRunEvents) {
964
- const cat = this.topicCategoryKey(ev);
965
- if (cat in counts) counts[cat]++;
966
- }
967
- const labels = { loop: 'Loop', iteration: 'Iteration', backend: 'Backend', review: 'Review', coordination: 'Coordination', error: 'Error', operator: 'Operator', completion: 'Completion' };
968
- return Object.keys(this.journalCategoryFilter).map(key => ({
969
- key,
970
- label: labels[key] || key,
971
- color: this.categoryColors[key] || '#666',
972
- count: counts[key] || 0,
973
- enabled: this.journalCategoryFilter[key],
974
- }));
975
- },
976
-
977
- filteredJournalEvents() {
978
- const search = (this.journalSearch || '').toLowerCase();
979
- return this.selectedRunEvents.filter(ev => {
980
- const cat = this.topicCategoryKey(ev);
981
- if (!this.journalCategoryFilter[cat]) return false;
982
- if (search) {
983
- const text = JSON.stringify(ev).toLowerCase();
984
- if (!text.includes(search)) return false;
985
- }
986
- return true;
987
- });
988
- },
989
-
990
- journalGroups() {
991
- const events = this.filteredJournalEvents();
992
- const groups = {};
993
- const order = [];
994
- for (const ev of events) {
995
- const iter = ev.iteration;
996
- const key = iter ? 'iter-' + iter : 'system';
997
- if (!groups[key]) {
998
- const label = iter ? '\\u2500\\u2500 iter ' + iter + ' \\u2500\\u2500' : '\\u2500\\u2500 system \\u2500\\u2500';
999
- groups[key] = { key, label, events: [] };
1000
- order.push(key);
1001
- }
1002
- groups[key].events.push(ev);
1003
- }
1004
- return order.map(k => groups[k]);
1005
- },
1006
-
1007
- eventSummary(ev) {
1008
- const parts = [];
1009
- if (ev.iteration) parts.push('[iter ' + ev.iteration + ']');
1010
- if (ev.ts) parts.push(this.timeAgo(ev.ts));
1011
- parts.push(ev.topic || JSON.stringify(ev).slice(0, 80));
1012
- const f = ev.fields || {};
1013
- const t = ev.topic || '';
1014
- if (t === 'iteration.start') {
1015
- const hints = [];
1016
- if (f.recent_event) hints.push(f.recent_event);
1017
- if (f.suggested_roles) hints.push('\\u2192 ' + f.suggested_roles);
1018
- if (f.allowed_events) hints.push('\\u00b7 emits ' + f.allowed_events);
1019
- if (f.backpressure && String(f.backpressure) !== 'none' && String(f.backpressure).trim() !== '') {
1020
- hints.push('[BP: ' + f.backpressure + ']');
1021
- }
1022
- if (hints.length) {
1023
- parts.push('\\u2014 ' + hints.join(' '));
1024
- } else if (f.prompt) {
1025
- const objMatch = String(f.prompt).match(/Objective:\\s*\\n?([^\\n]+)/);
1026
- if (objMatch) {
1027
- const preview = objMatch[1].trim().slice(0, 100);
1028
- parts.push('\\u2014 ' + preview + (objMatch[1].trim().length > 100 ? '...' : ''));
1029
- }
1030
- }
1031
- } else if (t === 'review.start') {
1032
- const f = ev.fields || {};
1033
- parts.push('Review Started');
1034
- const hint = [];
1035
- if (f.reason) hint.push(String(f.reason).slice(0, 60));
1036
- if (hint.length) parts.push('\\u2014 ' + hint.join(' '));
1037
- } else if (t === 'review.finish') {
1038
- const f = ev.fields || {};
1039
- parts.push('Review Finished');
1040
- const hint = [];
1041
- if (f.decision) hint.push('decision=' + f.decision);
1042
- if (f.output) hint.push(String(f.output).replace(/\\s+/g, ' ').trim().slice(0, 80));
1043
- if (hint.length) parts.push('\\u2014 ' + hint.join(' '));
1044
- } else if (t === 'iteration.finish' || t === 'backend.finish') {
1045
- const hint = [];
1046
- if (f.exit_code !== undefined) hint.push('exit=' + f.exit_code);
1047
- if (f.timed_out === 'true' || f.timed_out === true) hint.push('TIMEOUT');
1048
- if (f.elapsed_s !== undefined) hint.push(f.elapsed_s + 's');
1049
- if (f.output) hint.push(String(f.output).replace(/\\s+/g, ' ').trim().slice(0, 80));
1050
- if (hint.length) parts.push('\\u2014 ' + hint.join(' '));
1051
- } else if (ev.payload) {
1052
- parts.push('\\u2014 ' + String(ev.payload).slice(0, 60));
1053
- }
1054
- return parts.join(' ');
1055
- },
1056
- };
1057
- }
1058
- </script>
1059
- </body>
1060
- </html>`;
1061
- }
1062
- //# sourceMappingURL=shell.js.map