karajan-code 4.70.4 → 5.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 (380) hide show
  1. package/README.md +2 -2
  2. package/package.json +6 -14
  3. package/packages/hu-board/package.json +1 -1
  4. package/packages/hu-board/public/app.js +4 -18
  5. package/packages/hu-board/public/index.html +5 -2
  6. package/packages/hu-board/public/styles.css +26 -0
  7. package/packages/hu-board/public/utils/api.js +0 -74
  8. package/packages/hu-board/public/utils/board-tour.js +62 -0
  9. package/packages/hu-board/public/utils/board-view.js +49 -144
  10. package/packages/hu-board/public/utils/command-launcher.js +8 -70
  11. package/packages/hu-board/public/utils/formatters.js +10 -0
  12. package/packages/hu-board/public/utils/governance-view.js +13 -1
  13. package/packages/hu-board/public/utils/hu-actions.js +17 -68
  14. package/packages/hu-board/public/utils/init-listeners.js +7 -8
  15. package/packages/hu-board/public/utils/log-panel.js +3 -16
  16. package/packages/hu-board/public/utils/maggle-mode.js +2 -12
  17. package/packages/hu-board/public/utils/modals.js +7 -0
  18. package/packages/hu-board/public/utils/project-picker-view.js +1 -1
  19. package/packages/hu-board/public/utils/server-push.js +3 -22
  20. package/packages/hu-board/public/utils/shared-board-notice.js +33 -0
  21. package/packages/hu-board/public/utils/story-detail-view.js +5 -19
  22. package/packages/hu-board/src/cleanup-zombies.js +0 -1
  23. package/packages/hu-board/src/command-runner.js +36 -25
  24. package/packages/hu-board/src/db-connection.js +282 -0
  25. package/packages/hu-board/src/db-paths.js +113 -0
  26. package/packages/hu-board/src/db-queries.js +188 -0
  27. package/packages/hu-board/src/db-tombstones.js +51 -0
  28. package/packages/hu-board/src/db.js +28 -619
  29. package/packages/hu-board/src/ephemeral-cleaner.js +2 -3
  30. package/packages/hu-board/src/hu-zombie-reaper.js +5 -1
  31. package/packages/hu-board/src/plan-mutations.js +3 -153
  32. package/packages/hu-board/src/plans-service.js +55 -0
  33. package/packages/hu-board/src/routes/api/commands.js +122 -0
  34. package/packages/hu-board/src/routes/api/plans.js +55 -0
  35. package/packages/hu-board/src/routes/api/projects.js +267 -0
  36. package/packages/hu-board/src/routes/api/prompts.js +135 -0
  37. package/packages/hu-board/src/routes/api/sessions.js +95 -0
  38. package/packages/hu-board/src/routes/api/stories.js +183 -0
  39. package/packages/hu-board/src/routes/api/system.js +241 -0
  40. package/packages/hu-board/src/routes/api/tombstones.js +38 -0
  41. package/packages/hu-board/src/routes/api.js +24 -1371
  42. package/packages/hu-board/src/routes/governance.js +23 -1
  43. package/packages/hu-board/src/routes/lanes.js +40 -0
  44. package/packages/hu-board/src/routes/rag.js +4 -3
  45. package/packages/hu-board/src/server.js +20 -34
  46. package/packages/hu-board/src/sync-files.js +318 -0
  47. package/packages/hu-board/src/sync-project.js +99 -0
  48. package/packages/hu-board/src/sync.js +22 -566
  49. package/packages/hu-board/src/zombie-reaper.js +1 -1
  50. package/scripts/dual-publish.mjs +19 -3
  51. package/scripts/postinstall.js +15 -2
  52. package/scripts/verify-pack-mcp.mjs +11 -7
  53. package/scripts/verify-pack.mjs +4 -4
  54. package/src/audit/audit-history.js +3 -2
  55. package/src/audit/dead-exports.js +68 -59
  56. package/src/audit/deterministic-summary.js +33 -13
  57. package/src/audit/npm-signatures.js +41 -0
  58. package/src/audit/sbom.js +35 -0
  59. package/src/checks/agent-token.js +112 -0
  60. package/src/checks/dir-setup.js +34 -1
  61. package/src/checks/native-build.js +21 -39
  62. package/src/checks/runner.js +128 -142
  63. package/src/cli/advanced-commands.js +6 -6
  64. package/src/cli/register-meta.js +42 -82
  65. package/src/cli/register-pipeline.js +8 -143
  66. package/src/cli/register-plan.js +9 -100
  67. package/src/cli/retired-commands.js +49 -0
  68. package/src/cli.js +18 -5
  69. package/src/commands/agent-run.js +40 -26
  70. package/src/commands/audit.js +127 -124
  71. package/src/commands/board.js +5 -9
  72. package/src/commands/check.js +29 -16
  73. package/src/commands/doctor.js +2 -0
  74. package/src/commands/env.js +176 -150
  75. package/src/commands/go.js +71 -53
  76. package/src/commands/harden.js +90 -81
  77. package/src/commands/hu-start.js +52 -0
  78. package/src/commands/hu.js +288 -221
  79. package/src/commands/identity.js +111 -78
  80. package/src/commands/init-atril.js +47 -0
  81. package/src/commands/init.js +11 -40
  82. package/src/commands/install-tools.js +70 -85
  83. package/src/commands/main-guard.js +78 -0
  84. package/src/commands/policy.js +226 -184
  85. package/src/commands/qmd.js +27 -21
  86. package/src/commands/rag.js +75 -48
  87. package/src/commands/review-gate.js +421 -341
  88. package/src/commands/start.js +4 -5
  89. package/src/commands/steward.js +96 -47
  90. package/src/commands/tournament.js +46 -37
  91. package/src/commands/worktree.js +94 -25
  92. package/src/config/loader.js +34 -17
  93. package/src/config/secrets.js +36 -0
  94. package/src/config.js +1 -0
  95. package/src/environment/adr.js +16 -2
  96. package/src/git/karajan-label.js +20 -8
  97. package/src/guards/main-guard.js +54 -0
  98. package/src/harden/hook-templates.js +16 -1
  99. package/src/harden/sentinel/posttooluse.mjs +18 -6
  100. package/src/harden/sentinel/pretooluse-sentinel.mjs +64 -36
  101. package/src/harden/sentinel/sentinel-lib.mjs +129 -26
  102. package/src/harden/sentinel/sentinel-shell.mjs +5 -16
  103. package/src/harden/sentinel/sessionstart.mjs +3 -2
  104. package/src/harden/sentinel/stop.mjs +5 -4
  105. package/src/harden/workflow-templates.js +1 -1
  106. package/src/hu/board-lookup.js +29 -0
  107. package/src/hu/gh-identity.js +23 -0
  108. package/src/hu/github-board.js +4 -2
  109. package/src/hu/lane-prune.js +15 -7
  110. package/src/hu/lane-setup.js +65 -0
  111. package/src/hu/lanes.js +66 -0
  112. package/src/hu/team-board-mirror.js +3 -2
  113. package/src/infrastructure/command-runner.js +1 -1
  114. package/src/infrastructure/file-system-service.js +1 -1
  115. package/src/mcp/handlers/direct-handlers.js +2 -292
  116. package/src/mcp/handlers/hu-handlers.js +1 -35
  117. package/src/mcp/handlers/management-handlers.js +2 -42
  118. package/src/mcp/server-handlers.js +16 -22
  119. package/src/mcp/tools.js +1 -196
  120. package/src/plan/lane-plans.js +54 -0
  121. package/src/plan/plan-store.js +7 -4
  122. package/src/policy/add.js +26 -12
  123. package/src/policy/adr-number-check.js +31 -0
  124. package/src/prompts/audit.js +299 -339
  125. package/src/prompts/card-context.js +10 -5
  126. package/src/prompts/reviewer.js +5 -2
  127. package/src/rag/auto-update.js +56 -43
  128. package/src/rag/bootstrap-index.js +28 -54
  129. package/src/rag/migrate.js +1 -1
  130. package/src/rag/onnx-fallback.js +2 -2
  131. package/src/rag/pid-lease.js +70 -0
  132. package/src/rag/project-store.js +2 -12
  133. package/src/review/card-first.js +57 -46
  134. package/src/review/gate-gitignore.js +23 -4
  135. package/src/review/gate-hook.js +12 -4
  136. package/src/review/one-shot-review.js +45 -35
  137. package/src/review/publish-pr.js +14 -2
  138. package/src/review/repo-docs.js +73 -0
  139. package/src/review/repo-stack.js +59 -0
  140. package/src/review/reviewer-fallback.js +19 -4
  141. package/src/review/seal-commit.js +29 -0
  142. package/src/review/sonar-pregate.js +59 -44
  143. package/src/review/third-party-review.js +90 -16
  144. package/src/review/third-party-size.js +43 -0
  145. package/src/review/third-party-skills.js +54 -0
  146. package/src/review/verify-pr.js +1 -24
  147. package/src/roles/audit-role.js +106 -125
  148. package/src/skills/atril-skills.js +5 -4
  149. package/src/sonar/scanner.js +116 -101
  150. package/src/steward/invariants.js +5 -4
  151. package/src/steward/phantom-sweep.js +66 -0
  152. package/src/tournament/judge.js +60 -53
  153. package/src/utils/gh-account.js +37 -0
  154. package/src/utils/git.js +0 -13
  155. package/src/utils/home-migration.js +7 -1
  156. package/src/utils/main-checkout.js +53 -0
  157. package/src/utils/qmd-collection.js +3 -1
  158. package/src/utils/welcome.js +3 -3
  159. package/templates/{skills → atril/commands}/kj-architect.md +5 -0
  160. package/templates/{skills → atril/commands}/kj-audit.md +5 -0
  161. package/templates/{skills → atril/commands}/kj-board.md +5 -0
  162. package/templates/{skills → atril/commands}/kj-code.md +5 -0
  163. package/templates/{skills → atril/commands}/kj-csv-transform.md +5 -0
  164. package/templates/{skills → atril/commands}/kj-data-report.md +5 -0
  165. package/templates/{skills → atril/commands}/kj-discover.md +5 -0
  166. package/templates/{skills → atril/commands}/kj-rag-query.md +5 -0
  167. package/templates/{skills → atril/commands}/kj-review.md +5 -0
  168. package/templates/{skills → atril/commands}/kj-security.md +5 -0
  169. package/templates/{skills → atril/commands}/kj-sonar.md +5 -0
  170. package/templates/{skills → atril/commands}/kj-sql-analysis.md +5 -0
  171. package/templates/{skills → atril/commands}/kj-test.md +5 -0
  172. package/packages/hu-board/public/utils/run-launcher.js +0 -169
  173. package/packages/hu-board/src/run-tracker.js +0 -121
  174. package/src/activity-log.js +0 -59
  175. package/src/agents/host-agent.js +0 -38
  176. package/src/agents/model-registry.js +0 -142
  177. package/src/audit/plan-adherence.js +0 -224
  178. package/src/autonomy/arbiter-role.js +0 -71
  179. package/src/autonomy/arbiter.js +0 -22
  180. package/src/autonomy/decider.js +0 -18
  181. package/src/autonomy/decision-resolver.js +0 -58
  182. package/src/autonomy/outcome-report.js +0 -55
  183. package/src/autonomy/stage-ask.js +0 -30
  184. package/src/brain/decision-tracker.js +0 -125
  185. package/src/brain/decisor.js +0 -243
  186. package/src/brain/solomon-consult.js +0 -171
  187. package/src/brain/standby-scheduler.js +0 -8
  188. package/src/budget/comparison.js +0 -96
  189. package/src/canvas/parse-md.js +0 -238
  190. package/src/canvas/schema.js +0 -101
  191. package/src/canvas/to-flat.js +0 -85
  192. package/src/canvas/validate.js +0 -163
  193. package/src/ci/dispatch.js +0 -99
  194. package/src/ci/index.js +0 -3
  195. package/src/ci/pr-diff.js +0 -26
  196. package/src/cli/register-standby.js +0 -26
  197. package/src/commands/architect.js +0 -111
  198. package/src/commands/autorun.js +0 -49
  199. package/src/commands/researcher.js +0 -54
  200. package/src/commands/resume.js +0 -72
  201. package/src/commands/review.js +0 -89
  202. package/src/commands/run.js +0 -185
  203. package/src/commands/standby.js +0 -117
  204. package/src/commands/status.js +0 -36
  205. package/src/commands/triage.js +0 -78
  206. package/src/commands/undo.js +0 -62
  207. package/src/domains/domain-loader.js +0 -245
  208. package/src/domains/domain-registry.js +0 -140
  209. package/src/domains/domain-synthesizer.js +0 -129
  210. package/src/git/automation.js +0 -433
  211. package/src/git/coder-commit-guard.js +0 -40
  212. package/src/git/hu-automation.js +0 -243
  213. package/src/git/hu-snapshot.js +0 -10
  214. package/src/git/symlink-targets.js +0 -57
  215. package/src/golden/asserter.js +0 -92
  216. package/src/golden/loader.js +0 -52
  217. package/src/golden/runner.js +0 -92
  218. package/src/golden/schema.js +0 -41
  219. package/src/guards/duplicate-members.js +0 -86
  220. package/src/guards/intent-guard.js +0 -161
  221. package/src/guards/perf-guard.js +0 -126
  222. package/src/guards/policy-guard.js +0 -90
  223. package/src/guards/policy-resolver.js +0 -85
  224. package/src/guards/secret-redactor.js +0 -71
  225. package/src/hu/acceptance-runner.js +0 -138
  226. package/src/hu/lazy-planner.js +0 -109
  227. package/src/hu/parallel-executor.js +0 -94
  228. package/src/hu/routing-metrics.js +0 -17
  229. package/src/hu/split-validator.js +0 -143
  230. package/src/hu/splitting-detector.js +0 -158
  231. package/src/hu/splitting-generator.js +0 -175
  232. package/src/hu/store.js +0 -394
  233. package/src/infrastructure/mocks.js +0 -182
  234. package/src/mcp/handlers/run-handler.js +0 -318
  235. package/src/mcp/sovereignty-guard.js +0 -113
  236. package/src/mcp/tool-arg-normalizers.js +0 -16
  237. package/src/mutate/reviewer-signal.js +0 -76
  238. package/src/orchestrator/agent-fallback.js +0 -81
  239. package/src/orchestrator/brain-coordinator.js +0 -186
  240. package/src/orchestrator/ci-integration.js +0 -139
  241. package/src/orchestrator/config-init.js +0 -426
  242. package/src/orchestrator/direct-actions.js +0 -217
  243. package/src/orchestrator/drivers/error-recovery.js +0 -287
  244. package/src/orchestrator/drivers/init-context.js +0 -238
  245. package/src/orchestrator/drivers/iteration-loop.js +0 -382
  246. package/src/orchestrator/drivers/iteration-phases/coder-and-refactorer.js +0 -69
  247. package/src/orchestrator/drivers/iteration-phases/guards.js +0 -91
  248. package/src/orchestrator/drivers/iteration-phases/handle-approved.js +0 -29
  249. package/src/orchestrator/drivers/iteration-phases/quality-gates.js +0 -125
  250. package/src/orchestrator/drivers/iteration-phases/reviewer-gate.js +0 -62
  251. package/src/orchestrator/drivers/post-loop.js +0 -404
  252. package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +0 -137
  253. package/src/orchestrator/drivers/pre-loop-phases/config-deprecations.js +0 -47
  254. package/src/orchestrator/drivers/pre-loop-phases/ensure-addyosmani-skills.js +0 -84
  255. package/src/orchestrator/drivers/pre-loop-phases/inject-loaded-plan.js +0 -393
  256. package/src/orchestrator/drivers/pre-loop.js +0 -524
  257. package/src/orchestrator/drivers/run-hu-batch.js +0 -468
  258. package/src/orchestrator/feedback-enrichment.js +0 -140
  259. package/src/orchestrator/feedback-queue.js +0 -151
  260. package/src/orchestrator/flow-control.js +0 -170
  261. package/src/orchestrator/flow-runner.js +0 -365
  262. package/src/orchestrator/fs-leak-detector.js +0 -228
  263. package/src/orchestrator/hu-scheduler.js +0 -114
  264. package/src/orchestrator/hu-sub-pipeline.js +0 -642
  265. package/src/orchestrator/iteration-gate.js +0 -73
  266. package/src/orchestrator/iteration-stages.js +0 -9
  267. package/src/orchestrator/parallel-limiter.js +0 -74
  268. package/src/orchestrator/pipeline-context.js +0 -72
  269. package/src/orchestrator/post-loop-stages.js +0 -468
  270. package/src/orchestrator/pre-loop-stages.js +0 -11
  271. package/src/orchestrator/preflight-checks.js +0 -487
  272. package/src/orchestrator/repair/repair-detector.js +0 -117
  273. package/src/orchestrator/repair/repair-runner.js +0 -142
  274. package/src/orchestrator/reviewer-fallback.js +0 -45
  275. package/src/orchestrator/role-output-compressor.js +0 -189
  276. package/src/orchestrator/session-journal.js +0 -308
  277. package/src/orchestrator/solomon-escalation.js +0 -331
  278. package/src/orchestrator/solomon-rules.js +0 -212
  279. package/src/orchestrator/stages/acceptance-coverage-stage.js +0 -47
  280. package/src/orchestrator/stages/architect-stage.js +0 -172
  281. package/src/orchestrator/stages/coder-stage.js +0 -506
  282. package/src/orchestrator/stages/domain-curator-stage.js +0 -82
  283. package/src/orchestrator/stages/format-stage.js +0 -61
  284. package/src/orchestrator/stages/hu-reviewer-phases/detect-and-apply-splits.js +0 -127
  285. package/src/orchestrator/stages/hu-reviewer-stage.js +0 -419
  286. package/src/orchestrator/stages/perf-stage.js +0 -140
  287. package/src/orchestrator/stages/planner-stage.js +0 -85
  288. package/src/orchestrator/stages/rag-context-stage.js +0 -80
  289. package/src/orchestrator/stages/rag-preload-decisor.js +0 -58
  290. package/src/orchestrator/stages/research-stage.js +0 -69
  291. package/src/orchestrator/stages/reviewer-stage.js +0 -431
  292. package/src/orchestrator/stages/sonar-stage.js +0 -439
  293. package/src/orchestrator/stages/stage-classes.js +0 -84
  294. package/src/orchestrator/stages/stage-executor.js +0 -155
  295. package/src/orchestrator/stages/suite-green-stage.js +0 -62
  296. package/src/orchestrator/stages/tdd-discipline-stage.js +0 -56
  297. package/src/orchestrator/stages/tool-judge-stage.js +0 -53
  298. package/src/orchestrator/stages/triage-stage.js +0 -172
  299. package/src/orchestrator/standby.js +0 -71
  300. package/src/orchestrator/verification-gate.js +0 -183
  301. package/src/orchestrator.js +0 -22
  302. package/src/plan/adr-generator.js +0 -170
  303. package/src/plan/adr-loader.js +0 -60
  304. package/src/plan/plan-executor.js +0 -100
  305. package/src/plan/plan-validation.js +0 -4
  306. package/src/prompts/acceptance-coverage.js +0 -32
  307. package/src/prompts/arbiter.js +0 -38
  308. package/src/prompts/architect.js +0 -103
  309. package/src/prompts/hu-reviewer.js +0 -244
  310. package/src/prompts/tool-correctness-judge.js +0 -31
  311. package/src/prompts/triage.js +0 -57
  312. package/src/rag/embedder.js +0 -2
  313. package/src/rag/embedders/_cloud-base.js +0 -2
  314. package/src/rag/embedders/cohere.js +0 -2
  315. package/src/rag/embedders/mistral.js +0 -2
  316. package/src/rag/embedders/onnx.js +0 -2
  317. package/src/rag/embedders/openai.js +0 -2
  318. package/src/rag/embedders/voyage.js +0 -2
  319. package/src/rag/rerank.js +0 -4
  320. package/src/rag/where-parser.js +0 -4
  321. package/src/repeat-detector.js +0 -88
  322. package/src/review/diff-generator.js +0 -112
  323. package/src/review/git-stash-helper.js +0 -104
  324. package/src/review/schema.js +0 -31
  325. package/src/review/scope-filter.js +0 -152
  326. package/src/review/snapshot-diff.js +0 -122
  327. package/src/review/tdd-discipline.js +0 -90
  328. package/src/review/tdd-policy.js +0 -69
  329. package/src/roles/acceptance-coverage-role.js +0 -78
  330. package/src/roles/architect-role.js +0 -77
  331. package/src/roles/coder-role.js +0 -113
  332. package/src/roles/commiter-role.js +0 -113
  333. package/src/roles/domain-curator-role.js +0 -134
  334. package/src/roles/hu-reviewer-role.js +0 -64
  335. package/src/roles/impeccable-role.js +0 -85
  336. package/src/roles/index.js +0 -18
  337. package/src/roles/karajan-brain-role.js +0 -134
  338. package/src/roles/perf-role.js +0 -122
  339. package/src/roles/planner-role.js +0 -151
  340. package/src/roles/refactorer-role.js +0 -30
  341. package/src/roles/repairer-role.js +0 -181
  342. package/src/roles/researcher-role.js +0 -70
  343. package/src/roles/reviewer-role.js +0 -115
  344. package/src/roles/security-role.js +0 -73
  345. package/src/roles/solomon-role.js +0 -271
  346. package/src/roles/sonar-role.js +0 -72
  347. package/src/roles/tester-role.js +0 -235
  348. package/src/roles/tool-correctness-judge-role.js +0 -78
  349. package/src/roles/triage-role.js +0 -99
  350. package/src/session/journal/decisions-writer.js +0 -200
  351. package/src/session/journal/iteration-logger.js +0 -194
  352. package/src/session/journal/summary-writer.js +0 -320
  353. package/src/session/journal/tree-writer.js +0 -164
  354. package/src/session/journal/write-all.js +0 -89
  355. package/src/session-cleanup.js +0 -116
  356. package/src/skills/semantic-detector.js +0 -167
  357. package/src/skills/skill-detector.js +0 -385
  358. package/src/sonar/cloud-scanner.js +0 -78
  359. package/src/tracker-bootstrap.js +0 -44
  360. package/src/types/index.js +0 -38
  361. package/src/types/policy.js +0 -43
  362. package/src/types/solomon.js +0 -87
  363. package/src/utils/async-lock.js +0 -31
  364. package/src/utils/budget.js +0 -229
  365. package/src/utils/cwd-confirm.js +0 -39
  366. package/src/utils/display/event-handlers.js +0 -403
  367. package/src/utils/display/formatters.js +0 -132
  368. package/src/utils/display/header.js +0 -47
  369. package/src/utils/display/session-summary.js +0 -118
  370. package/src/utils/display/solomon.js +0 -42
  371. package/src/utils/pricing.js +0 -29
  372. package/src/utils/quota-simulator.js +0 -56
  373. package/src/utils/role-assigner.js +0 -137
  374. package/src/utils/rtk-wrapper.js +0 -87
  375. package/src/utils/run-registry.js +0 -9
  376. package/src/utils/status-dashboard.js +0 -254
  377. package/src/utils/tool-call-extractor.js +0 -56
  378. package/src/webperf/devtools-detect.js +0 -112
  379. package/src/webperf/webperf-role-integration.js +0 -66
  380. package/templates/skills/kj-run.md +0 -73
@@ -1,142 +0,0 @@
1
- const modelRegistry = new Map();
2
-
3
- export function registerModel(name, { provider, pricing, deprecated } = {}) {
4
- if (!name || typeof name !== "string") {
5
- throw new Error("Model name must be a non-empty string");
6
- }
7
- if (!pricing || typeof pricing.input_per_million !== "number" || typeof pricing.output_per_million !== "number") {
8
- throw new Error(`Model "${name}" requires pricing with input_per_million and output_per_million`);
9
- }
10
- modelRegistry.set(name, {
11
- name,
12
- provider: provider || name.split("/")[0],
13
- pricing: { input_per_million: pricing.input_per_million, output_per_million: pricing.output_per_million },
14
- deprecated: deprecated || null,
15
- });
16
- }
17
-
18
- export function registerModelAlias(alias, target, { provider } = {}) {
19
- const entry = modelRegistry.get(target);
20
- if (!entry) {
21
- throw new Error(`Target model "${target}" for alias "${alias}" not found`);
22
- }
23
- modelRegistry.set(alias, {
24
- ...entry,
25
- name: alias,
26
- provider: provider || entry.provider
27
- });
28
- }
29
-
30
- export function getModelPricing(name) {
31
- const entry = modelRegistry.get(name);
32
- return entry ? { ...entry.pricing } : null;
33
- }
34
-
35
- export function isModelDeprecated(name) {
36
- const entry = modelRegistry.get(name);
37
- if (!entry?.deprecated) return false;
38
- return new Date(entry.deprecated) <= new Date();
39
- }
40
-
41
- export function getModelInfo(name) {
42
- const entry = modelRegistry.get(name);
43
- if (!entry) return null;
44
- return { name: entry.name, provider: entry.provider, pricing: { ...entry.pricing }, deprecated: entry.deprecated };
45
- }
46
-
47
- export function getRegisteredModels() {
48
- return [...modelRegistry.entries()].map(([_name, entry]) => ({
49
- name: entry.name,
50
- provider: entry.provider,
51
- pricing: { ...entry.pricing },
52
- deprecated: entry.deprecated,
53
- }));
54
- }
55
-
56
- export function buildDefaultPricingTable() {
57
- const table = {};
58
- for (const [name, entry] of modelRegistry) {
59
- table[name] = { ...entry.pricing };
60
- }
61
- return table;
62
- }
63
-
64
- /**
65
- * Anthropic Claude Family
66
- * Pricing & Info: https://platform.claude.com/docs/en/about-claude/pricing
67
- */
68
- registerModel("claude-opus-4.6", { provider: "anthropic", pricing: { input_per_million: 5.0, output_per_million: 25.0 } });
69
- registerModel("claude-sonnet-4.6", { provider: "anthropic", pricing: { input_per_million: 3.0, output_per_million: 15.0 } });
70
- registerModel("claude-haiku-4.5", { provider: "anthropic", pricing: { input_per_million: 1.0, output_per_million: 5.0 } });
71
-
72
- // Default models & General aliases
73
- registerModel("claude", { provider: "anthropic", pricing: { input_per_million: 3, output_per_million: 15 } });
74
- registerModel("sonnet", { provider: "anthropic", pricing: { input_per_million: 3, output_per_million: 15 } });
75
- registerModel("opus", { provider: "anthropic", pricing: { input_per_million: 15, output_per_million: 75 } });
76
- registerModel("haiku", { provider: "anthropic", pricing: { input_per_million: 0.25, output_per_million: 1.25 } });
77
-
78
- /**
79
- * OpenAI GPT Family
80
- * Pricing: https://developers.openai.com/api/docs/pricing
81
- */
82
- registerModel("gpt-5.4-standard", { provider: "openai", pricing: { input_per_million: 2.5, output_per_million: 15.0 } });
83
- registerModel("gpt-5.4-thinking", { provider: "openai", pricing: { input_per_million: 2.5, output_per_million: 15.0 } });
84
- registerModel("gpt-5.4-pro", { provider: "openai", pricing: { input_per_million: 30.0, output_per_million: 180.0 } });
85
- registerModel("gpt-5.4-mini", { provider: "openai", pricing: { input_per_million: 0.75, output_per_million: 4.5 } });
86
-
87
- // Default models & General aliases
88
- registerModel("codex", { provider: "openai", pricing: { input_per_million: 1.5, output_per_million: 4 } });
89
- // KJC-TSK-0699: the models the codex CLI lists (0.146.1). List prices after the
90
- // 2026-07-30 cut; Sol at its base rate, not the temporary promotion.
91
- registerModel("gpt-5.6-sol", { provider: "openai", pricing: { input_per_million: 5.0, output_per_million: 30.0 } });
92
- registerModel("gpt-5.6-terra", { provider: "openai", pricing: { input_per_million: 2.0, output_per_million: 12.0 } });
93
- registerModel("gpt-5.6-luna", { provider: "openai", pricing: { input_per_million: 0.2, output_per_million: 1.2 } });
94
- registerModel("o4-mini", { provider: "openai", pricing: { input_per_million: 1.5, output_per_million: 4 } });
95
- registerModel("o3", { provider: "openai", pricing: { input_per_million: 10, output_per_million: 40 } });
96
-
97
- /**
98
- * Google Gemini Family
99
- * Pricing: https://ai.google.dev/gemini-api/docs/pricing
100
- */
101
- registerModel("gemini-3.1-pro-preview", { provider: "google", pricing: { input_per_million: 2.0, output_per_million: 12.0 } });
102
- registerModel("gemini-3.1-flash-lite", { provider: "google", pricing: { input_per_million: 0.25, output_per_million: 1.5 } });
103
- registerModel("gemini-3-flash-preview", { provider: "google", pricing: { input_per_million: 0.5, output_per_million: 3.0 } });
104
- registerModel("gemini-2.5-pro", { provider: "google", pricing: { input_per_million: 1.25, output_per_million: 5 } });
105
- registerModel("gemini-2.0-flash", { provider: "google", pricing: { input_per_million: 0.075, output_per_million: 0.3 } });
106
-
107
- // Default models & General aliases
108
- registerModelAlias("gemini", "gemini-2.5-pro");
109
-
110
- /**
111
- * Other Providers & CLI Aliases
112
- */
113
- registerModel("aider", { provider: "aider", pricing: { input_per_million: 3, output_per_million: 15 } });
114
- registerModel("opencode", { provider: "opencode", pricing: { input_per_million: 0, output_per_million: 0 } });
115
-
116
- /**
117
- * Moonshot Kimi Family (KJC-TSK-0633) — consumed through OpenCode as an
118
- * OpenAI-compatible provider (docs/providers-via-opencode.md).
119
- * Pricing: https://platform.moonshot.ai/docs/pricing — verify before
120
- * trusting for billing decisions; ids/prices move fast.
121
- */
122
- registerModel("kimi-k2", { provider: "moonshot", pricing: { input_per_million: 0.6, output_per_million: 2.5 } });
123
- registerModel("kimi-k2-thinking", { provider: "moonshot", pricing: { input_per_million: 0.6, output_per_million: 2.5 } });
124
- registerModelAlias("kimi", "kimi-k2");
125
- // Prefixed ids as the documented opencode.json snippet produces them.
126
- registerModelAlias("kimi/kimi-k2", "kimi-k2");
127
- registerModelAlias("kimi/kimi-k2-thinking", "kimi-k2-thinking");
128
-
129
- /**
130
- * DeepSeek Family (KJC-TSK-0633) — same OpenCode route.
131
- * Pricing: https://api-docs.deepseek.com/quick_start/pricing
132
- */
133
- registerModel("deepseek-chat", { provider: "deepseek", pricing: { input_per_million: 0.28, output_per_million: 0.42 } });
134
- registerModel("deepseek-reasoner", { provider: "deepseek", pricing: { input_per_million: 0.28, output_per_million: 0.42 } });
135
- registerModelAlias("deepseek", "deepseek-chat");
136
- registerModelAlias("deepseek/deepseek-chat", "deepseek-chat");
137
- registerModelAlias("deepseek/deepseek-reasoner", "deepseek-reasoner");
138
-
139
- // Common CLI Aliases (with provider overrides)
140
- registerModelAlias("aider/claude-3-7-sonnet", "claude-sonnet-4.6", { provider: "aider" });
141
- registerModelAlias("aider/gpt-4o", "gpt-5.4-standard", { provider: "aider" });
142
- registerModelAlias("opencode/minimax-m2.5", "opencode", { provider: "opencode" });
@@ -1,224 +0,0 @@
1
- /**
2
- * Plan adherence metric — KJC-TSK-0376 (deepeval-inspired).
3
- * Pure offline 0-100 score: how faithfully did the coder follow the plan?
4
- * Components (weighted): commit_attribution 40%, acceptance_tests 30%,
5
- * scope_discipline 20%, dependency_order 10%. Components return null
6
- * when no data; aggregator redistributes the weight.
7
- * See docs/plan-adherence.md (PR-C) for the full spec.
8
- */
9
-
10
- import { escapeRegExp } from "../utils/escape-regexp.js";
11
-
12
- const WEIGHTS = {
13
- commit_attribution: 40,
14
- acceptance_tests: 30,
15
- scope_discipline: 20,
16
- dependency_order: 10,
17
- };
18
-
19
- /**
20
- * Build a regex that matches the HU id anywhere in a commit message
21
- * (case-insensitive, word-boundary friendly). The `_` and `-` characters
22
- * appear inside HU ids so we anchor on whole-token rather than \b.
23
- */
24
- function huIdMatcher(huId) {
25
- const escaped = escapeRegExp(huId);
26
- return new RegExp(`(^|[^a-z0-9])${escaped}([^a-z0-9]|$)`, "i");
27
- }
28
-
29
- /**
30
- * Slugify an HU title for branch-name / scope matching. Mirrors the
31
- * `buildHuBranchName` slug rule (lowercase, non-alnum → "-").
32
- */
33
- function slugify(text) {
34
- return String(text || "")
35
- .toLowerCase()
36
- .replaceAll(/[^a-z0-9]+/g, "-")
37
- .replaceAll(/(^-+)|(-+$)/g, "");
38
- }
39
-
40
- /**
41
- * Try to attribute a single commit to one of the plan's HUs.
42
- *
43
- * Order of evidence, strongest first:
44
- * 1. The HU id appears in the commit message.
45
- * 2. The HU id appears in the branch name where the commit lives
46
- * (commit.branch is supplied by listCommitsBetween's caller when
47
- * it knows the per-HU branches).
48
- * 3. The HU title slug matches the commit message.
49
- *
50
- * Returns the matched huId, or null when none of the above fires.
51
- */
52
- export function attributeCommitToHu(commit, hus) {
53
- if (!commit || !Array.isArray(hus) || hus.length === 0) return null;
54
- const msg = String(commit.message || "");
55
- const branch = String(commit.branch || "");
56
- for (const hu of hus) {
57
- if (!hu?.id) continue;
58
- const matcher = huIdMatcher(hu.id);
59
- if (matcher.test(msg)) return hu.id;
60
- if (branch && matcher.test(branch)) return hu.id;
61
- }
62
- // Fallback: title slug
63
- for (const hu of hus) {
64
- const slug = slugify(hu.title);
65
- if (!slug || slug.length < 6) continue;
66
- if (slugify(msg).includes(slug)) return hu.id;
67
- }
68
- return null;
69
- }
70
-
71
- /**
72
- * Component 1: commit attribution. Returns null when the run produced
73
- * no commits at all (avoids penalising analysis-only or doc-only runs).
74
- */
75
- export function computeCommitAttribution(commits, plan) {
76
- if (!Array.isArray(commits) || commits.length === 0) return null;
77
- if (!plan?.hus || plan.hus.length === 0) return null;
78
- let attributed = 0;
79
- for (const commit of commits) {
80
- if (attributeCommitToHu(commit, plan.hus)) attributed += 1;
81
- }
82
- return Math.round((attributed / commits.length) * 100);
83
- }
84
-
85
- /**
86
- * Component 2: acceptance test coverage. Heuristic: each HU declares
87
- * `acceptance_tests`. We check whether at least one commit from that
88
- * HU's pool has a `test:`-prefixed message. Per-HU score (1 or 0),
89
- * averaged across HUs that DO declare tests. Returns null when no HU
90
- * declares acceptance tests.
91
- */
92
- export function computeAcceptanceTestCoverage(commits, plan) {
93
- if (!plan?.hus || plan.hus.length === 0) return null;
94
- if (!Array.isArray(commits) || commits.length === 0) return null;
95
- const husWithTests = plan.hus.filter(
96
- (hu) => Array.isArray(hu?.acceptance_tests) && hu.acceptance_tests.length > 0,
97
- );
98
- if (husWithTests.length === 0) return null;
99
-
100
- let covered = 0;
101
- for (const hu of husWithTests) {
102
- const huCommits = (commits || []).filter(
103
- (c) => attributeCommitToHu(c, [hu]) === hu.id,
104
- );
105
- const hasTestCommit = huCommits.some((c) =>
106
- /^test[:(]/i.test(String(c.message || "").trim()),
107
- );
108
- if (hasTestCommit) covered += 1;
109
- }
110
- return Math.round((covered / husWithTests.length) * 100);
111
- }
112
-
113
- /**
114
- * Component 3: scope discipline. For each file changed by the run, we
115
- * try to match it against at least one HU's id slug, title slug, or
116
- * `scope` text. A file that matches no HU is flagged as out-of-scope.
117
- * Returns null when the run changed no files.
118
- */
119
- export function computeScopeDiscipline(filesChanged, plan) {
120
- if (!Array.isArray(filesChanged) || filesChanged.length === 0) return null;
121
- if (!plan?.hus || plan.hus.length === 0) return null;
122
- const huKeywords = plan.hus.map((hu) => ({
123
- id: hu.id,
124
- matchers: [
125
- slugify(hu.id),
126
- slugify(hu.title),
127
- // Pull alpha-rich words from `scope` text (length >= 4).
128
- ...String(hu.scope || "")
129
- .toLowerCase()
130
- .split(/[^a-z]+/)
131
- .filter((w) => w.length >= 4),
132
- ].filter(Boolean),
133
- }));
134
- let inScope = 0;
135
- for (const file of filesChanged) {
136
- const slug = slugify(file);
137
- const matched = huKeywords.some((hk) =>
138
- hk.matchers.some((m) => slug.includes(m) || file.includes(m)),
139
- );
140
- if (matched) inScope += 1;
141
- }
142
- return Math.round((inScope / filesChanged.length) * 100);
143
- }
144
-
145
- /**
146
- * Component 4: dependency order. For every `(parent, child)` edge
147
- * declared via `child.blocked_by`, check that the EARLIEST commit
148
- * attributed to `parent` is older than the EARLIEST commit attributed
149
- * to `child`. Returns null when no dependency edges exist.
150
- *
151
- * `commits` are expected oldest-first (the shape `listCommitsBetween`
152
- * returns). When that's not the case the score still makes sense — we
153
- * just compare relative positions in the array.
154
- */
155
- export function computeDependencyOrder(commits, plan) {
156
- if (!plan?.hus || plan.hus.length === 0) return null;
157
- const edges = [];
158
- for (const hu of plan.hus) {
159
- for (const parentId of hu.blocked_by || []) {
160
- edges.push([parentId, hu.id]);
161
- }
162
- }
163
- if (edges.length === 0) return null;
164
- if (!Array.isArray(commits) || commits.length === 0) return null;
165
-
166
- // Build huId → first commit index (oldest first attribution).
167
- const firstIndex = new Map();
168
- commits.forEach((commit, idx) => {
169
- const huId = attributeCommitToHu(commit, plan.hus);
170
- if (huId && !firstIndex.has(huId)) firstIndex.set(huId, idx);
171
- });
172
-
173
- let respected = 0;
174
- let evaluable = 0;
175
- for (const [parentId, childId] of edges) {
176
- const p = firstIndex.get(parentId);
177
- const c = firstIndex.get(childId);
178
- if (p === undefined || c === undefined) continue; // can't evaluate
179
- evaluable += 1;
180
- if (p < c) respected += 1;
181
- }
182
- if (evaluable === 0) return null;
183
- return Math.round((respected / evaluable) * 100);
184
- }
185
-
186
- /**
187
- * Aggregator: compute every component and weight them. Components
188
- * that return `null` are excluded and their weight redistributed
189
- * proportionally across the rest, so a run that legitimately has no
190
- * acceptance tests or no dependencies isn't penalised.
191
- *
192
- * Returns the full structured result (see file header for shape).
193
- */
194
- export function computePlanAdherenceScore({ commits, plan, filesChanged }) {
195
- const breakdown = {
196
- commit_attribution: computeCommitAttribution(commits, plan),
197
- acceptance_tests: computeAcceptanceTestCoverage(commits, plan),
198
- scope_discipline: computeScopeDiscipline(filesChanged, plan),
199
- dependency_order: computeDependencyOrder(commits, plan),
200
- };
201
-
202
- // Weighted average over non-null components only.
203
- let totalWeight = 0;
204
- let weightedSum = 0;
205
- for (const [key, weight] of Object.entries(WEIGHTS)) {
206
- const value = breakdown[key];
207
- if (value === null || value === undefined) continue;
208
- totalWeight += weight;
209
- weightedSum += value * weight;
210
- }
211
- const score = totalWeight === 0 ? null : Math.round(weightedSum / totalWeight);
212
-
213
- // Per-HU detail: was the HU "touched" (attributed at least one commit)?
214
- const hu_scores = (plan?.hus || []).map((hu) => {
215
- const huCommits = (commits || []).filter(
216
- (c) => attributeCommitToHu(c, [hu]) === hu.id,
217
- );
218
- const issues = [];
219
- if (huCommits.length === 0) issues.push("no commit attributed");
220
- return { huId: hu.id, attributed: huCommits.length > 0, issues };
221
- });
222
-
223
- return { score, breakdown, hu_scores };
224
- }
@@ -1,71 +0,0 @@
1
- /**
2
- * ArbiterRole — the autonomous decision authority that resolves agent conflicts
3
- * by picking the least-bad verdict (KJC-TSK-0573, épica KJC-PCS-0062).
4
- *
5
- * Extends AgentRole (so it inherits Brain recovery / standby) following the
6
- * TriageRole pattern: a cheap decisor model emits a closed-set verdict, and any
7
- * parse failure degrades to BLOCK_AND_CONTINUE — the pipeline never crashes and
8
- * never blocks on the Arbiter.
9
- */
10
-
11
- import { AgentRole } from "../roles/agent-role.js";
12
- import { extractFirstJson } from "../utils/json-extract.js";
13
- import { buildArbiterPrompt, VERDICTS } from "../prompts/arbiter.js";
14
-
15
- const CONSERVATIVE = "BLOCK_AND_CONTINUE";
16
- const VERDICT_SET = new Set(VERDICTS);
17
-
18
- function clampConfidence(value) {
19
- const n = Number(value);
20
- return Number.isFinite(n) ? Math.min(1, Math.max(0, n)) : 0;
21
- }
22
-
23
- export class ArbiterRole extends AgentRole {
24
- constructor(opts) {
25
- super({ ...opts, name: "arbiter" });
26
- }
27
-
28
- async buildPrompt(input) {
29
- return { prompt: buildArbiterPrompt(input) };
30
- }
31
-
32
- parseOutput(raw) {
33
- return extractFirstJson(raw);
34
- }
35
-
36
- buildSuccessResult(parsed, provider) {
37
- const verdict = VERDICT_SET.has(parsed?.verdict) ? parsed.verdict : CONSERVATIVE;
38
- return {
39
- verdict,
40
- confidence: clampConfidence(parsed?.confidence),
41
- rationale: String(parsed?.rationale || "").trim() || "no rationale",
42
- defect: parsed?.defect ? String(parsed.defect).trim() : null,
43
- directive: parsed?.directive ? String(parsed.directive).trim() : null,
44
- provider,
45
- };
46
- }
47
-
48
- buildSummary(parsed) {
49
- return `Arbiter: ${VERDICT_SET.has(parsed?.verdict) ? parsed.verdict : CONSERVATIVE}`;
50
- }
51
-
52
- // Never crash on garbage: degrade to the conservative verdict so the pipeline
53
- // moves on instead of aborting (ok:true keeps the run alive).
54
- handleParseNull(agentResult, provider) {
55
- return this.degraded(agentResult, provider, "unstructured output");
56
- }
57
-
58
- handleParseError(err, agentResult, provider) {
59
- return this.degraded(agentResult, provider, err?.message || "parse error");
60
- }
61
-
62
- degraded(agentResult, provider, why) {
63
- this.logger?.warn?.(`[arbiter] ${why} → ${CONSERVATIVE} (conservative)`);
64
- return {
65
- ok: true,
66
- result: { verdict: CONSERVATIVE, confidence: 0, rationale: `degraded: ${why}`, defect: null, directive: null, provider },
67
- summary: `Arbiter: ${CONSERVATIVE} (degraded)`,
68
- usage: agentResult.usage,
69
- };
70
- }
71
- }
@@ -1,22 +0,0 @@
1
- /**
2
- * createArbiter — adapt ArbiterRole to the function the decision-resolver
3
- * injects (KJC-TSK-0573). The resolver calls `arbiter(req)` and expects
4
- * `{ choice, rationale, ... }`; here `choice` is the Arbiter's verdict, which
5
- * the resolver then validates against the caller's options (AUTO-A).
6
- */
7
-
8
- import { ArbiterRole } from "./arbiter-role.js";
9
-
10
- export function createArbiter({ config = {}, logger = console, createAgentFn = null } = {}) {
11
- return async function arbiter(req) {
12
- const role = new ArbiterRole({ config, logger, createAgentFn });
13
- const { result } = await role.execute(req);
14
- return {
15
- choice: result.verdict,
16
- rationale: result.rationale,
17
- confidence: result.confidence,
18
- defect: result.defect,
19
- directive: result.directive,
20
- };
21
- };
22
- }
@@ -1,18 +0,0 @@
1
- /**
2
- * buildDecider — wire the active autonomy level to a ready decision resolver
3
- * (KJC-TSK-0572, design in docs/specs/autonomous-delivery.md §5).
4
- *
5
- * interactive → the human `ask`; assisted/autonomous → the Arbiter (AUTO-B).
6
- * Consumers (spec-review, reviewer, checkpoint…) call `resolve(...)` instead of
7
- * prompting directly, so the autonomy level decides who answers in one place.
8
- */
9
-
10
- import { createDecisionResolver } from "./decision-resolver.js";
11
- import { resolveAutonomy } from "./policy.js";
12
- import { createArbiter } from "./arbiter.js";
13
-
14
- export function buildDecider({ config = {}, flags = {}, ask = null, env = process.env, logger = console, createAgentFn = null } = {}) {
15
- const autonomy = resolveAutonomy({ config, flags, env });
16
- const arbiter = autonomy === "interactive" ? null : createArbiter({ config, logger, createAgentFn });
17
- return { autonomy, resolve: createDecisionResolver({ autonomy, ask, arbiter, logger }) };
18
- }
@@ -1,58 +0,0 @@
1
- /**
2
- * autonomy/decision-resolver — the single choke point for every pipeline
3
- * question (KJC-TSK-0572, design in docs/specs/autonomous-delivery.md §5).
4
- *
5
- * Today the "ask a human" logic is scattered (spec-review, checkpoint,
6
- * reviewer, board-bridge). This unifies it: callers ask `resolveDecision`
7
- * instead of prompting directly, and the autonomy level decides who answers —
8
- * the human (`ask`) or the Arbiter (`arbiter`, injected by AUTO-B).
9
- *
10
- * INVARIANT: in `autonomous` mode the resolver NEVER returns a null choice and
11
- * NEVER blocks — if the Arbiter can't decide it degrades to the option flagged
12
- * `conservative` (or the first option). Decisions are always traced.
13
- */
14
-
15
- import { RISK, usesArbiter } from "./policy.js";
16
-
17
- /** Pick the safe fallback: the option flagged conservative, else the first. */
18
- function conservativeOf(options) {
19
- return options.find((o) => o.conservative) ?? options[0] ?? null;
20
- }
21
-
22
- function decision(choice, rationale, source) {
23
- return { choice: choice ?? null, rationale, source };
24
- }
25
-
26
- /**
27
- * Build a resolver bound to an autonomy level and its two answer sources.
28
- *
29
- * @param {object} opts
30
- * @param {string} opts.autonomy - interactive | assisted | autonomous
31
- * @param {(question: string, context?: object) => Promise<string|null>} [opts.ask] - human prompt
32
- * @param {(input: object) => Promise<{choice: string, rationale?: string}>} [opts.arbiter] - AUTO-B
33
- * @returns {(req: object) => Promise<{choice, rationale, source}>}
34
- */
35
- export function createDecisionResolver({ autonomy = "interactive", ask = null, arbiter = null, logger = console } = {}) {
36
- return async function resolveDecision({ question, options = [], context = null, risk = RISK.LOW } = {}) {
37
- const fallback = conservativeOf(options);
38
-
39
- // Human path: interactive, or assisted with a high-risk decision.
40
- if (!usesArbiter(autonomy, risk)) {
41
- const answer = ask ? await ask(question, context) : null;
42
- return decision(answer, "human", "human");
43
- }
44
-
45
- // Arbiter path: must always yield a valid choice, never block.
46
- if (!arbiter) return decision(fallback?.value, "no arbiter available → conservative", "fallback");
47
- let verdict;
48
- try {
49
- verdict = await arbiter({ question, options, context, risk });
50
- } catch (err) {
51
- logger.warn?.(`decision-resolver: arbiter failed (${err.message}) → conservative`);
52
- return decision(fallback?.value, "arbiter error → conservative", "fallback");
53
- }
54
- const valid = verdict && options.some((o) => o.value === verdict.choice);
55
- if (!valid) return decision(fallback?.value, "arbiter gave no valid choice → conservative", "fallback");
56
- return decision(verdict.choice, verdict.rationale ?? "arbiter", "arbiter");
57
- };
58
- }
@@ -1,55 +0,0 @@
1
- /**
2
- * outcome-report — the auditable "meets the ask, with known defects" report
3
- * for an autonomous run (KJC-TSK-0577, design in docs/specs/autonomous-delivery.md §10).
4
- *
5
- * Pure: builds a serializable outcome from the run results + Arbiter decisions,
6
- * and renders it as lines (or the structure is emitted as --json). The point is
7
- * that an imperfect-but-delivered result is explicit and auditable: which HUs
8
- * met the ask, what the Arbiter decided, and what debt remains.
9
- */
10
-
11
- /**
12
- * @param {object} opts
13
- * @param {string} [opts.planRef]
14
- * @param {boolean} opts.delivered - the run met the minimum ask
15
- * @param {Array<{id, title?, met: boolean, note?}>} [opts.hus]
16
- * @param {Array<{verdict, rationale, hu?, defect?}>} [opts.decisions] - Arbiter log
17
- */
18
- export function buildOutcome({ planRef = null, delivered = false, hus = [], decisions = [] } = {}) {
19
- const met = hus.filter((h) => h.met).length;
20
- const residualDefects = [
21
- ...hus.filter((h) => !h.met).map((h) => ({ hu: h.id, detail: h.note || "acceptance criteria not fully met" })),
22
- ...decisions.filter((d) => d.defect).map((d) => ({ hu: d.hu ?? null, detail: d.defect })),
23
- ];
24
- return {
25
- verdict: delivered ? "DELIVERED" : "INCOMPLETE",
26
- planRef,
27
- hus: { total: hus.length, met, unmet: hus.length - met },
28
- decisions,
29
- residualDefects,
30
- };
31
- }
32
-
33
- /** Render an outcome (from buildOutcome) as human-readable lines. */
34
- export function formatOutcomeReport(outcome) {
35
- const lines = [
36
- `kj autorun — outcome: ${outcome.verdict}`,
37
- ` plan: ${outcome.planRef ?? "?"}`,
38
- ` HUs: ${outcome.hus.met}/${outcome.hus.total} met the ask`,
39
- ];
40
- if (outcome.decisions?.length) {
41
- lines.push(" Decisions (Arbiter — least-bad calls):");
42
- for (const d of outcome.decisions) {
43
- lines.push(` • ${d.verdict}${d.hu ? ` [${d.hu}]` : ""} — ${d.rationale}`);
44
- }
45
- }
46
- if (outcome.residualDefects?.length) {
47
- lines.push(" Known defects (delivered with debt):");
48
- for (const def of outcome.residualDefects) {
49
- lines.push(` • ${def.hu ? `[${def.hu}] ` : ""}${def.detail}`);
50
- }
51
- } else {
52
- lines.push(" No residual defects recorded.");
53
- }
54
- return lines;
55
- }
@@ -1,30 +0,0 @@
1
- /**
2
- * createAutonomyAskQuestion — make the stages' question function non-blocking in
3
- * autonomous mode (KJC-TSK-0576, AUTO-E, design in docs/specs/autonomous-delivery.md §9).
4
- *
5
- * In `autonomous` no stage asks a human or routes to the HU Board: the wrapper
6
- * answers in-process with the least-bad "keep going" choice, so the run never
7
- * pauses or aborts mid-loop. interactive and assisted keep the human prompts
8
- * (baseAsk) unchanged.
9
- *
10
- * The answer is chosen per stage so the EXISTING branches proceed (verified
11
- * against the stage code — no stage logic is touched):
12
- * - architect clarification: null → the stage continues best-effort (a truthy
13
- * answer would force a wasteful architect re-run).
14
- * - everything else (Solomon escalation, checkpoint, …): "continue" → parsed
15
- * as free-text guidance → the stage continues instead of pausing/aborting.
16
- */
17
- export function createAutonomyAskQuestion({ baseAsk = null, autonomy = "interactive", logger = console } = {}) {
18
- if (autonomy !== "autonomous") return baseAsk;
19
- const auto = async (_question, context = {}) => {
20
- const stage = context?.stage ?? null;
21
- logger?.info?.(`[autonomy] ${stage ? `${stage}: ` : ""}auto-continue (no human in the loop)`);
22
- return stage === "architect" ? null : "continue";
23
- };
24
- auto.interactive = false;
25
- // Marker so the orchestrator can tell an autonomous (unattended) run from an
26
- // interactive one even though both carry a truthy askQuestion — the wall-clock
27
- // backstop relies on it (KJC-TSK-0575, AUTO-D).
28
- auto.unattended = true;
29
- return auto;
30
- }