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,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 }) => {
@@ -10,7 +10,7 @@ import { withConfig } from "./_shared.js";
10
10
  export function registerRolesSkills(program, { pkgVersion }) {
11
11
  program
12
12
  .command("skills [action] [args...]")
13
- .description("Manage the skill cache (list | clear-cache | sync-addyosmani | list-addyosmani) and, through atril, the .karajan store (search | route | scan | install | remove | graph | enrich | config)")
13
+ .description("Manage the skill cache (list | clear-cache | sync-addyosmani | list-addyosmani) and, through atril, the .karajan store (search, which translates a non-English query first | route | scan | install | remove | graph | enrich | config)")
14
14
  // KJC-TSK-1193: atril's options (--json, --kind, --role, --root) travel to atril untouched.
15
15
  .allowUnknownOption()
16
16
  .action(async (action, args) => {
@@ -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
  }