karajan-code 4.70.4 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) 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/register-roles-skills.js +1 -1
  68. package/src/cli/retired-commands.js +49 -0
  69. package/src/cli.js +18 -5
  70. package/src/commands/agent-run.js +40 -26
  71. package/src/commands/audit.js +127 -124
  72. package/src/commands/board.js +5 -9
  73. package/src/commands/check.js +29 -16
  74. package/src/commands/doctor.js +2 -0
  75. package/src/commands/env.js +176 -150
  76. package/src/commands/go.js +71 -53
  77. package/src/commands/harden.js +90 -81
  78. package/src/commands/hu-start.js +52 -0
  79. package/src/commands/hu.js +288 -221
  80. package/src/commands/identity.js +111 -78
  81. package/src/commands/init-atril.js +47 -0
  82. package/src/commands/init.js +11 -40
  83. package/src/commands/install-tools.js +70 -85
  84. package/src/commands/main-guard.js +78 -0
  85. package/src/commands/policy.js +226 -184
  86. package/src/commands/qmd.js +27 -21
  87. package/src/commands/rag.js +121 -55
  88. package/src/commands/review-gate.js +421 -341
  89. package/src/commands/skills.js +4 -1
  90. package/src/commands/start.js +4 -5
  91. package/src/commands/steward.js +96 -47
  92. package/src/commands/tournament.js +46 -37
  93. package/src/commands/worktree.js +107 -26
  94. package/src/config/defaults.js +1 -0
  95. package/src/config/loader.js +34 -17
  96. package/src/config/role-resolver.js +1 -0
  97. package/src/config/schema.js +1 -0
  98. package/src/config/secrets.js +36 -0
  99. package/src/config.js +1 -0
  100. package/src/environment/adr.js +16 -2
  101. package/src/git/karajan-label.js +20 -8
  102. package/src/guards/main-guard.js +54 -0
  103. package/src/harden/hook-templates.js +16 -1
  104. package/src/harden/sentinel/posttooluse.mjs +18 -6
  105. package/src/harden/sentinel/pretooluse-sentinel.mjs +64 -36
  106. package/src/harden/sentinel/sentinel-lib.mjs +129 -26
  107. package/src/harden/sentinel/sentinel-shell.mjs +5 -16
  108. package/src/harden/sentinel/sessionstart.mjs +3 -2
  109. package/src/harden/sentinel/stop.mjs +5 -4
  110. package/src/harden/workflow-templates.js +1 -1
  111. package/src/hu/board-lookup.js +29 -0
  112. package/src/hu/gh-identity.js +23 -0
  113. package/src/hu/github-board.js +4 -2
  114. package/src/hu/lane-prune.js +83 -13
  115. package/src/hu/lane-setup.js +65 -0
  116. package/src/hu/lanes.js +66 -0
  117. package/src/hu/team-board-mirror.js +3 -2
  118. package/src/infrastructure/command-runner.js +1 -1
  119. package/src/infrastructure/file-system-service.js +1 -1
  120. package/src/mcp/handlers/direct-handlers.js +2 -292
  121. package/src/mcp/handlers/hu-handlers.js +1 -35
  122. package/src/mcp/handlers/management-handlers.js +2 -42
  123. package/src/mcp/handlers/rag-handler.js +9 -1
  124. package/src/mcp/server-handlers.js +16 -22
  125. package/src/mcp/tools.js +1 -196
  126. package/src/plan/lane-plans.js +54 -0
  127. package/src/plan/plan-store.js +7 -4
  128. package/src/policy/add.js +26 -12
  129. package/src/policy/adr-number-check.js +31 -0
  130. package/src/prompts/audit.js +299 -339
  131. package/src/prompts/card-context.js +10 -5
  132. package/src/prompts/reviewer.js +5 -2
  133. package/src/rag/auto-update.js +71 -44
  134. package/src/rag/bootstrap-index.js +46 -54
  135. package/src/rag/indexer.js +9 -4
  136. package/src/rag/migrate.js +1 -1
  137. package/src/rag/onnx-fallback.js +2 -2
  138. package/src/rag/pid-lease.js +181 -0
  139. package/src/rag/project-store.js +2 -12
  140. package/src/review/card-first.js +57 -46
  141. package/src/review/gate-gitignore.js +23 -4
  142. package/src/review/gate-hook.js +12 -4
  143. package/src/review/one-shot-review.js +45 -35
  144. package/src/review/publish-pr.js +14 -2
  145. package/src/review/repo-docs.js +73 -0
  146. package/src/review/repo-stack.js +59 -0
  147. package/src/review/reviewer-fallback.js +19 -4
  148. package/src/review/seal-commit.js +29 -0
  149. package/src/review/sonar-pregate.js +59 -44
  150. package/src/review/third-party-review.js +90 -16
  151. package/src/review/third-party-size.js +43 -0
  152. package/src/review/third-party-skills.js +54 -0
  153. package/src/review/verify-pr.js +1 -24
  154. package/src/roles/audit-role.js +106 -125
  155. package/src/skills/atril-cli.js +19 -1
  156. package/src/skills/atril-skills.js +5 -4
  157. package/src/skills/skills-search.js +72 -0
  158. package/src/skills/translate.js +62 -0
  159. package/src/sonar/scanner.js +116 -101
  160. package/src/steward/invariants.js +5 -4
  161. package/src/steward/phantom-sweep.js +66 -0
  162. package/src/tournament/judge.js +60 -53
  163. package/src/utils/gh-account.js +37 -0
  164. package/src/utils/git.js +0 -13
  165. package/src/utils/home-migration.js +7 -1
  166. package/src/utils/main-checkout.js +53 -0
  167. package/src/utils/qmd-collection.js +3 -1
  168. package/src/utils/welcome.js +3 -3
  169. package/templates/{skills → atril/commands}/kj-architect.md +5 -0
  170. package/templates/{skills → atril/commands}/kj-audit.md +5 -0
  171. package/templates/{skills → atril/commands}/kj-board.md +5 -0
  172. package/templates/{skills → atril/commands}/kj-code.md +5 -0
  173. package/templates/{skills → atril/commands}/kj-csv-transform.md +5 -0
  174. package/templates/{skills → atril/commands}/kj-data-report.md +5 -0
  175. package/templates/{skills → atril/commands}/kj-discover.md +5 -0
  176. package/templates/{skills → atril/commands}/kj-rag-query.md +5 -0
  177. package/templates/{skills → atril/commands}/kj-review.md +5 -0
  178. package/templates/{skills → atril/commands}/kj-security.md +5 -0
  179. package/templates/{skills → atril/commands}/kj-sonar.md +5 -0
  180. package/templates/{skills → atril/commands}/kj-sql-analysis.md +5 -0
  181. package/templates/{skills → atril/commands}/kj-test.md +5 -0
  182. package/packages/hu-board/public/utils/run-launcher.js +0 -169
  183. package/packages/hu-board/src/run-tracker.js +0 -121
  184. package/src/activity-log.js +0 -59
  185. package/src/agents/host-agent.js +0 -38
  186. package/src/agents/model-registry.js +0 -142
  187. package/src/audit/plan-adherence.js +0 -224
  188. package/src/autonomy/arbiter-role.js +0 -71
  189. package/src/autonomy/arbiter.js +0 -22
  190. package/src/autonomy/decider.js +0 -18
  191. package/src/autonomy/decision-resolver.js +0 -58
  192. package/src/autonomy/outcome-report.js +0 -55
  193. package/src/autonomy/stage-ask.js +0 -30
  194. package/src/brain/decision-tracker.js +0 -125
  195. package/src/brain/decisor.js +0 -243
  196. package/src/brain/solomon-consult.js +0 -171
  197. package/src/brain/standby-scheduler.js +0 -8
  198. package/src/budget/comparison.js +0 -96
  199. package/src/canvas/parse-md.js +0 -238
  200. package/src/canvas/schema.js +0 -101
  201. package/src/canvas/to-flat.js +0 -85
  202. package/src/canvas/validate.js +0 -163
  203. package/src/ci/dispatch.js +0 -99
  204. package/src/ci/index.js +0 -3
  205. package/src/ci/pr-diff.js +0 -26
  206. package/src/cli/register-standby.js +0 -26
  207. package/src/commands/architect.js +0 -111
  208. package/src/commands/autorun.js +0 -49
  209. package/src/commands/researcher.js +0 -54
  210. package/src/commands/resume.js +0 -72
  211. package/src/commands/review.js +0 -89
  212. package/src/commands/run.js +0 -185
  213. package/src/commands/standby.js +0 -117
  214. package/src/commands/status.js +0 -36
  215. package/src/commands/triage.js +0 -78
  216. package/src/commands/undo.js +0 -62
  217. package/src/domains/domain-loader.js +0 -245
  218. package/src/domains/domain-registry.js +0 -140
  219. package/src/domains/domain-synthesizer.js +0 -129
  220. package/src/git/automation.js +0 -433
  221. package/src/git/coder-commit-guard.js +0 -40
  222. package/src/git/hu-automation.js +0 -243
  223. package/src/git/hu-snapshot.js +0 -10
  224. package/src/git/symlink-targets.js +0 -57
  225. package/src/golden/asserter.js +0 -92
  226. package/src/golden/loader.js +0 -52
  227. package/src/golden/runner.js +0 -92
  228. package/src/golden/schema.js +0 -41
  229. package/src/guards/duplicate-members.js +0 -86
  230. package/src/guards/intent-guard.js +0 -161
  231. package/src/guards/perf-guard.js +0 -126
  232. package/src/guards/policy-guard.js +0 -90
  233. package/src/guards/policy-resolver.js +0 -85
  234. package/src/guards/secret-redactor.js +0 -71
  235. package/src/hu/acceptance-runner.js +0 -138
  236. package/src/hu/lazy-planner.js +0 -109
  237. package/src/hu/parallel-executor.js +0 -94
  238. package/src/hu/routing-metrics.js +0 -17
  239. package/src/hu/split-validator.js +0 -143
  240. package/src/hu/splitting-detector.js +0 -158
  241. package/src/hu/splitting-generator.js +0 -175
  242. package/src/hu/store.js +0 -394
  243. package/src/infrastructure/mocks.js +0 -182
  244. package/src/mcp/handlers/run-handler.js +0 -318
  245. package/src/mcp/sovereignty-guard.js +0 -113
  246. package/src/mcp/tool-arg-normalizers.js +0 -16
  247. package/src/mutate/reviewer-signal.js +0 -76
  248. package/src/orchestrator/agent-fallback.js +0 -81
  249. package/src/orchestrator/brain-coordinator.js +0 -186
  250. package/src/orchestrator/ci-integration.js +0 -139
  251. package/src/orchestrator/config-init.js +0 -426
  252. package/src/orchestrator/direct-actions.js +0 -217
  253. package/src/orchestrator/drivers/error-recovery.js +0 -287
  254. package/src/orchestrator/drivers/init-context.js +0 -238
  255. package/src/orchestrator/drivers/iteration-loop.js +0 -382
  256. package/src/orchestrator/drivers/iteration-phases/coder-and-refactorer.js +0 -69
  257. package/src/orchestrator/drivers/iteration-phases/guards.js +0 -91
  258. package/src/orchestrator/drivers/iteration-phases/handle-approved.js +0 -29
  259. package/src/orchestrator/drivers/iteration-phases/quality-gates.js +0 -125
  260. package/src/orchestrator/drivers/iteration-phases/reviewer-gate.js +0 -62
  261. package/src/orchestrator/drivers/post-loop.js +0 -404
  262. package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +0 -137
  263. package/src/orchestrator/drivers/pre-loop-phases/config-deprecations.js +0 -47
  264. package/src/orchestrator/drivers/pre-loop-phases/ensure-addyosmani-skills.js +0 -84
  265. package/src/orchestrator/drivers/pre-loop-phases/inject-loaded-plan.js +0 -393
  266. package/src/orchestrator/drivers/pre-loop.js +0 -524
  267. package/src/orchestrator/drivers/run-hu-batch.js +0 -468
  268. package/src/orchestrator/feedback-enrichment.js +0 -140
  269. package/src/orchestrator/feedback-queue.js +0 -151
  270. package/src/orchestrator/flow-control.js +0 -170
  271. package/src/orchestrator/flow-runner.js +0 -365
  272. package/src/orchestrator/fs-leak-detector.js +0 -228
  273. package/src/orchestrator/hu-scheduler.js +0 -114
  274. package/src/orchestrator/hu-sub-pipeline.js +0 -642
  275. package/src/orchestrator/iteration-gate.js +0 -73
  276. package/src/orchestrator/iteration-stages.js +0 -9
  277. package/src/orchestrator/parallel-limiter.js +0 -74
  278. package/src/orchestrator/pipeline-context.js +0 -72
  279. package/src/orchestrator/post-loop-stages.js +0 -468
  280. package/src/orchestrator/pre-loop-stages.js +0 -11
  281. package/src/orchestrator/preflight-checks.js +0 -487
  282. package/src/orchestrator/repair/repair-detector.js +0 -117
  283. package/src/orchestrator/repair/repair-runner.js +0 -142
  284. package/src/orchestrator/reviewer-fallback.js +0 -45
  285. package/src/orchestrator/role-output-compressor.js +0 -189
  286. package/src/orchestrator/session-journal.js +0 -308
  287. package/src/orchestrator/solomon-escalation.js +0 -331
  288. package/src/orchestrator/solomon-rules.js +0 -212
  289. package/src/orchestrator/stages/acceptance-coverage-stage.js +0 -47
  290. package/src/orchestrator/stages/architect-stage.js +0 -172
  291. package/src/orchestrator/stages/coder-stage.js +0 -506
  292. package/src/orchestrator/stages/domain-curator-stage.js +0 -82
  293. package/src/orchestrator/stages/format-stage.js +0 -61
  294. package/src/orchestrator/stages/hu-reviewer-phases/detect-and-apply-splits.js +0 -127
  295. package/src/orchestrator/stages/hu-reviewer-stage.js +0 -419
  296. package/src/orchestrator/stages/perf-stage.js +0 -140
  297. package/src/orchestrator/stages/planner-stage.js +0 -85
  298. package/src/orchestrator/stages/rag-context-stage.js +0 -80
  299. package/src/orchestrator/stages/rag-preload-decisor.js +0 -58
  300. package/src/orchestrator/stages/research-stage.js +0 -69
  301. package/src/orchestrator/stages/reviewer-stage.js +0 -431
  302. package/src/orchestrator/stages/sonar-stage.js +0 -439
  303. package/src/orchestrator/stages/stage-classes.js +0 -84
  304. package/src/orchestrator/stages/stage-executor.js +0 -155
  305. package/src/orchestrator/stages/suite-green-stage.js +0 -62
  306. package/src/orchestrator/stages/tdd-discipline-stage.js +0 -56
  307. package/src/orchestrator/stages/tool-judge-stage.js +0 -53
  308. package/src/orchestrator/stages/triage-stage.js +0 -172
  309. package/src/orchestrator/standby.js +0 -71
  310. package/src/orchestrator/verification-gate.js +0 -183
  311. package/src/orchestrator.js +0 -22
  312. package/src/plan/adr-generator.js +0 -170
  313. package/src/plan/adr-loader.js +0 -60
  314. package/src/plan/plan-executor.js +0 -100
  315. package/src/plan/plan-validation.js +0 -4
  316. package/src/prompts/acceptance-coverage.js +0 -32
  317. package/src/prompts/arbiter.js +0 -38
  318. package/src/prompts/architect.js +0 -103
  319. package/src/prompts/hu-reviewer.js +0 -244
  320. package/src/prompts/tool-correctness-judge.js +0 -31
  321. package/src/prompts/triage.js +0 -57
  322. package/src/rag/embedder.js +0 -2
  323. package/src/rag/embedders/_cloud-base.js +0 -2
  324. package/src/rag/embedders/cohere.js +0 -2
  325. package/src/rag/embedders/mistral.js +0 -2
  326. package/src/rag/embedders/onnx.js +0 -2
  327. package/src/rag/embedders/openai.js +0 -2
  328. package/src/rag/embedders/voyage.js +0 -2
  329. package/src/rag/rerank.js +0 -4
  330. package/src/rag/where-parser.js +0 -4
  331. package/src/repeat-detector.js +0 -88
  332. package/src/review/diff-generator.js +0 -112
  333. package/src/review/git-stash-helper.js +0 -104
  334. package/src/review/schema.js +0 -31
  335. package/src/review/scope-filter.js +0 -152
  336. package/src/review/snapshot-diff.js +0 -122
  337. package/src/review/tdd-discipline.js +0 -90
  338. package/src/review/tdd-policy.js +0 -69
  339. package/src/roles/acceptance-coverage-role.js +0 -78
  340. package/src/roles/architect-role.js +0 -77
  341. package/src/roles/coder-role.js +0 -113
  342. package/src/roles/commiter-role.js +0 -113
  343. package/src/roles/domain-curator-role.js +0 -134
  344. package/src/roles/hu-reviewer-role.js +0 -64
  345. package/src/roles/impeccable-role.js +0 -85
  346. package/src/roles/index.js +0 -18
  347. package/src/roles/karajan-brain-role.js +0 -134
  348. package/src/roles/perf-role.js +0 -122
  349. package/src/roles/planner-role.js +0 -151
  350. package/src/roles/refactorer-role.js +0 -30
  351. package/src/roles/repairer-role.js +0 -181
  352. package/src/roles/researcher-role.js +0 -70
  353. package/src/roles/reviewer-role.js +0 -115
  354. package/src/roles/security-role.js +0 -73
  355. package/src/roles/solomon-role.js +0 -271
  356. package/src/roles/sonar-role.js +0 -72
  357. package/src/roles/tester-role.js +0 -235
  358. package/src/roles/tool-correctness-judge-role.js +0 -78
  359. package/src/roles/triage-role.js +0 -99
  360. package/src/session/journal/decisions-writer.js +0 -200
  361. package/src/session/journal/iteration-logger.js +0 -194
  362. package/src/session/journal/summary-writer.js +0 -320
  363. package/src/session/journal/tree-writer.js +0 -164
  364. package/src/session/journal/write-all.js +0 -89
  365. package/src/session-cleanup.js +0 -116
  366. package/src/skills/semantic-detector.js +0 -167
  367. package/src/skills/skill-detector.js +0 -385
  368. package/src/sonar/cloud-scanner.js +0 -78
  369. package/src/tracker-bootstrap.js +0 -44
  370. package/src/types/index.js +0 -38
  371. package/src/types/policy.js +0 -43
  372. package/src/types/solomon.js +0 -87
  373. package/src/utils/async-lock.js +0 -31
  374. package/src/utils/budget.js +0 -229
  375. package/src/utils/cwd-confirm.js +0 -39
  376. package/src/utils/display/event-handlers.js +0 -403
  377. package/src/utils/display/formatters.js +0 -132
  378. package/src/utils/display/header.js +0 -47
  379. package/src/utils/display/session-summary.js +0 -118
  380. package/src/utils/display/solomon.js +0 -42
  381. package/src/utils/pricing.js +0 -29
  382. package/src/utils/quota-simulator.js +0 -56
  383. package/src/utils/role-assigner.js +0 -137
  384. package/src/utils/rtk-wrapper.js +0 -87
  385. package/src/utils/run-registry.js +0 -9
  386. package/src/utils/status-dashboard.js +0 -254
  387. package/src/utils/tool-call-extractor.js +0 -56
  388. package/src/webperf/devtools-detect.js +0 -112
  389. package/src/webperf/webperf-role-integration.js +0 -66
  390. 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
- }