@oisincoveney/pipeline 3.24.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. package/README.md +14 -2
  2. package/defaults/pipeline.yaml +23 -5
  3. package/defaults/profiles.yaml +104 -21
  4. package/dist/argo-graph.js +90 -88
  5. package/dist/argo-submit.d.ts +110 -138
  6. package/dist/argo-submit.js +363 -378
  7. package/dist/argo-workflow.d.ts +156 -177
  8. package/dist/argo-workflow.js +96 -138
  9. package/dist/backlog.js +5 -4
  10. package/dist/bench/eval-report.js +21 -12
  11. package/dist/claude-settings-config.js +23 -31
  12. package/dist/claude-user-config.js +6 -16
  13. package/dist/cli/bootstrap-commands.js +3 -3
  14. package/dist/cli/doctor.d.ts +1 -1
  15. package/dist/cli/doctor.js +176 -171
  16. package/dist/cli/factory-commands.js +13 -13
  17. package/dist/cli/format.js +92 -86
  18. package/dist/cli/loop-commands.js +21 -21
  19. package/dist/cli/mcp-gateway-commands.js +12 -12
  20. package/dist/cli/plan-commands.js +85 -116
  21. package/dist/cli/program.d.ts +3 -3
  22. package/dist/cli/program.js +41 -43
  23. package/dist/cli/run-command.d.ts +1 -1
  24. package/dist/cli/run-command.js +25 -25
  25. package/dist/cli/run-commands.js +31 -29
  26. package/dist/cli/run-resolver.d.ts +1 -1
  27. package/dist/cli/run-resolver.js +30 -32
  28. package/dist/cli/run-service.d.ts +2 -3
  29. package/dist/cli/run-service.js +229 -239
  30. package/dist/cli/submit-options.js +85 -83
  31. package/dist/cluster-doctor.js +147 -175
  32. package/dist/codex-config.js +24 -30
  33. package/dist/commands/bench-command.js +9 -7
  34. package/dist/commands/coordinator-command.js +35 -0
  35. package/dist/commands/pipeline-command.js +13 -7
  36. package/dist/commands/runner-command-command.js +39 -24
  37. package/dist/commands/runner-node-command.js +31 -0
  38. package/dist/commands/ticket/complete.js +29 -33
  39. package/dist/commands/ticket/create.js +84 -82
  40. package/dist/commands/ticket/graph-check.js +11 -11
  41. package/dist/commands/ticket/next.js +36 -36
  42. package/dist/commands/ticket/sequence.js +11 -12
  43. package/dist/commands/ticket/shared.d.ts +5 -2
  44. package/dist/commands/ticket/shared.js +63 -66
  45. package/dist/commands/ticket/start.js +58 -67
  46. package/dist/commands/ticket-command.js +2 -2
  47. package/dist/config/defaults.d.ts +139 -140
  48. package/dist/config/defaults.js +81 -80
  49. package/dist/config/lint.js +52 -64
  50. package/dist/config/load.d.ts +4 -5
  51. package/dist/config/load.js +64 -74
  52. package/dist/config/schema/catalog.d.ts +2 -1
  53. package/dist/config/schema/catalog.js +3 -2
  54. package/dist/config/schema/mcp.js +46 -52
  55. package/dist/config/schemas.d.ts +382 -528
  56. package/dist/config/schemas.js +400 -398
  57. package/dist/config/validate.d.ts +1 -2
  58. package/dist/config/validate.js +236 -201
  59. package/dist/config.d.ts +2 -2
  60. package/dist/context/repo-map.js +105 -119
  61. package/dist/coordinator/composition.js +169 -0
  62. package/dist/coordinator/config.js +71 -0
  63. package/dist/coordinator/run-owner.js +64 -0
  64. package/dist/coordinator/wave-advance.js +148 -0
  65. package/dist/coordinator/wave-scheduler.js +50 -0
  66. package/dist/credentials/broker.d.ts +6 -8
  67. package/dist/credentials/broker.js +17 -16
  68. package/dist/credentials/codex-config.js +15 -19
  69. package/dist/credentials/file-targets.js +9 -15
  70. package/dist/credentials/local-codex-auth-sync.js +55 -58
  71. package/dist/credentials/opencode-config.js +28 -32
  72. package/dist/credentials/runner.js +13 -13
  73. package/dist/effect-sync-errors.js +28 -0
  74. package/dist/factory/create-experiment.js +285 -121
  75. package/dist/factory/exec.js +10 -12
  76. package/dist/factory/git-credentials.js +4 -4
  77. package/dist/factory/stamp-answers.js +10 -11
  78. package/dist/factory/template-update.js +65 -44
  79. package/dist/factory-lane.d.ts +26 -40
  80. package/dist/factory-lane.js +26 -25
  81. package/dist/gates.js +3 -3
  82. package/dist/git-remote-url.js +17 -19
  83. package/dist/hooks.d.ts +26 -26
  84. package/dist/hooks.js +20 -22
  85. package/dist/index.d.ts +4 -3
  86. package/dist/index.js +27 -36
  87. package/dist/install-commands/claude-code.js +100 -92
  88. package/dist/install-commands/host-selection.js +3 -6
  89. package/dist/install-commands/opencode.js +264 -259
  90. package/dist/install-commands/planner.js +163 -181
  91. package/dist/install-commands/result-format.js +1 -3
  92. package/dist/install-commands/shared.js +25 -42
  93. package/dist/install-commands/writer.js +22 -25
  94. package/dist/install-commands.js +8 -8
  95. package/dist/jscpd-output.js +29 -0
  96. package/dist/json-config-merge.js +14 -20
  97. package/dist/json-line-values.js +17 -6
  98. package/dist/loop/argo-poll.d.ts +0 -1
  99. package/dist/loop/argo-poll.js +15 -95
  100. package/dist/loop/backlog-records.js +1 -3
  101. package/dist/loop/controller-deps.js +150 -161
  102. package/dist/loop/controller.js +164 -186
  103. package/dist/loop/gh-checks.js +62 -61
  104. package/dist/loop/gh-runner.js +22 -25
  105. package/dist/loop/loop-command.js +66 -58
  106. package/dist/loop/loop-controller-entrypoint.js +29 -30
  107. package/dist/loop/merge.js +36 -40
  108. package/dist/loop/run-terminal-poll.js +69 -0
  109. package/dist/mcp/gateway-config.js +25 -29
  110. package/dist/mcp/gateway-doctor.js +77 -119
  111. package/dist/mcp/gateway-reconcile.js +17 -22
  112. package/dist/mcp/gateway-runtime.js +1 -3
  113. package/dist/mcp/host-config.js +37 -40
  114. package/dist/mcp/host-renderers.js +10 -18
  115. package/dist/mcp/repo-local-backends.js +51 -54
  116. package/dist/mcp/toolhive-vmcp.js +39 -39
  117. package/dist/model-resolver.js +29 -33
  118. package/dist/moka-global-config.d.ts +78 -55
  119. package/dist/moka-global-config.js +93 -92
  120. package/dist/moka-submit.d.ts +2179 -866
  121. package/dist/moka-submit.js +97 -99
  122. package/dist/opencode-project-config.js +34 -40
  123. package/dist/package-assets.js +1 -3
  124. package/dist/path-refs.js +2 -2
  125. package/dist/pipeline-init.js +25 -25
  126. package/dist/pipeline-runtime.d.ts +15 -14
  127. package/dist/pipeline-runtime.js +51 -50
  128. package/dist/planned-node.js +6 -3
  129. package/dist/planning/compile.d.ts +5 -5
  130. package/dist/planning/compile.js +140 -139
  131. package/dist/planning/dependency-refs.js +5 -5
  132. package/dist/planning/generate.d.ts +1296 -1296
  133. package/dist/planning/generate.js +307 -314
  134. package/dist/planning/graph.d.ts +0 -1
  135. package/dist/planning/graph.js +131 -149
  136. package/dist/remote/argo/model.d.ts +104 -122
  137. package/dist/remote/argo/model.js +205 -197
  138. package/dist/remote/argo/policy.js +39 -47
  139. package/dist/remote/argo/storage.js +81 -85
  140. package/dist/remote/jobs/execution-identity.js +70 -0
  141. package/dist/remote/jobs/job-outcome.js +108 -0
  142. package/dist/remote/jobs/manifest.js +96 -0
  143. package/dist/remote/jobs/model.d.ts +158 -0
  144. package/dist/remote/jobs/model.js +162 -0
  145. package/dist/remote/jobs/node-bootstrap.js +213 -0
  146. package/dist/remote/jobs/policy.js +123 -0
  147. package/dist/remote/jobs/reconcile.js +100 -0
  148. package/dist/remote/jobs/run-spec-client.js +64 -0
  149. package/dist/remote/jobs/run-spec-path.js +31 -0
  150. package/dist/remote/jobs/run-spec-server.d.ts +34 -0
  151. package/dist/remote/jobs/run-spec-server.js +116 -0
  152. package/dist/remote/jobs/submit.d.ts +23 -0
  153. package/dist/remote/jobs/submit.js +116 -0
  154. package/dist/remote/jobs/watch.js +59 -0
  155. package/dist/remote/submit/argo-submission.d.ts +3 -1
  156. package/dist/remote/submit/argo-submission.js +53 -58
  157. package/dist/remote/submit/compilation.d.ts +2 -0
  158. package/dist/remote/submit/compilation.js +46 -49
  159. package/dist/remote/submit/event-boundary.js +62 -76
  160. package/dist/remote/submit/hook-events.d.ts +6 -0
  161. package/dist/remote/submit/io.d.ts +7 -1
  162. package/dist/remote/submit/io.js +40 -43
  163. package/dist/remote/submit/jobs-submission.d.ts +59 -0
  164. package/dist/remote/submit/jobs-submission.js +97 -0
  165. package/dist/remote/submit/jobs-submit-result.d.ts +25 -0
  166. package/dist/remote/submit/jobs-submit-result.js +34 -0
  167. package/dist/remote/submit/options.d.ts +49 -0
  168. package/dist/remote/submit/options.js +27 -0
  169. package/dist/remote/submit/service.d.ts +40 -1
  170. package/dist/remote/submit/service.js +67 -49
  171. package/dist/run-control/command-context.js +6 -8
  172. package/dist/run-control/commands.js +10 -10
  173. package/dist/run-control/contracts.d.ts +52 -101
  174. package/dist/run-control/contracts.js +83 -69
  175. package/dist/run-control/detach.js +66 -72
  176. package/dist/run-control/execution-store.js +0 -0
  177. package/dist/run-control/file-errors.js +1 -3
  178. package/dist/run-control/logical-segment.js +3 -3
  179. package/dist/run-control/next-node.js +67 -78
  180. package/dist/run-control/postgres/postgres-run-control-store.js +196 -225
  181. package/dist/run-control/resume-command.js +34 -41
  182. package/dist/run-control/run-artifacts-command.js +84 -105
  183. package/dist/run-control/run-command-domain.js +7 -11
  184. package/dist/run-control/run-control-store.js +9 -9
  185. package/dist/run-control/run-query-command.js +73 -100
  186. package/dist/run-control/run-record.js +5 -3
  187. package/dist/run-control/run-state-lock.js +5 -5
  188. package/dist/run-control/runtime-event-projection.js +38 -50
  189. package/dist/run-control/runtime-reporter.js +86 -102
  190. package/dist/run-control/stop-command.js +42 -53
  191. package/dist/run-control/store-fs-effects.js +3 -1
  192. package/dist/run-control/store-manifest.js +38 -13
  193. package/dist/run-control/store-paths.js +3 -3
  194. package/dist/run-control/store.js +1 -1
  195. package/dist/run-control/submit-result.js +21 -21
  196. package/dist/run-control/supervisor.js +78 -68
  197. package/dist/run-control/workspace.js +2 -2
  198. package/dist/run-state/git-refs.js +258 -307
  199. package/dist/runner/opencode-excludes.js +4 -4
  200. package/dist/runner/subprocess-result.js +28 -37
  201. package/dist/runner/subprocess.js +41 -41
  202. package/dist/runner/timeouts.js +14 -13
  203. package/dist/runner-command/dynamic-command.js +46 -39
  204. package/dist/runner-command/environment-commands.js +91 -0
  205. package/dist/runner-command/finalize.js +174 -153
  206. package/dist/runner-command/lifecycle-context.js +115 -130
  207. package/dist/runner-command/lifecycle.js +78 -72
  208. package/dist/runner-command/pre-schedule.js +203 -223
  209. package/dist/runner-command/run.js +450 -448
  210. package/dist/runner-command/schedule-source-options.js +8 -10
  211. package/dist/runner-command/select-ready-wave.js +39 -30
  212. package/dist/runner-command/task-descriptor.js +11 -17
  213. package/dist/runner-command-contract.d.ts +147 -157
  214. package/dist/runner-command-contract.js +403 -411
  215. package/dist/runner-event-schema.d.ts +364 -505
  216. package/dist/runner-event-schema.js +187 -175
  217. package/dist/runner-event-sink.js +37 -43
  218. package/dist/runner-output.js +6 -6
  219. package/dist/runner.d.ts +57 -37
  220. package/dist/runner.js +176 -127
  221. package/dist/runtime/actor-ids.d.ts +1 -0
  222. package/dist/runtime/actor-ids.js +2 -2
  223. package/dist/runtime/agent-node/agent-node.js +99 -110
  224. package/dist/runtime/agent-node/handoff-finalization.js +23 -24
  225. package/dist/runtime/agent-node/model-selection.js +19 -22
  226. package/dist/runtime/agent-node/output-finalization.js +174 -204
  227. package/dist/runtime/agent-node/prompt-rendering.js +208 -251
  228. package/dist/runtime/agent-node/session-execution.js +43 -39
  229. package/dist/runtime/builtins/builtins.js +218 -284
  230. package/dist/runtime/changed-files/changed-files.js +29 -34
  231. package/dist/runtime/command-executor/command-executor.js +31 -23
  232. package/dist/runtime/config-error.js +1 -3
  233. package/dist/runtime/context/context.js +35 -37
  234. package/dist/runtime/contracts/contracts.d.ts +3 -0
  235. package/dist/runtime/contracts/index.d.ts +1 -1
  236. package/dist/runtime/detached-race.js +11 -14
  237. package/dist/runtime/drain-merge/drain-merge.js +139 -164
  238. package/dist/runtime/durable-store/acquisition.js +5 -3
  239. package/dist/runtime/durable-store/durable-store.d.ts +3 -1
  240. package/dist/runtime/durable-store/postgres/client.js +29 -0
  241. package/dist/runtime/durable-store/postgres/migrate-substrate.js +34 -29
  242. package/dist/runtime/durable-store/postgres/postgres-store.js +18 -20
  243. package/dist/runtime/events/events.js +273 -331
  244. package/dist/runtime/events/index.js +2 -2
  245. package/dist/runtime/execution-envelope.js +44 -0
  246. package/dist/runtime/gates/adjudication/llm-judge.js +21 -24
  247. package/dist/runtime/gates/adjudication/structured-claim.js +15 -16
  248. package/dist/runtime/gates/adjudicator/adjudicator.js +27 -27
  249. package/dist/runtime/gates/adjudicator/index.js +2 -2
  250. package/dist/runtime/gates/contract.js +5 -9
  251. package/dist/runtime/gates/gates.js +9 -8
  252. package/dist/runtime/gates/kinds/acceptance/acceptance.js +68 -71
  253. package/dist/runtime/gates/kinds/acceptance/index.js +2 -2
  254. package/dist/runtime/gates/kinds/artifact/artifact.js +4 -4
  255. package/dist/runtime/gates/kinds/artifact/index.js +2 -2
  256. package/dist/runtime/gates/kinds/builtin/builtin.js +4 -4
  257. package/dist/runtime/gates/kinds/builtin/index.js +2 -2
  258. package/dist/runtime/gates/kinds/changed-files/changed-files.js +31 -35
  259. package/dist/runtime/gates/kinds/changed-files/index.js +2 -2
  260. package/dist/runtime/gates/kinds/command/command.js +3 -3
  261. package/dist/runtime/gates/kinds/command/index.js +2 -2
  262. package/dist/runtime/gates/kinds/json-schema/index.js +2 -2
  263. package/dist/runtime/gates/kinds/json-schema/json-schema.js +7 -6
  264. package/dist/runtime/gates/kinds/verdict/index.js +2 -2
  265. package/dist/runtime/gates/kinds/verdict/verdict.js +3 -3
  266. package/dist/runtime/gates/orchestrator.js +72 -86
  267. package/dist/runtime/gates/registry.js +1 -3
  268. package/dist/runtime/handoff.d.ts +2 -1
  269. package/dist/runtime/handoff.js +43 -46
  270. package/dist/runtime/hooks/command-hook.js +57 -71
  271. package/dist/runtime/hooks/context.js +21 -25
  272. package/dist/runtime/hooks/events.js +84 -100
  273. package/dist/runtime/hooks/execution.js +6 -12
  274. package/dist/runtime/hooks/hooks.js +34 -23
  275. package/dist/runtime/hooks/invocation.js +23 -29
  276. package/dist/runtime/hooks/module-hook.js +36 -35
  277. package/dist/runtime/hooks/policy.js +32 -29
  278. package/dist/runtime/hooks/results.js +56 -66
  279. package/dist/runtime/journal-acquisition.d.ts +3 -2
  280. package/dist/runtime/journal-acquisition.js +14 -14
  281. package/dist/runtime/json-validation/json-validation.js +51 -72
  282. package/dist/runtime/launch-plan-args.js +39 -0
  283. package/dist/runtime/local-scheduler.js +46 -48
  284. package/dist/runtime/node-execution.js +376 -445
  285. package/dist/runtime/node-protocol/node-protocol.js +36 -79
  286. package/dist/runtime/node-state-store.d.ts +4 -1
  287. package/dist/runtime/node-state-store.js +13 -57
  288. package/dist/runtime/node-state-tracker.js +46 -54
  289. package/dist/runtime/open-pull-request/open-pull-request.js +201 -187
  290. package/dist/runtime/opencode-adapter.js +23 -24
  291. package/dist/runtime/opencode-agent-name.js +6 -6
  292. package/dist/runtime/opencode-runtime.js +115 -93
  293. package/dist/runtime/opencode-server.js +39 -53
  294. package/dist/runtime/opencode-session-executor.js +312 -344
  295. package/dist/runtime/parallel-node/parallel-node.js +123 -134
  296. package/dist/runtime/parallel-worktrees/parallel-worktrees.js +90 -73
  297. package/dist/runtime/protected-paths/protected-paths.js +70 -71
  298. package/dist/runtime/remediation/remediation.js +202 -231
  299. package/dist/runtime/retry.js +8 -10
  300. package/dist/runtime/run-journal.d.ts +2 -0
  301. package/dist/runtime/run-journal.js +7 -7
  302. package/dist/runtime/runtime-results.js +54 -69
  303. package/dist/runtime/scheduled-dependencies.d.ts +2 -1
  304. package/dist/runtime/scheduled-dependencies.js +61 -75
  305. package/dist/runtime/scheduler.js +179 -202
  306. package/dist/runtime/services/agent-node-runtime-service.js +3 -3
  307. package/dist/runtime/services/backlog-service.d.ts +1 -2
  308. package/dist/runtime/services/backlog-service.js +8 -14
  309. package/dist/runtime/services/command-executor-service.js +1 -1
  310. package/dist/runtime/services/config-io-service.js +24 -21
  311. package/dist/runtime/services/drain-merge-git-service.js +1 -1
  312. package/dist/runtime/services/file-system-service.js +9 -7
  313. package/dist/runtime/services/git-porcelain-service.js +6 -6
  314. package/dist/runtime/services/kubernetes-argo-service.d.ts +10 -3
  315. package/dist/runtime/services/kubernetes-argo-service.js +90 -84
  316. package/dist/runtime/services/kubernetes-jobs-read-service.js +115 -0
  317. package/dist/runtime/services/kubernetes-jobs-service.d.ts +37 -0
  318. package/dist/runtime/services/kubernetes-jobs-service.js +45 -0
  319. package/dist/runtime/services/kubernetes-jobs-watch-service.js +61 -0
  320. package/dist/runtime/services/kubernetes-lease-service.js +21 -0
  321. package/dist/runtime/services/mcp-gateway-service.js +143 -94
  322. package/dist/runtime/services/open-pull-request-git-service.js +1 -3
  323. package/dist/runtime/services/opencode-runtime-server-service.js +10 -12
  324. package/dist/runtime/services/opencode-sdk-service.js +7 -7
  325. package/dist/runtime/services/repo-io-service.js +10 -12
  326. package/dist/runtime/services/run-journal-file-service.js +2 -2
  327. package/dist/runtime/services/runner-command-io-service.js +48 -52
  328. package/dist/runtime/services/runner-event-sink-http-service.js +32 -39
  329. package/dist/runtime/step/step-node.js +15 -15
  330. package/dist/runtime/workflow-execution.js +56 -57
  331. package/dist/runtime/workflow-lifecycle.js +82 -101
  332. package/dist/runtime/yeet-event-record.js +104 -0
  333. package/dist/runtime/yeet-executor.js +184 -0
  334. package/dist/safe-json.js +16 -16
  335. package/dist/schedule/backlog-context.js +122 -116
  336. package/dist/schedule/baseline.js +249 -255
  337. package/dist/schedule/passes/coverage.js +63 -68
  338. package/dist/schedule/passes/drain-merge.js +34 -40
  339. package/dist/schedule/passes/ids.js +15 -17
  340. package/dist/schedule/passes/models.js +40 -37
  341. package/dist/schedule/passes/open-pull-request.js +16 -20
  342. package/dist/schedule/passes/references.js +18 -22
  343. package/dist/schedule/prompts.js +135 -141
  344. package/dist/schedule/scheduling-roles.js +8 -14
  345. package/dist/schema-boundary.d.ts +4 -0
  346. package/dist/schema-boundary.js +145 -0
  347. package/dist/serialized-write-queue.js +2 -2
  348. package/dist/standard-output-schemas.js +61 -59
  349. package/dist/strings.js +12 -12
  350. package/dist/task-ref.js +5 -5
  351. package/dist/tickets/apply-ticket-plan.js +52 -61
  352. package/dist/tickets/backlog-task-store.d.ts +15 -23
  353. package/dist/tickets/backlog-task-store.js +82 -94
  354. package/dist/tickets/completion/complete-ticket.js +53 -59
  355. package/dist/tickets/ticket-graph-dto.d.ts +24 -48
  356. package/dist/tickets/ticket-graph-dto.js +40 -40
  357. package/dist/tickets/ticket-graph.d.ts +7 -2
  358. package/dist/tickets/ticket-graph.js +36 -50
  359. package/dist/tickets/ticket-plan-command-args.js +6 -10
  360. package/dist/tickets/ticket-plan-render.js +10 -16
  361. package/dist/tickets/ticket-plan.d.ts +32 -41
  362. package/dist/tickets/ticket-plan.js +97 -77
  363. package/dist/tickets/ticket-selection.d.ts +3 -1
  364. package/dist/tickets/ticket-selection.js +37 -52
  365. package/dist/tickets/ticket-task-index.js +13 -17
  366. package/dist/tickets/validation-error-format.js +3 -10
  367. package/dist/token-estimator.js +12 -7
  368. package/dist/unknown-fields.js +21 -0
  369. package/dist/workflow-submit-contract.d.ts +9 -10
  370. package/dist/workflow-submit-contract.js +10 -9
  371. package/docs/adr-moka-postgres-schema-isolation.md +48 -0
  372. package/docs/adr-opencode-first-goal-loop-runtime.md +11 -11
  373. package/docs/config-architecture.md +13 -13
  374. package/docs/mcp-host-isolation.md +1 -0
  375. package/docs/moka-orchestrator-design.md +3 -3
  376. package/docs/operator-guide.md +1 -1
  377. package/docs/pipeline-console-runner-contract.md +10 -6
  378. package/docs/runtime-actor-model.md +18 -18
  379. package/docs/runtime-test-subsystems.md +200 -0
  380. package/docs/slash-command-adapter-contract.md +3 -3
  381. package/package.json +49 -85
  382. package/dist/config/schema/reference-validation.js +0 -83
@@ -1,2 +1,2 @@
1
- import { childReporter, createPublicRuntimeObservabilityEmitter, emit, emitAgentFinish, emitAgentStart, emitGateFinish, emitGateStart, emitNodeFinish, emitNodeOutputRecorded, emitNodeStart, emitWorkflowFinish, emitWorkflowPlanned, emitWorkflowStarted, runtimeNodeActorDescriptor, runtimeSystemId } from "./events.js";
2
- export { childReporter, createPublicRuntimeObservabilityEmitter, emit, emitAgentFinish, emitAgentStart, emitGateFinish, emitGateStart, emitNodeFinish, emitNodeOutputRecorded, emitNodeStart, emitWorkflowFinish, emitWorkflowPlanned, emitWorkflowStarted, runtimeNodeActorDescriptor, runtimeSystemId };
1
+ import { agentFinishEvent, agentStartEvent, childReporter, createPublicRuntimeObservabilityEmitter, emit, emitAgentFinish, emitAgentStart, emitGateFinish, emitGateStart, emitNodeFinish, emitNodeOutputRecorded, emitNodeStart, emitWorkflowFinish, emitWorkflowPlanned, emitWorkflowStarted, runtimeNodeActorDescriptor, runtimeSystemId } from "./events.js";
2
+ export { agentFinishEvent, agentStartEvent, childReporter, createPublicRuntimeObservabilityEmitter, emit, emitAgentFinish, emitAgentStart, emitGateFinish, emitGateStart, emitNodeFinish, emitNodeOutputRecorded, emitNodeStart, emitWorkflowFinish, emitWorkflowPlanned, emitWorkflowStarted, runtimeNodeActorDescriptor, runtimeSystemId };
@@ -0,0 +1,44 @@
1
+ import { nonNegativeInteger, parseStrictWithSchema, positiveInteger, requiredString, struct } from "../schema-boundary.js";
2
+ //#region src/runtime/execution-envelope.ts
3
+ /**
4
+ * ENG-57.6: the Engine-owned execution envelope that wraps — never modifies —
5
+ * the yeet `Event`. yeet owns the runtime `Event` wire type (`@oisin-ee/yeet-api`)
6
+ * and must not learn about Engine scheduling; the Engine owns the two identity
7
+ * axes that name WHICH execution produced an event:
8
+ *
9
+ * - `generation`: the semantic-execution counter (a coordinator-decided node
10
+ * retry increments it; it is baked into the Job identity/name).
11
+ * - `attempt`: the Kubernetes crash-retry index WITHIN one generation (a Job's
12
+ * `backoffLimit` re-runs the same execution's pod; each pod is a new attempt).
13
+ *
14
+ * Carrying both on every event is what makes a crash retry (same generation,
15
+ * higher attempt) distinguishable from a semantic node retry (higher
16
+ * generation) — see {@link classifyRetry}. The wrapped `event` is generic and
17
+ * opaque: the envelope validates only its own meta, so the yeet Event stays a
18
+ * verbatim, unchanged passthrough.
19
+ */
20
+ const executionEnvelopeMetaSchema = struct({
21
+ attempt: positiveInteger,
22
+ generation: nonNegativeInteger,
23
+ nodeId: requiredString,
24
+ runId: requiredString
25
+ });
26
+ /** Validate untrusted envelope meta at a boundary (rejects attempt < 1, negative generation). */
27
+ const parseExecutionEnvelopeMeta = (input) => parseStrictWithSchema(executionEnvelopeMetaSchema, input);
28
+ /**
29
+ * Wrap a runtime/yeet event in its execution envelope. The event is carried by
30
+ * reference, unchanged; only the Engine-owned identity axes are added around it.
31
+ */
32
+ const wrapExecutionEvent = (identity, attempt, event) => {
33
+ return {
34
+ ...parseExecutionEnvelopeMeta({
35
+ attempt,
36
+ generation: identity.generation,
37
+ nodeId: identity.nodeId,
38
+ runId: identity.runId
39
+ }),
40
+ event
41
+ };
42
+ };
43
+ //#endregion
44
+ export { executionEnvelopeMetaSchema, parseExecutionEnvelopeMeta, wrapExecutionEvent };
@@ -1,3 +1,4 @@
1
+ import { Option } from "effect";
1
2
  //#region src/runtime/gates/adjudication/llm-judge.ts
2
3
  const HONOR_POLICIES = [
3
4
  {
@@ -14,27 +15,13 @@ const HONOR_POLICIES = [
14
15
  }
15
16
  ];
16
17
  const TRIVIAL_REFUSAL = "trivial completion claim refused without consulting llm-judge: no non-blank claimed evidence";
17
- /**
18
- * Adjudicates the residual acceptance criteria — the un-encodable residue the
19
- * deterministic and structured-claim layers could not settle — against the
20
- * agent's {@link CompletionClaim}, anchored to deterministic evidence. Returns
21
- * one {@link UnmetCriterion} for every residue criterion that is refused for
22
- * trivial input, fails anchoring, or the judge marks unsatisfied. Honored
23
- * criteria are omitted. Pure given the injected `judge`.
24
- */
25
- function llmJudgeUnmet(residue, claim, deterministicEvidence, judge) {
26
- return residue.flatMap((criterion) => {
27
- const failure = adjudicateCriterion(criterion, claimedEvidenceFor(criterion, claim), deterministicEvidence, judge);
28
- return failure ? [failure] : [];
29
- });
30
- }
31
- function adjudicateCriterion(criterion, claimedEvidence, deterministicEvidence, judge) {
18
+ const adjudicateCriterion = (criterion, claimedEvidence, deterministicEvidence, judge) => {
32
19
  const meaningful = claimedEvidence.filter((item) => item.trim().length > 0);
33
- if (meaningful.length === 0) return {
20
+ if (meaningful.length === 0) return Option.some({
34
21
  criterion: criterion.id,
35
22
  evidence: claimedEvidence,
36
23
  reason: TRIVIAL_REFUSAL
37
- };
24
+ });
38
25
  const verdict = judge({
39
26
  claimedEvidence: meaningful,
40
27
  criterion,
@@ -42,15 +29,25 @@ function adjudicateCriterion(criterion, claimedEvidence, deterministicEvidence,
42
29
  });
43
30
  const anchored = verdict.citedEvidence.filter((item) => deterministicEvidence.includes(item));
44
31
  const broken = HONOR_POLICIES.find((policy) => policy.failed(verdict, anchored));
45
- if (!broken) return;
46
- return {
32
+ if (broken === void 0) return Option.none();
33
+ return Option.some({
47
34
  criterion: criterion.id,
48
35
  evidence: verdict.citedEvidence.length > 0 ? verdict.citedEvidence : meaningful,
49
36
  reason: broken.reason
50
- };
51
- }
52
- function claimedEvidenceFor(criterion, claim) {
53
- return claim.criteria.find((entry) => entry.criterion === criterion.id)?.evidence ?? [];
54
- }
37
+ });
38
+ };
39
+ const claimedEvidenceFor = (criterion, claim) => claim.criteria.find((entry) => entry.criterion === criterion.id)?.evidence ?? [];
40
+ /**
41
+ * Adjudicates the residual acceptance criteria — the un-encodable residue the
42
+ * deterministic and structured-claim layers could not settle — against the
43
+ * agent's {@link CompletionClaim}, anchored to deterministic evidence. Returns
44
+ * one {@link UnmetCriterion} for every residue criterion that is refused for
45
+ * trivial input, fails anchoring, or the judge marks unsatisfied. Honored
46
+ * criteria are omitted. Pure given the injected `judge`.
47
+ */
48
+ const llmJudgeUnmet = (residue, claim, deterministicEvidence, judge) => residue.flatMap((criterion) => {
49
+ const failure = adjudicateCriterion(criterion, claimedEvidenceFor(criterion, claim), deterministicEvidence, judge);
50
+ return Option.isSome(failure) ? [failure.value] : [];
51
+ });
55
52
  //#endregion
56
53
  export { llmJudgeUnmet };
@@ -1,3 +1,4 @@
1
+ import { Option } from "effect";
1
2
  //#region src/runtime/gates/adjudication/structured-claim.ts
2
3
  /**
3
4
  * Ordered completeness rules. Each rule is independently testable;
@@ -7,27 +8,27 @@
7
8
  const COMPLETENESS_RULES = [
8
9
  {
9
10
  reason: (id) => `no claim entry for criterion '${id}'`,
10
- test: (entry) => entry === void 0
11
+ test: Option.isNone
11
12
  },
12
13
  {
13
14
  reason: (id) => `empty evidence for criterion '${id}'`,
14
- test: (entry) => entry !== void 0 && entry.evidence.length === 0
15
+ test: (entry) => Option.isSome(entry) && entry.value.evidence.length === 0
15
16
  },
16
17
  {
17
18
  reason: (id) => `blank evidence for criterion '${id}'`,
18
- test: (entry) => entry !== void 0 && entry.evidence.length > 0 && entry.evidence.every((s) => !s.trim())
19
+ test: (entry) => Option.isSome(entry) && entry.value.evidence.length > 0 && entry.value.evidence.every((s) => s.trim().length === 0)
19
20
  }
20
21
  ];
21
- function criterionUnmet(criterion, claim) {
22
- const entry = claim.criteria.find((e) => e.criterion === criterion.id);
22
+ const criterionUnmet = (criterion, claim) => {
23
+ const entry = Option.fromUndefinedOr(claim.criteria.find((e) => e.criterion === criterion.id));
23
24
  const rule = COMPLETENESS_RULES.find((r) => r.test(entry));
24
- if (rule === void 0) return null;
25
- return {
25
+ if (rule === void 0) return Option.none();
26
+ return Option.some({
26
27
  criterion: criterion.id,
27
- evidence: entry?.evidence ?? [],
28
+ evidence: Option.isSome(entry) ? entry.value.evidence : [],
28
29
  reason: rule.reason(criterion.id)
29
- };
30
- }
30
+ });
31
+ };
31
32
  /**
32
33
  * Structured-claim adjudication layer (PIPE-90.7): deterministic, pure
33
34
  * check below the LLM-judge in the completion pipeline.
@@ -42,11 +43,9 @@ function criterionUnmet(criterion, claim) {
42
43
  * entry. Returns an empty array when the claim covers all declared
43
44
  * criteria. Pure — no I/O, no LLM, deterministic.
44
45
  */
45
- function structuredClaimUnmet(criteria, claim) {
46
- return criteria.flatMap((criterion) => {
47
- const unmet = criterionUnmet(criterion, claim);
48
- return unmet === null ? [] : [unmet];
49
- });
50
- }
46
+ const structuredClaimUnmet = (criteria, claim) => criteria.flatMap((criterion) => {
47
+ const unmet = criterionUnmet(criterion, claim);
48
+ return Option.isSome(unmet) ? [unmet.value] : [];
49
+ });
51
50
  //#endregion
52
51
  export { structuredClaimUnmet };
@@ -1,12 +1,33 @@
1
1
  import { evaluateGate } from "../registry.js";
2
2
  //#region src/runtime/gates/adjudicator/adjudicator.ts
3
3
  /**
4
+ * Maps a failing deterministic gate to its structured refusal. A criterion-aware
5
+ * gate (acceptance) already reports `unmet`; a binary gate (command, artifact,
6
+ * ...) reports only pass/fail, so synthesize one entry per covered criterion —
7
+ * or, when the gate covers nothing, a single entry keyed by the gate id so the
8
+ * failure is never swallowed.
9
+ */
10
+ const gateUnmet = (gate, result) => {
11
+ if (result.unmet && result.unmet.length > 0) return result.unmet;
12
+ const reason = result.reason ?? `deterministic gate '${result.gateId}' failed`;
13
+ if (gate.covers.length === 0) return [{
14
+ criterion: result.gateId,
15
+ evidence: result.evidence,
16
+ reason
17
+ }];
18
+ return gate.covers.map((id) => ({
19
+ criterion: id,
20
+ evidence: result.evidence,
21
+ reason
22
+ }));
23
+ };
24
+ /**
4
25
  * Runs the deterministic layer: every {@link DeterministicGate} through the
5
26
  * registry's {@link evaluateGate}. Each gate's `covers` ids are settled
6
27
  * (excluded from the residue) whether it passes or fails; passing gates feed the
7
28
  * anchor evidence pool, failing gates feed the structured refusal.
8
29
  */
9
- async function runDeterministicLayer(gates) {
30
+ const runDeterministicLayer = async (gates) => {
10
31
  const covered = /* @__PURE__ */ new Set();
11
32
  const evidence = [];
12
33
  const unmet = [];
@@ -21,49 +42,28 @@ async function runDeterministicLayer(gates) {
21
42
  evidence,
22
43
  unmet
23
44
  };
24
- }
25
- /**
26
- * Maps a failing deterministic gate to its structured refusal. A criterion-aware
27
- * gate (acceptance) already reports `unmet`; a binary gate (command, artifact,
28
- * ...) reports only pass/fail, so synthesize one entry per covered criterion —
29
- * or, when the gate covers nothing, a single entry keyed by the gate id so the
30
- * failure is never swallowed.
31
- */
32
- function gateUnmet(gate, result) {
33
- if (result.unmet && result.unmet.length > 0) return result.unmet;
34
- const reason = result.reason ?? `deterministic gate '${result.gateId}' failed`;
35
- if (gate.covers.length === 0) return [{
36
- criterion: result.gateId,
37
- evidence: result.evidence,
38
- reason
39
- }];
40
- return gate.covers.map((id) => ({
41
- criterion: id,
42
- evidence: result.evidence,
43
- reason
44
- }));
45
- }
45
+ };
46
46
  /**
47
47
  * The llm-judge residue: criteria neither settled by a deterministic gate nor
48
48
  * already flagged incomplete by the structured-claim layer. Only this residue
49
49
  * reaches the judge, keeping it from re-adjudicating settled criteria.
50
50
  */
51
- function residueCriteria(criteria, covered, structured) {
51
+ const residueCriteria = (criteria, covered, structured) => {
52
52
  const structuredIds = new Set(structured.map((entry) => entry.criterion));
53
53
  return criteria.filter((criterion) => !(covered.has(criterion.id) || structuredIds.has(criterion.id)));
54
- }
54
+ };
55
55
  /**
56
56
  * Collapses the layer union to one entry per distinct failing criterion id,
57
57
  * keeping the earliest (deterministic before structured-claim before llm-judge)
58
58
  * — the most authoritative reason for that criterion.
59
59
  */
60
- function dedupeByCriterion(entries) {
60
+ const dedupeByCriterion = (entries) => {
61
61
  const seen = /* @__PURE__ */ new Set();
62
62
  return entries.filter((entry) => {
63
63
  if (seen.has(entry.criterion)) return false;
64
64
  seen.add(entry.criterion);
65
65
  return true;
66
66
  });
67
- }
67
+ };
68
68
  //#endregion
69
69
  export { dedupeByCriterion, residueCriteria, runDeterministicLayer };
@@ -21,7 +21,7 @@ import { dedupeByCriterion, residueCriteria, runDeterministicLayer } from "./adj
21
21
  * The union is deduped by criterion id (earliest layer wins) so every distinct
22
22
  * failing criterion appears exactly once. `passed` is true iff `unmet` is empty.
23
23
  */
24
- async function adjudicate(input) {
24
+ const adjudicate = async (input) => {
25
25
  const deterministic = await runDeterministicLayer(input.deterministicGates ?? []);
26
26
  const structured = structuredClaimUnmet(input.criteria, input.claim);
27
27
  const judged = llmJudgeUnmet(residueCriteria(input.criteria, deterministic.covered, structured), input.claim, deterministic.evidence, input.judge);
@@ -34,6 +34,6 @@ async function adjudicate(input) {
34
34
  passed: unmet.length === 0,
35
35
  unmet
36
36
  };
37
- }
37
+ };
38
38
  //#endregion
39
39
  export { adjudicate };
@@ -5,9 +5,7 @@
5
5
  * union when `kind` is a type parameter, so this guard carries the narrowing
6
6
  * without a type assertion.
7
7
  */
8
- function hasKind(gate, kind) {
9
- return gate.kind === kind;
10
- }
8
+ const hasKind = (gate, kind) => gate.kind === kind;
11
9
  /**
12
10
  * Binds one gate kind to its narrowly-typed evaluator and adapts it to the
13
11
  * uniform {@link GateEvaluator} shape. The {@link hasKind} guard narrows the
@@ -15,11 +13,9 @@ function hasKind(gate, kind) {
15
13
  * wired to the wrong key, surfacing the bug instead of silently evaluating the
16
14
  * wrong gate.
17
15
  */
18
- function forKind(kind, evaluate) {
19
- return (input) => {
20
- if (!hasKind(input.gate, kind)) throw new Error(`gate registry mismatch: handler '${kind}' received '${input.gate.kind}'`);
21
- return evaluate(input.gate, input);
22
- };
23
- }
16
+ const forKind = (kind, evaluate) => async (input) => {
17
+ if (!hasKind(input.gate, kind)) throw new Error(`gate registry mismatch: handler '${kind}' received '${input.gate.kind}'`);
18
+ return await evaluate(input.gate, input);
19
+ };
24
20
  //#endregion
25
21
  export { forKind };
@@ -2,29 +2,30 @@ import { parseJsonResult } from "../../safe-json.js";
2
2
  import { readOptionalFile } from "../json-validation/json-validation.js";
3
3
  import "../json-validation/index.js";
4
4
  import { join } from "node:path";
5
+ import { Option } from "effect";
5
6
  //#region src/runtime/gates/gates.ts
6
7
  /**
7
8
  * Resolves the raw JSON string for a gate that targets either the node's stdout
8
9
  * output or an artifact file. Returns `{ evidence }` on read error so callers
9
10
  * can short-circuit before parsing.
10
11
  */
11
- function gateJsonSource(gate, context, attempt) {
12
+ const gateJsonSource = (gate, context, attempt) => {
12
13
  if (gate.target === "artifact") {
13
- if (!gate.path) return { evidence: "missing JSON artifact path" };
14
+ if (gate.path === void 0 || gate.path.length === 0) return { evidence: "missing JSON artifact path" };
14
15
  const source = readOptionalFile(join(context.worktreePath, gate.path));
15
- return source === null ? { evidence: `missing JSON artifact: ${gate.path}` } : { source };
16
+ return Option.isNone(source) ? { evidence: `missing JSON artifact: ${gate.path}` } : { source: source.value };
16
17
  }
17
18
  return { source: attempt.output };
18
- }
19
+ };
19
20
  /**
20
21
  * Parses the gate JSON source to an unknown value. Returns `{ evidence }` on
21
22
  * parse error so callers can short-circuit with a failed gate result.
22
23
  */
23
- function parseGateJson(gate, context, attempt) {
24
+ const parseGateJson = (gate, context, attempt) => {
24
25
  const src = gateJsonSource(gate, context, attempt);
25
- if (src.evidence) return { evidence: src.evidence };
26
+ if (src.evidence !== void 0 && src.evidence.length > 0) return { evidence: src.evidence };
26
27
  const parsed = parseJsonResult(src.source ?? "", "gate JSON");
27
- return parsed.error ? { evidence: parsed.error } : { value: parsed.value };
28
- }
28
+ return parsed.error !== void 0 && parsed.error.length > 0 ? { evidence: parsed.error } : { value: parsed.value };
29
+ };
29
30
  //#endregion
30
31
  export { parseGateJson };
@@ -1,13 +1,76 @@
1
1
  import { isRecord } from "../../../../safe-json.js";
2
2
  import { parseGateJson } from "../../gates.js";
3
3
  //#region src/runtime/gates/kinds/acceptance/acceptance.ts
4
+ const effectiveTaskContext = (node, context) => node.taskContext ?? context.taskContext;
5
+ const acceptanceEntries = (value, key = "acceptance") => {
6
+ if (!isRecord(value)) return [];
7
+ const raw = value[key] ?? value.criteria ?? value.acceptanceCriteria;
8
+ return Array.isArray(raw) ? raw.filter((item) => isRecord(item)) : [];
9
+ };
10
+ const coverageCountUnmetCriteria = (id, count) => {
11
+ const unmet = [];
12
+ if (count === 0) unmet.push({
13
+ criterion: id,
14
+ evidence: [`criterion '${id}' absent from acceptance report`],
15
+ reason: `missing acceptance criterion '${id}'`
16
+ });
17
+ if (count > 1) unmet.push({
18
+ criterion: id,
19
+ evidence: [`criterion '${id}' reported ${count} times`],
20
+ reason: `duplicate acceptance criterion '${id}'`
21
+ });
22
+ return unmet;
23
+ };
24
+ const hasNonEmptyEvidence = (value) => Array.isArray(value) && value.some((item) => typeof item === "string" && item.trim().length > 0);
25
+ const entryUnmetCriteria = (entry, expectedIds, seen) => {
26
+ const id = typeof entry.id === "string" ? entry.id : "";
27
+ if (id.length === 0) return [{
28
+ criterion: "",
29
+ evidence: ["acceptance entry has no id field"],
30
+ reason: "acceptance entry missing id"
31
+ }];
32
+ seen.set(id, (seen.get(id) ?? 0) + 1);
33
+ const unmet = [];
34
+ if (!expectedIds.has(id)) unmet.push({
35
+ criterion: id,
36
+ evidence: [`id '${id}' not in task acceptance context`],
37
+ reason: `extra acceptance criterion '${id}'`
38
+ });
39
+ const { verdict } = entry;
40
+ if (verdict !== "PASS") unmet.push({
41
+ criterion: id,
42
+ evidence: [`reported verdict '${String(verdict)}'`],
43
+ reason: `acceptance criterion '${id}' verdict '${String(verdict)}'`
44
+ });
45
+ if (verdict === "PASS" && !hasNonEmptyEvidence(entry.evidence)) unmet.push({
46
+ criterion: id,
47
+ evidence: ["verdict 'PASS' reported without supporting evidence"],
48
+ reason: `acceptance criterion '${id}' has no evidence`
49
+ });
50
+ return unmet;
51
+ };
52
+ /**
53
+ * Structured refusal producer (PIPE-90.1): the single source of truth for which
54
+ * acceptance criteria a node failed to satisfy. Each {@link UnmetCriterion}
55
+ * names the criterion, a human-readable reason, and deterministic proof. The
56
+ * acceptance gate's flat `evidence` field is the `reason` projection of this,
57
+ * so refusal text and ordering stay in lockstep with the structured form.
58
+ */
59
+ const acceptanceUnmetCriteria = (expected, entries) => {
60
+ const unmet = [];
61
+ const expectedIds = new Set(expected.map((criterion) => criterion.id));
62
+ const seen = /* @__PURE__ */ new Map();
63
+ for (const entry of entries) unmet.push(...entryUnmetCriteria(entry, expectedIds, seen));
64
+ for (const id of expectedIds) unmet.push(...coverageCountUnmetCriteria(id, seen.get(id) ?? 0));
65
+ return unmet;
66
+ };
4
67
  /**
5
68
  * Evaluates whether the node's JSON output (or artifact) covers all acceptance
6
69
  * criteria declared in the task context. Uses
7
70
  * {@link acceptanceUnmetCriteria} as the single source of truth for which
8
71
  * criteria remain unmet, so refusal text and structured form stay in lockstep.
9
72
  */
10
- function evaluateAcceptanceGate(gate, gateId, nodeId, context, attempt, node) {
73
+ const evaluateAcceptanceGate = (gate, gateId, nodeId, context, attempt, node) => {
11
74
  const expected = (node ? effectiveTaskContext(node, context) : context.taskContext)?.acceptanceCriteria ?? [];
12
75
  if (expected.length === 0) return {
13
76
  evidence: ["no acceptance criteria in task context"],
@@ -18,7 +81,7 @@ function evaluateAcceptanceGate(gate, gateId, nodeId, context, attempt, node) {
18
81
  reason: gate.required === false ? void 0 : "missing task acceptance context"
19
82
  };
20
83
  const parsed = parseGateJson(gate, context, attempt);
21
- if (parsed.evidence) return {
84
+ if (parsed.evidence !== void 0 && parsed.evidence.length > 0) return {
22
85
  evidence: [parsed.evidence],
23
86
  gateId,
24
87
  kind: gate.kind,
@@ -26,7 +89,8 @@ function evaluateAcceptanceGate(gate, gateId, nodeId, context, attempt, node) {
26
89
  passed: false,
27
90
  reason: "acceptance gate JSON parse failed"
28
91
  };
29
- const unmet = acceptanceUnmetCriteria(expected, acceptanceEntries(parsed.value, gate.acceptance_key));
92
+ const entries = acceptanceEntries(parsed.value, gate.acceptance_key);
93
+ const unmet = acceptanceUnmetCriteria(expected, entries);
30
94
  const passed = unmet.length === 0;
31
95
  return {
32
96
  evidence: passed ? ["acceptance coverage passed"] : unmet.map((item) => item.reason),
@@ -37,73 +101,6 @@ function evaluateAcceptanceGate(gate, gateId, nodeId, context, attempt, node) {
37
101
  reason: passed ? void 0 : "acceptance coverage failed",
38
102
  unmet
39
103
  };
40
- }
41
- function effectiveTaskContext(node, context) {
42
- return node.taskContext ?? context.taskContext;
43
- }
44
- function acceptanceEntries(value, key = "acceptance") {
45
- if (!isRecord(value)) return [];
46
- const raw = value[key] ?? value.criteria ?? value.acceptanceCriteria;
47
- return Array.isArray(raw) ? raw.filter((item) => isRecord(item)) : [];
48
- }
49
- /**
50
- * Structured refusal producer (PIPE-90.1): the single source of truth for which
51
- * acceptance criteria a node failed to satisfy. Each {@link UnmetCriterion}
52
- * names the criterion, a human-readable reason, and deterministic proof. The
53
- * acceptance gate's flat `evidence` field is the `reason` projection of this,
54
- * so refusal text and ordering stay in lockstep with the structured form.
55
- */
56
- function acceptanceUnmetCriteria(expected, entries) {
57
- const unmet = [];
58
- const expectedIds = new Set(expected.map((criterion) => criterion.id));
59
- const seen = /* @__PURE__ */ new Map();
60
- for (const entry of entries) unmet.push(...entryUnmetCriteria(entry, expectedIds, seen));
61
- for (const id of expectedIds) unmet.push(...coverageCountUnmetCriteria(id, seen.get(id) ?? 0));
62
- return unmet;
63
- }
64
- function entryUnmetCriteria(entry, expectedIds, seen) {
65
- const id = typeof entry.id === "string" ? entry.id : "";
66
- if (!id) return [{
67
- criterion: "",
68
- evidence: ["acceptance entry has no id field"],
69
- reason: "acceptance entry missing id"
70
- }];
71
- seen.set(id, (seen.get(id) ?? 0) + 1);
72
- const unmet = [];
73
- if (!expectedIds.has(id)) unmet.push({
74
- criterion: id,
75
- evidence: [`id '${id}' not in task acceptance context`],
76
- reason: `extra acceptance criterion '${id}'`
77
- });
78
- const verdict = entry.verdict;
79
- if (verdict !== "PASS") unmet.push({
80
- criterion: id,
81
- evidence: [`reported verdict '${String(verdict)}'`],
82
- reason: `acceptance criterion '${id}' verdict '${String(verdict)}'`
83
- });
84
- if (verdict === "PASS" && !hasNonEmptyEvidence(entry.evidence)) unmet.push({
85
- criterion: id,
86
- evidence: ["verdict 'PASS' reported without supporting evidence"],
87
- reason: `acceptance criterion '${id}' has no evidence`
88
- });
89
- return unmet;
90
- }
91
- function coverageCountUnmetCriteria(id, count) {
92
- const unmet = [];
93
- if (count === 0) unmet.push({
94
- criterion: id,
95
- evidence: [`criterion '${id}' absent from acceptance report`],
96
- reason: `missing acceptance criterion '${id}'`
97
- });
98
- if (count > 1) unmet.push({
99
- criterion: id,
100
- evidence: [`criterion '${id}' reported ${count} times`],
101
- reason: `duplicate acceptance criterion '${id}'`
102
- });
103
- return unmet;
104
- }
105
- function hasNonEmptyEvidence(value) {
106
- return Array.isArray(value) && value.filter((item) => typeof item === "string" && item.trim()).length > 0;
107
- }
104
+ };
108
105
  //#endregion
109
106
  export { acceptanceUnmetCriteria, evaluateAcceptanceGate };
@@ -2,8 +2,8 @@ import { forKind } from "../../contract.js";
2
2
  import { evaluateAcceptanceGate } from "./acceptance.js";
3
3
  //#region src/runtime/gates/kinds/acceptance/index.ts
4
4
  const acceptanceModule = {
5
- kind: "acceptance",
6
- evaluate: forKind("acceptance", (gate, input) => evaluateAcceptanceGate(gate, input.gateId, input.nodeId, input.context, input.attempt, input.node))
5
+ evaluate: forKind("acceptance", (gate, input) => evaluateAcceptanceGate(gate, input.gateId, input.nodeId, input.context, input.attempt, input.node)),
6
+ kind: "acceptance"
7
7
  };
8
8
  //#endregion
9
9
  export { acceptanceModule };
@@ -4,9 +4,9 @@ import { artifactExists } from "../../../../gates.js";
4
4
  * Checks whether the configured artifact path exists in the node's worktree.
5
5
  * A missing path or nonexistent file fails the gate.
6
6
  */
7
- function evaluateArtifactGate(gate, gateId, nodeId, context) {
8
- const path = gate.path ?? "";
9
- const passed = Boolean(path) && artifactExists(context.worktreePath, path);
7
+ const evaluateArtifactGate = (gate, gateId, nodeId, context) => {
8
+ const { path } = gate;
9
+ const passed = path.length > 0 && artifactExists(context.worktreePath, path);
10
10
  return {
11
11
  evidence: [passed ? `artifact exists: ${path}` : `missing artifact: ${path}`],
12
12
  gateId,
@@ -15,6 +15,6 @@ function evaluateArtifactGate(gate, gateId, nodeId, context) {
15
15
  passed,
16
16
  reason: passed ? void 0 : `missing artifact '${path}'`
17
17
  };
18
- }
18
+ };
19
19
  //#endregion
20
20
  export { evaluateArtifactGate };
@@ -2,8 +2,8 @@ import { forKind } from "../../contract.js";
2
2
  import { evaluateArtifactGate } from "./artifact.js";
3
3
  //#region src/runtime/gates/kinds/artifact/index.ts
4
4
  const artifactModule = {
5
- kind: "artifact",
6
- evaluate: forKind("artifact", (gate, input) => evaluateArtifactGate(gate, input.gateId, input.nodeId, input.context))
5
+ evaluate: forKind("artifact", (gate, input) => evaluateArtifactGate(gate, input.gateId, input.nodeId, input.context)),
6
+ kind: "artifact"
7
7
  };
8
8
  //#endregion
9
9
  export { artifactModule };
@@ -6,16 +6,16 @@ import "../../../builtins/index.js";
6
6
  * Context must satisfy {@link RuntimeContext} since {@link executeBuiltin} uses
7
7
  * the full runtime context (cwd, signal, store, etc.).
8
8
  */
9
- async function evaluateBuiltinGate(gate, gateId, nodeId, context) {
10
- const result = await executeBuiltin(gate.builtin ?? "", context);
9
+ const evaluateBuiltinGate = async (gate, gateId, nodeId, context) => {
10
+ const result = await executeBuiltin(gate.builtin, context);
11
11
  return {
12
12
  evidence: result.evidence,
13
13
  gateId,
14
14
  kind: gate.kind,
15
15
  nodeId,
16
16
  passed: result.exitCode === 0,
17
- reason: result.exitCode === 0 ? void 0 : `builtin '${gate.builtin ?? ""}' failed`
17
+ reason: result.exitCode === 0 ? void 0 : `builtin '${gate.builtin}' failed`
18
18
  };
19
- }
19
+ };
20
20
  //#endregion
21
21
  export { evaluateBuiltinGate };
@@ -2,8 +2,8 @@ import { forKind } from "../../contract.js";
2
2
  import { evaluateBuiltinGate } from "./builtin.js";
3
3
  //#region src/runtime/gates/kinds/builtin/index.ts
4
4
  const builtinModule = {
5
- kind: "builtin",
6
- evaluate: forKind("builtin", (gate, input) => evaluateBuiltinGate(gate, input.gateId, input.nodeId, input.context))
5
+ evaluate: forKind("builtin", async (gate, input) => await evaluateBuiltinGate(gate, input.gateId, input.nodeId, input.context)),
6
+ kind: "builtin"
7
7
  };
8
8
  //#endregion
9
9
  export { builtinModule };