karajan-code 4.70.3 → 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 (388) 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/ai-surface.js +9 -7
  61. package/src/checks/config-files.js +8 -7
  62. package/src/checks/dir-setup.js +34 -1
  63. package/src/checks/native-build.js +21 -39
  64. package/src/checks/runner.js +128 -142
  65. package/src/cli/advanced-commands.js +6 -6
  66. package/src/cli/register-meta.js +42 -82
  67. package/src/cli/register-pipeline.js +8 -140
  68. package/src/cli/register-plan.js +9 -100
  69. package/src/cli/retired-commands.js +49 -0
  70. package/src/cli.js +18 -5
  71. package/src/commands/agent-run.js +40 -26
  72. package/src/commands/audit.js +127 -124
  73. package/src/commands/board.js +5 -9
  74. package/src/commands/check.js +29 -16
  75. package/src/commands/doctor.js +2 -0
  76. package/src/commands/env.js +176 -148
  77. package/src/commands/go.js +76 -55
  78. package/src/commands/harden.js +105 -86
  79. package/src/commands/hu-start.js +52 -0
  80. package/src/commands/hu.js +288 -221
  81. package/src/commands/identity.js +111 -78
  82. package/src/commands/init-atril.js +47 -0
  83. package/src/commands/init.js +11 -40
  84. package/src/commands/install-tools.js +70 -85
  85. package/src/commands/main-guard.js +78 -0
  86. package/src/commands/policy.js +226 -184
  87. package/src/commands/qmd.js +27 -21
  88. package/src/commands/rag.js +75 -48
  89. package/src/commands/review-gate.js +422 -339
  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 +94 -25
  94. package/src/config/loader.js +34 -17
  95. package/src/config/overrides.js +2 -1
  96. package/src/config/secrets.js +36 -0
  97. package/src/config.js +1 -0
  98. package/src/environment/adr.js +16 -2
  99. package/src/environment/board-access.js +11 -9
  100. package/src/git/karajan-label.js +20 -8
  101. package/src/guards/main-guard.js +54 -0
  102. package/src/harden/branch-protection.js +36 -3
  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 +81 -35
  106. package/src/harden/sentinel/sentinel-lib.mjs +149 -23
  107. package/src/harden/sentinel/sentinel-shell.mjs +64 -0
  108. package/src/harden/sentinel/sessionstart.mjs +3 -2
  109. package/src/harden/sentinel/stop.mjs +5 -4
  110. package/src/harden/workflow-engine.js +12 -1
  111. package/src/harden/workflow-templates.js +1 -1
  112. package/src/hu/board-lookup.js +29 -0
  113. package/src/hu/gh-identity.js +23 -0
  114. package/src/hu/github-board.js +4 -2
  115. package/src/hu/lane-prune.js +15 -7
  116. package/src/hu/lane-setup.js +65 -0
  117. package/src/hu/lanes.js +66 -0
  118. package/src/hu/team-board-mirror.js +3 -2
  119. package/src/infrastructure/command-runner.js +1 -1
  120. package/src/infrastructure/file-system-service.js +1 -1
  121. package/src/mcp/handlers/direct-handlers.js +2 -292
  122. package/src/mcp/handlers/hu-handlers.js +44 -55
  123. package/src/mcp/handlers/management-handlers.js +2 -42
  124. package/src/mcp/server-handlers.js +16 -22
  125. package/src/mcp/tools.js +5 -200
  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 +56 -43
  134. package/src/rag/bootstrap-index.js +28 -54
  135. package/src/rag/migrate.js +1 -1
  136. package/src/rag/onnx-fallback.js +2 -2
  137. package/src/rag/pid-lease.js +70 -0
  138. package/src/rag/project-store.js +2 -12
  139. package/src/review/card-first.js +57 -46
  140. package/src/review/dual-review.js +5 -4
  141. package/src/review/gate-gitignore.js +23 -4
  142. package/src/review/gate-hook.js +47 -0
  143. package/src/review/one-shot-review.js +51 -37
  144. package/src/review/publish-pr.js +18 -3
  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 +34 -3
  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 +2 -26
  154. package/src/roles/audit-role.js +106 -125
  155. package/src/skills/atril-skills.js +5 -4
  156. package/src/sonar/scanner.js +116 -101
  157. package/src/steward/invariants.js +5 -4
  158. package/src/steward/phantom-sweep.js +66 -0
  159. package/src/tournament/judge.js +60 -53
  160. package/src/utils/agent-home.js +33 -0
  161. package/src/utils/gh-account.js +37 -0
  162. package/src/utils/git.js +0 -13
  163. package/src/utils/home-migration.js +7 -1
  164. package/src/utils/main-checkout.js +53 -0
  165. package/src/utils/qmd-collection.js +3 -1
  166. package/src/utils/welcome.js +3 -3
  167. package/templates/{skills → atril/commands}/kj-architect.md +5 -0
  168. package/templates/{skills → atril/commands}/kj-audit.md +5 -0
  169. package/templates/{skills → atril/commands}/kj-board.md +5 -0
  170. package/templates/{skills → atril/commands}/kj-code.md +5 -0
  171. package/templates/{skills → atril/commands}/kj-csv-transform.md +5 -0
  172. package/templates/{skills → atril/commands}/kj-data-report.md +5 -0
  173. package/templates/{skills → atril/commands}/kj-discover.md +5 -0
  174. package/templates/{skills → atril/commands}/kj-rag-query.md +5 -0
  175. package/templates/{skills → atril/commands}/kj-review.md +5 -0
  176. package/templates/{skills → atril/commands}/kj-security.md +5 -0
  177. package/templates/{skills → atril/commands}/kj-sonar.md +5 -0
  178. package/templates/{skills → atril/commands}/kj-sql-analysis.md +5 -0
  179. package/templates/{skills → atril/commands}/kj-test.md +5 -0
  180. package/packages/hu-board/public/utils/run-launcher.js +0 -169
  181. package/packages/hu-board/src/run-tracker.js +0 -121
  182. package/src/activity-log.js +0 -59
  183. package/src/agents/host-agent.js +0 -38
  184. package/src/agents/model-registry.js +0 -142
  185. package/src/audit/plan-adherence.js +0 -224
  186. package/src/autonomy/arbiter-role.js +0 -71
  187. package/src/autonomy/arbiter.js +0 -22
  188. package/src/autonomy/decider.js +0 -18
  189. package/src/autonomy/decision-resolver.js +0 -58
  190. package/src/autonomy/outcome-report.js +0 -55
  191. package/src/autonomy/stage-ask.js +0 -30
  192. package/src/brain/decision-tracker.js +0 -125
  193. package/src/brain/decisor.js +0 -243
  194. package/src/brain/solomon-consult.js +0 -171
  195. package/src/brain/standby-scheduler.js +0 -8
  196. package/src/budget/comparison.js +0 -96
  197. package/src/canvas/parse-md.js +0 -238
  198. package/src/canvas/schema.js +0 -101
  199. package/src/canvas/to-flat.js +0 -85
  200. package/src/canvas/validate.js +0 -163
  201. package/src/ci/dispatch.js +0 -99
  202. package/src/ci/index.js +0 -3
  203. package/src/ci/pr-diff.js +0 -26
  204. package/src/cli/register-standby.js +0 -26
  205. package/src/commands/architect.js +0 -111
  206. package/src/commands/autorun.js +0 -49
  207. package/src/commands/researcher.js +0 -54
  208. package/src/commands/resume.js +0 -72
  209. package/src/commands/review.js +0 -89
  210. package/src/commands/run.js +0 -185
  211. package/src/commands/standby.js +0 -117
  212. package/src/commands/status.js +0 -36
  213. package/src/commands/triage.js +0 -78
  214. package/src/commands/undo.js +0 -62
  215. package/src/domains/domain-loader.js +0 -245
  216. package/src/domains/domain-registry.js +0 -140
  217. package/src/domains/domain-synthesizer.js +0 -129
  218. package/src/git/automation.js +0 -433
  219. package/src/git/coder-commit-guard.js +0 -40
  220. package/src/git/hu-automation.js +0 -243
  221. package/src/git/hu-snapshot.js +0 -10
  222. package/src/git/symlink-targets.js +0 -57
  223. package/src/golden/asserter.js +0 -92
  224. package/src/golden/loader.js +0 -52
  225. package/src/golden/runner.js +0 -92
  226. package/src/golden/schema.js +0 -41
  227. package/src/guards/duplicate-members.js +0 -86
  228. package/src/guards/intent-guard.js +0 -161
  229. package/src/guards/perf-guard.js +0 -126
  230. package/src/guards/policy-guard.js +0 -90
  231. package/src/guards/policy-resolver.js +0 -85
  232. package/src/guards/secret-redactor.js +0 -71
  233. package/src/hu/acceptance-runner.js +0 -138
  234. package/src/hu/lazy-planner.js +0 -109
  235. package/src/hu/parallel-executor.js +0 -94
  236. package/src/hu/routing-metrics.js +0 -17
  237. package/src/hu/split-validator.js +0 -143
  238. package/src/hu/splitting-detector.js +0 -158
  239. package/src/hu/splitting-generator.js +0 -175
  240. package/src/hu/store.js +0 -394
  241. package/src/infrastructure/mocks.js +0 -182
  242. package/src/mcp/handlers/run-handler.js +0 -318
  243. package/src/mcp/sovereignty-guard.js +0 -113
  244. package/src/mcp/tool-arg-normalizers.js +0 -16
  245. package/src/mutate/reviewer-signal.js +0 -76
  246. package/src/orchestrator/agent-fallback.js +0 -81
  247. package/src/orchestrator/brain-coordinator.js +0 -186
  248. package/src/orchestrator/ci-integration.js +0 -139
  249. package/src/orchestrator/config-init.js +0 -426
  250. package/src/orchestrator/direct-actions.js +0 -217
  251. package/src/orchestrator/drivers/error-recovery.js +0 -287
  252. package/src/orchestrator/drivers/init-context.js +0 -238
  253. package/src/orchestrator/drivers/iteration-loop.js +0 -382
  254. package/src/orchestrator/drivers/iteration-phases/coder-and-refactorer.js +0 -69
  255. package/src/orchestrator/drivers/iteration-phases/guards.js +0 -91
  256. package/src/orchestrator/drivers/iteration-phases/handle-approved.js +0 -29
  257. package/src/orchestrator/drivers/iteration-phases/quality-gates.js +0 -125
  258. package/src/orchestrator/drivers/iteration-phases/reviewer-gate.js +0 -62
  259. package/src/orchestrator/drivers/post-loop.js +0 -404
  260. package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +0 -137
  261. package/src/orchestrator/drivers/pre-loop-phases/config-deprecations.js +0 -47
  262. package/src/orchestrator/drivers/pre-loop-phases/ensure-addyosmani-skills.js +0 -84
  263. package/src/orchestrator/drivers/pre-loop-phases/inject-loaded-plan.js +0 -393
  264. package/src/orchestrator/drivers/pre-loop.js +0 -524
  265. package/src/orchestrator/drivers/run-hu-batch.js +0 -468
  266. package/src/orchestrator/feedback-enrichment.js +0 -140
  267. package/src/orchestrator/feedback-queue.js +0 -151
  268. package/src/orchestrator/flow-control.js +0 -170
  269. package/src/orchestrator/flow-runner.js +0 -365
  270. package/src/orchestrator/fs-leak-detector.js +0 -228
  271. package/src/orchestrator/hu-scheduler.js +0 -114
  272. package/src/orchestrator/hu-sub-pipeline.js +0 -642
  273. package/src/orchestrator/iteration-gate.js +0 -73
  274. package/src/orchestrator/iteration-stages.js +0 -9
  275. package/src/orchestrator/parallel-limiter.js +0 -74
  276. package/src/orchestrator/pipeline-context.js +0 -72
  277. package/src/orchestrator/post-loop-stages.js +0 -468
  278. package/src/orchestrator/pre-loop-stages.js +0 -11
  279. package/src/orchestrator/preflight-checks.js +0 -487
  280. package/src/orchestrator/repair/repair-detector.js +0 -117
  281. package/src/orchestrator/repair/repair-runner.js +0 -142
  282. package/src/orchestrator/reviewer-fallback.js +0 -45
  283. package/src/orchestrator/role-output-compressor.js +0 -189
  284. package/src/orchestrator/session-journal.js +0 -308
  285. package/src/orchestrator/solomon-escalation.js +0 -331
  286. package/src/orchestrator/solomon-rules.js +0 -212
  287. package/src/orchestrator/stages/acceptance-coverage-stage.js +0 -47
  288. package/src/orchestrator/stages/architect-stage.js +0 -172
  289. package/src/orchestrator/stages/coder-stage.js +0 -506
  290. package/src/orchestrator/stages/domain-curator-stage.js +0 -82
  291. package/src/orchestrator/stages/format-stage.js +0 -61
  292. package/src/orchestrator/stages/hu-reviewer-phases/detect-and-apply-splits.js +0 -127
  293. package/src/orchestrator/stages/hu-reviewer-stage.js +0 -419
  294. package/src/orchestrator/stages/perf-stage.js +0 -140
  295. package/src/orchestrator/stages/planner-stage.js +0 -85
  296. package/src/orchestrator/stages/rag-context-stage.js +0 -80
  297. package/src/orchestrator/stages/rag-preload-decisor.js +0 -58
  298. package/src/orchestrator/stages/research-stage.js +0 -69
  299. package/src/orchestrator/stages/reviewer-stage.js +0 -431
  300. package/src/orchestrator/stages/sonar-stage.js +0 -439
  301. package/src/orchestrator/stages/stage-classes.js +0 -84
  302. package/src/orchestrator/stages/stage-executor.js +0 -155
  303. package/src/orchestrator/stages/suite-green-stage.js +0 -62
  304. package/src/orchestrator/stages/tdd-discipline-stage.js +0 -56
  305. package/src/orchestrator/stages/tool-judge-stage.js +0 -53
  306. package/src/orchestrator/stages/triage-stage.js +0 -172
  307. package/src/orchestrator/standby.js +0 -71
  308. package/src/orchestrator/verification-gate.js +0 -183
  309. package/src/orchestrator.js +0 -22
  310. package/src/plan/adr-generator.js +0 -170
  311. package/src/plan/adr-loader.js +0 -60
  312. package/src/plan/plan-executor.js +0 -100
  313. package/src/plan/plan-validation.js +0 -4
  314. package/src/prompts/acceptance-coverage.js +0 -32
  315. package/src/prompts/arbiter.js +0 -38
  316. package/src/prompts/architect.js +0 -103
  317. package/src/prompts/hu-reviewer.js +0 -244
  318. package/src/prompts/tool-correctness-judge.js +0 -31
  319. package/src/prompts/triage.js +0 -57
  320. package/src/rag/embedder.js +0 -2
  321. package/src/rag/embedders/_cloud-base.js +0 -2
  322. package/src/rag/embedders/cohere.js +0 -2
  323. package/src/rag/embedders/mistral.js +0 -2
  324. package/src/rag/embedders/onnx.js +0 -2
  325. package/src/rag/embedders/openai.js +0 -2
  326. package/src/rag/embedders/voyage.js +0 -2
  327. package/src/rag/rerank.js +0 -4
  328. package/src/rag/where-parser.js +0 -4
  329. package/src/repeat-detector.js +0 -88
  330. package/src/review/diff-generator.js +0 -112
  331. package/src/review/git-stash-helper.js +0 -104
  332. package/src/review/schema.js +0 -31
  333. package/src/review/scope-filter.js +0 -152
  334. package/src/review/snapshot-diff.js +0 -122
  335. package/src/review/tdd-discipline.js +0 -90
  336. package/src/review/tdd-policy.js +0 -69
  337. package/src/roles/acceptance-coverage-role.js +0 -78
  338. package/src/roles/architect-role.js +0 -77
  339. package/src/roles/coder-role.js +0 -113
  340. package/src/roles/commiter-role.js +0 -113
  341. package/src/roles/domain-curator-role.js +0 -134
  342. package/src/roles/hu-reviewer-role.js +0 -64
  343. package/src/roles/impeccable-role.js +0 -85
  344. package/src/roles/index.js +0 -18
  345. package/src/roles/karajan-brain-role.js +0 -134
  346. package/src/roles/perf-role.js +0 -122
  347. package/src/roles/planner-role.js +0 -151
  348. package/src/roles/refactorer-role.js +0 -30
  349. package/src/roles/repairer-role.js +0 -181
  350. package/src/roles/researcher-role.js +0 -70
  351. package/src/roles/reviewer-role.js +0 -115
  352. package/src/roles/security-role.js +0 -73
  353. package/src/roles/solomon-role.js +0 -271
  354. package/src/roles/sonar-role.js +0 -72
  355. package/src/roles/tester-role.js +0 -235
  356. package/src/roles/tool-correctness-judge-role.js +0 -78
  357. package/src/roles/triage-role.js +0 -99
  358. package/src/session/journal/decisions-writer.js +0 -200
  359. package/src/session/journal/iteration-logger.js +0 -194
  360. package/src/session/journal/summary-writer.js +0 -320
  361. package/src/session/journal/tree-writer.js +0 -164
  362. package/src/session/journal/write-all.js +0 -89
  363. package/src/session-cleanup.js +0 -116
  364. package/src/skills/semantic-detector.js +0 -167
  365. package/src/skills/skill-detector.js +0 -385
  366. package/src/sonar/cloud-scanner.js +0 -78
  367. package/src/tracker-bootstrap.js +0 -44
  368. package/src/types/index.js +0 -38
  369. package/src/types/policy.js +0 -43
  370. package/src/types/solomon.js +0 -87
  371. package/src/utils/async-lock.js +0 -31
  372. package/src/utils/budget.js +0 -229
  373. package/src/utils/cwd-confirm.js +0 -39
  374. package/src/utils/display/event-handlers.js +0 -403
  375. package/src/utils/display/formatters.js +0 -132
  376. package/src/utils/display/header.js +0 -47
  377. package/src/utils/display/session-summary.js +0 -118
  378. package/src/utils/display/solomon.js +0 -42
  379. package/src/utils/pricing.js +0 -29
  380. package/src/utils/quota-simulator.js +0 -56
  381. package/src/utils/role-assigner.js +0 -137
  382. package/src/utils/rtk-wrapper.js +0 -87
  383. package/src/utils/run-registry.js +0 -9
  384. package/src/utils/status-dashboard.js +0 -254
  385. package/src/utils/tool-call-extractor.js +0 -56
  386. package/src/webperf/devtools-detect.js +0 -112
  387. package/src/webperf/webperf-role-integration.js +0 -66
  388. package/templates/skills/kj-run.md +0 -73
package/src/ci/pr-diff.js DELETED
@@ -1,26 +0,0 @@
1
- /**
2
- * Read PR diff via gh CLI for Karajan CI flow.
3
- * The reviewer reads the PR diff instead of local git diff.
4
- */
5
-
6
- import { runCommand } from "../utils/process.js";
7
-
8
- /**
9
- * Get the diff of a PR via `gh pr diff <number>`.
10
- * Returns the diff string or throws on failure.
11
- */
12
- export async function getPrDiff(prNumber) {
13
- if (!prNumber) throw new Error("prNumber is required");
14
-
15
- const res = await runCommand("gh", [
16
- "pr",
17
- "diff",
18
- String(prNumber)
19
- ]);
20
-
21
- if (res.exitCode !== 0) {
22
- throw new Error(`gh pr diff ${prNumber} failed: ${res.stderr || res.stdout}`);
23
- }
24
-
25
- return res.stdout;
26
- }
@@ -1,26 +0,0 @@
1
- // KJC-TSK-0414 PR2: registra `kj standby list` + `kj standby resume <id>`.
2
- // `resume` es subcomando de standby para no colisionar con el `kj resume`
3
- // pre-existente (Solomon pauses con --answer). Modelos mentales distintos:
4
- // - `kj resume <id> --answer X` → Solomon pauseado (existente)
5
- // - `kj standby resume <id>` → run hibernada por quota
6
- import { resumeCommand, standbyListCommand } from "../commands/standby.js";
7
-
8
- export function registerStandby(program) {
9
- const standby = program.command("standby").description("Sesiones hibernadas (QUOTA_EXHAUSTED_DAILY etc.)");
10
- standby
11
- .command("list", { isDefault: true })
12
- .description("Lista sesiones pendientes de reanudar")
13
- .option("--json", "Output JSON")
14
- .action(async (flags) => {
15
- await standbyListCommand({ json: flags.json });
16
- });
17
-
18
- standby
19
- .command("resume")
20
- .description("Reanuda una sesión hibernada (re-spawn comando original)")
21
- .argument("<sessionId>")
22
- .option("--force", "Reanudar aunque cooldownUntil todavía esté en el futuro (no recomendado)")
23
- .action(async (sessionId, flags) => {
24
- await resumeCommand({ sessionId, force: Boolean(flags.force) });
25
- });
26
- }
@@ -1,111 +0,0 @@
1
- import { createAgent } from "../agents/index.js";
2
- import { assertAgentsAvailable } from "../agents/availability.js";
3
- import { resolveRole } from "../config.js";
4
- import { buildArchitectPrompt, parseArchitectOutput } from "../prompts/architect.js";
5
- import { createCliProgressReporter } from "../utils/cli-progress.js";
6
- import { withBrainRecovery } from "../brain/with-brain-recovery.js";
7
-
8
- // KJC-BUG-0313 (#2061): the agent answers each list with plain strings or with
9
- // objects; both render, and a section with neither prints nothing, never "undefined".
10
- function section(title, items, render, lines) {
11
- if (!items?.length) return;
12
- lines.push(`### ${title}`);
13
- for (const item of items) lines.push(...(typeof item === "string" ? [`- ${item}`] : render(item)));
14
- lines.push("");
15
- }
16
-
17
- const named = (o, detail) => [`- **${o.name ?? o.decision ?? JSON.stringify(o)}**${detail ? `: ${detail}` : ""}`];
18
- const contract = (c) => [`- \`${c.method || "GET"} ${c.endpoint ?? c.path ?? ""}\``];
19
- const tradeoff = (t) => [...named(t, t.rationale), ...(t.alternatives?.length ? [` Alternatives: ${t.alternatives.join(", ")}`] : [])];
20
- const entity = (e) => named(e, Array.isArray(e.fields) ? e.fields.join(", ") : e.description);
21
-
22
- function formatArchitecture(arch, lines) {
23
- if (arch.type) lines.push(`**Type:** ${arch.type}`, "");
24
- section("Layers", arch.layers, (l) => named(l, l.responsibility), lines);
25
- section("Patterns", arch.patterns, (p) => [`- ${p.name ?? JSON.stringify(p)}`], lines);
26
- section("Data Model", arch.dataModel?.entities, entity, lines);
27
- // A contract given as a string ("GET /x") is code too: same backticks as an object's.
28
- section("API Contracts", arch.apiContracts?.map((c) => (typeof c === "string" ? { raw: c } : c)), (c) => (c.raw ? [`- \`${c.raw}\``] : contract(c)), lines);
29
- section("Dependencies", arch.dependencies, (d) => named(d, d.reason), lines);
30
- section("Tradeoffs", arch.tradeoffs, tradeoff, lines);
31
- }
32
-
33
- export function formatArchitect(result) {
34
- const lines = [];
35
- lines.push(`## Architecture Design`);
36
- lines.push(`**Verdict:** ${result.verdict || "unknown"}`, "");
37
-
38
- if (result.architecture) formatArchitecture(result.architecture, lines);
39
-
40
- if (result.questions?.length) {
41
- lines.push("### Clarification Questions");
42
- for (const q of result.questions) lines.push(`- ${q.question || q}`);
43
- lines.push("");
44
- }
45
-
46
- if (result.summary) lines.push(`---\n${result.summary}`);
47
- return lines.join("\n");
48
- }
49
-
50
- export async function architectCommand({ task, config, logger, context, json }) {
51
- const { withCliRunLog } = await import("../utils/cli-run-log.js");
52
- return withCliRunLog("architect", { projectDir: config?.projectDir, logger }, async ({ runLog }) => {
53
- const architectRole = resolveRole(config, "architect");
54
- await assertAgentsAvailable([architectRole.provider]);
55
- logger.info(`Architect (${architectRole.provider}) starting...`);
56
- runLog.logText(`[architect] provider=${architectRole.provider}`);
57
-
58
- const agent = createAgent(architectRole.provider, config, logger);
59
- const prompt = await buildArchitectPrompt({ task, researchContext: context });
60
- const progress = createCliProgressReporter({ role: "architect" });
61
- let result;
62
- try {
63
- result = await withBrainRecovery({
64
- agent, taskArgs: { prompt, onOutput: progress.onOutput, role: "architect" },
65
- role: "architect", provider: architectRole.provider, logger,
66
- });
67
- progress.finish(result.ok ? "done" : (result.action || "failed"));
68
- } catch (err) { progress.finish("failed"); throw err; }
69
-
70
- if (!result.ok) {
71
- throw new Error(result.error || result.output || "Architect failed");
72
- }
73
-
74
- const parsed = parseArchitectOutput(result.output);
75
-
76
- if (json) {
77
- console.log(JSON.stringify(parsed || result.output, null, 2));
78
- return { ok: true };
79
- }
80
-
81
- if (parsed?.verdict) {
82
- console.log(formatArchitect(parsed));
83
- } else {
84
- console.log(result.output);
85
- }
86
-
87
- // Persist ADRs from the architect's tradeoffs[] (v2.7.5). One ADR
88
- // per tradeoff in Nygard format under `~/.kj/plans/_loose/adrs/`.
89
- // Coder/reviewer in subsequent runs can pull the active ADRs into
90
- // their prompt for context — done in a follow-up PR.
91
- if (parsed?.architecture && config?.projectDir) {
92
- try {
93
- const { persistAdrsFromArchitecture } = await import("../plan/adr-generator.js");
94
- const { adrs, paths } = await persistAdrsFromArchitecture({
95
- projectDir: config.projectDir,
96
- planId: null, // standalone architect → "_loose" bucket
97
- architecture: parsed.architecture,
98
- });
99
- if (paths.length > 0) {
100
- console.log(`\n${adrs.length} ADR${adrs.length === 1 ? "" : "s"} written:`);
101
- for (const p of paths) console.log(` - ${p}`);
102
- }
103
- } catch (err) {
104
- logger.warn(`ADR write skipped: ${err.message}`);
105
- }
106
- }
107
-
108
- logger.info("Architect completed.");
109
- return { ok: true };
110
- });
111
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * `kj autorun <spec>` — the unattended delivery chain (KJC-TSK-0574, épica
3
- * KJC-PCS-0062, design in docs/specs/autonomous-delivery.md §7).
4
- *
5
- * One command: spec → plan → run all HUs → outcome. It reuses `kj plan` and
6
- * `kj run --plan` rather than reimplementing them, and defaults to the
7
- * `autonomous` level so the Arbiter resolves every gate (no human in the loop).
8
- * The rich outcome report lands in AUTO-F; here we chain + propagate exit code.
9
- */
10
-
11
- import { planGenerateCommand } from "./plan/generate.js";
12
- import { runCommandHandler } from "./run.js";
13
- import { buildOutcome, formatOutcomeReport } from "../autonomy/outcome-report.js";
14
-
15
- export async function autorunCommand({
16
- task,
17
- config,
18
- logger = console,
19
- flags = {},
20
- planFn = planGenerateCommand,
21
- runFn = runCommandHandler,
22
- } = {}) {
23
- // autorun implies unattended: default to autonomous unless the user picked a
24
- // level explicitly (so `kj autorun --autonomy assisted` still works).
25
- const autoFlags = flags.autonomy || flags.autonomous ? flags : { ...flags, autonomous: true };
26
-
27
- logger.info?.("kj autorun — planning…");
28
- const plan = await planFn({ task, config, logger, flags: autoFlags });
29
- if (!plan?.ok || !plan.planId) {
30
- logger.error?.(`kj autorun: planning failed${plan?.reason ? ` (${plan.reason})` : ""}.`);
31
- return { ok: false, stage: "plan", reason: plan?.reason ?? "plan-failed" };
32
- }
33
-
34
- logger.info?.(`kj autorun — running plan ${plan.ref ?? plan.planId} (${plan.huCount ?? "?"} HUs)…`);
35
- const run = await runFn({ config, logger, flags: { ...autoFlags, plan: plan.planId } });
36
-
37
- const ok = run?.ok === true;
38
- // AUTO-F: emit the auditable outcome — delivered/incomplete, HUs that met the
39
- // ask, Arbiter decisions and residual defects (enriched as the run surfaces
40
- // them; baseline today is delivered + plan ref).
41
- const outcome = buildOutcome({
42
- planRef: plan.ref ?? plan.planId,
43
- delivered: ok,
44
- hus: run?.hus ?? [],
45
- decisions: run?.decisions ?? [],
46
- });
47
- for (const line of formatOutcomeReport(outcome)) logger.info?.(line);
48
- return { ok, stage: ok ? "done" : "run", planId: plan.planId, ref: plan.ref ?? plan.planId, outcome };
49
- }
@@ -1,54 +0,0 @@
1
- import { createAgent } from "../agents/index.js";
2
- import { assertAgentsAvailable } from "../agents/availability.js";
3
- import { resolveRole } from "../config.js";
4
- import { createCliProgressReporter } from "../utils/cli-progress.js";
5
- import { withBrainRecovery } from "../brain/with-brain-recovery.js";
6
-
7
- const SUBAGENT_PREAMBLE = [
8
- "IMPORTANT: You are running as a Karajan sub-agent.",
9
- "Do NOT ask about using Karajan, do NOT mention Karajan, do NOT suggest orchestration.",
10
- "Do NOT use any MCP tools. Focus only on researching the codebase."
11
- ].join(" ");
12
-
13
- function buildResearchPrompt(task) {
14
- return [
15
- SUBAGENT_PREAMBLE,
16
- "Investigate the codebase for the following task.",
17
- "Identify affected files, patterns, constraints, prior decisions, risks, and test coverage.",
18
- "Return a single valid JSON object with your findings and nothing else.",
19
- '{"affected_files":[string],"patterns":[string],"constraints":[string],"prior_decisions":[string],"risks":[string],"test_coverage":string}',
20
- `## Task\n${task}`
21
- ].join("\n\n");
22
- }
23
-
24
- export async function researcherCommand({ task, config, logger }) {
25
- const { withCliRunLog } = await import("../utils/cli-run-log.js");
26
- return withCliRunLog("researcher", { projectDir: config?.projectDir, logger }, async ({ runLog }) => {
27
- const researcherRole = resolveRole(config, "researcher");
28
- await assertAgentsAvailable([researcherRole.provider]);
29
- logger.info(`Researcher (${researcherRole.provider}) starting...`);
30
- runLog.logText(`[researcher] provider=${researcherRole.provider}`);
31
-
32
- const agent = createAgent(researcherRole.provider, config, logger);
33
- const prompt = buildResearchPrompt(task);
34
- const progress = createCliProgressReporter({ role: "researcher" });
35
- let result;
36
- try {
37
- result = await withBrainRecovery({
38
- agent, taskArgs: { prompt, onOutput: progress.onOutput, role: "researcher" },
39
- role: "researcher", provider: researcherRole.provider, logger,
40
- });
41
- progress.finish(result.ok ? "done" : (result.action || "failed"));
42
- } catch (err) { progress.finish("failed"); throw err; }
43
-
44
- if (!result.ok) {
45
- throw new Error(result.error || result.output || "Researcher failed");
46
- }
47
-
48
- if (result.output) {
49
- console.log(result.output);
50
- }
51
- logger.info("Researcher completed.");
52
- return { ok: true };
53
- });
54
- }
@@ -1,72 +0,0 @@
1
- import { EventEmitter } from "node:events";
2
- import { resumeFlow } from "../orchestrator.js";
3
- import { sweepOnResume } from "./steward.js";
4
- import { createActivityLog } from "../activity-log.js";
5
- import { printEvent } from "../utils/display/event-handlers.js";
6
- import { withCliRunLog } from "../utils/cli-run-log.js";
7
- import { registerRun, unregisterRun } from "../utils/run-registry.js";
8
- import { createCliAskQuestion } from "../utils/cli-ask-question.js";
9
-
10
- export async function resumeCommand({ sessionId, answer, config, logger, flags }) {
11
- const jsonMode = flags?.json;
12
- const quietMode = config.output?.quiet !== false;
13
- // STW-E (KJC-TSK-0793): resuming work is when someone is in front to review
14
- // the state — sweep if the report went stale; adoption stays explicit.
15
- await sweepOnResume({ config, logger });
16
-
17
- // Same wrapper as every other CLI command — without it `.kj/run.log`
18
- // is never opened during the resume and `kj-tail` stays silent
19
- // (every line of the resumed run goes only to the per-session
20
- // activity log + the local console). Also registers the run so the
21
- // HU Board shows it as live and can offer its Stop button.
22
- return withCliRunLog("resume", { projectDir: config?.projectDir, logger }, async ({ forwardProgress }) => {
23
- const runId = registerRun({
24
- pid: process.pid,
25
- planId: flags?.plan || null,
26
- huIds: null,
27
- projectDir: config?.projectDir || process.cwd(),
28
- source: "cli-resume",
29
- });
30
- const cleanupRegistry = () => { if (runId) unregisterRun(runId); };
31
- process.once("exit", cleanupRegistry);
32
- process.once("SIGTERM", () => { cleanupRegistry(); process.exit(143); });
33
- process.once("SIGINT", () => { cleanupRegistry(); process.exit(130); });
34
-
35
- const emitter = new EventEmitter();
36
- let activityLog = null;
37
- forwardProgress(emitter);
38
-
39
- emitter.on("progress", (event) => {
40
- if (!activityLog && event.sessionId) {
41
- activityLog = createActivityLog(event.sessionId);
42
- logger.onLog((entry) => activityLog.write(entry));
43
- }
44
- if (activityLog) {
45
- activityLog.writeEvent(event);
46
- }
47
- if (!jsonMode) {
48
- printEvent(event, { quiet: quietMode });
49
- }
50
- });
51
-
52
- // KJC-BUG-0081 round 2 — propagate `flags` so the helper honours
53
- // `--yes` here too. Before this fix, `kj resume <id> --yes` in
54
- // non-TTY mode still routed every prompt to the HU Board bridge
55
- // and hung, exactly the bug the original PR #995 fixed for `kj run`.
56
- const askQuestion = createCliAskQuestion({ sessionId, flags });
57
- const result = await resumeFlow({
58
- sessionId,
59
- answer: answer || null,
60
- config,
61
- logger,
62
- flags: flags || {},
63
- emitter,
64
- askQuestion
65
- });
66
-
67
- if (jsonMode || !answer) {
68
- console.log(JSON.stringify(result, null, 2));
69
- }
70
- return result;
71
- });
72
- }
@@ -1,89 +0,0 @@
1
- import { createAgent } from "../agents/index.js";
2
- import { assertAgentsAvailable } from "../agents/availability.js";
3
- import { computeBaseRef, generateDiff } from "../review/diff-generator.js";
4
- import { buildReviewerPrompt } from "../prompts/reviewer.js";
5
- import { resolveRole } from "../config.js";
6
- import { resolveReviewProfile } from "../review/profiles.js";
7
- import { withCliRunLog } from "../utils/cli-run-log.js";
8
- import { createCliProgressReporter } from "../utils/cli-progress.js";
9
-
10
- export async function reviewCommand({ task, config, logger, baseRef }) {
11
- return withCliRunLog("review", { projectDir: config?.projectDir, logger }, async ({ runLog }) => {
12
- const reviewerRole = resolveRole(config, "reviewer");
13
- await assertAgentsAvailable([reviewerRole.provider]);
14
- logger.info(`Reviewer (${reviewerRole.provider}) starting...`);
15
- runLog.logText(`[reviewer] provider=${reviewerRole.provider} baseRef=${baseRef || "(auto)"}`);
16
- const reviewer = createAgent(reviewerRole.provider, config, logger);
17
-
18
- let diff;
19
- if (config.ci?.enabled) {
20
- // CI mode: read diff from open PR
21
- const { detectRepo, detectPrNumber } = await import("../ci/repo.js");
22
- const { getPrDiff } = await import("../ci/pr-diff.js");
23
- const repo = await detectRepo();
24
- const prNumber = await detectPrNumber();
25
- if (!prNumber) {
26
- throw new Error("CI enabled but no open PR found for current branch. Create a PR first or disable CI.");
27
- }
28
- logger.info(`CI: reading PR diff #${prNumber}`);
29
- diff = await getPrDiff(prNumber);
30
- // Store for dispatch later
31
- config._ci_pr = { repo, prNumber };
32
- } else {
33
- const resolvedBase = await computeBaseRef({ baseBranch: config.base_branch, baseRef });
34
- diff = await generateDiff({ baseRef: resolvedBase });
35
- }
36
-
37
- const { rules } = await resolveReviewProfile({ mode: config.review_mode, projectDir: process.cwd() });
38
-
39
- const prompt = await buildReviewerPrompt({ task, diff, reviewRules: rules, mode: config.review_mode });
40
- const progress = createCliProgressReporter({ role: "reviewer" });
41
- let result;
42
- try {
43
- result = await reviewer.reviewTask({ prompt, onOutput: progress.onOutput, role: "reviewer" });
44
- progress.finish(result.ok ? "done" : "failed");
45
- } catch (err) { progress.finish("failed"); throw err; }
46
- if (!result.ok) {
47
- if (result.error) logger.error(result.error);
48
- throw new Error(result.error || result.output || `Reviewer failed (exit ${result.exitCode})`);
49
- }
50
- console.log(result.output);
51
- logger.info(`Reviewer completed (exit ${result.exitCode})`);
52
-
53
- // CI: dispatch review result
54
- if (config.ci?.enabled && config._ci_pr) {
55
- try {
56
- const { dispatchReview, dispatchComment } = await import("../ci/dispatch.js");
57
- const { repo, prNumber } = config._ci_pr;
58
- const bc = config.ci;
59
-
60
- // Try to parse structured review from output
61
- let review;
62
- try {
63
- review = JSON.parse(result.output);
64
- } catch { /* output is not JSON */
65
- review = { approved: true, summary: result.output };
66
- }
67
-
68
- const event = review.approved ? "APPROVE" : "REQUEST_CHANGES";
69
- await dispatchReview({
70
- repo, prNumber, event,
71
- body: review.summary || result.output.slice(0, 500),
72
- agent: "Reviewer", ciConfig: bc
73
- });
74
-
75
- await dispatchComment({
76
- repo, prNumber, agent: "Reviewer",
77
- body: `Standalone review: ${event}\n\n${review.summary || result.output.slice(0, 1000)}`,
78
- ciConfig: bc
79
- });
80
-
81
- logger.info(`CI: dispatched review for PR #${prNumber}`);
82
- } catch (err) {
83
- logger.warn(`CI dispatch failed (non-blocking): ${err.message}`);
84
- }
85
- }
86
- runLog.logText(`[reviewer] finished (exit=${result.exitCode})`);
87
- return { ok: true };
88
- });
89
- }
@@ -1,185 +0,0 @@
1
- import { EventEmitter } from "node:events";
2
- import { runFlow } from "../orchestrator.js";
3
- import { assertAgentsAvailable } from "../agents/availability.js";
4
- import { createActivityLog } from "../activity-log.js";
5
- import { withCliRunLog } from "../utils/cli-run-log.js";
6
- import { registerRun, unregisterRun } from "../utils/run-registry.js";
7
- import { printHeader } from "../utils/display/header.js";
8
- import { printEvent } from "../utils/display/event-handlers.js";
9
- import { printResumeHint } from "../utils/display/resume-hint.js";
10
- import { resolveRole } from "../config.js";
11
- import { parseCardId } from "../planning-game/adapter.js";
12
- import { confirmCwd } from "../utils/cwd-confirm.js";
13
- import { runSpecReview } from "../spec-review/run-spec-review.js";
14
- import { maybeAutoUpdate } from "../rag/auto-update.js";
15
-
16
- // Re-export the shared helper so existing imports (tests, MCP wrappers)
17
- // keep working. KJC-BUG-0081 round 2 split the body into utils/ because
18
- // resume.js also needs the same contract.
19
- import { createCliAskQuestion } from "../utils/cli-ask-question.js";
20
- import { buildDecider } from "../autonomy/decider.js";
21
- import { createAutonomyAskQuestion } from "../autonomy/stage-ask.js";
22
- export { createCliAskQuestion };
23
-
24
- export async function runCommandHandler({ task, config, logger, flags }) {
25
- // PR-F (cwd confirmation): when launching from an interactive
26
- // terminal, surface the working directory so the user can abort if
27
- // they typed `kj run` from the wrong place. The user's words:
28
- // "todas las que lo lancé desde terminal te garantizo que estaba
29
- // en la carpeta del proyecto … aún así preguntar por si acaso".
30
- //
31
- // Skip the prompt when:
32
- // - --yes / -y is set (CI / scripted runs),
33
- // - --json mode is on (machine-readable output, no TTY assumed),
34
- // - stdin is not a TTY (piped, board-spawned subprocess, MCP).
35
- const projectDir = config?.projectDir || process.cwd();
36
- const canPrompt = process.stdin.isTTY && process.stdout.isTTY
37
- && !flags?.yes && !flags?.json;
38
- if (canPrompt) {
39
- const ok = await confirmCwd(projectDir);
40
- if (!ok) {
41
- console.log("Aborted by user.");
42
- return { ok: false, aborted: true };
43
- }
44
- }
45
-
46
- // KJC-TSK-0455 — Pre-run drift check. Default ON; opt out with
47
- // --no-rag-update (flag) or config.rag.autoUpdate.onRun=false. If the
48
- // local index is behind HEAD we re-embed the delta before the agents
49
- // start reading from the RAG store; on any failure we log and move on
50
- // so a broken vector store never blocks a run.
51
- await maybeAutoUpdate({ projectDir, config, logger, flags });
52
-
53
- // Best-effort session cleanup before starting
54
- try {
55
- const { cleanupExpiredSessions } = await import("../session-cleanup.js");
56
- await cleanupExpiredSessions({ logger });
57
- } catch { /* non-blocking */ }
58
-
59
- const requiredProviders = [
60
- resolveRole(config, "coder").provider
61
- ];
62
- if (config.pipeline?.reviewer?.enabled !== false) {
63
- requiredProviders.push(resolveRole(config, "reviewer").provider);
64
- }
65
- if (config.pipeline?.triage?.enabled) requiredProviders.push(resolveRole(config, "triage").provider);
66
- if (config.pipeline?.planner?.enabled) requiredProviders.push(resolveRole(config, "planner").provider);
67
- if (config.pipeline?.refactorer?.enabled) requiredProviders.push(resolveRole(config, "refactorer").provider);
68
- if (config.pipeline?.researcher?.enabled) requiredProviders.push(resolveRole(config, "researcher").provider);
69
- if (config.pipeline?.tester?.enabled) requiredProviders.push(resolveRole(config, "tester").provider);
70
- if (config.pipeline?.security?.enabled) requiredProviders.push(resolveRole(config, "security").provider);
71
- await assertAgentsAvailable(requiredProviders);
72
-
73
- // --- Planning Game: resolve card ID ---
74
- const pgCardId = flags?.pgTask || parseCardId(task);
75
- const pgProject = flags?.pgProject || config.planning_game?.project_id || null;
76
-
77
- const jsonMode = flags?.json;
78
- // Quiet mode is the default; --verbose disables it
79
- const quietMode = config.output?.quiet !== false;
80
-
81
- return withCliRunLog("run", { projectDir: config?.projectDir, logger }, async ({ runLog, forwardProgress }) => {
82
- runLog.logText(`[kj_run] task="${String(task).slice(0, 80)}..."`);
83
-
84
- // KJC-TSK-0396 extensión: registrar el PID + planId + huIds en
85
- // ~/.karajan/runs/<runId>.json para que el HU Board pueda mostrar
86
- // el botón ⏹ Stop incluso cuando el run se lanza desde terminal
87
- // externa (no solo desde el botón ▶ Run del board). Best-effort:
88
- // si la escritura falla, el run sigue su curso normal. Limpieza
89
- // garantizada en el finally del withCliRunLog vía registry.unregisterRun.
90
- const huIdsFromFlag = typeof flags?.hu === "string"
91
- ? flags.hu.split(",").map((s) => s.trim()).filter(Boolean)
92
- : null;
93
- const runId = registerRun({
94
- pid: process.pid,
95
- planId: flags?.plan || null,
96
- huIds: huIdsFromFlag,
97
- projectDir: config?.projectDir || process.cwd(),
98
- source: "cli",
99
- });
100
- const cleanupRegistry = () => { if (runId) unregisterRun(runId); };
101
- // Cubrir todos los caminos de salida del proceso.
102
- process.once("exit", cleanupRegistry);
103
- process.once("SIGTERM", () => { cleanupRegistry(); process.exit(143); });
104
- process.once("SIGINT", () => { cleanupRegistry(); process.exit(130); });
105
-
106
- const emitter = new EventEmitter();
107
- let activityLog = null;
108
-
109
- // Mirror every progress event into .kj/run.log so kj-tail works identically
110
- // whether the command came from the MCP server or the CLI (KJC-TSK-0327 follow-up).
111
- forwardProgress(emitter);
112
-
113
- emitter.on("progress", (event) => {
114
- if (!activityLog && event.sessionId) {
115
- activityLog = createActivityLog(event.sessionId);
116
- logger.onLog((entry) => activityLog.write(entry));
117
- }
118
-
119
- if (activityLog) {
120
- activityLog.writeEvent(event);
121
- }
122
-
123
- if (!jsonMode) {
124
- printEvent(event, { quiet: quietMode });
125
- }
126
- });
127
-
128
- if (!jsonMode) {
129
- printHeader({ task: task, config });
130
- }
131
-
132
- const askQuestion = createCliAskQuestion({ flags });
133
-
134
- // Autonomy (KJC-PCS-0062): wire the level to a resolver. In autonomous mode
135
- // every gate is decided by the Arbiter instead of the human; interactive
136
- // keeps the human prompts. The decider is threaded into the gates below.
137
- const { autonomy, resolve: decide } = buildDecider({ config, flags, ask: askQuestion, logger });
138
-
139
- // Spec-reviewer pre-pipeline audit (KJC-PCS-0048). Runs BEFORE
140
- // anything else — surfaces ambiguity / missing scope / missing AC.
141
- // In autonomous mode the Arbiter decides (never aborts); interactive
142
- // lets the user bail. Bypass with --skip-spec-review.
143
- const reviewResult = await runSpecReview({ spec: task, config, logger, askQuestion, flags, resolve: decide, autonomy });
144
- if (!reviewResult.proceed) {
145
- logger.info("Aborted by user after spec review.");
146
- cleanupRegistry();
147
- return { ok: false, aborted: true, reason: "spec-review-cancelled" };
148
- }
149
- // If the user refined the spec via [r]efine, downstream runs the
150
- // REFINED text (not the original) so the pipeline acts on what the
151
- // user actually approved.
152
- const effectiveTask = reviewResult.refined && reviewResult.finalSpec ? reviewResult.finalSpec : task;
153
-
154
- // AUTO-E: in autonomous mode the stages never ask a human or block on the
155
- // board — they auto-continue with the least-bad choice. interactive/assisted
156
- // keep the human prompts.
157
- const stageAsk = createAutonomyAskQuestion({ baseAsk: askQuestion, autonomy, logger });
158
-
159
- let result;
160
- try {
161
- result = await runFlow({ task: effectiveTask, config, logger, flags, emitter, askQuestion: stageAsk, pgTaskId: pgCardId || null, pgProject: pgProject || null });
162
- } finally {
163
- // KJC-TSK-0396: limpia el registro pase lo que pase (éxito,
164
- // throw, o paused). Los handlers de SIGINT/SIGTERM/exit son
165
- // backstop para casos donde el throw no llega aquí (segfault,
166
- // kill -9, etc.).
167
- cleanupRegistry();
168
- }
169
-
170
- if (jsonMode) {
171
- console.log(JSON.stringify(result, null, 2));
172
- } else {
173
- // Last line printed: if the run stopped (hibernated / paused /
174
- // failed), tell the user the exact command to resume it.
175
- printResumeHint(result);
176
- }
177
- // Surface per-HU results so `kj autorun` can build a real outcome report
178
- // (KJC-BUG-0090: it showed "0/0 met the ask" because only { ok } came back).
179
- // The plan run returns them as `huResults` (run-hu-batch finalResult).
180
- const hus = Array.isArray(result?.huResults)
181
- ? result.huResults.map((r) => ({ id: r.huId, met: r.approved === true }))
182
- : [];
183
- return { ok: !result?.paused && result?.approved !== false, hus };
184
- });
185
- }