@karajan-family/code 4.21.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 (746) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +98 -0
  3. package/bin/karajan-mcp.js +2 -0
  4. package/bin/kj-rag-mcp.js +75 -0
  5. package/bin/kj-tail +361 -0
  6. package/bin/kj.js +2 -0
  7. package/docs/README.es.md +80 -0
  8. package/docs/karajan-code-logo-small.png +0 -0
  9. package/library/logical-clocks-lamport.md +40 -0
  10. package/package.json +140 -0
  11. package/packages/ai-trash/README.md +37 -0
  12. package/packages/ai-trash/bin/kj-trash.js +10 -0
  13. package/packages/ai-trash/package.json +43 -0
  14. package/packages/ai-trash/src/cli.js +200 -0
  15. package/packages/ai-trash/src/destructive-parser.js +74 -0
  16. package/packages/ai-trash/src/git-snapshot.js +128 -0
  17. package/packages/ai-trash/src/hook.js +137 -0
  18. package/packages/ai-trash/src/index.js +14 -0
  19. package/packages/ai-trash/src/install.js +73 -0
  20. package/packages/ai-trash/src/logger.js +60 -0
  21. package/packages/ai-trash/src/manifest.js +91 -0
  22. package/packages/ai-trash/src/permissions.js +26 -0
  23. package/packages/ai-trash/src/snapshot.js +66 -0
  24. package/packages/ai-trash/src/ulid.js +66 -0
  25. package/packages/hu-board/README.md +69 -0
  26. package/packages/hu-board/package.json +28 -0
  27. package/packages/hu-board/public/app.js +259 -0
  28. package/packages/hu-board/public/index.html +77 -0
  29. package/packages/hu-board/public/pipeline.css +132 -0
  30. package/packages/hu-board/public/pipeline.html +48 -0
  31. package/packages/hu-board/public/pipeline.js +200 -0
  32. package/packages/hu-board/public/rag.html +21 -0
  33. package/packages/hu-board/public/rag.js +39 -0
  34. package/packages/hu-board/public/styles.css +973 -0
  35. package/packages/hu-board/public/utils/api.js +139 -0
  36. package/packages/hu-board/public/utils/board-view.js +473 -0
  37. package/packages/hu-board/public/utils/command-launcher.js +213 -0
  38. package/packages/hu-board/public/utils/config-editor.js +181 -0
  39. package/packages/hu-board/public/utils/dashboard-view.js +103 -0
  40. package/packages/hu-board/public/utils/formatters.js +300 -0
  41. package/packages/hu-board/public/utils/graph-view.js +216 -0
  42. package/packages/hu-board/public/utils/hu-actions.js +224 -0
  43. package/packages/hu-board/public/utils/init-listeners.js +180 -0
  44. package/packages/hu-board/public/utils/log-panel.js +222 -0
  45. package/packages/hu-board/public/utils/modals.js +309 -0
  46. package/packages/hu-board/public/utils/plan-rollup-view.js +53 -0
  47. package/packages/hu-board/public/utils/preflight-view.js +89 -0
  48. package/packages/hu-board/public/utils/project-actions.js +143 -0
  49. package/packages/hu-board/public/utils/project-picker-view.js +139 -0
  50. package/packages/hu-board/public/utils/run-launcher.js +169 -0
  51. package/packages/hu-board/public/utils/server-push.js +252 -0
  52. package/packages/hu-board/public/utils/sessions-view.js +199 -0
  53. package/packages/hu-board/public/utils/story-detail-view.js +324 -0
  54. package/packages/hu-board/public/utils/story-edit-form.js +271 -0
  55. package/packages/hu-board/public/wiki.html +32 -0
  56. package/packages/hu-board/public/wiki.js +53 -0
  57. package/packages/hu-board/src/auth.js +92 -0
  58. package/packages/hu-board/src/boot-info.js +16 -0
  59. package/packages/hu-board/src/cleanup-zombies.js +145 -0
  60. package/packages/hu-board/src/command-runner.js +133 -0
  61. package/packages/hu-board/src/config-yaml.js +531 -0
  62. package/packages/hu-board/src/db.js +963 -0
  63. package/packages/hu-board/src/ephemeral-cleaner.js +196 -0
  64. package/packages/hu-board/src/event-bus.js +58 -0
  65. package/packages/hu-board/src/format.js +207 -0
  66. package/packages/hu-board/src/hu-zombie-reaper.js +103 -0
  67. package/packages/hu-board/src/journal-parser.js +180 -0
  68. package/packages/hu-board/src/plan-mutations.js +424 -0
  69. package/packages/hu-board/src/preflight.js +286 -0
  70. package/packages/hu-board/src/routes/api.js +1374 -0
  71. package/packages/hu-board/src/routes/pipeline.js +45 -0
  72. package/packages/hu-board/src/routes/rag.js +42 -0
  73. package/packages/hu-board/src/routes/wiki.js +43 -0
  74. package/packages/hu-board/src/run-tracker.js +121 -0
  75. package/packages/hu-board/src/server.js +438 -0
  76. package/packages/hu-board/src/sync.js +732 -0
  77. package/packages/hu-board/src/token-store.js +56 -0
  78. package/packages/hu-board/src/zombie-reaper.js +206 -0
  79. package/scripts/ai-attribution-guard.yml +84 -0
  80. package/scripts/audit-test-diet.mjs +151 -0
  81. package/scripts/build-sea.mjs +150 -0
  82. package/scripts/diet-baseline.mjs +170 -0
  83. package/scripts/dual-publish.mjs +67 -0
  84. package/scripts/esbuild-sea.config.mjs +273 -0
  85. package/scripts/git-hooks/post-merge +18 -0
  86. package/scripts/install-binary.ps1 +174 -0
  87. package/scripts/install-binary.sh +159 -0
  88. package/scripts/install-guard-all-repos.sh +85 -0
  89. package/scripts/install-kj.sh +193 -0
  90. package/scripts/install.js +901 -0
  91. package/scripts/install.sh +7 -0
  92. package/scripts/postinstall.js +117 -0
  93. package/scripts/protect-all-repos.sh +88 -0
  94. package/scripts/quickstart-gate.mjs +97 -0
  95. package/scripts/regen-arch-stats.sh +71 -0
  96. package/scripts/setup-multi-instance.sh +150 -0
  97. package/scripts/verify-pack.mjs +278 -0
  98. package/src/activity-log.js +59 -0
  99. package/src/agents/agy-agent.js +62 -0
  100. package/src/agents/aider-agent.js +78 -0
  101. package/src/agents/availability.js +52 -0
  102. package/src/agents/base-agent.js +134 -0
  103. package/src/agents/claude-agent.js +413 -0
  104. package/src/agents/codex-agent.js +112 -0
  105. package/src/agents/copilot-agent.js +65 -0
  106. package/src/agents/gemini-agent.js +85 -0
  107. package/src/agents/host-agent.js +38 -0
  108. package/src/agents/index.js +59 -0
  109. package/src/agents/kimi-agent.js +45 -0
  110. package/src/agents/model-registry.js +137 -0
  111. package/src/agents/opencode-agent.js +72 -0
  112. package/src/agents/qwen-agent.js +20 -0
  113. package/src/agents/resolve-bin.js +73 -0
  114. package/src/audit/agent-readiness.js +259 -0
  115. package/src/audit/ai-slop-findings.js +102 -0
  116. package/src/audit/audit-fallback.js +66 -0
  117. package/src/audit/audit-history-display.js +61 -0
  118. package/src/audit/audit-history.js +102 -0
  119. package/src/audit/basal-cost.js +281 -0
  120. package/src/audit/circular-deps.js +144 -0
  121. package/src/audit/dead-exports.js +186 -0
  122. package/src/audit/deterministic-summary.js +327 -0
  123. package/src/audit/harness-scorecard.js +100 -0
  124. package/src/audit/harness-section.js +81 -0
  125. package/src/audit/infra-findings.js +100 -0
  126. package/src/audit/injection-findings.js +114 -0
  127. package/src/audit/issue-filter.js +133 -0
  128. package/src/audit/osv-findings.js +167 -0
  129. package/src/audit/plan-adherence.js +224 -0
  130. package/src/audit/semgrep-findings.js +129 -0
  131. package/src/audit/sonar-findings.js +93 -0
  132. package/src/audit/webperf-input.js +133 -0
  133. package/src/autonomy/arbiter-role.js +71 -0
  134. package/src/autonomy/arbiter.js +22 -0
  135. package/src/autonomy/decider.js +18 -0
  136. package/src/autonomy/decision-resolver.js +58 -0
  137. package/src/autonomy/outcome-report.js +55 -0
  138. package/src/autonomy/policy.js +41 -0
  139. package/src/autonomy/stage-ask.js +30 -0
  140. package/src/bootstrap.js +276 -0
  141. package/src/brain/agent-error-classifier.js +116 -0
  142. package/src/brain/decision-tracker.js +125 -0
  143. package/src/brain/decisor.js +243 -0
  144. package/src/brain/solomon-consult.js +171 -0
  145. package/src/brain/standby-scheduler.js +8 -0
  146. package/src/brain/standby-store.js +12 -0
  147. package/src/brain/with-brain-recovery.js +235 -0
  148. package/src/budget/comparison.js +96 -0
  149. package/src/canvas/parse-md.js +238 -0
  150. package/src/canvas/schema.js +101 -0
  151. package/src/canvas/to-flat.js +85 -0
  152. package/src/canvas/validate.js +163 -0
  153. package/src/checks/ai-surface.js +79 -0
  154. package/src/checks/ai-trash.js +34 -0
  155. package/src/checks/binaries.js +207 -0
  156. package/src/checks/ci.js +105 -0
  157. package/src/checks/config-files.js +217 -0
  158. package/src/checks/dir-setup.js +103 -0
  159. package/src/checks/guarantee-level.js +38 -0
  160. package/src/checks/hardware.js +150 -0
  161. package/src/checks/harness-scorecard.js +41 -0
  162. package/src/checks/mcp-health.js +169 -0
  163. package/src/checks/method.js +73 -0
  164. package/src/checks/native-build.js +67 -0
  165. package/src/checks/node.js +70 -0
  166. package/src/checks/ollama.js +41 -0
  167. package/src/checks/orphans.js +77 -0
  168. package/src/checks/ports.js +188 -0
  169. package/src/checks/project-checks.js +245 -0
  170. package/src/checks/qmd.js +41 -0
  171. package/src/checks/rag-hooks.js +54 -0
  172. package/src/checks/release-check.js +102 -0
  173. package/src/checks/rtk.js +36 -0
  174. package/src/checks/runner.js +326 -0
  175. package/src/checks/skills.js +53 -0
  176. package/src/checks/sonar.js +67 -0
  177. package/src/checks/squeezr.js +36 -0
  178. package/src/checks/system.js +53 -0
  179. package/src/checks/tokens.js +172 -0
  180. package/src/checks/types.js +103 -0
  181. package/src/ci/dispatch.js +99 -0
  182. package/src/ci/index.js +3 -0
  183. package/src/ci/pr-diff.js +26 -0
  184. package/src/ci/repo.js +45 -0
  185. package/src/cli/_shared.js +30 -0
  186. package/src/cli/advanced-commands.js +61 -0
  187. package/src/cli/register-meta.js +772 -0
  188. package/src/cli/register-pipeline.js +335 -0
  189. package/src/cli/register-plan.js +224 -0
  190. package/src/cli/register-roles-skills.js +54 -0
  191. package/src/cli/register-sonar.js +28 -0
  192. package/src/cli/register-standby.js +26 -0
  193. package/src/cli.js +155 -0
  194. package/src/commands/advanced.js +31 -0
  195. package/src/commands/agent-run.js +63 -0
  196. package/src/commands/agents.js +105 -0
  197. package/src/commands/architect.js +123 -0
  198. package/src/commands/audit.js +430 -0
  199. package/src/commands/autorun.js +49 -0
  200. package/src/commands/board.js +458 -0
  201. package/src/commands/check.js +40 -0
  202. package/src/commands/clean.js +145 -0
  203. package/src/commands/code.js +45 -0
  204. package/src/commands/config.js +74 -0
  205. package/src/commands/discover.js +105 -0
  206. package/src/commands/doctor.js +251 -0
  207. package/src/commands/env.js +207 -0
  208. package/src/commands/harden.js +203 -0
  209. package/src/commands/hu.js +210 -0
  210. package/src/commands/identity.js +60 -0
  211. package/src/commands/init.js +950 -0
  212. package/src/commands/install-tools.js +432 -0
  213. package/src/commands/mutate.js +94 -0
  214. package/src/commands/ollama.js +44 -0
  215. package/src/commands/onboard.js +45 -0
  216. package/src/commands/plan/_shared.js +55 -0
  217. package/src/commands/plan/add-hu.js +23 -0
  218. package/src/commands/plan/delete.js +9 -0
  219. package/src/commands/plan/fix.js +99 -0
  220. package/src/commands/plan/generate.js +532 -0
  221. package/src/commands/plan/index.js +13 -0
  222. package/src/commands/plan/list.js +21 -0
  223. package/src/commands/plan/migrate-result.js +41 -0
  224. package/src/commands/plan/ready.js +46 -0
  225. package/src/commands/plan/remove-hu.js +17 -0
  226. package/src/commands/plan/share.js +85 -0
  227. package/src/commands/plan/show.js +81 -0
  228. package/src/commands/plan/unshare.js +41 -0
  229. package/src/commands/plan/validate.js +20 -0
  230. package/src/commands/plan.js +17 -0
  231. package/src/commands/policy.js +164 -0
  232. package/src/commands/privacy.js +45 -0
  233. package/src/commands/qmd.js +86 -0
  234. package/src/commands/rag-mcp.js +18 -0
  235. package/src/commands/rag.js +173 -0
  236. package/src/commands/report-issue.js +77 -0
  237. package/src/commands/report.js +469 -0
  238. package/src/commands/researcher.js +54 -0
  239. package/src/commands/resume.js +68 -0
  240. package/src/commands/review-gate.js +355 -0
  241. package/src/commands/review.js +89 -0
  242. package/src/commands/roles.js +116 -0
  243. package/src/commands/run.js +185 -0
  244. package/src/commands/scan.js +18 -0
  245. package/src/commands/skills.js +86 -0
  246. package/src/commands/sonar.js +53 -0
  247. package/src/commands/standby.js +117 -0
  248. package/src/commands/start.js +121 -0
  249. package/src/commands/status.js +36 -0
  250. package/src/commands/sync.js +103 -0
  251. package/src/commands/telemetry.js +70 -0
  252. package/src/commands/tournament.js +85 -0
  253. package/src/commands/triage.js +78 -0
  254. package/src/commands/undo.js +62 -0
  255. package/src/commands/watch.js +46 -0
  256. package/src/commands/webperf.js +162 -0
  257. package/src/commands/worktree.js +76 -0
  258. package/src/config/defaults.js +270 -0
  259. package/src/config/loader.js +204 -0
  260. package/src/config/overrides.js +220 -0
  261. package/src/config/role-resolver.js +171 -0
  262. package/src/config/schema.js +299 -0
  263. package/src/config/test-harness.js +78 -0
  264. package/src/config.js +34 -0
  265. package/src/domains/domain-loader.js +245 -0
  266. package/src/domains/domain-registry.js +140 -0
  267. package/src/domains/domain-synthesizer.js +129 -0
  268. package/src/environment/adr.js +45 -0
  269. package/src/environment/board-access.js +97 -0
  270. package/src/environment/board-select.js +59 -0
  271. package/src/environment/briefs.js +129 -0
  272. package/src/environment/issue-report.js +72 -0
  273. package/src/environment/mcp-wiring.js +44 -0
  274. package/src/environment/playbook.js +127 -0
  275. package/src/git/automation.js +334 -0
  276. package/src/git/hu-automation.js +171 -0
  277. package/src/git/hu-snapshot.js +10 -0
  278. package/src/golden/asserter.js +92 -0
  279. package/src/golden/loader.js +52 -0
  280. package/src/golden/runner.js +92 -0
  281. package/src/golden/schema.js +41 -0
  282. package/src/guards/intent-guard.js +161 -0
  283. package/src/guards/output-guard.js +149 -0
  284. package/src/guards/perf-guard.js +126 -0
  285. package/src/guards/policy-guard.js +90 -0
  286. package/src/guards/policy-resolver.js +85 -0
  287. package/src/guards/secret-redactor.js +71 -0
  288. package/src/harden/advisory.js +203 -0
  289. package/src/harden/alternatives.js +50 -0
  290. package/src/harden/check.js +81 -0
  291. package/src/harden/config-engine.js +128 -0
  292. package/src/harden/config-templates.js +122 -0
  293. package/src/harden/guidelines-engine.js +48 -0
  294. package/src/harden/guidelines-templates.js +36 -0
  295. package/src/harden/harden-engine.js +80 -0
  296. package/src/harden/harness-hooks.js +107 -0
  297. package/src/harden/hook-commands.js +25 -0
  298. package/src/harden/hook-templates.js +183 -0
  299. package/src/harden/interactive.js +76 -0
  300. package/src/harden/sentinel-hooks.js +721 -0
  301. package/src/harden/stack-roots.js +105 -0
  302. package/src/harden/test-on-push.js +38 -0
  303. package/src/harden/workflow-engine.js +116 -0
  304. package/src/harden/workflow-templates.js +285 -0
  305. package/src/hu/acceptance-runner.js +138 -0
  306. package/src/hu/auto-generator.js +358 -0
  307. package/src/hu/graph.js +71 -0
  308. package/src/hu/lazy-planner.js +109 -0
  309. package/src/hu/model-router.js +108 -0
  310. package/src/hu/parallel-executor.js +94 -0
  311. package/src/hu/split-validator.js +143 -0
  312. package/src/hu/splitting-detector.js +158 -0
  313. package/src/hu/splitting-generator.js +175 -0
  314. package/src/hu/store.js +392 -0
  315. package/src/hu/worktree-bootstrap.js +59 -0
  316. package/src/identity/bootstrap.js +48 -0
  317. package/src/identity/compare.js +38 -0
  318. package/src/identity/detect.js +51 -0
  319. package/src/identity/store.js +66 -0
  320. package/src/infrastructure/command-runner.js +44 -0
  321. package/src/infrastructure/environment.js +38 -0
  322. package/src/infrastructure/file-system-service.js +63 -0
  323. package/src/infrastructure/mocks.js +182 -0
  324. package/src/lang/chunk-go.js +94 -0
  325. package/src/lang/chunk-java.js +90 -0
  326. package/src/lang/chunk-python.js +88 -0
  327. package/src/lang/chunk-rust.js +102 -0
  328. package/src/lang/go.js +14 -0
  329. package/src/lang/java.js +16 -0
  330. package/src/lang/js.js +8 -0
  331. package/src/lang/python.js +14 -0
  332. package/src/lang/registry.js +79 -0
  333. package/src/lang/rust.js +14 -0
  334. package/src/lang/tree-sitter-loader.js +45 -0
  335. package/src/mcp/direct-role-runner.js +112 -0
  336. package/src/mcp/error-classifiers.js +66 -0
  337. package/src/mcp/handlers/direct-handlers.js +486 -0
  338. package/src/mcp/handlers/hu-handlers.js +93 -0
  339. package/src/mcp/handlers/management-handlers.js +265 -0
  340. package/src/mcp/handlers/rag-handler.js +52 -0
  341. package/src/mcp/handlers/run-handler.js +313 -0
  342. package/src/mcp/orphan-guard.js +131 -0
  343. package/src/mcp/preflight.js +47 -0
  344. package/src/mcp/progress.js +149 -0
  345. package/src/mcp/response-compressor.js +81 -0
  346. package/src/mcp/run-kj.js +135 -0
  347. package/src/mcp/server-handlers.js +79 -0
  348. package/src/mcp/server.js +66 -0
  349. package/src/mcp/shared-helpers.js +297 -0
  350. package/src/mcp/sovereignty-guard.js +112 -0
  351. package/src/mcp/suggest-handler.js +92 -0
  352. package/src/mcp/tool-arg-normalizers.js +16 -0
  353. package/src/mcp/tools.js +432 -0
  354. package/src/mutate/diff-scope.js +105 -0
  355. package/src/mutate/reviewer-signal.js +76 -0
  356. package/src/mutate/runner.js +72 -0
  357. package/src/mutate/tool-registry.js +90 -0
  358. package/src/onboarder/cache.js +24 -0
  359. package/src/onboarder/collectors/framework-multilang.js +64 -0
  360. package/src/onboarder/collectors/index.js +136 -0
  361. package/src/orchestrator/agent-fallback.js +81 -0
  362. package/src/orchestrator/brain-coordinator.js +186 -0
  363. package/src/orchestrator/ci-integration.js +139 -0
  364. package/src/orchestrator/config-init.js +510 -0
  365. package/src/orchestrator/direct-actions.js +217 -0
  366. package/src/orchestrator/drivers/error-recovery.js +287 -0
  367. package/src/orchestrator/drivers/init-context.js +227 -0
  368. package/src/orchestrator/drivers/iteration-loop.js +380 -0
  369. package/src/orchestrator/drivers/iteration-phases/coder-and-refactorer.js +69 -0
  370. package/src/orchestrator/drivers/iteration-phases/guards.js +84 -0
  371. package/src/orchestrator/drivers/iteration-phases/handle-approved.js +29 -0
  372. package/src/orchestrator/drivers/iteration-phases/quality-gates.js +114 -0
  373. package/src/orchestrator/drivers/iteration-phases/reviewer-gate.js +60 -0
  374. package/src/orchestrator/drivers/post-loop.js +383 -0
  375. package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +136 -0
  376. package/src/orchestrator/drivers/pre-loop-phases/config-deprecations.js +47 -0
  377. package/src/orchestrator/drivers/pre-loop-phases/ensure-addyosmani-skills.js +84 -0
  378. package/src/orchestrator/drivers/pre-loop-phases/inject-loaded-plan.js +391 -0
  379. package/src/orchestrator/drivers/pre-loop.js +507 -0
  380. package/src/orchestrator/drivers/run-hu-batch.js +427 -0
  381. package/src/orchestrator/feedback-enrichment.js +140 -0
  382. package/src/orchestrator/feedback-queue.js +151 -0
  383. package/src/orchestrator/flow-control.js +170 -0
  384. package/src/orchestrator/flow-runner.js +364 -0
  385. package/src/orchestrator/fs-leak-detector.js +210 -0
  386. package/src/orchestrator/hu-scheduler.js +114 -0
  387. package/src/orchestrator/hu-sub-pipeline.js +616 -0
  388. package/src/orchestrator/integrations.js +81 -0
  389. package/src/orchestrator/iteration-gate.js +73 -0
  390. package/src/orchestrator/iteration-stages.js +9 -0
  391. package/src/orchestrator/parallel-limiter.js +74 -0
  392. package/src/orchestrator/pipeline-context.js +72 -0
  393. package/src/orchestrator/post-loop-stages.js +468 -0
  394. package/src/orchestrator/pre-loop-stages.js +11 -0
  395. package/src/orchestrator/preflight-checks.js +462 -0
  396. package/src/orchestrator/repair/repair-detector.js +117 -0
  397. package/src/orchestrator/repair/repair-runner.js +142 -0
  398. package/src/orchestrator/reviewer-fallback.js +45 -0
  399. package/src/orchestrator/role-output-compressor.js +189 -0
  400. package/src/orchestrator/session-journal.js +308 -0
  401. package/src/orchestrator/solomon-escalation.js +305 -0
  402. package/src/orchestrator/solomon-rules.js +212 -0
  403. package/src/orchestrator/stages/architect-stage.js +172 -0
  404. package/src/orchestrator/stages/coder-stage.js +480 -0
  405. package/src/orchestrator/stages/domain-curator-stage.js +82 -0
  406. package/src/orchestrator/stages/hu-reviewer-phases/detect-and-apply-splits.js +127 -0
  407. package/src/orchestrator/stages/hu-reviewer-stage.js +394 -0
  408. package/src/orchestrator/stages/perf-stage.js +140 -0
  409. package/src/orchestrator/stages/planner-stage.js +85 -0
  410. package/src/orchestrator/stages/rag-context-stage.js +77 -0
  411. package/src/orchestrator/stages/rag-preload-decisor.js +58 -0
  412. package/src/orchestrator/stages/research-stage.js +69 -0
  413. package/src/orchestrator/stages/reviewer-stage.js +422 -0
  414. package/src/orchestrator/stages/sonar-stage.js +421 -0
  415. package/src/orchestrator/stages/stage-classes.js +84 -0
  416. package/src/orchestrator/stages/stage-executor.js +155 -0
  417. package/src/orchestrator/stages/tdd-discipline-stage.js +56 -0
  418. package/src/orchestrator/stages/tool-judge-stage.js +53 -0
  419. package/src/orchestrator/stages/triage-stage.js +172 -0
  420. package/src/orchestrator/standby.js +71 -0
  421. package/src/orchestrator/verification-gate.js +183 -0
  422. package/src/orchestrator.js +22 -0
  423. package/src/plan/adr-generator.js +170 -0
  424. package/src/plan/adr-loader.js +60 -0
  425. package/src/plan/plan-executor.js +100 -0
  426. package/src/plan/plan-fixer.js +192 -0
  427. package/src/plan/plan-hu-ops.js +16 -0
  428. package/src/plan/plan-id.js +4 -0
  429. package/src/plan/plan-migrate-result.js +24 -0
  430. package/src/plan/plan-reviewer.js +236 -0
  431. package/src/plan/plan-schema.js +334 -0
  432. package/src/plan/plan-store.js +260 -0
  433. package/src/plan/plan-structural-pass.js +122 -0
  434. package/src/plan/plan-validation.js +4 -0
  435. package/src/plan/preflight-hu.js +105 -0
  436. package/src/plan/spec-detector.js +61 -0
  437. package/src/plan/tests-synthesizer.js +131 -0
  438. package/src/planning-game/adapter.js +108 -0
  439. package/src/planning-game/architect-adrs.js +45 -0
  440. package/src/planning-game/client.js +108 -0
  441. package/src/planning-game/decomposition.js +87 -0
  442. package/src/planning-game/pipeline-adapter.js +251 -0
  443. package/src/plugins/loader.js +67 -0
  444. package/src/policy/add.js +111 -0
  445. package/src/policy/decisions.js +42 -0
  446. package/src/policy/engine.js +82 -0
  447. package/src/policy/exceptions.js +60 -0
  448. package/src/privacy/onboarding.js +35 -0
  449. package/src/privacy/scan.js +120 -0
  450. package/src/prompts/arbiter.js +38 -0
  451. package/src/prompts/architect.js +103 -0
  452. package/src/prompts/audit.js +474 -0
  453. package/src/prompts/coder.js +287 -0
  454. package/src/prompts/diff-clip.js +27 -0
  455. package/src/prompts/discover.js +222 -0
  456. package/src/prompts/hu-reviewer.js +219 -0
  457. package/src/prompts/planner.js +312 -0
  458. package/src/prompts/prompt-layout.js +80 -0
  459. package/src/prompts/prompt-resolver.js +120 -0
  460. package/src/prompts/reviewer.js +75 -0
  461. package/src/prompts/rtk-snippet.js +25 -0
  462. package/src/prompts/spec-reviewer.js +66 -0
  463. package/src/prompts/split-signal.js +82 -0
  464. package/src/prompts/start-decision.js +52 -0
  465. package/src/prompts/tool-correctness-judge.js +31 -0
  466. package/src/prompts/triage.js +57 -0
  467. package/src/rag/auto-update.js +72 -0
  468. package/src/rag/chunker-ast.js +56 -0
  469. package/src/rag/chunker.js +132 -0
  470. package/src/rag/embedder.js +2 -0
  471. package/src/rag/embedders/_cloud-base.js +2 -0
  472. package/src/rag/embedders/cohere.js +2 -0
  473. package/src/rag/embedders/factory.js +2 -0
  474. package/src/rag/embedders/mistral.js +2 -0
  475. package/src/rag/embedders/onnx.js +2 -0
  476. package/src/rag/embedders/openai.js +2 -0
  477. package/src/rag/embedders/voyage.js +2 -0
  478. package/src/rag/eval.js +61 -0
  479. package/src/rag/governed-embedder.js +39 -0
  480. package/src/rag/indexer.js +199 -0
  481. package/src/rag/library.js +62 -0
  482. package/src/rag/ollama-capability.js +59 -0
  483. package/src/rag/ollama-manager.js +98 -0
  484. package/src/rag/onnx-fallback.js +69 -0
  485. package/src/rag/rerank.js +4 -0
  486. package/src/rag/retriever.js +2 -0
  487. package/src/rag/vec-store.js +17 -0
  488. package/src/rag/watcher.js +62 -0
  489. package/src/rag/where-parser.js +4 -0
  490. package/src/repeat-detector.js +88 -0
  491. package/src/review/card-first.js +99 -0
  492. package/src/review/card-verify.js +83 -0
  493. package/src/review/diff-generator.js +112 -0
  494. package/src/review/gate-gitignore.js +77 -0
  495. package/src/review/git-stash-helper.js +104 -0
  496. package/src/review/mutation-pregate.js +48 -0
  497. package/src/review/one-shot-review.js +122 -0
  498. package/src/review/parser.js +80 -0
  499. package/src/review/policy-gate.js +26 -0
  500. package/src/review/profiles.js +66 -0
  501. package/src/review/reviewer-fallback.js +125 -0
  502. package/src/review/schema.js +31 -0
  503. package/src/review/scope-filter.js +152 -0
  504. package/src/review/snapshot-diff.js +122 -0
  505. package/src/review/solomon-arbitration.js +113 -0
  506. package/src/review/sonar-pregate.js +63 -0
  507. package/src/review/tdd-discipline.js +90 -0
  508. package/src/review/tdd-policy.js +69 -0
  509. package/src/review/tests-with-code.js +33 -0
  510. package/src/review/verdict-store.js +87 -0
  511. package/src/review/workspace.js +21 -0
  512. package/src/roles/agent-role.js +194 -0
  513. package/src/roles/architect-role.js +77 -0
  514. package/src/roles/audit-role.js +258 -0
  515. package/src/roles/base-role.js +165 -0
  516. package/src/roles/coder-role.js +107 -0
  517. package/src/roles/commiter-role.js +110 -0
  518. package/src/roles/discover-role.js +81 -0
  519. package/src/roles/domain-curator-role.js +141 -0
  520. package/src/roles/hu-reviewer-role.js +64 -0
  521. package/src/roles/impeccable-role.js +85 -0
  522. package/src/roles/index.js +18 -0
  523. package/src/roles/karajan-brain-role.js +134 -0
  524. package/src/roles/onboarder-role.js +61 -0
  525. package/src/roles/perf-role.js +122 -0
  526. package/src/roles/planner-role.js +151 -0
  527. package/src/roles/refactorer-role.js +30 -0
  528. package/src/roles/repairer-role.js +181 -0
  529. package/src/roles/researcher-role.js +70 -0
  530. package/src/roles/reviewer-role.js +104 -0
  531. package/src/roles/security-role.js +73 -0
  532. package/src/roles/solomon-role.js +265 -0
  533. package/src/roles/sonar-role.js +70 -0
  534. package/src/roles/spec-reviewer-role.js +106 -0
  535. package/src/roles/tester-role.js +235 -0
  536. package/src/roles/tool-correctness-judge-role.js +78 -0
  537. package/src/roles/triage-role.js +99 -0
  538. package/src/session/journal/decisions-writer.js +200 -0
  539. package/src/session/journal/iteration-logger.js +194 -0
  540. package/src/session/journal/summary-writer.js +320 -0
  541. package/src/session/journal/tree-writer.js +164 -0
  542. package/src/session/journal/write-all.js +89 -0
  543. package/src/session/mutators.js +339 -0
  544. package/src/session/runtime-overrides.js +59 -0
  545. package/src/session/store.js +106 -0
  546. package/src/session-cleanup.js +116 -0
  547. package/src/skills/addyosmani-catalog.js +315 -0
  548. package/src/skills/addyosmani-role-map.js +139 -0
  549. package/src/skills/openskills-client.js +157 -0
  550. package/src/skills/semantic-detector.js +167 -0
  551. package/src/skills/skill-detector.js +385 -0
  552. package/src/skills/skill-loader.js +219 -0
  553. package/src/skills/skills-cache.js +128 -0
  554. package/src/sonar/api.js +128 -0
  555. package/src/sonar/cloud-scanner.js +78 -0
  556. package/src/sonar/config-resolver.js +88 -0
  557. package/src/sonar/credentials.js +60 -0
  558. package/src/sonar/discovery.js +124 -0
  559. package/src/sonar/enforcer.js +19 -0
  560. package/src/sonar/issue-filter.js +12 -0
  561. package/src/sonar/manager.js +181 -0
  562. package/src/sonar/project-key.js +120 -0
  563. package/src/sonar/scanner.js +307 -0
  564. package/src/sonar/token-bootstrap.js +205 -0
  565. package/src/sonar/token-recovery.js +67 -0
  566. package/src/spec-review/refine-loop.js +58 -0
  567. package/src/spec-review/run-spec-review.js +119 -0
  568. package/src/start/assessment.js +74 -0
  569. package/src/start/maturity.js +73 -0
  570. package/src/start/start-decider-role.js +79 -0
  571. package/src/start/sweep.js +157 -0
  572. package/src/sync/apply-canvas-patch.js +55 -0
  573. package/src/sync/detect-drift.js +113 -0
  574. package/src/tournament/crown.js +88 -0
  575. package/src/tournament/judge.js +150 -0
  576. package/src/tournament/run.js +142 -0
  577. package/src/tournament/scoreboard.js +124 -0
  578. package/src/tracker-bootstrap.js +44 -0
  579. package/src/types/agent.js +55 -0
  580. package/src/types/config.js +114 -0
  581. package/src/types/hu.js +47 -0
  582. package/src/types/index.js +38 -0
  583. package/src/types/policy.js +43 -0
  584. package/src/types/session.js +75 -0
  585. package/src/types/solomon.js +87 -0
  586. package/src/types/stage.js +68 -0
  587. package/src/utils/agent-detect.js +93 -0
  588. package/src/utils/ai-trash.js +48 -0
  589. package/src/utils/async-lock.js +31 -0
  590. package/src/utils/atomic-write.js +6 -0
  591. package/src/utils/banner.js +66 -0
  592. package/src/utils/binary-sources.js +70 -0
  593. package/src/utils/board-prompt-bridge.js +108 -0
  594. package/src/utils/budget.js +229 -0
  595. package/src/utils/cli-ask-question.js +93 -0
  596. package/src/utils/cli-progress.js +220 -0
  597. package/src/utils/cli-run-log.js +83 -0
  598. package/src/utils/cwd-confirm.js +39 -0
  599. package/src/utils/derive-project-name-from-cwd.js +119 -0
  600. package/src/utils/display/event-handlers.js +403 -0
  601. package/src/utils/display/formatters.js +132 -0
  602. package/src/utils/display/header.js +47 -0
  603. package/src/utils/display/resume-hint.js +41 -0
  604. package/src/utils/display/session-summary.js +118 -0
  605. package/src/utils/display/solomon.js +42 -0
  606. package/src/utils/display/spec-findings.js +44 -0
  607. package/src/utils/doc-links.js +29 -0
  608. package/src/utils/docker-install.js +34 -0
  609. package/src/utils/escape-regexp.js +15 -0
  610. package/src/utils/events.js +35 -0
  611. package/src/utils/fs.js +19 -0
  612. package/src/utils/garbage-collector.js +481 -0
  613. package/src/utils/git.js +279 -0
  614. package/src/utils/home-migration.js +87 -0
  615. package/src/utils/injection-guard.js +186 -0
  616. package/src/utils/install-hints.js +180 -0
  617. package/src/utils/json-extract.js +64 -0
  618. package/src/utils/locale.js +59 -0
  619. package/src/utils/logger.js +96 -0
  620. package/src/utils/managed-markers.js +93 -0
  621. package/src/utils/manifest-sniff.js +82 -0
  622. package/src/utils/messages.js +61 -0
  623. package/src/utils/model-selector.js +107 -0
  624. package/src/utils/os-detect.js +79 -0
  625. package/src/utils/paths.js +13 -0
  626. package/src/utils/pending-user-action.js +95 -0
  627. package/src/utils/port-check.js +6 -0
  628. package/src/utils/port-occupant.js +96 -0
  629. package/src/utils/pricing.js +29 -0
  630. package/src/utils/process.js +4 -0
  631. package/src/utils/project-detect.js +160 -0
  632. package/src/utils/prompt-project-name.js +35 -0
  633. package/src/utils/provider-env.js +116 -0
  634. package/src/utils/qmd-collection.js +72 -0
  635. package/src/utils/qmd-detect.js +18 -0
  636. package/src/utils/qmd-install.js +37 -0
  637. package/src/utils/quota-simulator.js +56 -0
  638. package/src/utils/rate-limit-detector.js +181 -0
  639. package/src/utils/repo-cleaner.js +79 -0
  640. package/src/utils/retry.js +88 -0
  641. package/src/utils/role-assigner.js +137 -0
  642. package/src/utils/role-env.js +58 -0
  643. package/src/utils/rtk-detect.js +18 -0
  644. package/src/utils/rtk-install.js +38 -0
  645. package/src/utils/rtk-wrapper.js +87 -0
  646. package/src/utils/run-context.js +75 -0
  647. package/src/utils/run-log.js +217 -0
  648. package/src/utils/run-registry.js +9 -0
  649. package/src/utils/shared-paths.js +12 -0
  650. package/src/utils/squeezr-detect.js +21 -0
  651. package/src/utils/squeezr-install.js +37 -0
  652. package/src/utils/stack-detect.js +135 -0
  653. package/src/utils/stall-detector.js +159 -0
  654. package/src/utils/status-dashboard.js +254 -0
  655. package/src/utils/task-file.js +109 -0
  656. package/src/utils/telemetry.js +124 -0
  657. package/src/utils/templates-root.js +61 -0
  658. package/src/utils/tool-call-extractor.js +56 -0
  659. package/src/utils/tool-governor.js +116 -0
  660. package/src/utils/tool-installer.js +93 -0
  661. package/src/utils/update-check.js +280 -0
  662. package/src/utils/vector-store-orphans.js +89 -0
  663. package/src/utils/welcome.js +47 -0
  664. package/src/utils/with-timeout.js +42 -0
  665. package/src/utils/wizard.js +47 -0
  666. package/src/webperf/cwv-gate.js +94 -0
  667. package/src/webperf/devtools-detect.js +112 -0
  668. package/src/webperf/scanner.js +209 -0
  669. package/src/webperf/webperf-role-integration.js +66 -0
  670. package/templates/coder-rules.md +45 -0
  671. package/templates/docker-compose.sonar.yml +60 -0
  672. package/templates/domains/example-dental.md +57 -0
  673. package/templates/kj.config.yml +128 -0
  674. package/templates/review-rules.md +17 -0
  675. package/templates/roles/architect/anthropic.md +74 -0
  676. package/templates/roles/architect/default.md +72 -0
  677. package/templates/roles/architect/google.md +61 -0
  678. package/templates/roles/architect/openai.md +60 -0
  679. package/templates/roles/architect/opencode.md +59 -0
  680. package/templates/roles/architect.md +76 -0
  681. package/templates/roles/audit.md +68 -0
  682. package/templates/roles/coder/anthropic.md +81 -0
  683. package/templates/roles/coder/default.md +78 -0
  684. package/templates/roles/coder/google.md +87 -0
  685. package/templates/roles/coder/openai.md +68 -0
  686. package/templates/roles/coder/opencode.md +58 -0
  687. package/templates/roles/coder.md +152 -0
  688. package/templates/roles/commiter.md +44 -0
  689. package/templates/roles/discover.md +167 -0
  690. package/templates/roles/domain-curator.md +52 -0
  691. package/templates/roles/hu-reviewer.md +236 -0
  692. package/templates/roles/impeccable-design.md +87 -0
  693. package/templates/roles/impeccable.md +125 -0
  694. package/templates/roles/karajan-brain.md +95 -0
  695. package/templates/roles/onboarder.md +45 -0
  696. package/templates/roles/planner/anthropic.md +59 -0
  697. package/templates/roles/planner/default.md +57 -0
  698. package/templates/roles/planner/google.md +75 -0
  699. package/templates/roles/planner/openai.md +55 -0
  700. package/templates/roles/planner/opencode.md +62 -0
  701. package/templates/roles/planner.md +61 -0
  702. package/templates/roles/refactorer.md +48 -0
  703. package/templates/roles/repairer.md +103 -0
  704. package/templates/roles/researcher.md +41 -0
  705. package/templates/roles/reviewer/anthropic.md +61 -0
  706. package/templates/roles/reviewer/default.md +62 -0
  707. package/templates/roles/reviewer/google.md +63 -0
  708. package/templates/roles/reviewer/openai.md +57 -0
  709. package/templates/roles/reviewer/opencode.md +42 -0
  710. package/templates/roles/reviewer-paranoid.md +38 -0
  711. package/templates/roles/reviewer-relaxed.md +34 -0
  712. package/templates/roles/reviewer-strict.md +37 -0
  713. package/templates/roles/reviewer.md +62 -0
  714. package/templates/roles/security.md +54 -0
  715. package/templates/roles/solomon/anthropic.md +71 -0
  716. package/templates/roles/solomon/default.md +83 -0
  717. package/templates/roles/solomon/google.md +61 -0
  718. package/templates/roles/solomon/openai.md +53 -0
  719. package/templates/roles/solomon/opencode.md +55 -0
  720. package/templates/roles/solomon.md +83 -0
  721. package/templates/roles/sonar.md +49 -0
  722. package/templates/roles/spec-reviewer.md +47 -0
  723. package/templates/roles/tester.md +50 -0
  724. package/templates/roles/triage.md +69 -0
  725. package/templates/skills/kj-architect.md +45 -0
  726. package/templates/skills/kj-audit.md +63 -0
  727. package/templates/skills/kj-board.md +16 -0
  728. package/templates/skills/kj-code.md +51 -0
  729. package/templates/skills/kj-csv-transform.md +40 -0
  730. package/templates/skills/kj-data-report.md +44 -0
  731. package/templates/skills/kj-discover.md +24 -0
  732. package/templates/skills/kj-rag-query.md +50 -0
  733. package/templates/skills/kj-review.md +47 -0
  734. package/templates/skills/kj-run.md +73 -0
  735. package/templates/skills/kj-security.md +49 -0
  736. package/templates/skills/kj-sonar.md +41 -0
  737. package/templates/skills/kj-sql-analysis.md +40 -0
  738. package/templates/skills/kj-test.md +40 -0
  739. package/templates/workflows/automerge.yml +30 -0
  740. package/templates/workflows/houston-override.yml +46 -0
  741. package/templates/workflows/kj-ci-gateway.yml +58 -0
  742. package/vendor/tree-sitter-grammars/README.md +21 -0
  743. package/vendor/tree-sitter-grammars/go.wasm +0 -0
  744. package/vendor/tree-sitter-grammars/java.wasm +0 -0
  745. package/vendor/tree-sitter-grammars/python.wasm +0 -0
  746. package/vendor/tree-sitter-grammars/rust.wasm +0 -0
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Session mutators — the single site where the orchestrator mutates a
3
+ * session object in memory.
4
+ *
5
+ * Rationale (TSK-0337, KJC-PCS-0040 Oleada 3): pre-v2.7.5 there were ~68
6
+ * direct `session.x = value` assignments scattered across 18 files, with
7
+ * one file (flow-runner.js) alone accounting for 142 touches. The audit
8
+ * called this out as a HIGH finding: when a reviewer-retry bug landed in
9
+ * production, a maintainer had to grep the whole tree to find every site
10
+ * that writes to `session.last_reviewer_feedback` or
11
+ * `session.reviewer_retry_count`.
12
+ *
13
+ * The mutators below are intentionally **mechanical** — each wraps a
14
+ * single assignment — so the migration from `session.x = y` to
15
+ * `setX(session, y)` is pure plumbing and preserves exact existing
16
+ * semantics. The value is NOT validation or side-effects; it's that
17
+ * grepping `setReviewerFeedback(` finds every writer in seconds. Adding
18
+ * validation, event emission or persistence hooks later becomes a
19
+ * one-liner inside the mutator rather than a tree-wide edit.
20
+ *
21
+ * Complementary architecture test:
22
+ * tests/architecture/session-write-boundary.test.js
23
+ * enforces a budget on the remaining direct `session.x = y` assignments
24
+ * outside `src/session/`. The budget only decreases; any new direct
25
+ * assignment requires either going through a mutator or explicit audit.
26
+ *
27
+ * Naming convention:
28
+ * - setX — overwrite field X with a new value.
29
+ * - incrementX — numeric +1 (returns the new value).
30
+ * - resetX — numeric 0 or null.
31
+ * - clearX — delete the field entirely (when `in` matters).
32
+ * - appendToX — push onto an array field.
33
+ * - assignX — shallow-merge object into an object field.
34
+ *
35
+ * No mutator persists the session — callers are still responsible for
36
+ * `await saveSession(session)` afterwards. This keeps the mutator
37
+ * functions synchronous and cheap.
38
+ */
39
+
40
+ // --- Retry counters -------------------------------------------------------
41
+
42
+ export const RETRY_KINDS = Object.freeze([
43
+ "reviewer",
44
+ "sonar",
45
+ "tester",
46
+ "security",
47
+ "standby",
48
+ "repeated_issue",
49
+ "auto_resume",
50
+ "checkpoint_stall",
51
+ ]);
52
+
53
+ const RETRY_FIELD = {
54
+ reviewer: "reviewer_retry_count",
55
+ sonar: "sonar_retry_count",
56
+ tester: "tester_retry_count",
57
+ security: "security_retry_count",
58
+ standby: "standby_retry_count",
59
+ repeated_issue: "repeated_issue_count",
60
+ auto_resume: "auto_resume_count",
61
+ checkpoint_stall: "_checkpoint_stall_count",
62
+ };
63
+
64
+ export function setRetryCount(session, kind, value) {
65
+ const field = RETRY_FIELD[kind];
66
+ if (!field) throw new Error(`setRetryCount: unknown retry kind "${kind}"`);
67
+ session[field] = Number(value) || 0;
68
+ return session[field];
69
+ }
70
+
71
+ export function incrementRetryCount(session, kind) {
72
+ const field = RETRY_FIELD[kind];
73
+ if (!field) throw new Error(`incrementRetryCount: unknown retry kind "${kind}"`);
74
+ session[field] = (session[field] || 0) + 1;
75
+ return session[field];
76
+ }
77
+
78
+ export function resetRetryCount(session, kind) {
79
+ return setRetryCount(session, kind, 0);
80
+ }
81
+
82
+ /**
83
+ * Reset all well-known retry/repeat counters to 0. Called at the top of
84
+ * every resume path so a resumed session doesn't inherit the previous
85
+ * run's stall state.
86
+ */
87
+ export function resetAllRetryCounters(session) {
88
+ for (const kind of RETRY_KINDS) {
89
+ // Skip checkpoint_stall: it's internal state owned by flow-control,
90
+ // not something resume should touch.
91
+ if (kind === "checkpoint_stall") continue;
92
+ setRetryCount(session, kind, 0);
93
+ }
94
+ }
95
+
96
+ // --- Feedback -------------------------------------------------------------
97
+
98
+ export function setReviewerFeedback(session, text) {
99
+ session.last_reviewer_feedback = text;
100
+ }
101
+
102
+ export function appendReviewerFeedback(session, text) {
103
+ session.last_reviewer_feedback = session.last_reviewer_feedback
104
+ ? `${session.last_reviewer_feedback}\n${text}`
105
+ : text;
106
+ }
107
+
108
+ export function setSonarSummary(session, text) {
109
+ session.last_sonar_summary = text;
110
+ }
111
+
112
+ export function setCoderTranscript(session, text) {
113
+ session.last_coder_transcript = text;
114
+ }
115
+
116
+ export function setSonarIssueSignature(session, sig) {
117
+ session.last_sonar_issue_signature = sig;
118
+ }
119
+
120
+ export function setReviewerIssueSignature(session, sig) {
121
+ session.last_reviewer_issue_signature = sig;
122
+ }
123
+
124
+ // Issue-signature repetition counters (distinct from retry_count:
125
+ // reset only when the signature changes, not every iteration).
126
+ export function setSonarRepeatCount(session, value) {
127
+ session.sonar_repeat_count = Number(value) || 0;
128
+ }
129
+ export function setReviewerRepeatCount(session, value) {
130
+ session.reviewer_repeat_count = Number(value) || 0;
131
+ }
132
+
133
+ // --- Status ---------------------------------------------------------------
134
+
135
+ /**
136
+ * In-memory status change. The persisting variant is `markSessionStatus` in
137
+ * store.js, which also writes to disk; `setStatus` is for transient mutations
138
+ * inside the runner (e.g. standby enter/exit) where the caller persists
139
+ * later via `saveSession`.
140
+ */
141
+ export function setStatus(session, status) {
142
+ session.status = status;
143
+ }
144
+
145
+ // --- Stage results (KJC-BUG-0058: resume must skip completed stages) ------
146
+
147
+ /**
148
+ * Persist a pre-loop stage result on the session, plus mirror its name in
149
+ * a flat `stages_completed` array used by `resumeFlow` to know what to skip.
150
+ *
151
+ * Both shapes are kept in sync so callers can read either: the rich
152
+ * `stage_results[name]` for the full payload, or the cheap
153
+ * `stages_completed` for a fast membership check.
154
+ */
155
+ export function setStageResult(session, name, result) {
156
+ if (!session.stage_results) session.stage_results = {};
157
+ session.stage_results[name] = result;
158
+ if (!Array.isArray(session.stages_completed)) session.stages_completed = [];
159
+ if (!session.stages_completed.includes(name)) session.stages_completed.push(name);
160
+ }
161
+
162
+ /**
163
+ * Stage *bundles* capture cross-stage context that a stage exports beyond
164
+ * its stageResult (e.g. researcher → researchContext, architect →
165
+ * architectContext, planner → plannedTask). Resume needs these to feed
166
+ * downstream stages without re-running the upstream one. The bundle is
167
+ * always shaped `{ stageResult, ...extras }` and `setStageBundle` mirrors
168
+ * the stageResult into `stage_results[name]` so legacy readers keep working.
169
+ */
170
+ export function setStageBundle(session, name, bundle) {
171
+ if (!session.stage_bundles) session.stage_bundles = {};
172
+ session.stage_bundles[name] = bundle;
173
+ setStageResult(session, name, bundle?.stageResult ?? bundle);
174
+ }
175
+
176
+ // --- Alternative agent (rate-limit recovery) ------------------------------
177
+
178
+ export function setAlternativeAgent(session, stage, provider) {
179
+ session._alternative_agent = { stage, provider };
180
+ }
181
+
182
+ export function clearAlternativeAgent(session) {
183
+ delete session._alternative_agent;
184
+ }
185
+
186
+ // --- Standby state --------------------------------------------------------
187
+
188
+ export function setStandby(session, { agent, cooldownMs, cooldownUntil }) {
189
+ session.standby_agent = agent;
190
+ session.standby_cooldown_ms = cooldownMs;
191
+ session.standby_cooldown_until = cooldownUntil;
192
+ }
193
+
194
+ export function clearStandby(session) {
195
+ delete session.standby_agent;
196
+ delete session.standby_cooldown_ms;
197
+ delete session.standby_cooldown_until;
198
+ }
199
+
200
+ // --- CI state -------------------------------------------------------------
201
+
202
+ export function setCiEarlyPr(session, { prNumber, prUrl, commits }) {
203
+ session.ci_pr_number = prNumber;
204
+ session.ci_pr_url = prUrl;
205
+ session.ci_commits = commits;
206
+ }
207
+
208
+ export function appendCiCommits(session, commits) {
209
+ session.ci_commits = [...(session.ci_commits ?? []), ...commits];
210
+ }
211
+
212
+ // --- Pre-loop & policy metadata -------------------------------------------
213
+
214
+ export function setPreflight(session, result) {
215
+ session.preflight = result;
216
+ }
217
+
218
+ export function setResolvedPolicies(session, policies) {
219
+ session.resolved_policies = policies;
220
+ }
221
+
222
+ export function setPgCard(session, card) {
223
+ session.pg_card = card;
224
+ }
225
+
226
+ export function setPgTaskId(session, id) {
227
+ session.pg_task_id = id;
228
+ }
229
+
230
+ export function appendPgCommits(session, commits) {
231
+ session.pg_commits = [...(session.pg_commits ?? []), ...commits];
232
+ }
233
+
234
+ export function setPreLoopContext(session, { research, architect, plan }) {
235
+ if (research !== undefined) session.research_context = research;
236
+ if (architect !== undefined) session.architect_context = architect;
237
+ if (plan !== undefined) session.loaded_plan = plan;
238
+ }
239
+
240
+ export function setPlanRef(session, ref) {
241
+ session._planRef = ref;
242
+ }
243
+
244
+ export function setPlanSyncCallback(session, fn) {
245
+ session._syncResultsToPlan = fn;
246
+ }
247
+
248
+ /**
249
+ * Live status updater: invoked by hu-sub-pipeline after every status
250
+ * change so the plan JSON gets the new status immediately, not only at
251
+ * the end of the run. Without this, the board reads an unchanged plan
252
+ * file during execution and the columns appear frozen until the run
253
+ * completes (the bug we're fixing in PR1).
254
+ *
255
+ * Signature: async (huId, status) => void
256
+ */
257
+ export function setLiveStatusUpdater(session, fn) {
258
+ session._liveStatusUpdater = fn;
259
+ }
260
+
261
+ export function getLiveStatusUpdater(session) {
262
+ return session._liveStatusUpdater || null;
263
+ }
264
+
265
+ /**
266
+ * Live outcome updater (PR3): invoked by hu-sub-pipeline after each
267
+ * HU's runSingleHu finishes. The plan JSON gets the per-HU outcome
268
+ * stamped immediately so the board can show a "📄 ver resumen"
269
+ * indicator next to each card without waiting for the run to end.
270
+ *
271
+ * Signature: async (huId, outcome) => void
272
+ */
273
+ export function setLiveOutcomeUpdater(session, fn) {
274
+ session._liveOutcomeUpdater = fn;
275
+ }
276
+
277
+ export function getLiveOutcomeUpdater(session) {
278
+ return session._liveOutcomeUpdater || null;
279
+ }
280
+
281
+ // --- Skills ---------------------------------------------------------------
282
+
283
+ export function setAddyosmaniSkills(session, payload) {
284
+ session.addyosmaniSkills = payload;
285
+ }
286
+
287
+ export function setAutoInstalledSkills(session, skills) {
288
+ session.autoInstalledSkills = skills;
289
+ }
290
+
291
+ export function setSkillsRecommended(session, skills) {
292
+ session.skillsRecommended = skills;
293
+ }
294
+
295
+ // --- Journal breadcrumbs --------------------------------------------------
296
+
297
+ export function setJournalContext(session, { dir, files, iterations, decisions, startedAt }) {
298
+ if (dir !== undefined) session._journalDir = dir;
299
+ if (files !== undefined) session._journalFiles = files;
300
+ if (iterations !== undefined) session._journalIterations = iterations;
301
+ if (decisions !== undefined) session._journalDecisions = decisions;
302
+ if (startedAt !== undefined) session._startedAt = startedAt;
303
+ }
304
+
305
+ // --- Session outcome ------------------------------------------------------
306
+
307
+ export function setBudget(session, budget) {
308
+ session.budget = budget;
309
+ }
310
+
311
+ export function setDeferredIssues(session, issues) {
312
+ session.deferred_issues = issues;
313
+ }
314
+
315
+ export function setRtkSavings(session, savings) {
316
+ session.rtk_savings = savings;
317
+ }
318
+
319
+ // --- Paused state (resume) ------------------------------------------------
320
+
321
+ export function setPausedState(session, state) {
322
+ session.paused_state = state;
323
+ }
324
+
325
+ // --- Brain decisions (decisor tracker) -----------------------------------
326
+
327
+ export function setBrainDecisions(session, decisions) {
328
+ session.brainDecisions = decisions;
329
+ }
330
+
331
+ // --- Suggestions (MCP) ----------------------------------------------------
332
+
333
+ export function setSuggestions(session, suggestions) {
334
+ session.suggestions = suggestions;
335
+ }
336
+
337
+ export function touch(session) {
338
+ session.updated_at = new Date().toISOString();
339
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * In-memory runtime overrides (e.g. `roles.coder.provider` set for the
3
+ * current process session, not persisted to disk).
4
+ *
5
+ * Why this lives at the session layer (not under `src/mcp/`):
6
+ *
7
+ * Pre-v2.7.5, the overrides store lived in `src/mcp/preflight.js`. That
8
+ * made `src/commands/agents.js` (CLI) do
9
+ * `await import("../mcp/preflight.js")`
10
+ * which is a **layer violation**: commands are the top layer, MCP is a
11
+ * peer interface. A CLI command knowing about the MCP server's
12
+ * preflight state coupled two runtimes that should be independent.
13
+ *
14
+ * The "runtime override" concept is runtime-agnostic — both CLI and MCP
15
+ * need an in-memory scratchpad for "this process should use this
16
+ * provider for role X for the rest of its life". Putting it here makes
17
+ * both layers depend on `src/session/` (a neutral module) instead of on
18
+ * each other.
19
+ *
20
+ * Lifetime: the store lives for as long as the Node process. CLI
21
+ * invocations are short-lived (override is lost at exit — that's fine,
22
+ * they write to config if they want persistence). The MCP server process
23
+ * is long-lived; the override survives across tool calls until
24
+ * `clearRuntimeOverrides()` is called (typically by `ackPreflight()`).
25
+ *
26
+ * Contents: a flat `{ [key]: value }` map. Keys are typically role names
27
+ * (`coder`, `reviewer`, `planner`), values are provider slugs (`claude`,
28
+ * `codex`, `gemini`). Consumers shape-validate at read time.
29
+ */
30
+
31
+ let overrides = {};
32
+
33
+ /**
34
+ * Return a shallow copy of the current overrides. Never returns the
35
+ * internal reference so callers cannot mutate it by accident.
36
+ */
37
+ export function getRuntimeOverrides() {
38
+ return { ...overrides };
39
+ }
40
+
41
+ /**
42
+ * Set a single override. Silently rejects nullish keys.
43
+ *
44
+ * @param {string} key
45
+ * @param {unknown} value
46
+ */
47
+ export function setRuntimeOverride(key, value) {
48
+ if (!key) return;
49
+ overrides[key] = value;
50
+ }
51
+
52
+ /**
53
+ * Drop all overrides. Used by `ackPreflight()` after it transfers its
54
+ * configured overrides onto this store, to ensure we start from a clean
55
+ * slate per MCP session.
56
+ */
57
+ export function clearRuntimeOverrides() {
58
+ overrides = {};
59
+ }
@@ -0,0 +1,106 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { ensureDir, exists } from "../utils/fs.js";
4
+ import { getSessionRoot } from "../utils/paths.js";
5
+ import { writeJsonAtomic } from "../utils/atomic-write.js";
6
+
7
+ const SESSION_ROOT = getSessionRoot();
8
+
9
+ function newSessionId() {
10
+ const now = new Date();
11
+ const stamp = now.toISOString().replaceAll(/[:.]/g, "-");
12
+ return `s_${stamp}`;
13
+ }
14
+
15
+ export async function createSession(initial = {}) {
16
+ const id = initial.id || newSessionId();
17
+ const dir = path.join(SESSION_ROOT, id);
18
+ await ensureDir(dir);
19
+ const data = {
20
+ id,
21
+ created_at: new Date().toISOString(),
22
+ updated_at: new Date().toISOString(),
23
+ status: "running",
24
+ checkpoints: [],
25
+ ...initial
26
+ };
27
+ await saveSession(data);
28
+ return data;
29
+ }
30
+
31
+ export async function saveSession(session) {
32
+ const dir = path.join(SESSION_ROOT, session.id);
33
+ await ensureDir(dir);
34
+ session.updated_at = new Date().toISOString();
35
+ await writeJsonAtomic(path.join(dir, "session.json"), session);
36
+ }
37
+
38
+ export async function loadSession(sessionId) {
39
+ const file = path.join(SESSION_ROOT, sessionId, "session.json");
40
+ if (!(await exists(file))) {
41
+ throw new Error(`Session not found: ${sessionId}`);
42
+ }
43
+ const raw = await fs.readFile(file, "utf8");
44
+ return JSON.parse(raw);
45
+ }
46
+
47
+ export async function addCheckpoint(session, checkpoint) {
48
+ // Defensive: any caller that builds a stub session (e.g. the init-error
49
+ // path in flow-runner.js, where `tempSession = { id, task, status }` has
50
+ // no checkpoints array) would otherwise crash with
51
+ // "Cannot read properties of undefined (reading 'push')". Guard once here
52
+ // so the bug class is gone instead of fixing every call site.
53
+ if (!Array.isArray(session.checkpoints)) session.checkpoints = [];
54
+ session.checkpoints.push({ at: new Date().toISOString(), ...checkpoint });
55
+ await saveSession(session);
56
+ }
57
+
58
+ export async function markSessionStatus(session, status) {
59
+ session.status = status;
60
+ await saveSession(session);
61
+ }
62
+
63
+ export async function pauseSession(session, { question, context: pauseContext }) {
64
+ session.status = "paused";
65
+ session.paused_state = {
66
+ question,
67
+ context: pauseContext,
68
+ paused_at: new Date().toISOString()
69
+ };
70
+ await saveSession(session);
71
+ }
72
+
73
+ export async function loadMostRecentSession() {
74
+ let entries;
75
+ try {
76
+ entries = await fs.readdir(SESSION_ROOT, { withFileTypes: true });
77
+ } catch { /* session root does not exist yet */
78
+ return null;
79
+ }
80
+ const dirs = entries.filter(e => e.isDirectory()).map(e => e.name).sort();
81
+ for (let i = dirs.length - 1; i >= 0; i--) {
82
+ try {
83
+ return await loadSession(dirs[i]);
84
+ } catch { /* session.json missing or malformed */
85
+ continue;
86
+ }
87
+ }
88
+ return null;
89
+ }
90
+
91
+ export async function resumeSessionWithAnswer(sessionId, answer) {
92
+ const session = await loadSession(sessionId);
93
+ const resumable = new Set(["paused", "running", "failed", "stopped"]);
94
+ if (!resumable.has(session.status)) {
95
+ throw new Error(`Session ${sessionId} cannot be resumed (status: ${session.status})`);
96
+ }
97
+ const pausedState = session.paused_state;
98
+ if (!pausedState) {
99
+ throw new Error(`Session ${sessionId} has no paused state`);
100
+ }
101
+ session.paused_state.answer = answer;
102
+ session.paused_state.resumed_at = new Date().toISOString();
103
+ session.status = "running";
104
+ await saveSession(session);
105
+ return session;
106
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Automatic cleanup of expired sessions.
3
+ *
4
+ * Policy (by status):
5
+ * - failed / stopped: removed after 1 day
6
+ * - approved: removed after 7 days
7
+ * - running (stale): marked failed + removed after 1 day (crash without cleanup)
8
+ * - paused: kept (user may want to resume)
9
+ *
10
+ * Runs automatically at the start of every kj_run (best-effort, non-blocking).
11
+ */
12
+
13
+ import fs from "node:fs/promises";
14
+ import path from "node:path";
15
+ import { getSessionRoot } from "./utils/paths.js";
16
+
17
+ const ONE_DAY_MS = 24 * 60 * 60 * 1000;
18
+ const DEFAULT_APPROVED_EXPIRY_DAYS = 7;
19
+
20
+ function buildPolicy(expiryDays) {
21
+ const approvedMs = (expiryDays ?? DEFAULT_APPROVED_EXPIRY_DAYS) * ONE_DAY_MS;
22
+ return {
23
+ failed: { expiryMs: ONE_DAY_MS },
24
+ stopped: { expiryMs: ONE_DAY_MS },
25
+ running: { expiryMs: ONE_DAY_MS }, // stale — crashed without marking failed
26
+ approved: { expiryMs: approvedMs },
27
+ paused: null // never auto-delete
28
+ };
29
+ }
30
+
31
+ const POLICY = buildPolicy();
32
+
33
+ function shouldRemove(session, policy = POLICY) {
34
+ const status = session.status || "unknown";
35
+ const entry = policy[status];
36
+ if (!entry) return false;
37
+
38
+ const updatedAt = new Date(session.updated_at || session.created_at).getTime();
39
+ return Date.now() - updatedAt > entry.expiryMs;
40
+ }
41
+
42
+ async function tryCleanupSession({ sessionDir, dirName, removed, errors, logger, policy }) {
43
+ const sessionFile = path.join(sessionDir, "session.json");
44
+ let session;
45
+ try {
46
+ const raw = await fs.readFile(sessionFile, "utf8");
47
+ session = JSON.parse(raw);
48
+ } catch {
49
+ // Orphan dir without valid session.json — remove if older than 1 day
50
+ const stat = await fs.stat(sessionDir).catch(() => null);
51
+ if (stat && Date.now() - stat.mtimeMs > ONE_DAY_MS) {
52
+ try {
53
+ await fs.rm(sessionDir, { recursive: true, force: true });
54
+ removed.push(dirName);
55
+ logger?.debug?.(`Orphan session dir removed: ${dirName}`);
56
+ } catch (err) {
57
+ errors.push({ session: dirName, error: err.message });
58
+ }
59
+ }
60
+ return;
61
+ }
62
+
63
+ if (!shouldRemove(session, policy)) return;
64
+
65
+ try {
66
+ await fs.rm(sessionDir, { recursive: true, force: true });
67
+ removed.push(dirName);
68
+ logger?.debug?.(`Session cleaned up: ${dirName} (status: ${session.status})`);
69
+ } catch (err) {
70
+ errors.push({ session: dirName, error: err.message });
71
+ }
72
+ }
73
+
74
+ export async function cleanupExpiredSessions({ logger, config } = {}) {
75
+ const expiryDays = config?.session?.expiry_days;
76
+ const policy = expiryDays ? buildPolicy(expiryDays) : POLICY;
77
+ const sessionRoot = getSessionRoot();
78
+
79
+ let entries;
80
+ try {
81
+ entries = await fs.readdir(sessionRoot, { withFileTypes: true });
82
+ } catch { /* session root does not exist */
83
+ return { removed: 0, errors: [] };
84
+ }
85
+
86
+ const dirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("s_"));
87
+ const removed = [];
88
+ const errors = [];
89
+
90
+ for (const dir of dirs) {
91
+ const sessionDir = path.join(sessionRoot, dir.name);
92
+ await tryCleanupSession({ sessionDir, dirName: dir.name, removed, errors, logger, policy });
93
+ }
94
+
95
+ if (removed.length > 0) {
96
+ logger?.info?.(`Cleaned up ${removed.length} expired session(s)`);
97
+ }
98
+
99
+ // Truncate oversized project run logs
100
+ const maxLogSizeMb = config?.output?.max_log_size_mb ?? 50;
101
+ await truncateOversizedLog(path.join(process.cwd(), ".kj", "run.log"), maxLogSizeMb, logger);
102
+
103
+ return { removed: removed.length, errors };
104
+ }
105
+
106
+ async function truncateOversizedLog(logPath, maxSizeMb, logger) {
107
+ if (maxSizeMb <= 0) return;
108
+ try {
109
+ const stat = await fs.stat(logPath);
110
+ const maxBytes = maxSizeMb * 1024 * 1024;
111
+ if (stat.size > maxBytes) {
112
+ await fs.truncate(logPath, 0);
113
+ logger?.info?.(`Truncated oversized log ${logPath} (was ${(stat.size / 1024 / 1024).toFixed(1)}MB, limit ${maxSizeMb}MB)`);
114
+ }
115
+ } catch { /* file doesn't exist or can't be read */ }
116
+ }