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,8 +1,9 @@
1
1
  import { initCommand } from "../commands/init.js";
2
2
  import { ollamaStartCommand, ollamaStopCommand, ollamaStatusCommand, ollamaPullCommand } from "../commands/ollama.js";
3
3
  import { configCommand } from "../commands/config.js";
4
+ import { checkSecretsCommand } from "../config/secrets.js";
4
5
  import { codeCommand } from "../commands/code.js";
5
- import { reviewCommand } from "../commands/review.js";
6
+ import { retire } from "./retired-commands.js";
6
7
  import { tournamentCommand } from "../commands/tournament.js";
7
8
  import { resolveTaskInput } from "../utils/task-file.js";
8
9
  import { reviewGateCommand, solomonCommand } from "../commands/review-gate.js";
@@ -10,9 +11,6 @@ import { scanCommand } from "../commands/scan.js";
10
11
  import { installToolsCommand } from "../commands/install-tools.js";
11
12
  import { doctorCommand } from "../commands/doctor.js";
12
13
  import { reportCommand } from "../commands/report.js";
13
- import { runCommandHandler } from "../commands/run.js";
14
- import { statusCommand } from "../commands/status.js";
15
- import { loadPlan } from "../plan/plan-store.js";
16
14
  import { withConfig } from "./_shared.js";
17
15
  import { publishPrReview } from "../review/publish-pr.js";
18
16
  import { verifyPrReview } from "../review/verify-pr.js";
@@ -52,139 +50,15 @@ export function registerPipeline(program, { pkgVersion }) {
52
50
  .description("Show current config")
53
51
  .option("--json", "Show as JSON")
54
52
  .option("--edit", "Open config in $EDITOR for editing")
53
+ .option("--check-secrets <file>", "Exit 1 when a project kj.config.yml (or - for stdin) holds a secret (ADR 0032)")
55
54
  .action(async (flags) => {
55
+ if (flags.checkSecrets) return checkSecretsCommand(flags.checkSecrets);
56
56
  await configCommand(flags);
57
57
  });
58
58
 
59
- program
60
- .command("run")
61
- .description("Run coder+sonar+reviewer loop")
62
- .argument("[task]", "Task description (REQUIRED — provide as argument or via --task-file)")
63
- .option("--task-file <path>", "Read the task from a file (e.g. .md). Alternative to the positional task argument.")
64
- .option("-y, --yes", "Skip the cwd confirmation prompt (CI / scripted runs).")
65
- .option("--non-interactive", "Agents/CI: auto-answer prompts with their safe defaults (warn → continue) and stop with exit code 1 when there is none (fail). Also enabled by KJ_NON_INTERACTIVE=1.")
66
- .option("--planner <name>")
67
- .option("--coder <name>")
68
- .option("--reviewer <name>")
69
- .option("--refactorer <name>")
70
- .option("--planner-model <name>")
71
- .option("--coder-model <name>")
72
- .option("--reviewer-model <name>")
73
- .option("--refactorer-model <name>")
74
- .option("--profile <name>", "Model profile for every role without an explicit model: frugal | standard | deep (the reviewer never goes below standard)")
75
- .option("--enable-planner")
76
- .option("--enable-reviewer")
77
- .option("--enable-refactorer")
78
- .option("--enable-researcher")
79
- .option("--enable-tester")
80
- .option("--enable-security")
81
- .option("--enable-impeccable")
82
- .option("--enable-perf")
83
- .option("--enable-triage")
84
- .option("--enable-discover")
85
- .option("--enable-architect")
86
- .option("--plan <planId>", "Plan ID from kj plan. Loads persisted plan context and skips researcher/architect/planner.")
87
- // PR4: launch a single HU (or comma-separated list) instead of the
88
- // entire plan. The board uses this for the per-HU ▶ button so the
89
- // user can re-run only a failed HU without restarting the whole
90
- // plan. Requires --plan to also be set.
91
- .option("--hu <huIds>", "Comma-separated HU IDs to run. When set, the plan's other HUs are skipped. Requires --plan.")
92
- .option("--enable-hu-reviewer")
93
- .option("--hu-file <path>", "YAML file with HU stories to certify before coding")
94
- .option("--enable-serena")
95
- .option("--mode <name>")
96
- .option("--max-iterations <n>")
97
- .option("--max-iteration-minutes <n>")
98
- .option("--max-total-minutes <n>")
99
- .option("--base-branch <name>")
100
- .option("--base-ref <ref>")
101
- .option("--coder-fallback <name>")
102
- .option("--reviewer-fallback <name>")
103
- .option("--reviewer-retries <n>")
104
- .option("--auto-commit")
105
- .option("--auto-push")
106
- .option("--auto-pr")
107
- .option("--enable-ci", "Enable Karajan CI (early PR + dispatch comments/reviews)")
108
- .option("--branch-prefix <prefix>")
109
- .option("--task-type <type>", "Explicit task type: sw, infra, doc, add-tests, refactor")
110
- .option("--methodology <name>")
111
- .option("--no-auto-rebase")
112
- .option("--no-sonar")
113
- .option("--enable-sonarcloud", "Enable SonarCloud scan (complementary to SonarQube)")
114
- .option("--no-sonarcloud")
115
- .option("--checkpoint-interval <n>", "Minutes between interactive checkpoints (default: 5)")
116
- .option("--step", "Pause after each iteration with a report and ask before continuing")
117
- .option("--parallel <n>", "Concurrent HU lanes for plan runs (default: 1, sequential)")
118
- .option("--pg-task <cardId>", "Planning Game card ID (e.g., KJC-TSK-0042)")
119
- .option("--pg-project <projectId>", "Planning Game project ID")
120
- .option("--auto-simplify", "Auto-simplify pipeline for simple tasks (disable reviewer/tester)")
121
- .option("--no-auto-simplify", "Force full pipeline regardless of triage level")
122
- .option("--smart-models", "Enable smart model selection based on triage complexity")
123
- .option("--no-smart-models", "Disable smart model selection")
124
- .option("--design", "Activate design refactoring mode (impeccable role applies design changes)")
125
- .option("--domain <text-or-path>", "Domain knowledge: inline text or path to .md file")
126
- .option("--skills-mode <mode>", "Skill detection mode: auto|regex|semantic|none (default: auto)")
127
- .option("--brain <mode>", "Brain decisor: on|off (default: on). When off, only legacy flags drive routing.")
128
- .option("--skip-role <role...>", "Force one or more roles OFF regardless of triage (e.g. --skip-role tester security)")
129
- .option("--force-role <role...>", "Force one or more roles ON regardless of triage")
130
- .option("--skip-spec-review", "Bypass the spec-reviewer pre-pipeline audit")
131
- .option("--autonomy <level>", "Autonomy level: interactive | assisted | autonomous (default: interactive)")
132
- .option("--autonomous", "Shortcut for --autonomy autonomous: the Arbiter resolves every gate, no human prompts")
133
- .option("--no-rag-update", "Skip the pre-run RAG drift check (KJC-TSK-0455). Same as config.rag.autoUpdate.onRun=false.")
134
- .option("--dry-run", "Show what would be executed without running anything")
135
- .option("--json", "Output JSON only (no styled display)")
136
- .option("-q, --quiet", "Show only stage status lines, suppress raw agent output (default)")
137
- .option("-v, --verbose", "Show full agent output (stream-json, raw lines)")
138
- .action(async (task, flags) => {
139
- // KJC-BUG-0448: run's --profile is the model profile; harden and check use
140
- // --profile for the harness, so the config loader reads modelProfile.
141
- if (flags.profile) flags.modelProfile = flags.profile;
142
- await withConfig(pkgVersion, "run", flags, async ({ config, logger }) => {
143
- // If `--plan <id>` was passed and the user didn't provide a task
144
- // argument or --task-file, fall back to the task embedded in the
145
- // plan JSON. The whole point of `kj plan generate` is that the
146
- // task is captured once and re-used; forcing the user to repeat
147
- // --task-file on every run is friction with no upside.
148
- let effectiveTask = task;
149
- if (!task && !flags.taskFile && flags.plan) {
150
- // config.projectDir is only populated post-init; before runFlow
151
- // it can still be undefined. Plans are stored under cwd, so
152
- // that's the correct fallback for the lookup.
153
- const projectDir = config.projectDir || process.cwd();
154
- const plan = await loadPlan(projectDir, flags.plan);
155
- if (plan?.task && String(plan.task).trim()) {
156
- effectiveTask = plan.task;
157
- }
158
- }
159
- const resolvedTask = await resolveTaskInput({ task: effectiveTask, taskFile: flags.taskFile, projectDir: config.projectDir, logger, indexFirstBytes: config.docs?.indexFirstBytes });
160
- const res = await runCommandHandler({ task: resolvedTask, config, logger, flags });
161
- // KJC-TSK-0674 (issue #1289): an aborted run (spec-review cancel,
162
- // unanswerable non-interactive gate) must be observable by CI.
163
- if (res?.aborted) process.exitCode = 1;
164
- });
165
- });
166
-
167
- program
168
- .command("autorun")
169
- .description("Unattended delivery: spec → plan → run all HUs → outcome (defaults to --autonomous)")
170
- .argument("[task]", "Spec/task description (or use --task-file)")
171
- .option("--task-file <path>", "Read the spec from a file (e.g. spec.md)")
172
- .option("--autonomy <level>", "interactive | assisted | autonomous (default: autonomous)")
173
- .option("--autonomous", "Shortcut for --autonomy autonomous")
174
- .option("--skip-spec-review", "Bypass the spec-reviewer pre-pipeline audit")
175
- .action(async (task, flags) => {
176
- const code = await withConfig(pkgVersion, "autorun", flags, async ({ config, logger }) => {
177
- const { autorunCommand } = await import("../commands/autorun.js");
178
- const resolvedTask = await resolveTaskInput({ task, taskFile: flags.taskFile, projectDir: config.projectDir, logger });
179
- const res = await autorunCommand({ task: resolvedTask, config, logger, flags });
180
- return res?.ok ? 0 : 1;
181
- });
182
- if (Number.isInteger(code)) process.exit(code);
183
- });
184
-
185
59
  program
186
60
  .command("code")
187
- .description("Run only coder")
61
+ .description("Have the coder declared in your panel write (--agent, --card)")
188
62
  .argument("[task]", "Task description (REQUIRED — provide as argument or via --task-file)")
189
63
  .option("--task-file <path>", "Read the task from a file (e.g. .md)")
190
64
  .option("--coder <name>")
@@ -245,8 +119,8 @@ export function registerPipeline(program, { pkgVersion }) {
245
119
 
246
120
  program
247
121
  .command("review")
248
- .description("Run only reviewer (--staged/--check: v4 cross-AI gate with recorded verdict)")
249
- .argument("[task]", "Task description (REQUIRED — provide as argument or via --task-file)")
122
+ .description("Cross-AI review gate: --staged/--check/--range record a verdict tied to the exact diff")
123
+ .argument("[task]", "What the change does, for the reviewer (optional; or via --task-file)")
250
124
  .option("--task-file <path>", "Read the task from a file (e.g. .md)")
251
125
  .option("--reviewer <name>")
252
126
  .option("--reviewer-model <name>")
@@ -310,8 +184,7 @@ export function registerPipeline(program, { pkgVersion }) {
310
184
  await reviewGateCommand({ config, logger, flags: { ...flags, task: gateTask } });
311
185
  return;
312
186
  }
313
- const resolvedTask = await resolveTaskInput({ task, taskFile: flags.taskFile, projectDir: config.projectDir, logger });
314
- await reviewCommand({ task: resolvedTask, config, logger, baseRef: flags.baseRef });
187
+ retire("review");
315
188
  });
316
189
  });
317
190
 
@@ -364,14 +237,6 @@ export function registerPipeline(program, { pkgVersion }) {
364
237
  }
365
238
  });
366
239
 
367
- program
368
- .command("status")
369
- .description("Show pipeline dashboard with HU progress")
370
- .option("-n, --lines <n>", "Max log lines to read", "50")
371
- .action(async (flags) => {
372
- await statusCommand({ lines: Number(flags.lines) });
373
- });
374
-
375
240
  program
376
241
  .command("report")
377
242
  .description("Show latest session report")
@@ -1,5 +1,4 @@
1
1
  import {
2
- planGenerateCommand,
3
2
  planListCommand,
4
3
  planShowCommand,
5
4
  planReadyCommand,
@@ -13,113 +12,23 @@ import {
13
12
  planUnshareCommand,
14
13
  } from "../commands/plan.js";
15
14
  import { planLicenseCommand } from "../commands/plan/license.js";
16
- import { parseCanvasMarkdown } from "../canvas/parse-md.js";
17
- import { validateCanvas } from "../canvas/validate.js";
18
- import { canvasToTask } from "../canvas/to-flat.js";
19
15
  import { withConfig } from "./_shared.js";
16
+ import { retire } from "./retired-commands.js";
20
17
 
21
18
  /**
22
19
  * Register the `plan` parent command and every sub-command that lives
23
- * under it (generate / list / show / ready / validate / delete /
24
- * add-hu / remove-hu). Centralising plan management here keeps the
25
- * REASONS Canvas auto-detection logic in one file alongside the
26
- * planner entrypoint.
20
+ * under it (list / show / ready / validate / delete / add-hu / remove-hu...).
27
21
  */
28
22
  export function registerPlan(program, { pkgVersion }) {
29
- const plan = program.command("plan").description("Plan management (generate, review, approve, execute)");
23
+ const plan = program.command("plan").description("Plan management (list, show, validate, approve)");
30
24
 
25
+ // KJC-TSK-1317: retired in 5.0; it answers to say what replaced it.
31
26
  plan
32
- .command("generate", { isDefault: true })
33
- .description("Generate implementation plan with HUs")
34
- .argument("[task]", "Task description (REQUIRED — provide as argument or via --task-file)")
35
- .option("--task-file <path>", "Read the task from a file (e.g. .md)")
36
- .option("--planner <name>")
37
- .option("--planner-model <name>")
38
- .option("--context <text>", "Additional context for the planner")
39
- .option("--json", "Output raw JSON plan")
40
- // Tests-first quality knobs (v2.7.5). Default is "thorough":
41
- // when the planner skips acceptance_tests on some HUs, run a
42
- // focused synthesizer pass to fill them in. Disable with these
43
- // flags only if you explicitly want a fast / sketch plan.
44
- .option("--no-tests-synth", "Skip the tests-synthesizer pass that fills in missing acceptance_tests")
45
- .option("--no-plan-review", "Skip the high-level plan reviewer pass (gaps / deps / overlap / order)")
46
- .option("--skip-spec-review", "Bypass the spec-reviewer pre-pipeline audit")
47
- .option("--quick", "Sketch mode — skip every quality pass after the initial planner call")
48
- .option("--no-preflight-hu", "Skip auto-injection of [PREFLIGHT-000] HU at the top of the generated plan")
49
- .option("--use-onboarding", "Inject the cached Architecture Brief (~/.karajan/onboarding/<slug>.md) into the planner context")
50
- .option("-y, --yes", "Skip the project-name prompt (use the auto-derived default).")
51
- .option("--no-interactive", "Force non-interactive mode (no prompts, use defaults).")
52
- .action(async (task, flags) => {
53
- await withConfig(pkgVersion, "plan", flags, async ({ config, logger }) => {
54
- const { resolveTaskInput } = await import("../utils/task-file.js");
55
- const resolvedTask = await resolveTaskInput({ task, taskFile: flags.taskFile, projectDir: config.projectDir, logger, indexFirstBytes: config.docs?.indexFirstBytes });
56
-
57
- // REASONS Canvas auto-detection: a SPEC that contains
58
- // `## REASONS:Section` headings is treated as a structured
59
- // Canvas — parsed + validated BEFORE the planner runs. This
60
- // catches broken acceptance tests (jq syntax, bash parse,
61
- // gherkin missing Given/Then, the 2026-04-29 as-binding
62
- // misuse class) at plan-time, without spending LLM dollars.
63
- //
64
- // Detection by file CONTENTS, not by CLI flag — the Canvas
65
- // format is the signal. Flat SPECs without REASONS sections
66
- // continue through the legacy path unchanged (back-compat).
67
- if (typeof resolvedTask === "string" && /^##\s+REASONS:/m.test(resolvedTask)) {
68
- let parsed;
69
- try {
70
- parsed = parseCanvasMarkdown(resolvedTask);
71
- } catch (err) {
72
- throw new Error(`Canvas parse error: ${err.message}`, { cause: err });
73
- }
74
- const validation = validateCanvas(parsed);
75
- if (!validation.valid) {
76
- const lines = ["Canvas validation failed."];
77
- if (validation.schemaIssues) {
78
- lines.push("Schema issues:");
79
- for (const issue of validation.schemaIssues) {
80
- lines.push(` - ${issue.path?.map((p) => p.key).join(".") || "(root)"}: ${issue.message}`);
81
- }
82
- }
83
- if (validation.testIssues) {
84
- lines.push("Acceptance test issues:");
85
- for (const issue of validation.testIssues) {
86
- lines.push(` - Operation #${issue.operationIndex + 1} "${issue.operationTitle}", test #${issue.testIndex + 1} (${issue.type}, ${issue.kind}):`);
87
- lines.push(` ${issue.content}`);
88
- lines.push(` → ${issue.error}`);
89
- }
90
- }
91
- throw new Error(lines.join("\n"));
92
- }
93
- // Pass the Canvas-derived flat task to the existing planner.
94
- // Norms + Safeguards ride along under explicit headings the
95
- // coder prompt can grep for.
96
- const taskFromCanvas = canvasToTask(validation.canvas);
97
- // KJC-TSK-0348: remember WHERE the Canvas lived on disk so
98
- // `kj sync --apply` later knows which file to patch.
99
- let sourceCanvasPath = null;
100
- if (typeof flags?.taskFile === "string" && flags.taskFile.length > 0) {
101
- const path = await import("node:path");
102
- sourceCanvasPath = path.isAbsolute(flags.taskFile)
103
- ? flags.taskFile
104
- : path.resolve(config.projectDir || process.cwd(), flags.taskFile);
105
- }
106
- await planGenerateCommand({ task: taskFromCanvas, config, logger, flags, sourceCanvasPath });
107
- return;
108
- }
109
- await planGenerateCommand({
110
- task: resolvedTask, config, logger, json: flags.json, context: flags.context,
111
- flags: {
112
- noTestsSynth: flags.testsSynth === false,
113
- noPlanReview: flags.planReview === false,
114
- quick: Boolean(flags.quick),
115
- yes: Boolean(flags.yes),
116
- interactive: flags.interactive,
117
- preflightHu: flags.preflightHu !== false, // KJC-TSK-0397
118
- useOnboarding: Boolean(flags.useOnboarding), // KJC-TSK-0384 PR 3
119
- },
120
- });
121
- });
122
- });
27
+ .command("generate", { hidden: true })
28
+ .argument("[args...]")
29
+ .allowUnknownOption()
30
+ .allowExcessArguments()
31
+ .action(() => retire("plan generate"));
123
32
 
124
33
  plan.command("list").description("List all plans").action(async (flags) => {
125
34
  await withConfig(pkgVersion, "plan", flags, async ({ config }) => {
@@ -0,0 +1,49 @@
1
+ // KJC-TSK-1317: the pipeline commands retired in 5.0. In v4 the host agent does
2
+ // the work and kj governs it, so kj no longer drives a coder of its own. Each
3
+ // retired command still answers, hidden from the help, to say what replaced it.
4
+
5
+ const GUIDE = "https://github.com/manufosela/karajan-code/blob/main/MIGRATION-v5.md";
6
+ const BY_THE_AGENT = "Your agent (Claude Code, OpenCode...) does the work now and kj governs it: split the task with kj brief planner + kj hu add, one lane per card with kj worktree start, and kj review --staged before every commit.";
7
+ const brief = (role) => `Use kj brief ${role}: your agent applies the role itself.`;
8
+
9
+ /** Retired command → [how it is named, what replaces it]. */
10
+ export const RETIRED = {
11
+ run: ["kj run", BY_THE_AGENT],
12
+ autorun: ["kj autorun", BY_THE_AGENT],
13
+ resume: ["kj resume", BY_THE_AGENT],
14
+ standby: ["kj standby", BY_THE_AGENT],
15
+ "plan generate": ["kj plan generate", "Your agent plans with kj brief planner and puts each piece on the board with kj hu add."],
16
+ status: ["kj status", "The HU board shows the work in progress: kj board start."],
17
+ undo: ["kj undo", "Every reviewed step is its own commit: undo it with git."],
18
+ triage: ["kj triage", brief("triage")],
19
+ researcher: ["kj researcher", brief("researcher")],
20
+ architect: ["kj architect", brief("architect")],
21
+ review: ["kj review with a task", "Use kj review --staged: it reviews the exact diff you are about to commit."],
22
+ };
23
+
24
+ /** The notice a retired command (or MCP tool) answers with. */
25
+ export const retiredMessage = (name) => {
26
+ const [label, instead] = RETIRED[name];
27
+ return `${label} was retired in 5.0. ${instead}\nMigration guide: ${GUIDE}`;
28
+ };
29
+
30
+ /** Print the notice and fail, without starting anything. */
31
+ export const retire = (name) => {
32
+ process.stderr.write(`${retiredMessage(name)}\n`);
33
+ process.exitCode = 1;
34
+ };
35
+
36
+ const TOP_LEVEL = ["run", "autorun", "resume", "standby", "status", "undo", "triage", "researcher", "architect"];
37
+
38
+ /** Register the retired top-level commands, hidden, taking any argument. */
39
+ export function registerRetired(program) {
40
+ for (const name of TOP_LEVEL) {
41
+ program
42
+ .command(name, { hidden: true })
43
+ .description("Retired in 5.0")
44
+ .argument("[args...]")
45
+ .allowUnknownOption()
46
+ .allowExcessArguments()
47
+ .action(() => retire(name));
48
+ }
49
+ }
package/src/cli.js CHANGED
@@ -10,11 +10,12 @@ import { registerPlan } from "./cli/register-plan.js";
10
10
  import { registerRolesSkills } from "./cli/register-roles-skills.js";
11
11
  import { registerMeta } from "./cli/register-meta.js";
12
12
  import { registerSonar } from "./cli/register-sonar.js";
13
- import { registerStandby } from "./cli/register-standby.js";
13
+ import { registerRetired } from "./cli/retired-commands.js";
14
14
  import { printUpdateNotice } from "./utils/update-check.js";
15
15
  import { printWelcomeScreen } from "./utils/welcome.js";
16
16
  import { migrateKjToKarajan } from "./utils/home-migration.js";
17
17
  import { pinGitDiffFormat } from "./utils/git-diff-format.js";
18
+ import { pinGhAccount } from "./utils/gh-account.js";
18
19
 
19
20
  // KJC-BUG-0408: every git kj runs prints a/ and b/, whatever the user's gitconfig says.
20
21
  pinGitDiffFormat();
@@ -65,8 +66,8 @@ program.addHelpText(
65
66
  `
66
67
  Getting started (the basics — start here):
67
68
  kj init Set up Karajan in this project (run once)
68
- kj run "<task>" Build or fix something end-to-end (coder + review)
69
- kj plan "<task>" Break a task into user stories first, then run them
69
+ kj hu add "<title>" Put a piece of work on the board before it starts
70
+ kj review --staged Have another AI review the diff you are about to commit
70
71
  kj doctor Check your environment is ready
71
72
  kj harden Add quality git hooks + CI to any repo
72
73
 
@@ -78,7 +79,7 @@ registerPlan(program, { pkgVersion: PKG_VERSION });
78
79
  registerRolesSkills(program, { pkgVersion: PKG_VERSION });
79
80
  registerMeta(program, { pkgVersion: PKG_VERSION });
80
81
  registerSonar(program);
81
- registerStandby(program);
82
+ registerRetired(program);
82
83
 
83
84
  /**
84
85
  * Find subcommands whose name is "close enough" to a typo. Used by the
@@ -124,7 +125,7 @@ function levenshtein(a, b) {
124
125
  program.action(async (_opts, command) => {
125
126
  if (command.args.length > 0) {
126
127
  const bad = command.args[0];
127
- const known = program.commands.map((c) => c.name()).sort();
128
+ const known = program.commands.filter((c) => !c._hidden).map((c) => c.name()).sort();
128
129
  process.stderr.write(`error: '${bad}' no es un comando válido de kj\n`);
129
130
  const suggestions = suggestSimilarCommands(bad, known);
130
131
  if (suggestions.length > 0) {
@@ -140,6 +141,18 @@ program.action(async (_opts, command) => {
140
141
  printWelcomeScreen({ version: PKG_VERSION, config });
141
142
  });
142
143
 
144
+ // KJC-BUG-0458 (ADR 0040): every gh kj runs uses the repo's account, not whichever another
145
+ // session left active. A broken config is each command's to report; here it only means the
146
+ // account comes from the remote. Kept in a top-level try: the SEA build wraps from here on.
147
+ try {
148
+ const { config } = await loadConfig().catch(() => ({ config: null }));
149
+ const githubAccount = config?.review?.github_account ?? null;
150
+ const ghPin = pinGhAccount({ account: githubAccount });
151
+ if (githubAccount && ghPin.reason) console.warn(`\x1b[33m[warn]\x1b[0m review.github_account: ${ghPin.reason}`);
152
+ } catch (err) {
153
+ console.warn(`\x1b[33m[warn]\x1b[0m gh account not pinned: ${err.message}`);
154
+ }
155
+
143
156
  // One-shot ~/.kj/ → ~/.karajan/ consolidation. Idempotent via marker
144
157
  // file; failures non-blocking. See src/utils/home-migration.js.
145
158
  // Static import — the migrator runs on every kj invocation, no
@@ -8,10 +8,8 @@
8
8
  import { createAgent, getAvailableAgents } from "../agents/index.js";
9
9
  import { detectAvailableAgents } from "../utils/agent-detect.js";
10
10
 
11
- export async function agentRunCommand({ agent, task, config = {}, logger = null, flags = {} }) {
12
- if (!task || !task.trim()) {
13
- throw new Error("kj agent run requires a task: kj agent run <agent> \"<task>\"");
14
- }
11
+ // The agent must be one kj supports AND installed here; both errors name what is available.
12
+ async function assertAgentAvailable(agent) {
15
13
  const known = getAvailableAgents().map((a) => a.name);
16
14
  const detected = await detectAvailableAgents();
17
15
  const up = detected.filter((a) => a.available).map((a) => a.name).join(", ") || "none";
@@ -22,15 +20,44 @@ export async function agentRunCommand({ agent, task, config = {}, logger = null,
22
20
  if (!entry?.available) {
23
21
  throw new Error(`agent "${agent}" is not available on this machine (available: ${up}) — install its CLI or pick another`);
24
22
  }
23
+ }
25
24
 
26
- let timeoutMs;
27
- if (flags.timeoutMinutes !== undefined) {
28
- const minutes = Number(flags.timeoutMinutes);
29
- if (!Number.isFinite(minutes) || minutes <= 0) {
30
- throw new Error(`--timeout-minutes must be a positive number, got "${flags.timeoutMinutes}"`);
31
- }
32
- timeoutMs = minutes * 60000;
25
+ function timeoutMsOf(flags) {
26
+ if (flags.timeoutMinutes === undefined) return undefined;
27
+ const minutes = Number(flags.timeoutMinutes);
28
+ if (!Number.isFinite(minutes) || minutes <= 0) {
29
+ throw new Error(`--timeout-minutes must be a positive number, got "${flags.timeoutMinutes}"`);
33
30
  }
31
+ return minutes * 60000;
32
+ }
33
+
34
+ function delegationResult(agent, result) {
35
+ return {
36
+ ok: Boolean(result?.ok),
37
+ agent,
38
+ output: result?.output || "",
39
+ error: result?.error || null,
40
+ usage: result?.tokens_out != null
41
+ ? { tokens_in: result.tokens_in ?? null, tokens_out: result.tokens_out, cached_tokens: result.cached_tokens ?? null }
42
+ : null,
43
+ };
44
+ }
45
+
46
+ function printResult(res, json) {
47
+ if (json) {
48
+ console.log(JSON.stringify(res));
49
+ return;
50
+ }
51
+ if (res.output) console.log(res.output);
52
+ if (!res.ok && res.error) console.error(res.error);
53
+ }
54
+
55
+ export async function agentRunCommand({ agent, task, config = {}, logger = null, flags = {} }) {
56
+ if (!task || !task.trim()) {
57
+ throw new Error("kj agent run requires a task: kj agent run <agent> \"<task>\"");
58
+ }
59
+ await assertAgentAvailable(agent);
60
+ const timeoutMs = timeoutMsOf(flags);
34
61
 
35
62
  // --json must emit ONLY the serialized result — no informational lines,
36
63
  // and a crash of the delegated subprocess still yields one JSON payload.
@@ -43,21 +70,8 @@ export async function agentRunCommand({ agent, task, config = {}, logger = null,
43
70
  result = { ok: false, output: "", error: err.message };
44
71
  }
45
72
 
46
- const res = {
47
- ok: Boolean(result?.ok),
48
- agent,
49
- output: result?.output || "",
50
- error: result?.error || null,
51
- usage: result?.tokens_out != null
52
- ? { tokens_in: result.tokens_in ?? null, tokens_out: result.tokens_out, cached_tokens: result.cached_tokens ?? null }
53
- : null,
54
- };
55
- if (flags.json) {
56
- console.log(JSON.stringify(res));
57
- } else {
58
- if (res.output) console.log(res.output);
59
- if (!res.ok && res.error) console.error(res.error);
60
- }
73
+ const res = delegationResult(agent, result);
74
+ printResult(res, flags.json);
61
75
  process.exitCode = res.ok ? 0 : 1;
62
76
  return res;
63
77
  }