@the-open-engine/zeroshot 6.38.0 → 6.39.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 (381) hide show
  1. package/cli/event-copy.js +8 -7
  2. package/cli/event-copy.ts +12 -0
  3. package/cli/index.js +7 -31
  4. package/cli/json-export.js +61 -64
  5. package/cli/json-export.ts +112 -0
  6. package/cli/message-formatter-utils.js +68 -56
  7. package/cli/message-formatter-utils.ts +121 -0
  8. package/cli/message-formatters-normal.js +124 -259
  9. package/cli/message-formatters-normal.ts +250 -0
  10. package/cli/message-formatters-watch.js +81 -84
  11. package/cli/message-formatters-watch.ts +189 -0
  12. package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
  13. package/lib/agent-cli-provider/adapters/codex.js +3 -1
  14. package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
  15. package/lib/cluster/generated/protocol-schema.cjs +1 -1
  16. package/lib/cluster/generated/protocol-schema.mjs +1 -1
  17. package/lib/cluster/generated/protocol.d.cts +8 -0
  18. package/lib/cluster/generated/protocol.d.mts +8 -0
  19. package/lib/cluster/generated/protocol.d.ts +8 -0
  20. package/lib/clusters-registry.d.ts +23 -0
  21. package/lib/clusters-registry.js +17 -29
  22. package/lib/completion.d.ts +12 -0
  23. package/lib/completion.js +84 -94
  24. package/lib/compose-utils.d.ts +32 -0
  25. package/lib/compose-utils.js +57 -72
  26. package/lib/detached-startup.d.ts +83 -0
  27. package/lib/detached-startup.js +231 -302
  28. package/lib/docker-config.d.ts +43 -0
  29. package/lib/docker-config.js +150 -325
  30. package/lib/docker-env-auth.d.ts +17 -0
  31. package/lib/docker-env-auth.js +75 -0
  32. package/lib/git-remote-utils.d.ts +48 -0
  33. package/lib/git-remote-utils.js +147 -213
  34. package/lib/id-detector.d.ts +15 -0
  35. package/lib/id-detector.js +37 -41
  36. package/lib/path-check.d.ts +30 -0
  37. package/lib/path-check.js +42 -45
  38. package/lib/process-liveness.d.ts +16 -0
  39. package/lib/process-liveness.js +19 -12
  40. package/lib/provider-credential-path.d.ts +16 -0
  41. package/lib/provider-credential-path.js +31 -29
  42. package/lib/provider-defaults.d.ts +30 -0
  43. package/lib/provider-defaults.js +47 -42
  44. package/lib/provider-detection.d.ts +11 -0
  45. package/lib/provider-detection.js +91 -54
  46. package/lib/provider-names.d.ts +38 -0
  47. package/lib/provider-names.js +56 -64
  48. package/lib/repo-settings.d.ts +28 -0
  49. package/lib/repo-settings.js +83 -59
  50. package/lib/run-mode.d.ts +21 -0
  51. package/lib/run-mode.js +21 -20
  52. package/lib/run-plan.d.ts +28 -0
  53. package/lib/run-plan.js +17 -16
  54. package/lib/settings/claude-auth.d.ts +35 -0
  55. package/lib/settings/claude-auth.js +30 -47
  56. package/lib/settings-defaults.d.ts +20 -0
  57. package/lib/settings-defaults.js +149 -0
  58. package/lib/settings-error.d.ts +7 -0
  59. package/lib/settings-error.js +8 -0
  60. package/lib/settings-issue-providers.d.ts +10 -0
  61. package/lib/settings-issue-providers.js +12 -0
  62. package/lib/settings-models.d.ts +22 -0
  63. package/lib/settings-models.js +93 -0
  64. package/lib/settings-storage.d.ts +23 -0
  65. package/lib/settings-storage.js +205 -0
  66. package/lib/settings-validation.d.ts +7 -0
  67. package/lib/settings-validation.js +182 -0
  68. package/lib/settings.d.ts +29 -0
  69. package/lib/settings.js +41 -736
  70. package/lib/setup-apply-types.d.ts +66 -0
  71. package/lib/setup-apply-types.js +2 -0
  72. package/lib/setup-apply.d.ts +39 -0
  73. package/lib/setup-apply.js +267 -264
  74. package/lib/setup-journal.d.ts +41 -0
  75. package/lib/setup-journal.js +119 -76
  76. package/lib/setup-plan-types.d.ts +102 -0
  77. package/lib/setup-plan-types.js +2 -0
  78. package/lib/setup-plan.d.ts +30 -0
  79. package/lib/setup-plan.js +300 -324
  80. package/lib/setup-undo.d.ts +44 -0
  81. package/lib/setup-undo.js +61 -74
  82. package/lib/start-cluster-config.d.ts +26 -0
  83. package/lib/start-cluster-config.js +56 -0
  84. package/lib/start-cluster-environment.d.ts +40 -0
  85. package/lib/start-cluster-environment.js +134 -0
  86. package/lib/start-cluster-run-options.d.ts +53 -0
  87. package/lib/start-cluster-run-options.js +147 -0
  88. package/lib/start-cluster.d.ts +64 -0
  89. package/lib/start-cluster.js +98 -454
  90. package/lib/stream-json-parser.d.ts +17 -0
  91. package/lib/stream-json-parser.js +51 -52
  92. package/npm-shrinkwrap.json +2 -2
  93. package/package.json +12 -6
  94. package/scripts/postinstall.js +27 -0
  95. package/scripts/rust-distribution.js +23 -14
  96. package/src/agent/agent-command-proofs-context.js +35 -45
  97. package/src/agent/agent-command-proofs-context.ts +87 -0
  98. package/src/agent/agent-config-settings.js +19 -0
  99. package/src/agent/agent-config-settings.ts +41 -0
  100. package/src/agent/agent-config.js +122 -231
  101. package/src/agent/agent-config.ts +285 -0
  102. package/src/agent/agent-context-builder.js +38 -273
  103. package/src/agent/agent-context-builder.ts +51 -0
  104. package/src/agent/agent-context-environment-sections.js +105 -0
  105. package/src/agent/agent-context-environment-sections.ts +134 -0
  106. package/src/agent/agent-context-packs.js +165 -0
  107. package/src/agent/agent-context-packs.ts +296 -0
  108. package/src/agent/agent-context-prompt-sections.js +100 -0
  109. package/src/agent/agent-context-prompt-sections.ts +148 -0
  110. package/src/agent/agent-context-sections.js +25 -334
  111. package/src/agent/agent-context-sections.ts +36 -0
  112. package/src/agent/agent-context-sources.js +96 -149
  113. package/src/agent/agent-context-sources.ts +253 -0
  114. package/src/agent/agent-context-types.js +2 -0
  115. package/src/agent/agent-context-types.ts +132 -0
  116. package/src/agent/agent-context-validation-sections.js +73 -0
  117. package/src/agent/agent-context-validation-sections.ts +129 -0
  118. package/src/agent/agent-input-injector.js +99 -118
  119. package/src/agent/agent-input-injector.ts +195 -0
  120. package/src/agent/agent-liveness-poll.js +74 -78
  121. package/src/agent/agent-liveness-poll.ts +163 -0
  122. package/src/agent/agent-quality-gate-schema.js +77 -86
  123. package/src/agent/agent-quality-gate-schema.ts +135 -0
  124. package/src/agent/agent-quality-gates-context.js +44 -50
  125. package/src/agent/agent-quality-gates-context.ts +91 -0
  126. package/src/agent/agent-stuck-detector.js +171 -239
  127. package/src/agent/agent-stuck-detector.ts +288 -0
  128. package/src/agent/agent-trigger-evaluator.js +29 -46
  129. package/src/agent/agent-trigger-evaluator.ts +98 -0
  130. package/src/agent/context-metrics.js +110 -141
  131. package/src/agent/context-metrics.ts +261 -0
  132. package/src/agent/context-pack-builder.js +72 -358
  133. package/src/agent/context-pack-builder.ts +105 -0
  134. package/src/agent/context-pack-core.js +70 -0
  135. package/src/agent/context-pack-core.ts +96 -0
  136. package/src/agent/context-pack-selection.js +119 -0
  137. package/src/agent/context-pack-selection.ts +187 -0
  138. package/src/agent/context-pack-truncation.js +139 -0
  139. package/src/agent/context-pack-truncation.ts +208 -0
  140. package/src/agent/context-pack-types.js +2 -0
  141. package/src/agent/context-pack-types.ts +98 -0
  142. package/src/agent/context-replay-policy.js +30 -39
  143. package/src/agent/context-replay-policy.ts +71 -0
  144. package/src/agent/critical-agent-policy.js +6 -10
  145. package/src/agent/critical-agent-policy.ts +20 -0
  146. package/src/agent/guidance-queue.js +74 -87
  147. package/src/agent/guidance-queue.ts +166 -0
  148. package/src/agent/output-extraction-error-detail.js +45 -0
  149. package/src/agent/output-extraction-error-detail.ts +49 -0
  150. package/src/agent/output-extraction-failures.js +125 -0
  151. package/src/agent/output-extraction-failures.ts +149 -0
  152. package/src/agent/output-extraction-json.js +234 -0
  153. package/src/agent/output-extraction-json.ts +235 -0
  154. package/src/agent/output-extraction-pi.js +124 -0
  155. package/src/agent/output-extraction-pi.ts +137 -0
  156. package/src/agent/output-extraction-types.js +2 -0
  157. package/src/agent/output-extraction-types.ts +49 -0
  158. package/src/agent/output-extraction.js +17 -617
  159. package/src/agent/output-extraction.ts +30 -0
  160. package/src/agent/output-reformatter-errors.js +83 -0
  161. package/src/agent/output-reformatter-errors.ts +106 -0
  162. package/src/agent/output-reformatter-types.js +2 -0
  163. package/src/agent/output-reformatter-types.ts +86 -0
  164. package/src/agent/output-reformatter.js +140 -185
  165. package/src/agent/output-reformatter.ts +238 -0
  166. package/src/agent/pi-terminal-lifecycle-types.js +2 -0
  167. package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
  168. package/src/agent/pi-terminal-lifecycle.js +186 -206
  169. package/src/agent/pi-terminal-lifecycle.ts +297 -0
  170. package/src/agent/provider-control-plane.js +22 -21
  171. package/src/agent/provider-control-plane.ts +52 -0
  172. package/src/agent/provider-terminal-failure-types.js +2 -0
  173. package/src/agent/provider-terminal-failure-types.ts +60 -0
  174. package/src/agent/provider-terminal-failure.js +194 -191
  175. package/src/agent/provider-terminal-failure.ts +262 -0
  176. package/src/agent/rate-limit-backoff.js +31 -74
  177. package/src/agent/rate-limit-backoff.ts +71 -0
  178. package/src/agent/schema-utils.js +85 -125
  179. package/src/agent/schema-utils.ts +148 -0
  180. package/src/agent/structured-output-error.js +34 -33
  181. package/src/agent/structured-output-error.ts +105 -0
  182. package/src/agent/validation-platform.js +27 -27
  183. package/src/agent/validation-platform.ts +49 -0
  184. package/src/agent-cli-provider/adapters/codex.ts +3 -1
  185. package/src/attach/attach-client.js +232 -405
  186. package/src/attach/attach-client.ts +300 -0
  187. package/src/attach/attach-server-cleanup.js +43 -0
  188. package/src/attach/attach-server-cleanup.ts +39 -0
  189. package/src/attach/attach-server-clients.js +117 -0
  190. package/src/attach/attach-server-clients.ts +122 -0
  191. package/src/attach/attach-server-events.js +38 -0
  192. package/src/attach/attach-server-events.ts +36 -0
  193. package/src/attach/attach-server-pty.js +45 -0
  194. package/src/attach/attach-server-pty.ts +64 -0
  195. package/src/attach/attach-server-runtime.js +73 -0
  196. package/src/attach/attach-server-runtime.ts +62 -0
  197. package/src/attach/attach-server-socket.js +28 -0
  198. package/src/attach/attach-server-socket.ts +23 -0
  199. package/src/attach/attach-server-types.js +2 -0
  200. package/src/attach/attach-server-types.ts +82 -0
  201. package/src/attach/attach-server.js +106 -523
  202. package/src/attach/attach-server.ts +158 -0
  203. package/src/attach/index.js +18 -35
  204. package/src/attach/index.ts +18 -0
  205. package/src/attach/protocol.js +95 -184
  206. package/src/attach/protocol.ts +181 -0
  207. package/src/attach/ring-buffer.js +76 -102
  208. package/src/attach/ring-buffer.ts +109 -0
  209. package/src/attach/send-input.js +64 -75
  210. package/src/attach/send-input.ts +94 -0
  211. package/src/attach/socket-discovery.js +164 -218
  212. package/src/attach/socket-discovery.ts +230 -0
  213. package/src/attach/socket-paths.js +42 -61
  214. package/src/attach/socket-paths.ts +81 -0
  215. package/src/claude-credentials.js +51 -54
  216. package/src/claude-credentials.ts +89 -0
  217. package/src/cluster/generated/protocol-schema.ts +1 -1
  218. package/src/cluster/generated/protocol.ts +2 -1
  219. package/src/command-proofs.js +110 -141
  220. package/src/command-proofs.ts +216 -0
  221. package/src/config-router.js +81 -73
  222. package/src/config-router.ts +131 -0
  223. package/src/copy-worker.js +53 -29
  224. package/src/copy-worker.ts +75 -0
  225. package/src/darwin-keychain-boundary.js +80 -111
  226. package/src/darwin-keychain-boundary.ts +148 -0
  227. package/src/guidance-topics.js +4 -5
  228. package/src/guidance-topics.ts +10 -0
  229. package/src/input-helpers.js +33 -54
  230. package/src/input-helpers.ts +58 -0
  231. package/src/ledger-sequence.js +45 -48
  232. package/src/ledger-sequence.ts +63 -0
  233. package/src/legacy-lib/clusters-registry.ts +40 -0
  234. package/src/legacy-lib/completion.ts +148 -0
  235. package/src/legacy-lib/compose-utils.ts +102 -0
  236. package/src/legacy-lib/detached-startup.ts +449 -0
  237. package/src/legacy-lib/docker-config.ts +282 -0
  238. package/src/legacy-lib/docker-env-auth.ts +116 -0
  239. package/src/legacy-lib/git-remote-utils.ts +244 -0
  240. package/src/legacy-lib/id-detector.ts +57 -0
  241. package/src/legacy-lib/js-yaml.d.ts +3 -0
  242. package/src/legacy-lib/omelette.d.ts +15 -0
  243. package/src/legacy-lib/path-check.ts +89 -0
  244. package/src/legacy-lib/process-liveness.ts +36 -0
  245. package/src/legacy-lib/provider-credential-path.ts +57 -0
  246. package/src/legacy-lib/provider-defaults.ts +114 -0
  247. package/src/legacy-lib/provider-detection.ts +67 -0
  248. package/src/legacy-lib/provider-names.ts +126 -0
  249. package/src/legacy-lib/repo-settings.ts +88 -0
  250. package/src/legacy-lib/run-mode.ts +58 -0
  251. package/src/legacy-lib/run-plan.ts +49 -0
  252. package/src/legacy-lib/settings/claude-auth.ts +80 -0
  253. package/src/legacy-lib/settings-defaults.ts +212 -0
  254. package/src/legacy-lib/settings-error.ts +8 -0
  255. package/src/legacy-lib/settings-issue-providers.ts +18 -0
  256. package/src/legacy-lib/settings-models.ts +124 -0
  257. package/src/legacy-lib/settings-storage.ts +277 -0
  258. package/src/legacy-lib/settings-validation.ts +220 -0
  259. package/src/legacy-lib/settings.ts +87 -0
  260. package/src/legacy-lib/setup-apply-types.ts +70 -0
  261. package/src/legacy-lib/setup-apply.ts +456 -0
  262. package/src/legacy-lib/setup-journal.ts +185 -0
  263. package/src/legacy-lib/setup-plan-types.ts +96 -0
  264. package/src/legacy-lib/setup-plan.ts +500 -0
  265. package/src/legacy-lib/setup-undo.ts +142 -0
  266. package/src/legacy-lib/start-cluster-config.ts +124 -0
  267. package/src/legacy-lib/start-cluster-environment.ts +165 -0
  268. package/src/legacy-lib/start-cluster-run-options.ts +279 -0
  269. package/src/legacy-lib/start-cluster.ts +237 -0
  270. package/src/legacy-lib/stream-json-parser.ts +88 -0
  271. package/src/message-buffer.js +55 -71
  272. package/src/message-buffer.ts +107 -0
  273. package/src/message-bus-bridge.js +92 -133
  274. package/src/message-bus-bridge.ts +149 -0
  275. package/src/name-generator-shared.js +220 -0
  276. package/src/name-generator-shared.ts +231 -0
  277. package/src/name-generator.js +8 -217
  278. package/src/name-generator.ts +27 -0
  279. package/src/omp-blob-root.js +83 -64
  280. package/src/omp-blob-root.ts +116 -0
  281. package/src/omp-config-overlay.js +65 -38
  282. package/src/omp-config-overlay.ts +110 -0
  283. package/src/omp-execution-fingerprint.js +38 -43
  284. package/src/omp-execution-fingerprint.ts +92 -0
  285. package/src/omp-session-limits.js +10 -15
  286. package/src/omp-session-limits.ts +53 -0
  287. package/src/omp-session-partition.js +2 -2
  288. package/src/omp-session-verifier.js +1 -1
  289. package/src/orchestrator.js +19 -4
  290. package/src/providers/anthropic/index.js +3 -1
  291. package/src/providers/anthropic/index.ts +13 -0
  292. package/src/providers/capabilities.js +19 -27
  293. package/src/providers/capabilities.ts +44 -0
  294. package/src/providers/google/index.js +3 -1
  295. package/src/providers/google/index.ts +13 -0
  296. package/src/providers/openai/index.js +3 -1
  297. package/src/providers/openai/index.ts +13 -0
  298. package/src/providers/opencode/index.js +3 -1
  299. package/src/providers/opencode/index.ts +13 -0
  300. package/src/quality-gates.js +67 -127
  301. package/src/quality-gates.ts +149 -0
  302. package/src/repo-settings-access.js +40 -0
  303. package/src/repo-settings-access.ts +64 -0
  304. package/src/schemas/sub-cluster.js +127 -183
  305. package/src/schemas/sub-cluster.ts +238 -0
  306. package/src/state-snapshot-normalization.js +224 -0
  307. package/src/state-snapshot-normalization.ts +222 -0
  308. package/src/state-snapshot.js +192 -359
  309. package/src/state-snapshot.ts +291 -0
  310. package/src/state-snapshotter.js +118 -130
  311. package/src/state-snapshotter.ts +167 -0
  312. package/src/sub-cluster-wrapper.js +4 -13
  313. package/src/task-run-model-args.js +87 -124
  314. package/src/task-run-model-args.ts +204 -0
  315. package/src/task-runner.js +5 -25
  316. package/src/task-runner.ts +28 -0
  317. package/src/task-startup-error.js +73 -58
  318. package/src/task-startup-error.ts +126 -0
  319. package/src/template-validation/consensus-gate-contracts.js +2 -0
  320. package/src/template-validation/consensus-gate-contracts.ts +70 -0
  321. package/src/template-validation/consensus-gate-scenarios.js +76 -0
  322. package/src/template-validation/consensus-gate-scenarios.ts +130 -0
  323. package/src/template-validation/consensus-gate-stage.js +34 -0
  324. package/src/template-validation/consensus-gate-stage.ts +56 -0
  325. package/src/template-validation/random-topology-contracts.js +2 -0
  326. package/src/template-validation/random-topology-contracts.ts +54 -0
  327. package/src/template-validation/random-topology-dispatch.js +25 -0
  328. package/src/template-validation/random-topology-dispatch.ts +33 -0
  329. package/src/template-validation/random-topology-message-loop.js +53 -0
  330. package/src/template-validation/random-topology-message-loop.ts +73 -0
  331. package/src/template-validation/random-topology-operations.js +79 -0
  332. package/src/template-validation/random-topology-operations.ts +101 -0
  333. package/src/template-validation/random-topology-runtime.js +25 -0
  334. package/src/template-validation/random-topology-runtime.ts +43 -0
  335. package/src/template-validation/random-topology-scenario.js +52 -0
  336. package/src/template-validation/random-topology-scenario.ts +57 -0
  337. package/src/template-validation/random-topology-schema.js +159 -0
  338. package/src/template-validation/random-topology-schema.ts +190 -0
  339. package/src/template-validation/random-topology-state.js +28 -0
  340. package/src/template-validation/random-topology-state.ts +30 -0
  341. package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
  342. package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
  343. package/src/template-validation/random-topology-trigger.js +75 -0
  344. package/src/template-validation/random-topology-trigger.ts +88 -0
  345. package/src/template-validation/report-formatter.js +40 -46
  346. package/src/template-validation/report-formatter.ts +101 -0
  347. package/src/template-validation/simulate-consensus-gates.js +111 -302
  348. package/src/template-validation/simulate-consensus-gates.ts +196 -0
  349. package/src/template-validation/simulate-random-topology.js +26 -519
  350. package/src/template-validation/simulate-random-topology.ts +57 -0
  351. package/src/template-validation/simulate-two-stage-validation.js +41 -265
  352. package/src/template-validation/simulate-two-stage-validation.ts +55 -0
  353. package/src/template-validation/simulation-agent-runtime.js +25 -0
  354. package/src/template-validation/simulation-agent-runtime.ts +40 -0
  355. package/src/template-validation/simulation-agent.js +29 -0
  356. package/src/template-validation/simulation-agent.ts +73 -0
  357. package/src/template-validation/simulation-runtime.js +34 -0
  358. package/src/template-validation/simulation-runtime.ts +72 -0
  359. package/src/template-validation/two-stage-contracts.js +2 -0
  360. package/src/template-validation/two-stage-contracts.ts +41 -0
  361. package/src/template-validation/two-stage-inputs.js +21 -0
  362. package/src/template-validation/two-stage-inputs.ts +29 -0
  363. package/src/template-validation/two-stage-results.js +30 -0
  364. package/src/template-validation/two-stage-results.ts +40 -0
  365. package/src/template-validation/two-stage-scenario.js +86 -0
  366. package/src/template-validation/two-stage-scenario.ts +120 -0
  367. package/src/worktree-claude-config.js +182 -220
  368. package/src/worktree-claude-config.ts +272 -0
  369. package/src/worktree-tooling-env.js +103 -125
  370. package/src/worktree-tooling-env.ts +142 -0
  371. package/task-lib/completion.js +2 -3
  372. package/task-lib/completion.ts +9 -0
  373. package/task-lib/config.js +1 -4
  374. package/task-lib/config.ts +11 -0
  375. package/task-lib/name-generator.js +4 -226
  376. package/task-lib/name-generator.ts +11 -0
  377. package/task-lib/omp-session-cleanup.js +1 -1
  378. package/task-lib/omp-storage-root.js +8 -12
  379. package/task-lib/omp-storage-root.ts +62 -0
  380. package/task-lib/process-termination.js +143 -166
  381. package/task-lib/process-termination.ts +268 -0
@@ -1,283 +1,148 @@
1
- /**
2
- * Normal mode message formatters
3
- * Full-detail message display for non-watch mode
4
- *
5
- * All functions accept an optional `print` parameter for output routing.
6
- * When StatusFooter is active, pass safePrint to avoid terminal garbling.
7
- */
8
-
9
- const chalk = require('chalk');
10
- const { EVENT_COPY, formatMergeStatus } = require('./event-copy');
11
-
12
- /**
13
- * Format AGENT_LIFECYCLE events
14
- * @param {Object} msg - Message object
15
- * @param {string} prefix - Formatted message prefix
16
- * @param {Function} [print=console.log] - Print function for output
17
- * @returns {boolean} True if message was handled
18
- */
1
+ "use strict";
2
+ const chalk = require("chalk");
3
+ const eventCopy = require("./event-copy");
4
+ const formatterUtils = require("./message-formatter-utils");
5
+ const { EVENT_COPY, formatMergeStatus } = eventCopy;
6
+ const { formatLifecycleEvent, partitionValidationCriteria } = formatterUtils;
7
+ function isCriterionResults(value) {
8
+ return Array.isArray(value);
9
+ }
19
10
  function formatAgentLifecycle(msg, prefix, print = console.log) {
20
- const data = msg.content?.data;
21
- const event = data?.event;
22
-
23
- let icon, eventText;
24
- switch (event) {
25
- case 'STARTED':
26
- icon = chalk.green('▶');
27
- const triggers = data.triggers?.join(', ') || 'none';
28
- eventText = `started (listening for: ${chalk.dim(triggers)})`;
29
- break;
30
- case 'TASK_STARTED':
31
- icon = chalk.yellow('⚡');
32
- eventText = `${chalk.cyan(data.triggeredBy)} → task #${data.iteration} (${chalk.dim(data.model)})`;
33
- break;
34
- case 'TASK_COMPLETED':
35
- icon = chalk.green('✓');
36
- eventText = `task #${data.iteration} completed`;
37
- break;
38
- default:
39
- icon = chalk.dim('•');
40
- eventText = event || 'unknown event';
41
- }
42
-
43
- print(`${prefix} ${icon} ${eventText}`);
44
- return true;
11
+ const { icon, eventText } = formatLifecycleEvent(msg.content?.data);
12
+ print(`${prefix} ${icon} ${eventText}`);
13
+ return true;
45
14
  }
46
-
47
- /**
48
- * Format AGENT_ERROR events
49
- * @param {Object} msg - Message object
50
- * @param {string} prefix - Formatted message prefix
51
- * @param {string} timestamp - Formatted timestamp
52
- * @param {Function} [print=console.log] - Print function for output
53
- * @returns {boolean} True if message was handled
54
- */
55
15
  function formatAgentError(msg, prefix, timestamp, print = console.log) {
56
- print('');
57
- print(chalk.bold.red(`${'─'.repeat(60)}`));
58
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.red('Error: agent failed')}`);
59
-
60
- if (msg.content?.text) {
61
- print(`${prefix} ${chalk.red(msg.content.text)}`);
62
- }
63
-
64
- if (msg.content?.data?.stack) {
65
- const stackLines = msg.content.data.stack.split('\n').slice(0, 5);
66
- for (const line of stackLines) {
67
- if (line.trim()) print(`${prefix} ${chalk.dim(line)}`);
16
+ print('');
17
+ print(chalk.bold.red(`${'─'.repeat(60)}`));
18
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.red('Error: agent failed')}`);
19
+ if (msg.content?.text) {
20
+ print(`${prefix} ${chalk.red(msg.content.text)}`);
21
+ }
22
+ if (msg.content?.data?.stack) {
23
+ const stackLines = msg.content.data.stack.split('\n').slice(0, 5);
24
+ for (const line of stackLines) {
25
+ if (line.trim())
26
+ print(`${prefix} ${chalk.dim(line)}`);
27
+ }
68
28
  }
69
- }
70
-
71
- print(`${prefix} Next: inspect the agent logs and retry after fixing the cause.`);
72
- print(chalk.bold.red(`${'─'.repeat(60)}`));
73
- return true;
29
+ print(`${prefix} Next: inspect the agent logs and retry after fixing the cause.`);
30
+ print(chalk.bold.red(`${'─'.repeat(60)}`));
31
+ return true;
74
32
  }
75
-
76
- /**
77
- * Format ISSUE_OPENED events
78
- * @param {Object} msg - Message object
79
- * @param {string} prefix - Formatted message prefix
80
- * @param {string} timestamp - Formatted timestamp
81
- * @param {Set} shownNewTaskForCluster - Set tracking shown tasks
82
- * @param {Function} [print=console.log] - Print function for output
83
- * @returns {boolean} True if message was handled
84
- */
85
33
  function formatIssueOpened(msg, prefix, timestamp, shownNewTaskForCluster, print = console.log) {
86
- // Skip duplicate - conductor re-publishes after spawning agents
87
- if (shownNewTaskForCluster.has(msg.cluster_id)) {
88
- return true;
89
- }
90
- shownNewTaskForCluster.add(msg.cluster_id);
91
-
92
- print('');
93
- print(chalk.bold.blue(`${''.repeat(60)}`));
94
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.blue('📋 New task')}`);
95
-
96
- if (msg.content?.text) {
97
- const lines = msg.content.text.split('\n').slice(0, 3);
98
- for (const line of lines) {
99
- if (line.trim() && line.trim() !== '# Manual Input') {
100
- print(`${prefix} ${chalk.white(line)}`);
101
- }
34
+ // Skip duplicate - conductor re-publishes after spawning agents
35
+ if (!shownNewTaskForCluster.has(msg.cluster_id)) {
36
+ shownNewTaskForCluster.add(msg.cluster_id);
37
+ print('');
38
+ print(chalk.bold.blue(`${'─'.repeat(60)}`));
39
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.blue('📋 New task')}`);
40
+ if (msg.content?.text) {
41
+ const lines = msg.content.text.split('\n').slice(0, 3);
42
+ for (const line of lines) {
43
+ if (line.trim() && line.trim() !== '# Manual Input') {
44
+ print(`${prefix} ${chalk.white(line)}`);
45
+ }
46
+ }
47
+ }
48
+ print(chalk.bold.blue(`${'─'.repeat(60)}`));
102
49
  }
103
- }
104
-
105
- print(chalk.bold.blue(`${'─'.repeat(60)}`));
106
- return true;
50
+ return true;
107
51
  }
108
-
109
- /**
110
- * Format IMPLEMENTATION_READY events
111
- * @param {Object} msg - Message object
112
- * @param {string} prefix - Formatted message prefix
113
- * @param {string} timestamp - Formatted timestamp
114
- * @param {Function} [print=console.log] - Print function for output
115
- * @returns {boolean} True if message was handled
116
- */
117
52
  function formatImplementationReady(msg, prefix, timestamp, print = console.log) {
118
- print(
119
- `${prefix} ${chalk.gray(timestamp)} ${chalk.bold.yellow(`✅ ${EVENT_COPY.IMPLEMENTATION_READY.toUpperCase()}`)}`
120
- );
121
-
122
- if (msg.content?.data?.commit) {
123
- print(
124
- `${prefix} ${chalk.gray('Commit:')} ${chalk.cyan(msg.content.data.commit.substring(0, 8))}`
125
- );
126
- }
127
-
128
- return true;
53
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.yellow(`✅ ${EVENT_COPY.IMPLEMENTATION_READY.toUpperCase()}`)}`);
54
+ if (msg.content?.data?.commit) {
55
+ print(`${prefix} ${chalk.gray('Commit:')} ${chalk.cyan(msg.content.data.commit.substring(0, 8))}`);
56
+ }
57
+ return true;
129
58
  }
130
-
131
- /**
132
- * Format VALIDATION_RESULT events
133
- * @param {Object} msg - Message object
134
- * @param {string} prefix - Formatted message prefix
135
- * @param {string} timestamp - Formatted timestamp
136
- * @param {Function} [print=console.log] - Print function for output
137
- * @returns {boolean} True if message was handled
138
- */
139
59
  function formatValidationResult(msg, prefix, timestamp, print = console.log) {
140
- const data = msg.content?.data || {};
141
- const approved = data.approved === true || data.approved === 'true';
142
- const status = approved ? chalk.bold.green('✓ Approved') : chalk.bold.red('✗ Rejected');
143
-
144
- print(`${prefix} ${chalk.gray(timestamp)} ${status}`);
145
-
146
- // Show summary if present and not a template variable
147
- if (msg.content?.text && !msg.content.text.includes('{{')) {
148
- print(`${prefix} ${msg.content.text.substring(0, 100)}`);
149
- }
150
-
151
- // Show CANNOT_VALIDATE (permanent) as warnings, CANNOT_VALIDATE_YET (temporary) as errors
152
- const criteriaResults = data.criteriaResults;
153
- if (Array.isArray(criteriaResults)) {
154
- // CANNOT_VALIDATE_YET = temporary, treated as FAIL (work incomplete)
155
- const cannotValidateYet = criteriaResults.filter((c) => c.status === 'CANNOT_VALIDATE_YET');
156
- if (cannotValidateYet.length > 0) {
157
- print(
158
- `${prefix} ${chalk.red('❌ Cannot validate yet')} (${cannotValidateYet.length} criteria - work incomplete):`
159
- );
160
- for (const cv of cannotValidateYet) {
161
- print(`${prefix} ${chalk.red('•')} ${cv.id}: ${cv.reason || 'No reason provided'}`);
162
- }
60
+ const data = msg.content?.data || {};
61
+ const approved = data.approved === true || data.approved === 'true';
62
+ const status = approved ? chalk.bold.green('✓ Approved') : chalk.bold.red('✗ Rejected');
63
+ print(`${prefix} ${chalk.gray(timestamp)} ${status}`);
64
+ // Show summary if present and not a template variable
65
+ if (msg.content?.text && !msg.content.text.includes('{{')) {
66
+ print(`${prefix} ${msg.content.text.substring(0, 100)}`);
163
67
  }
164
-
165
- // CANNOT_VALIDATE = permanent, treated as PASS (environmental limitation)
166
- const cannotValidate = criteriaResults.filter((c) => c.status === 'CANNOT_VALIDATE');
167
- if (cannotValidate.length > 0) {
168
- print(
169
- `${prefix} ${chalk.yellow('⚠️ Could not validate')} (${cannotValidate.length} criteria - permanent):`
170
- );
171
- for (const cv of cannotValidate) {
172
- print(`${prefix} ${chalk.yellow('•')} ${cv.id}: ${cv.reason || 'No reason provided'}`);
173
- }
68
+ // Show CANNOT_VALIDATE (permanent) as warnings, CANNOT_VALIDATE_YET (temporary) as errors
69
+ const criteriaResults = data.criteriaResults;
70
+ if (isCriterionResults(criteriaResults)) {
71
+ const { cannotValidateYet, cannotValidate } = partitionValidationCriteria(criteriaResults);
72
+ if (cannotValidateYet.length > 0) {
73
+ print(`${prefix} ${chalk.red(' Cannot validate yet')} (${cannotValidateYet.length} criteria - work incomplete):`);
74
+ for (const criterion of cannotValidateYet) {
75
+ print(`${prefix} ${chalk.red('•')} ${criterion.id}: ${criterion.reason || 'No reason provided'}`);
76
+ }
77
+ }
78
+ if (cannotValidate.length > 0) {
79
+ print(`${prefix} ${chalk.yellow('⚠️ Could not validate')} (${cannotValidate.length} criteria - permanent):`);
80
+ for (const criterion of cannotValidate) {
81
+ print(`${prefix} ${chalk.yellow('•')} ${criterion.id}: ${criterion.reason || 'No reason provided'}`);
82
+ }
83
+ }
174
84
  }
175
- }
176
-
177
- // Show full JSON data structure
178
- print(`${prefix} ${chalk.dim(JSON.stringify(data, null, 2).split('\n').join(`\n${prefix} `))}`);
179
-
180
- return true;
85
+ // Show full JSON data structure
86
+ print(`${prefix} ${chalk.dim(JSON.stringify(data, null, 2).split('\n').join(`\n${prefix} `))}`);
87
+ return true;
181
88
  }
182
-
183
- /**
184
- * Format CLUSTER_COMPLETE events
185
- * @param {Object} msg - Message object
186
- * @param {string} prefix - Formatted message prefix
187
- * @param {string} timestamp - Formatted timestamp
188
- * @param {Function} [print=console.log] - Print function for output
189
- * @returns {boolean} True if message was handled
190
- */
191
89
  function formatClusterComplete(msg, prefix, timestamp, print = console.log) {
192
- print('');
193
- print(chalk.bold.green(`${'═'.repeat(60)}`));
194
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.green('🎉 Cluster complete')}`);
195
- if (msg.content?.data?.reason) {
196
- print(`${prefix} ${chalk.green(msg.content.data.reason)}`);
197
- }
198
- print(chalk.bold.green(`${'═'.repeat(60)}`));
199
- return true;
90
+ print('');
91
+ print(chalk.bold.green(`${'═'.repeat(60)}`));
92
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.green('🎉 Cluster complete')}`);
93
+ if (msg.content?.data?.reason) {
94
+ print(`${prefix} ${chalk.green(msg.content.data.reason)}`);
95
+ }
96
+ print(chalk.bold.green(`${'═'.repeat(60)}`));
97
+ return true;
200
98
  }
201
-
202
- /**
203
- * Format CLUSTER_FAILED events
204
- * @param {Object} msg - Message object
205
- * @param {string} prefix - Formatted message prefix
206
- * @param {string} timestamp - Formatted timestamp
207
- * @param {Function} [print=console.log] - Print function for output
208
- * @returns {boolean} True if message was handled
209
- */
210
99
  function formatClusterFailed(msg, prefix, timestamp, print = console.log) {
211
- print('');
212
- print(chalk.bold.red(`${'═'.repeat(60)}`));
213
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.red('Error: cluster failed')}`);
214
- if (msg.content?.text) print(`${prefix} ${chalk.red(msg.content.text)}`);
215
- if (msg.content?.data?.reason) print(`${prefix} ${chalk.red(msg.content.data.reason)}`);
216
- print(`${prefix} Next: inspect the cluster logs, then resume after fixing the cause.`);
217
- print(chalk.bold.red(`${'═'.repeat(60)}`));
218
- return true;
100
+ print('');
101
+ print(chalk.bold.red(`${'═'.repeat(60)}`));
102
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.red('Error: cluster failed')}`);
103
+ if (msg.content?.text)
104
+ print(`${prefix} ${chalk.red(msg.content.text)}`);
105
+ if (msg.content?.data?.reason)
106
+ print(`${prefix} ${chalk.red(msg.content.data.reason)}`);
107
+ print(`${prefix} Next: inspect the cluster logs, then resume after fixing the cause.`);
108
+ print(chalk.bold.red(`${'═'.repeat(60)}`));
109
+ return true;
219
110
  }
220
-
221
- /**
222
- * Format PR_CREATED events
223
- * @param {Object} msg - Message object
224
- * @param {string} prefix - Formatted message prefix
225
- * @param {string} timestamp - Formatted timestamp
226
- * @param {Function} [print=console.log] - Print function for output
227
- * @returns {boolean} True if message was handled
228
- */
229
111
  function formatPrCreated(msg, prefix, timestamp, print = console.log) {
230
- const prNumber = msg.content?.data?.pr_number || '';
231
- const prUrl = msg.content?.data?.pr_url || '';
232
-
233
- print(''); // Blank line before PR notification
234
- print(chalk.bold.green(`${'─'.repeat(60)}`));
235
- print(
236
- `${prefix} ${chalk.gray(timestamp)} ${chalk.bold.green(`🎉 ${EVENT_COPY.PR_CREATED.toUpperCase()}`)}`
237
- );
238
-
239
- if (prNumber) {
240
- print(`${prefix} ${chalk.gray('PR:')} ${chalk.cyan(`#${prNumber}`)}`);
241
- }
242
- if (prUrl) {
243
- print(`${prefix} ${chalk.gray('URL:')} ${chalk.blue(prUrl)}`);
244
- }
245
-
246
- const mergeStatus = formatMergeStatus(msg.content?.data?.merged);
247
- if (mergeStatus) {
248
- print(
249
- `${prefix} ${chalk.gray('Merge:')} ${mergeStatus === 'merged' ? chalk.green(mergeStatus) : chalk.yellow(mergeStatus)}`
250
- );
251
- }
252
-
253
- print(chalk.bold.green(`${'─'.repeat(60)}`));
254
- return true;
112
+ const prNumber = msg.content?.data?.pr_number || '';
113
+ const prUrl = msg.content?.data?.pr_url || '';
114
+ print(''); // Blank line before PR notification
115
+ print(chalk.bold.green(`${''.repeat(60)}`));
116
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.green(`🎉 ${EVENT_COPY.PR_CREATED.toUpperCase()}`)}`);
117
+ if (prNumber) {
118
+ print(`${prefix} ${chalk.gray('PR:')} ${chalk.cyan(`#${prNumber}`)}`);
119
+ }
120
+ if (prUrl) {
121
+ print(`${prefix} ${chalk.gray('URL:')} ${chalk.blue(prUrl)}`);
122
+ }
123
+ const mergeStatus = formatMergeStatus(msg.content?.data?.merged);
124
+ if (mergeStatus) {
125
+ const formattedMergeStatus = mergeStatus === 'merged' ? chalk.green(mergeStatus) : chalk.yellow(mergeStatus);
126
+ print(`${prefix} ${chalk.gray('Merge:')} ${formattedMergeStatus}`);
127
+ }
128
+ print(chalk.bold.green(`${'─'.repeat(60)}`));
129
+ return true;
255
130
  }
256
-
257
- /**
258
- * Format generic messages (fallback)
259
- * @param {Object} msg - Message object
260
- * @param {string} prefix - Formatted message prefix
261
- * @param {string} timestamp - Formatted timestamp
262
- * @param {Function} [print=console.log] - Print function for output
263
- * @returns {boolean} True if message was handled
264
- */
265
131
  function formatGenericMessage(msg, prefix, timestamp, print = console.log) {
266
- print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold(msg.topic)}`);
267
- if (msg.content?.text) {
268
- print(`${prefix} ${msg.content.text}`);
269
- }
270
- return true;
132
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold(msg.topic)}`);
133
+ if (msg.content?.text) {
134
+ print(`${prefix} ${msg.content.text}`);
135
+ }
136
+ return true;
271
137
  }
272
-
273
138
  module.exports = {
274
- formatAgentLifecycle,
275
- formatAgentError,
276
- formatIssueOpened,
277
- formatImplementationReady,
278
- formatValidationResult,
279
- formatPrCreated,
280
- formatClusterComplete,
281
- formatClusterFailed,
282
- formatGenericMessage,
139
+ formatAgentLifecycle,
140
+ formatAgentError,
141
+ formatIssueOpened,
142
+ formatImplementationReady,
143
+ formatValidationResult,
144
+ formatPrCreated,
145
+ formatClusterComplete,
146
+ formatClusterFailed,
147
+ formatGenericMessage,
283
148
  };
@@ -0,0 +1,250 @@
1
+ import chalk = require('chalk');
2
+ import eventCopy = require('./event-copy');
3
+ import formatterUtils = require('./message-formatter-utils');
4
+
5
+ const { EVENT_COPY, formatMergeStatus } = eventCopy;
6
+ const { formatLifecycleEvent, partitionValidationCriteria } = formatterUtils;
7
+
8
+ interface CriterionResult {
9
+ status?: string;
10
+ id?: string | number;
11
+ reason?: string;
12
+ }
13
+
14
+ interface NormalMessageData {
15
+ event?: string;
16
+ triggers?: readonly string[];
17
+ triggeredBy?: string | number;
18
+ iteration?: string | number;
19
+ model?: string;
20
+ stack?: string;
21
+ commit?: string;
22
+ approved?: boolean | string;
23
+ criteriaResults?: readonly CriterionResult[];
24
+ reason?: string;
25
+ pr_number?: string | number;
26
+ pr_url?: string;
27
+ merged?: unknown;
28
+ }
29
+
30
+ interface NormalMessage {
31
+ cluster_id?: string;
32
+ topic?: string;
33
+ content?: {
34
+ text?: string;
35
+ data?: NormalMessageData;
36
+ };
37
+ }
38
+
39
+ type PrintLine = (text: string) => void;
40
+
41
+ function isCriterionResults(value: unknown): value is readonly CriterionResult[] {
42
+ return Array.isArray(value);
43
+ }
44
+
45
+ function formatAgentLifecycle(
46
+ msg: NormalMessage,
47
+ prefix: string,
48
+ print: PrintLine = console.log
49
+ ): true {
50
+ const { icon, eventText } = formatLifecycleEvent(msg.content?.data);
51
+ print(`${prefix} ${icon} ${eventText}`);
52
+ return true;
53
+ }
54
+
55
+ function formatAgentError(
56
+ msg: NormalMessage,
57
+ prefix: string,
58
+ timestamp: string,
59
+ print: PrintLine = console.log
60
+ ): true {
61
+ print('');
62
+ print(chalk.bold.red(`${'─'.repeat(60)}`));
63
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.red('Error: agent failed')}`);
64
+ if (msg.content?.text) {
65
+ print(`${prefix} ${chalk.red(msg.content.text)}`);
66
+ }
67
+ if (msg.content?.data?.stack) {
68
+ const stackLines = msg.content.data.stack.split('\n').slice(0, 5);
69
+ for (const line of stackLines) {
70
+ if (line.trim()) print(`${prefix} ${chalk.dim(line)}`);
71
+ }
72
+ }
73
+ print(`${prefix} Next: inspect the agent logs and retry after fixing the cause.`);
74
+ print(chalk.bold.red(`${'─'.repeat(60)}`));
75
+ return true;
76
+ }
77
+
78
+ function formatIssueOpened(
79
+ msg: NormalMessage,
80
+ prefix: string,
81
+ timestamp: string,
82
+ shownNewTaskForCluster: Set<string | undefined>,
83
+ print: PrintLine = console.log
84
+ ): true {
85
+ // Skip duplicate - conductor re-publishes after spawning agents
86
+ if (!shownNewTaskForCluster.has(msg.cluster_id)) {
87
+ shownNewTaskForCluster.add(msg.cluster_id);
88
+ print('');
89
+ print(chalk.bold.blue(`${'─'.repeat(60)}`));
90
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.blue('📋 New task')}`);
91
+ if (msg.content?.text) {
92
+ const lines = msg.content.text.split('\n').slice(0, 3);
93
+ for (const line of lines) {
94
+ if (line.trim() && line.trim() !== '# Manual Input') {
95
+ print(`${prefix} ${chalk.white(line)}`);
96
+ }
97
+ }
98
+ }
99
+ print(chalk.bold.blue(`${'─'.repeat(60)}`));
100
+ }
101
+ return true;
102
+ }
103
+
104
+ function formatImplementationReady(
105
+ msg: NormalMessage,
106
+ prefix: string,
107
+ timestamp: string,
108
+ print: PrintLine = console.log
109
+ ): true {
110
+ print(
111
+ `${prefix} ${chalk.gray(timestamp)} ${chalk.bold.yellow(`✅ ${EVENT_COPY.IMPLEMENTATION_READY.toUpperCase()}`)}`
112
+ );
113
+ if (msg.content?.data?.commit) {
114
+ print(
115
+ `${prefix} ${chalk.gray('Commit:')} ${chalk.cyan(msg.content.data.commit.substring(0, 8))}`
116
+ );
117
+ }
118
+ return true;
119
+ }
120
+
121
+ function formatValidationResult(
122
+ msg: NormalMessage,
123
+ prefix: string,
124
+ timestamp: string,
125
+ print: PrintLine = console.log
126
+ ): true {
127
+ const data = msg.content?.data || {};
128
+ const approved = data.approved === true || data.approved === 'true';
129
+ const status = approved ? chalk.bold.green('✓ Approved') : chalk.bold.red('✗ Rejected');
130
+ print(`${prefix} ${chalk.gray(timestamp)} ${status}`);
131
+ // Show summary if present and not a template variable
132
+ if (msg.content?.text && !msg.content.text.includes('{{')) {
133
+ print(`${prefix} ${msg.content.text.substring(0, 100)}`);
134
+ }
135
+ // Show CANNOT_VALIDATE (permanent) as warnings, CANNOT_VALIDATE_YET (temporary) as errors
136
+ const criteriaResults = data.criteriaResults;
137
+ if (isCriterionResults(criteriaResults)) {
138
+ const { cannotValidateYet, cannotValidate } =
139
+ partitionValidationCriteria(criteriaResults);
140
+ if (cannotValidateYet.length > 0) {
141
+ print(
142
+ `${prefix} ${chalk.red('❌ Cannot validate yet')} (${cannotValidateYet.length} criteria - work incomplete):`
143
+ );
144
+ for (const criterion of cannotValidateYet) {
145
+ print(
146
+ `${prefix} ${chalk.red('•')} ${criterion.id}: ${criterion.reason || 'No reason provided'}`
147
+ );
148
+ }
149
+ }
150
+ if (cannotValidate.length > 0) {
151
+ print(
152
+ `${prefix} ${chalk.yellow('⚠️ Could not validate')} (${cannotValidate.length} criteria - permanent):`
153
+ );
154
+ for (const criterion of cannotValidate) {
155
+ print(
156
+ `${prefix} ${chalk.yellow('•')} ${criterion.id}: ${criterion.reason || 'No reason provided'}`
157
+ );
158
+ }
159
+ }
160
+ }
161
+ // Show full JSON data structure
162
+ print(`${prefix} ${chalk.dim(JSON.stringify(data, null, 2).split('\n').join(`\n${prefix} `))}`);
163
+ return true;
164
+ }
165
+
166
+ function formatClusterComplete(
167
+ msg: NormalMessage,
168
+ prefix: string,
169
+ timestamp: string,
170
+ print: PrintLine = console.log
171
+ ): true {
172
+ print('');
173
+ print(chalk.bold.green(`${'═'.repeat(60)}`));
174
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.green('🎉 Cluster complete')}`);
175
+ if (msg.content?.data?.reason) {
176
+ print(`${prefix} ${chalk.green(msg.content.data.reason)}`);
177
+ }
178
+ print(chalk.bold.green(`${'═'.repeat(60)}`));
179
+ return true;
180
+ }
181
+
182
+ function formatClusterFailed(
183
+ msg: NormalMessage,
184
+ prefix: string,
185
+ timestamp: string,
186
+ print: PrintLine = console.log
187
+ ): true {
188
+ print('');
189
+ print(chalk.bold.red(`${'═'.repeat(60)}`));
190
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold.red('Error: cluster failed')}`);
191
+ if (msg.content?.text) print(`${prefix} ${chalk.red(msg.content.text)}`);
192
+ if (msg.content?.data?.reason) print(`${prefix} ${chalk.red(msg.content.data.reason)}`);
193
+ print(`${prefix} Next: inspect the cluster logs, then resume after fixing the cause.`);
194
+ print(chalk.bold.red(`${'═'.repeat(60)}`));
195
+ return true;
196
+ }
197
+
198
+ function formatPrCreated(
199
+ msg: NormalMessage,
200
+ prefix: string,
201
+ timestamp: string,
202
+ print: PrintLine = console.log
203
+ ): true {
204
+ const prNumber = msg.content?.data?.pr_number || '';
205
+ const prUrl = msg.content?.data?.pr_url || '';
206
+ print(''); // Blank line before PR notification
207
+ print(chalk.bold.green(`${'─'.repeat(60)}`));
208
+ print(
209
+ `${prefix} ${chalk.gray(timestamp)} ${chalk.bold.green(`🎉 ${EVENT_COPY.PR_CREATED.toUpperCase()}`)}`
210
+ );
211
+ if (prNumber) {
212
+ print(`${prefix} ${chalk.gray('PR:')} ${chalk.cyan(`#${prNumber}`)}`);
213
+ }
214
+ if (prUrl) {
215
+ print(`${prefix} ${chalk.gray('URL:')} ${chalk.blue(prUrl)}`);
216
+ }
217
+ const mergeStatus = formatMergeStatus(msg.content?.data?.merged);
218
+ if (mergeStatus) {
219
+ const formattedMergeStatus =
220
+ mergeStatus === 'merged' ? chalk.green(mergeStatus) : chalk.yellow(mergeStatus);
221
+ print(`${prefix} ${chalk.gray('Merge:')} ${formattedMergeStatus}`);
222
+ }
223
+ print(chalk.bold.green(`${'─'.repeat(60)}`));
224
+ return true;
225
+ }
226
+
227
+ function formatGenericMessage(
228
+ msg: NormalMessage,
229
+ prefix: string,
230
+ timestamp: string,
231
+ print: PrintLine = console.log
232
+ ): true {
233
+ print(`${prefix} ${chalk.gray(timestamp)} ${chalk.bold(msg.topic)}`);
234
+ if (msg.content?.text) {
235
+ print(`${prefix} ${msg.content.text}`);
236
+ }
237
+ return true;
238
+ }
239
+
240
+ export = {
241
+ formatAgentLifecycle,
242
+ formatAgentError,
243
+ formatIssueOpened,
244
+ formatImplementationReady,
245
+ formatValidationResult,
246
+ formatPrCreated,
247
+ formatClusterComplete,
248
+ formatClusterFailed,
249
+ formatGenericMessage,
250
+ };