karajan-code 4.70.4 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. package/README.md +2 -2
  2. package/package.json +6 -14
  3. package/packages/hu-board/package.json +1 -1
  4. package/packages/hu-board/public/app.js +4 -18
  5. package/packages/hu-board/public/index.html +5 -2
  6. package/packages/hu-board/public/styles.css +26 -0
  7. package/packages/hu-board/public/utils/api.js +0 -74
  8. package/packages/hu-board/public/utils/board-tour.js +62 -0
  9. package/packages/hu-board/public/utils/board-view.js +49 -144
  10. package/packages/hu-board/public/utils/command-launcher.js +8 -70
  11. package/packages/hu-board/public/utils/formatters.js +10 -0
  12. package/packages/hu-board/public/utils/governance-view.js +13 -1
  13. package/packages/hu-board/public/utils/hu-actions.js +17 -68
  14. package/packages/hu-board/public/utils/init-listeners.js +7 -8
  15. package/packages/hu-board/public/utils/log-panel.js +3 -16
  16. package/packages/hu-board/public/utils/maggle-mode.js +2 -12
  17. package/packages/hu-board/public/utils/modals.js +7 -0
  18. package/packages/hu-board/public/utils/project-picker-view.js +1 -1
  19. package/packages/hu-board/public/utils/server-push.js +3 -22
  20. package/packages/hu-board/public/utils/shared-board-notice.js +33 -0
  21. package/packages/hu-board/public/utils/story-detail-view.js +5 -19
  22. package/packages/hu-board/src/cleanup-zombies.js +0 -1
  23. package/packages/hu-board/src/command-runner.js +36 -25
  24. package/packages/hu-board/src/db-connection.js +282 -0
  25. package/packages/hu-board/src/db-paths.js +113 -0
  26. package/packages/hu-board/src/db-queries.js +188 -0
  27. package/packages/hu-board/src/db-tombstones.js +51 -0
  28. package/packages/hu-board/src/db.js +28 -619
  29. package/packages/hu-board/src/ephemeral-cleaner.js +2 -3
  30. package/packages/hu-board/src/hu-zombie-reaper.js +5 -1
  31. package/packages/hu-board/src/plan-mutations.js +3 -153
  32. package/packages/hu-board/src/plans-service.js +55 -0
  33. package/packages/hu-board/src/routes/api/commands.js +122 -0
  34. package/packages/hu-board/src/routes/api/plans.js +55 -0
  35. package/packages/hu-board/src/routes/api/projects.js +267 -0
  36. package/packages/hu-board/src/routes/api/prompts.js +135 -0
  37. package/packages/hu-board/src/routes/api/sessions.js +95 -0
  38. package/packages/hu-board/src/routes/api/stories.js +183 -0
  39. package/packages/hu-board/src/routes/api/system.js +241 -0
  40. package/packages/hu-board/src/routes/api/tombstones.js +38 -0
  41. package/packages/hu-board/src/routes/api.js +24 -1371
  42. package/packages/hu-board/src/routes/governance.js +23 -1
  43. package/packages/hu-board/src/routes/lanes.js +40 -0
  44. package/packages/hu-board/src/routes/rag.js +4 -3
  45. package/packages/hu-board/src/server.js +20 -34
  46. package/packages/hu-board/src/sync-files.js +318 -0
  47. package/packages/hu-board/src/sync-project.js +99 -0
  48. package/packages/hu-board/src/sync.js +22 -566
  49. package/packages/hu-board/src/zombie-reaper.js +1 -1
  50. package/scripts/dual-publish.mjs +19 -3
  51. package/scripts/postinstall.js +15 -2
  52. package/scripts/verify-pack-mcp.mjs +11 -7
  53. package/scripts/verify-pack.mjs +4 -4
  54. package/src/audit/audit-history.js +3 -2
  55. package/src/audit/dead-exports.js +68 -59
  56. package/src/audit/deterministic-summary.js +33 -13
  57. package/src/audit/npm-signatures.js +41 -0
  58. package/src/audit/sbom.js +35 -0
  59. package/src/checks/agent-token.js +112 -0
  60. package/src/checks/dir-setup.js +34 -1
  61. package/src/checks/native-build.js +21 -39
  62. package/src/checks/runner.js +128 -142
  63. package/src/cli/advanced-commands.js +6 -6
  64. package/src/cli/register-meta.js +42 -82
  65. package/src/cli/register-pipeline.js +8 -143
  66. package/src/cli/register-plan.js +9 -100
  67. package/src/cli/retired-commands.js +49 -0
  68. package/src/cli.js +18 -5
  69. package/src/commands/agent-run.js +40 -26
  70. package/src/commands/audit.js +127 -124
  71. package/src/commands/board.js +5 -9
  72. package/src/commands/check.js +29 -16
  73. package/src/commands/doctor.js +2 -0
  74. package/src/commands/env.js +176 -150
  75. package/src/commands/go.js +71 -53
  76. package/src/commands/harden.js +90 -81
  77. package/src/commands/hu-start.js +52 -0
  78. package/src/commands/hu.js +288 -221
  79. package/src/commands/identity.js +111 -78
  80. package/src/commands/init-atril.js +47 -0
  81. package/src/commands/init.js +11 -40
  82. package/src/commands/install-tools.js +70 -85
  83. package/src/commands/main-guard.js +78 -0
  84. package/src/commands/policy.js +226 -184
  85. package/src/commands/qmd.js +27 -21
  86. package/src/commands/rag.js +75 -48
  87. package/src/commands/review-gate.js +421 -341
  88. package/src/commands/start.js +4 -5
  89. package/src/commands/steward.js +96 -47
  90. package/src/commands/tournament.js +46 -37
  91. package/src/commands/worktree.js +94 -25
  92. package/src/config/loader.js +34 -17
  93. package/src/config/secrets.js +36 -0
  94. package/src/config.js +1 -0
  95. package/src/environment/adr.js +16 -2
  96. package/src/git/karajan-label.js +20 -8
  97. package/src/guards/main-guard.js +54 -0
  98. package/src/harden/hook-templates.js +16 -1
  99. package/src/harden/sentinel/posttooluse.mjs +18 -6
  100. package/src/harden/sentinel/pretooluse-sentinel.mjs +64 -36
  101. package/src/harden/sentinel/sentinel-lib.mjs +129 -26
  102. package/src/harden/sentinel/sentinel-shell.mjs +5 -16
  103. package/src/harden/sentinel/sessionstart.mjs +3 -2
  104. package/src/harden/sentinel/stop.mjs +5 -4
  105. package/src/harden/workflow-templates.js +1 -1
  106. package/src/hu/board-lookup.js +29 -0
  107. package/src/hu/gh-identity.js +23 -0
  108. package/src/hu/github-board.js +4 -2
  109. package/src/hu/lane-prune.js +15 -7
  110. package/src/hu/lane-setup.js +65 -0
  111. package/src/hu/lanes.js +66 -0
  112. package/src/hu/team-board-mirror.js +3 -2
  113. package/src/infrastructure/command-runner.js +1 -1
  114. package/src/infrastructure/file-system-service.js +1 -1
  115. package/src/mcp/handlers/direct-handlers.js +2 -292
  116. package/src/mcp/handlers/hu-handlers.js +1 -35
  117. package/src/mcp/handlers/management-handlers.js +2 -42
  118. package/src/mcp/server-handlers.js +16 -22
  119. package/src/mcp/tools.js +1 -196
  120. package/src/plan/lane-plans.js +54 -0
  121. package/src/plan/plan-store.js +7 -4
  122. package/src/policy/add.js +26 -12
  123. package/src/policy/adr-number-check.js +31 -0
  124. package/src/prompts/audit.js +299 -339
  125. package/src/prompts/card-context.js +10 -5
  126. package/src/prompts/reviewer.js +5 -2
  127. package/src/rag/auto-update.js +56 -43
  128. package/src/rag/bootstrap-index.js +28 -54
  129. package/src/rag/migrate.js +1 -1
  130. package/src/rag/onnx-fallback.js +2 -2
  131. package/src/rag/pid-lease.js +70 -0
  132. package/src/rag/project-store.js +2 -12
  133. package/src/review/card-first.js +57 -46
  134. package/src/review/gate-gitignore.js +23 -4
  135. package/src/review/gate-hook.js +12 -4
  136. package/src/review/one-shot-review.js +45 -35
  137. package/src/review/publish-pr.js +14 -2
  138. package/src/review/repo-docs.js +73 -0
  139. package/src/review/repo-stack.js +59 -0
  140. package/src/review/reviewer-fallback.js +19 -4
  141. package/src/review/seal-commit.js +29 -0
  142. package/src/review/sonar-pregate.js +59 -44
  143. package/src/review/third-party-review.js +90 -16
  144. package/src/review/third-party-size.js +43 -0
  145. package/src/review/third-party-skills.js +54 -0
  146. package/src/review/verify-pr.js +1 -24
  147. package/src/roles/audit-role.js +106 -125
  148. package/src/skills/atril-skills.js +5 -4
  149. package/src/sonar/scanner.js +116 -101
  150. package/src/steward/invariants.js +5 -4
  151. package/src/steward/phantom-sweep.js +66 -0
  152. package/src/tournament/judge.js +60 -53
  153. package/src/utils/gh-account.js +37 -0
  154. package/src/utils/git.js +0 -13
  155. package/src/utils/home-migration.js +7 -1
  156. package/src/utils/main-checkout.js +53 -0
  157. package/src/utils/qmd-collection.js +3 -1
  158. package/src/utils/welcome.js +3 -3
  159. package/templates/{skills → atril/commands}/kj-architect.md +5 -0
  160. package/templates/{skills → atril/commands}/kj-audit.md +5 -0
  161. package/templates/{skills → atril/commands}/kj-board.md +5 -0
  162. package/templates/{skills → atril/commands}/kj-code.md +5 -0
  163. package/templates/{skills → atril/commands}/kj-csv-transform.md +5 -0
  164. package/templates/{skills → atril/commands}/kj-data-report.md +5 -0
  165. package/templates/{skills → atril/commands}/kj-discover.md +5 -0
  166. package/templates/{skills → atril/commands}/kj-rag-query.md +5 -0
  167. package/templates/{skills → atril/commands}/kj-review.md +5 -0
  168. package/templates/{skills → atril/commands}/kj-security.md +5 -0
  169. package/templates/{skills → atril/commands}/kj-sonar.md +5 -0
  170. package/templates/{skills → atril/commands}/kj-sql-analysis.md +5 -0
  171. package/templates/{skills → atril/commands}/kj-test.md +5 -0
  172. package/packages/hu-board/public/utils/run-launcher.js +0 -169
  173. package/packages/hu-board/src/run-tracker.js +0 -121
  174. package/src/activity-log.js +0 -59
  175. package/src/agents/host-agent.js +0 -38
  176. package/src/agents/model-registry.js +0 -142
  177. package/src/audit/plan-adherence.js +0 -224
  178. package/src/autonomy/arbiter-role.js +0 -71
  179. package/src/autonomy/arbiter.js +0 -22
  180. package/src/autonomy/decider.js +0 -18
  181. package/src/autonomy/decision-resolver.js +0 -58
  182. package/src/autonomy/outcome-report.js +0 -55
  183. package/src/autonomy/stage-ask.js +0 -30
  184. package/src/brain/decision-tracker.js +0 -125
  185. package/src/brain/decisor.js +0 -243
  186. package/src/brain/solomon-consult.js +0 -171
  187. package/src/brain/standby-scheduler.js +0 -8
  188. package/src/budget/comparison.js +0 -96
  189. package/src/canvas/parse-md.js +0 -238
  190. package/src/canvas/schema.js +0 -101
  191. package/src/canvas/to-flat.js +0 -85
  192. package/src/canvas/validate.js +0 -163
  193. package/src/ci/dispatch.js +0 -99
  194. package/src/ci/index.js +0 -3
  195. package/src/ci/pr-diff.js +0 -26
  196. package/src/cli/register-standby.js +0 -26
  197. package/src/commands/architect.js +0 -111
  198. package/src/commands/autorun.js +0 -49
  199. package/src/commands/researcher.js +0 -54
  200. package/src/commands/resume.js +0 -72
  201. package/src/commands/review.js +0 -89
  202. package/src/commands/run.js +0 -185
  203. package/src/commands/standby.js +0 -117
  204. package/src/commands/status.js +0 -36
  205. package/src/commands/triage.js +0 -78
  206. package/src/commands/undo.js +0 -62
  207. package/src/domains/domain-loader.js +0 -245
  208. package/src/domains/domain-registry.js +0 -140
  209. package/src/domains/domain-synthesizer.js +0 -129
  210. package/src/git/automation.js +0 -433
  211. package/src/git/coder-commit-guard.js +0 -40
  212. package/src/git/hu-automation.js +0 -243
  213. package/src/git/hu-snapshot.js +0 -10
  214. package/src/git/symlink-targets.js +0 -57
  215. package/src/golden/asserter.js +0 -92
  216. package/src/golden/loader.js +0 -52
  217. package/src/golden/runner.js +0 -92
  218. package/src/golden/schema.js +0 -41
  219. package/src/guards/duplicate-members.js +0 -86
  220. package/src/guards/intent-guard.js +0 -161
  221. package/src/guards/perf-guard.js +0 -126
  222. package/src/guards/policy-guard.js +0 -90
  223. package/src/guards/policy-resolver.js +0 -85
  224. package/src/guards/secret-redactor.js +0 -71
  225. package/src/hu/acceptance-runner.js +0 -138
  226. package/src/hu/lazy-planner.js +0 -109
  227. package/src/hu/parallel-executor.js +0 -94
  228. package/src/hu/routing-metrics.js +0 -17
  229. package/src/hu/split-validator.js +0 -143
  230. package/src/hu/splitting-detector.js +0 -158
  231. package/src/hu/splitting-generator.js +0 -175
  232. package/src/hu/store.js +0 -394
  233. package/src/infrastructure/mocks.js +0 -182
  234. package/src/mcp/handlers/run-handler.js +0 -318
  235. package/src/mcp/sovereignty-guard.js +0 -113
  236. package/src/mcp/tool-arg-normalizers.js +0 -16
  237. package/src/mutate/reviewer-signal.js +0 -76
  238. package/src/orchestrator/agent-fallback.js +0 -81
  239. package/src/orchestrator/brain-coordinator.js +0 -186
  240. package/src/orchestrator/ci-integration.js +0 -139
  241. package/src/orchestrator/config-init.js +0 -426
  242. package/src/orchestrator/direct-actions.js +0 -217
  243. package/src/orchestrator/drivers/error-recovery.js +0 -287
  244. package/src/orchestrator/drivers/init-context.js +0 -238
  245. package/src/orchestrator/drivers/iteration-loop.js +0 -382
  246. package/src/orchestrator/drivers/iteration-phases/coder-and-refactorer.js +0 -69
  247. package/src/orchestrator/drivers/iteration-phases/guards.js +0 -91
  248. package/src/orchestrator/drivers/iteration-phases/handle-approved.js +0 -29
  249. package/src/orchestrator/drivers/iteration-phases/quality-gates.js +0 -125
  250. package/src/orchestrator/drivers/iteration-phases/reviewer-gate.js +0 -62
  251. package/src/orchestrator/drivers/post-loop.js +0 -404
  252. package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +0 -137
  253. package/src/orchestrator/drivers/pre-loop-phases/config-deprecations.js +0 -47
  254. package/src/orchestrator/drivers/pre-loop-phases/ensure-addyosmani-skills.js +0 -84
  255. package/src/orchestrator/drivers/pre-loop-phases/inject-loaded-plan.js +0 -393
  256. package/src/orchestrator/drivers/pre-loop.js +0 -524
  257. package/src/orchestrator/drivers/run-hu-batch.js +0 -468
  258. package/src/orchestrator/feedback-enrichment.js +0 -140
  259. package/src/orchestrator/feedback-queue.js +0 -151
  260. package/src/orchestrator/flow-control.js +0 -170
  261. package/src/orchestrator/flow-runner.js +0 -365
  262. package/src/orchestrator/fs-leak-detector.js +0 -228
  263. package/src/orchestrator/hu-scheduler.js +0 -114
  264. package/src/orchestrator/hu-sub-pipeline.js +0 -642
  265. package/src/orchestrator/iteration-gate.js +0 -73
  266. package/src/orchestrator/iteration-stages.js +0 -9
  267. package/src/orchestrator/parallel-limiter.js +0 -74
  268. package/src/orchestrator/pipeline-context.js +0 -72
  269. package/src/orchestrator/post-loop-stages.js +0 -468
  270. package/src/orchestrator/pre-loop-stages.js +0 -11
  271. package/src/orchestrator/preflight-checks.js +0 -487
  272. package/src/orchestrator/repair/repair-detector.js +0 -117
  273. package/src/orchestrator/repair/repair-runner.js +0 -142
  274. package/src/orchestrator/reviewer-fallback.js +0 -45
  275. package/src/orchestrator/role-output-compressor.js +0 -189
  276. package/src/orchestrator/session-journal.js +0 -308
  277. package/src/orchestrator/solomon-escalation.js +0 -331
  278. package/src/orchestrator/solomon-rules.js +0 -212
  279. package/src/orchestrator/stages/acceptance-coverage-stage.js +0 -47
  280. package/src/orchestrator/stages/architect-stage.js +0 -172
  281. package/src/orchestrator/stages/coder-stage.js +0 -506
  282. package/src/orchestrator/stages/domain-curator-stage.js +0 -82
  283. package/src/orchestrator/stages/format-stage.js +0 -61
  284. package/src/orchestrator/stages/hu-reviewer-phases/detect-and-apply-splits.js +0 -127
  285. package/src/orchestrator/stages/hu-reviewer-stage.js +0 -419
  286. package/src/orchestrator/stages/perf-stage.js +0 -140
  287. package/src/orchestrator/stages/planner-stage.js +0 -85
  288. package/src/orchestrator/stages/rag-context-stage.js +0 -80
  289. package/src/orchestrator/stages/rag-preload-decisor.js +0 -58
  290. package/src/orchestrator/stages/research-stage.js +0 -69
  291. package/src/orchestrator/stages/reviewer-stage.js +0 -431
  292. package/src/orchestrator/stages/sonar-stage.js +0 -439
  293. package/src/orchestrator/stages/stage-classes.js +0 -84
  294. package/src/orchestrator/stages/stage-executor.js +0 -155
  295. package/src/orchestrator/stages/suite-green-stage.js +0 -62
  296. package/src/orchestrator/stages/tdd-discipline-stage.js +0 -56
  297. package/src/orchestrator/stages/tool-judge-stage.js +0 -53
  298. package/src/orchestrator/stages/triage-stage.js +0 -172
  299. package/src/orchestrator/standby.js +0 -71
  300. package/src/orchestrator/verification-gate.js +0 -183
  301. package/src/orchestrator.js +0 -22
  302. package/src/plan/adr-generator.js +0 -170
  303. package/src/plan/adr-loader.js +0 -60
  304. package/src/plan/plan-executor.js +0 -100
  305. package/src/plan/plan-validation.js +0 -4
  306. package/src/prompts/acceptance-coverage.js +0 -32
  307. package/src/prompts/arbiter.js +0 -38
  308. package/src/prompts/architect.js +0 -103
  309. package/src/prompts/hu-reviewer.js +0 -244
  310. package/src/prompts/tool-correctness-judge.js +0 -31
  311. package/src/prompts/triage.js +0 -57
  312. package/src/rag/embedder.js +0 -2
  313. package/src/rag/embedders/_cloud-base.js +0 -2
  314. package/src/rag/embedders/cohere.js +0 -2
  315. package/src/rag/embedders/mistral.js +0 -2
  316. package/src/rag/embedders/onnx.js +0 -2
  317. package/src/rag/embedders/openai.js +0 -2
  318. package/src/rag/embedders/voyage.js +0 -2
  319. package/src/rag/rerank.js +0 -4
  320. package/src/rag/where-parser.js +0 -4
  321. package/src/repeat-detector.js +0 -88
  322. package/src/review/diff-generator.js +0 -112
  323. package/src/review/git-stash-helper.js +0 -104
  324. package/src/review/schema.js +0 -31
  325. package/src/review/scope-filter.js +0 -152
  326. package/src/review/snapshot-diff.js +0 -122
  327. package/src/review/tdd-discipline.js +0 -90
  328. package/src/review/tdd-policy.js +0 -69
  329. package/src/roles/acceptance-coverage-role.js +0 -78
  330. package/src/roles/architect-role.js +0 -77
  331. package/src/roles/coder-role.js +0 -113
  332. package/src/roles/commiter-role.js +0 -113
  333. package/src/roles/domain-curator-role.js +0 -134
  334. package/src/roles/hu-reviewer-role.js +0 -64
  335. package/src/roles/impeccable-role.js +0 -85
  336. package/src/roles/index.js +0 -18
  337. package/src/roles/karajan-brain-role.js +0 -134
  338. package/src/roles/perf-role.js +0 -122
  339. package/src/roles/planner-role.js +0 -151
  340. package/src/roles/refactorer-role.js +0 -30
  341. package/src/roles/repairer-role.js +0 -181
  342. package/src/roles/researcher-role.js +0 -70
  343. package/src/roles/reviewer-role.js +0 -115
  344. package/src/roles/security-role.js +0 -73
  345. package/src/roles/solomon-role.js +0 -271
  346. package/src/roles/sonar-role.js +0 -72
  347. package/src/roles/tester-role.js +0 -235
  348. package/src/roles/tool-correctness-judge-role.js +0 -78
  349. package/src/roles/triage-role.js +0 -99
  350. package/src/session/journal/decisions-writer.js +0 -200
  351. package/src/session/journal/iteration-logger.js +0 -194
  352. package/src/session/journal/summary-writer.js +0 -320
  353. package/src/session/journal/tree-writer.js +0 -164
  354. package/src/session/journal/write-all.js +0 -89
  355. package/src/session-cleanup.js +0 -116
  356. package/src/skills/semantic-detector.js +0 -167
  357. package/src/skills/skill-detector.js +0 -385
  358. package/src/sonar/cloud-scanner.js +0 -78
  359. package/src/tracker-bootstrap.js +0 -44
  360. package/src/types/index.js +0 -38
  361. package/src/types/policy.js +0 -43
  362. package/src/types/solomon.js +0 -87
  363. package/src/utils/async-lock.js +0 -31
  364. package/src/utils/budget.js +0 -229
  365. package/src/utils/cwd-confirm.js +0 -39
  366. package/src/utils/display/event-handlers.js +0 -403
  367. package/src/utils/display/formatters.js +0 -132
  368. package/src/utils/display/header.js +0 -47
  369. package/src/utils/display/session-summary.js +0 -118
  370. package/src/utils/display/solomon.js +0 -42
  371. package/src/utils/pricing.js +0 -29
  372. package/src/utils/quota-simulator.js +0 -56
  373. package/src/utils/role-assigner.js +0 -137
  374. package/src/utils/rtk-wrapper.js +0 -87
  375. package/src/utils/run-registry.js +0 -9
  376. package/src/utils/status-dashboard.js +0 -254
  377. package/src/utils/tool-call-extractor.js +0 -56
  378. package/src/webperf/devtools-detect.js +0 -112
  379. package/src/webperf/webperf-role-integration.js +0 -66
  380. package/templates/skills/kj-run.md +0 -73
@@ -1,431 +0,0 @@
1
- /**
2
- * Reviewer stage logic + fetchReviewDiff.
3
- * Extracted from iteration-stages.js for maintainability.
4
- */
5
-
6
- import { addCheckpoint, markSessionStatus, saveSession } from "../../session/store.js";
7
- import { setReviewerFeedback, setDeferredIssues } from "../../session/mutators.js";
8
- import { generateDiff } from "../../review/diff-generator.js";
9
- import { redactSecrets } from "../../guards/secret-redactor.js";
10
- import { validateReviewResult } from "../../review/schema.js";
11
- import { filterReviewScope } from "../../review/scope-filter.js";
12
- import { emitProgress, makeEvent, emitAgentOutput } from "../../utils/events.js";
13
- import { runReviewerWithFallback } from "../reviewer-fallback.js";
14
- import { invokeSolomon } from "../solomon-escalation.js";
15
- import { detectRateLimit } from "../../utils/rate-limit-detector.js";
16
- import { createStallDetector } from "../../utils/stall-detector.js";
17
- import { applyQuotaSimulation } from "../../utils/quota-simulator.js";
18
- import { correctionNote } from "../../review/correction-rounds.js";
19
-
20
- function categorizeIssues(issues) {
21
- const categories = { security: 0, correctness: 0, tests: 0, style: 0, other: 0 };
22
- const securityKw = /inject(?:ion)?|xss|csrf|secret.?leak|credential.?expos|auth(?:entication|orization).?(?:bypass|fail|miss|broken|weak)|vulnerab|exploit|httponly|token.?expos/i;
23
- const styleKw = /naming|name|rename|style|format|indent|spacing|convention|cosmetic|readability|comment|jsdoc|whitespace/i;
24
- const testKw = /test|coverage|assert|spec|mock/i;
25
-
26
- for (const issue of issues || []) {
27
- const desc = issue.description || "";
28
- const sev = (issue.severity || "").toLowerCase();
29
- if (sev === "critical" || securityKw.test(desc)) categories.security++;
30
- else if (testKw.test(desc)) categories.tests++;
31
- else if (sev === "low" || sev === "minor" || styleKw.test(desc)) categories.style++;
32
- else categories.correctness++;
33
- }
34
- return categories;
35
- }
36
-
37
- // KJC-TSK-1017: the rejections before an approval are review corrections.
38
- export function approvedMessage(session) {
39
- const rejections = (session.checkpoints || []).filter((cp) => cp.stage === "reviewer" && cp.approved === false).length;
40
- return ["Review approved", correctionNote(rejections)].filter(Boolean).join(" — ");
41
- }
42
-
43
- function buildReviewHistory(session) {
44
- return (session.checkpoints || [])
45
- .filter(cp => cp.stage === "reviewer")
46
- .map(cp => ({ iteration: cp.iteration, note: cp.note || "" }));
47
- }
48
-
49
- async function handleReviewerStalledSolomon({ review, repeatCounts, repeatState, config, logger, emitter, eventBase, session, iteration, task, askQuestion, budgetSummary, repeatDetector, brainCtx }) {
50
- // DETERMINISTIC GUARD: security issues NEVER go to Solomon — always return to coder
51
- const categories = categorizeIssues(review.blocking_issues);
52
- if (categories.security > 0) {
53
- logger.info(`Reviewer found ${categories.security} security issue(s) — returning to coder (Solomon bypassed)`);
54
- emitProgress(emitter, makeEvent("reviewer:security-block", { ...eventBase, stage: "reviewer" }, {
55
- message: `${categories.security} security issue(s) detected — must be fixed before approval`,
56
- detail: { securityCount: categories.security, blockingIssues: review.blocking_issues }
57
- }));
58
- return { review, solomonApproved: false };
59
- }
60
-
61
- // Brain: when enabled, ALL paths go through Brain, not Solomon
62
- if (brainCtx?.enabled) {
63
- const logPrefix = repeatState.stalled
64
- ? `Reviewer stalled (${repeatCounts.reviewer} repeats)`
65
- : `Reviewer rejected (first rejection)`;
66
- logger.info(`Brain: ${logPrefix} — Brain will handle (Solomon bypassed)`);
67
- emitProgress(emitter, makeEvent("brain:escalate", { ...eventBase, stage: "reviewer" }, {
68
- message: `${logPrefix} — Brain handling`,
69
- detail: { repeats: repeatCounts.reviewer || 1, reason: repeatState.reason || "first_rejection" }
70
- }));
71
- // Push reviewer feedback into Brain queue
72
- const { processRoleOutput } = await import("../brain-coordinator.js");
73
- processRoleOutput(brainCtx, { roleName: "reviewer", output: review, iteration });
74
- return { review, solomonApproved: false };
75
- }
76
-
77
- const logPrefix = repeatState.stalled
78
- ? `Reviewer stalled (${repeatCounts.reviewer} repeats)`
79
- : `Reviewer rejected (first rejection)`;
80
- logger.warn(`${logPrefix}. Invoking Solomon mediation.`);
81
- emitProgress(
82
- emitter,
83
- makeEvent("solomon:escalate", { ...eventBase, stage: "reviewer" }, {
84
- message: `${logPrefix} — Solomon mediating`,
85
- detail: { repeats: repeatCounts.reviewer || 1, reason: repeatState.reason || "first_rejection" }
86
- })
87
- );
88
-
89
- const solomonResult = await invokeSolomon({
90
- config, logger, emitter, eventBase, stage: "reviewer", askQuestion, session, iteration,
91
- conflict: {
92
- stage: "reviewer",
93
- task,
94
- iterationCount: repeatCounts.reviewer || 1,
95
- maxIterations: config.session?.fail_fast_repeats ?? 2,
96
- isFirstRejection: !repeatState.stalled,
97
- isRepeat: repeatState.stalled,
98
- stalledReason: repeatState.reason || "first_rejection",
99
- blockingIssues: review.blocking_issues,
100
- issueCategories: categorizeIssues(review.blocking_issues),
101
- history: [
102
- ...buildReviewHistory(session),
103
- { agent: "reviewer", feedback: review.blocking_issues.map(x => x.description).join("; ") }
104
- ]
105
- }
106
- });
107
-
108
- if (solomonResult.action === "approve") {
109
- logger.info("Solomon overrode reviewer — approving code");
110
- emitProgress(emitter, makeEvent("solomon:override", { ...eventBase, stage: "solomon" }, {
111
- message: "Solomon overrode reviewer rejection — code approved",
112
- detail: { ruling: solomonResult.ruling?.result?.ruling }
113
- }));
114
- return { review: { ...review, approved: true, solomon_override: true }, solomonApproved: true };
115
- }
116
- if (solomonResult.action === "pause") {
117
- await markSessionStatus(session, "stalled");
118
- return { review, stalled: true, stalledResult: { paused: true, sessionId: session.id, question: solomonResult.question, context: "reviewer_stalled" } };
119
- }
120
- if (solomonResult.action === "continue") {
121
- repeatDetector.reviewer = { lastHash: null, repeatCount: 0 };
122
- if (solomonResult.humanGuidance) {
123
- setReviewerFeedback(session, `Solomon/user guidance: ${solomonResult.humanGuidance}`);
124
- await saveSession(session);
125
- }
126
- return { review };
127
- }
128
- if (solomonResult.action === "subtask") {
129
- return { review, stalled: true, stalledResult: { paused: true, sessionId: session.id, subtask: solomonResult.subtask, context: "reviewer_subtask" } };
130
- }
131
-
132
- // Fallback
133
- const message = `Manual intervention required: reviewer issues repeated ${repeatCounts.reviewer || 1} times.`;
134
- await markSessionStatus(session, "stalled");
135
- emitProgress(
136
- emitter,
137
- makeEvent("session:end", { ...eventBase, stage: "reviewer" }, {
138
- status: "stalled",
139
- message,
140
- detail: { reason: repeatState.reason, repeats: repeatCounts.reviewer, budget: budgetSummary() }
141
- })
142
- );
143
- return { review, stalled: true, stalledResult: { approved: false, sessionId: session.id, reason: "stalled" } };
144
- }
145
-
146
- async function handleReviewerRejection({ review, repeatDetector, config, logger, emitter, eventBase, session, iteration, task, askQuestion, budgetSummary, brainCtx }) {
147
- repeatDetector.addIteration([], review.blocking_issues);
148
- const repeatState = repeatDetector.isStalled();
149
-
150
- const solomonEnabled = Boolean(config.pipeline?.solomon?.enabled);
151
-
152
- // Brain: if enabled and bypass_solomon_on_correctness, push issues to queue and skip Solomon
153
- // for non-style rejections. Solomon is still consulted on genuine dilemmas (style-only, deadlock).
154
- if (brainCtx?.enabled && config.brain?.bypass_solomon_on_correctness !== false) {
155
- const cats = categorizeIssues(review.blocking_issues);
156
- const nonStyleIssues = cats.security + cats.correctness + cats.tests;
157
- // Only bypass if there ARE non-style issues (correctness, tests, security, or "other" is correctness)
158
- // If it's style-only, let Solomon evaluate whether to override
159
- if (nonStyleIssues > 0 || cats.other > 0) {
160
- const { processRoleOutput } = await import("../brain-coordinator.js");
161
- processRoleOutput(brainCtx, { roleName: "reviewer", output: review, iteration });
162
- logger.info(`Brain: reviewer rejected with ${nonStyleIssues} non-style issue(s) — bypassing Solomon, returning to coder`);
163
- emitProgress(emitter, makeEvent("brain:bypass-solomon", { ...eventBase, stage: "reviewer" }, {
164
- message: `Brain: ${nonStyleIssues} non-style issue(s) — sending to coder without Solomon`,
165
- detail: { categories: cats, queueSize: brainCtx.feedbackQueue.entries.length }
166
- }));
167
- // Persist flat feedback for compat with non-Brain flow
168
- setReviewerFeedback(session, review.blocking_issues
169
- .map((x, idx) => `R-${idx + 1} [${x.severity || "medium"}]: ${x.description}`)
170
- .join("\n"));
171
- await saveSession(session);
172
- return null; // null = continue to next iteration (coder fixes)
173
- }
174
- logger.info("Brain: reviewer rejected with style-only issues — consulting Solomon for dilemma");
175
- }
176
-
177
- // When Solomon is disabled, only act on stalls (legacy behavior)
178
- if (!solomonEnabled) {
179
- if (!repeatState.stalled) return null;
180
- const repeatCounts = repeatDetector.getRepeatCounts();
181
- return handleReviewerStalledSolomon({
182
- review, repeatCounts, repeatState, config, logger, emitter,
183
- eventBase, session, iteration, task, askQuestion,
184
- budgetSummary, repeatDetector, brainCtx
185
- });
186
- }
187
-
188
- // Solomon evaluates EVERY rejection
189
- const repeatCounts = repeatDetector.getRepeatCounts();
190
- const evaluateEventName = brainCtx?.enabled ? "brain:evaluate" : "solomon:evaluate";
191
- logger.info(`Reviewer rejected — ${brainCtx?.enabled ? "Brain" : "Solomon"} evaluating ${review.blocking_issues.length} blocking issue(s)`);
192
- emitProgress(emitter, makeEvent(evaluateEventName, { ...eventBase, stage: brainCtx?.enabled ? "brain" : "solomon" }, {
193
- message: `${brainCtx?.enabled ? "Brain" : "Solomon"} evaluating reviewer rejection`,
194
- detail: { blockingCount: review.blocking_issues.length, isRepeat: repeatState.stalled }
195
- }));
196
-
197
- return handleReviewerStalledSolomon({
198
- review, repeatCounts, repeatState, config, logger, emitter,
199
- eventBase, session, iteration, task, askQuestion,
200
- budgetSummary, repeatDetector, brainCtx
201
- });
202
- }
203
-
204
- export async function fetchReviewDiff(session, logger, projectDir = null) {
205
- let diff;
206
- if (session.ci_pr_number) {
207
- const { getPrDiff } = await import("../../ci/pr-diff.js");
208
- diff = await getPrDiff(session.ci_pr_number);
209
- logger.info(`Reviewer reading PR diff #${session.ci_pr_number}`);
210
- } else {
211
- diff = await generateDiff({ baseRef: session.session_start_sha, stageNewFiles: true, projectDir });
212
- }
213
- // Inbound boundary: mask hardcoded secrets before the diff reaches the
214
- // (possibly cloud) reviewer model. Runs BEFORE the injection guard below so
215
- // that guard still sees the real prompt-injection phrasing (KJC-TSK-0583).
216
- return redactSecrets(diff);
217
- }
218
-
219
- export async function runReviewerStage({ reviewerRole, config, logger, emitter, eventBase, session, trackBudget, iteration, reviewRules, task, repeatDetector, budgetSummary, askQuestion, brainCtx }) {
220
- logger.setContext({ iteration, stage: "reviewer" });
221
- emitProgress(
222
- emitter,
223
- makeEvent("reviewer:start", { ...eventBase, stage: "reviewer" }, {
224
- message: `Reviewer (${reviewerRole.provider}) running`,
225
- detail: { reviewer: reviewerRole.provider, provider: reviewerRole.provider, executorType: "agent" }
226
- })
227
- );
228
-
229
- let diff;
230
- try {
231
- diff = await fetchReviewDiff(session, logger, config?.projectDir || null);
232
- } catch (err) {
233
- logger.warn(`Review diff generation failed: ${err.message}`);
234
- return { approved: false, blocking_issues: [{ description: `Diff generation failed: ${err.message}` }], non_blocking_suggestions: [], summary: `Reviewer failed: cannot generate diff — ${err.message}`, confidence: 0 };
235
- }
236
-
237
- // Injection guard: scan diff before sending to AI reviewer
238
- const { scanDiff } = await import("../../utils/injection-guard.js");
239
- const guardResult = scanDiff(diff);
240
- if (!guardResult.clean) {
241
- logger.warn(`Injection guard: ${guardResult.summary}`);
242
- emitProgress(emitter, makeEvent("guard:injection", { ...eventBase, stage: "reviewer" }, {
243
- message: `Injection guard blocked review: ${guardResult.summary}`,
244
- detail: { findings: guardResult.findings, summary: guardResult.summary }
245
- }));
246
- return {
247
- approved: false,
248
- blocking_issues: guardResult.findings.map((f) => ({
249
- id: `INJECTION_${f.type.toUpperCase()}`,
250
- severity: "critical",
251
- description: `Potential prompt injection (${f.type}): ${f.snippet}`,
252
- line: f.line,
253
- })),
254
- non_blocking_suggestions: [],
255
- summary: `Review blocked by injection guard: ${guardResult.summary}`,
256
- confidence: 1,
257
- };
258
- }
259
-
260
- const reviewerOnOutput = (payload) => emitAgentOutput(emitter, eventBase, "reviewer", reviewerRole.provider, payload);
261
- const reviewerStall = createStallDetector({
262
- onOutput: reviewerOnOutput, emitter, eventBase, stage: "reviewer", provider: reviewerRole.provider
263
- });
264
- const reviewerStart = Date.now();
265
- let reviewerExec;
266
- try {
267
- reviewerExec = await runReviewerWithFallback({
268
- reviewerName: reviewerRole.provider,
269
- config,
270
- logger,
271
- emitter,
272
- reviewInput: { task, diff, reviewRules, onOutput: reviewerStall.onOutput },
273
- session,
274
- iteration,
275
- onAttemptResult: ({ reviewer, result }) => {
276
- trackBudget({ role: "reviewer", provider: reviewer, model: reviewerRole.model, result, duration_ms: Date.now() - reviewerStart });
277
- }
278
- });
279
- } catch (err) {
280
- logger.warn(`Reviewer threw: ${err.message}`);
281
- reviewerExec = { execResult: { ok: false, error: err.message }, attempts: [{ reviewer: reviewerRole.provider, result: { ok: false, error: err.message } }] };
282
- } finally {
283
- reviewerStall.stop();
284
- }
285
-
286
- if (applyQuotaSimulation(reviewerExec.execResult, { iteration, agent: reviewerRole.provider })) {
287
- // Reviewer wraps the agent call: detectRateLimit reads `lastAttempt.result.error`,
288
- // so propagate the synthetic line into the most recent attempt too.
289
- const last = reviewerExec.attempts?.at(-1);
290
- if (last) {
291
- if (!last.result || typeof last.result !== "object") last.result = {};
292
- last.result.error = reviewerExec.execResult.result.error;
293
- }
294
- }
295
-
296
- if (!reviewerExec.execResult?.ok) {
297
- const lastAttempt = reviewerExec.attempts.at(-1);
298
- const details =
299
- lastAttempt?.result?.error ||
300
- lastAttempt?.execResult?.summary ||
301
- `reviewer=${lastAttempt?.reviewer || "unknown"}`;
302
-
303
- const rateLimitCheck = detectRateLimit({
304
- stderr: lastAttempt?.result?.error || "",
305
- stdout: lastAttempt?.result?.output || ""
306
- });
307
-
308
- if (rateLimitCheck.isRateLimit) {
309
- // Enter standby instead of pausing
310
- return {
311
- action: "standby",
312
- standbyInfo: {
313
- agent: reviewerRole.provider,
314
- cooldownMs: rateLimitCheck.cooldownMs || (rateLimitCheck.isProviderOutage ? 30000 : null),
315
- cooldownUntil: rateLimitCheck.cooldownUntil,
316
- message: rateLimitCheck.message,
317
- isProviderOutage: rateLimitCheck.isProviderOutage || false
318
- }
319
- };
320
- }
321
-
322
- await markSessionStatus(session, "failed");
323
- emitProgress(
324
- emitter,
325
- makeEvent("reviewer:end", { ...eventBase, stage: "reviewer" }, {
326
- status: "fail",
327
- message: `Reviewer failed: ${details}`,
328
- detail: { provider: reviewerRole.provider, executorType: "agent" }
329
- })
330
- );
331
- throw new Error(`Reviewer failed: ${details}`);
332
- }
333
-
334
- const reviewResult = reviewerExec.execResult.result;
335
- let review;
336
- try {
337
- review = validateReviewResult({
338
- approved: reviewResult.approved,
339
- blocking_issues: reviewResult.blocking_issues || [],
340
- non_blocking_suggestions: reviewResult.non_blocking_suggestions || [],
341
- summary: reviewResult.raw_summary || "",
342
- confidence: reviewResult.confidence ?? 0
343
- });
344
- } catch (error_) {
345
- // KJC-BUG-0284 (#1982): a verdict kj cannot read is the reviewer's failure,
346
- // never a PARSE_ERROR defect handed to the coder (it sent one run in circles).
347
- const details = `the verdict could not be read: ${error_.message}`;
348
- logger.warn(`Reviewer output validation failed: ${error_.message}`);
349
- await markSessionStatus(session, "failed");
350
- emitProgress(
351
- emitter,
352
- makeEvent("reviewer:end", { ...eventBase, stage: "reviewer" }, {
353
- status: "fail",
354
- message: `Reviewer failed: ${details}`,
355
- detail: { provider: reviewerRole.provider, executorType: "agent" }
356
- })
357
- );
358
- throw new Error(`Reviewer failed: ${details}`, { cause: error_ });
359
- }
360
- // --- Scope filter: auto-defer out-of-scope blocking issues ---
361
- const { review: filteredReview, demoted, deferred, allDemoted } = filterReviewScope(review, diff);
362
- review = filteredReview;
363
-
364
- if (demoted.length > 0) {
365
- logger.info(`Scope filter: deferred ${demoted.length} out-of-scope issue(s)${allDemoted ? " — auto-approved" : ""}`);
366
-
367
- // Accumulate deferred issues in session for tracking
368
- if (!session.deferred_issues) setDeferredIssues(session, []);
369
- session.deferred_issues.push(...deferred);
370
- await saveSession(session);
371
-
372
- emitProgress(
373
- emitter,
374
- makeEvent("reviewer:scope_filter", { ...eventBase, stage: "reviewer" }, {
375
- message: `Scope filter deferred ${demoted.length} out-of-scope issue(s)`,
376
- detail: {
377
- demotedCount: demoted.length,
378
- autoApproved: allDemoted,
379
- totalDeferred: session.deferred_issues.length,
380
- deferred: deferred.map(d => ({ file: d.file, id: d.id, description: d.description }))
381
- }
382
- })
383
- );
384
- await addCheckpoint(session, {
385
- stage: "reviewer-scope-filter",
386
- iteration,
387
- demoted_count: demoted.length,
388
- auto_approved: allDemoted,
389
- total_deferred: session.deferred_issues.length
390
- });
391
- }
392
-
393
- // Feedback signature for stale detection: concatenated issue descriptions
394
- const feedbackSignature = review.blocking_issues
395
- .map(x => (x.description || "").slice(0, 120))
396
- .join("|") || "approved";
397
-
398
- await addCheckpoint(session, {
399
- stage: "reviewer",
400
- iteration,
401
- approved: review.approved,
402
- blocking_issues: review.blocking_issues.length,
403
- provider: reviewerRole.provider,
404
- model: reviewerRole.model || null,
405
- note: feedbackSignature
406
- });
407
-
408
- emitProgress(
409
- emitter,
410
- makeEvent("reviewer:end", { ...eventBase, stage: "reviewer" }, {
411
- status: review.approved ? "ok" : "fail",
412
- message: review.approved ? approvedMessage(session) : `Review rejected (${review.blocking_issues.length} blocking)`,
413
- detail: {
414
- approved: review.approved,
415
- blockingCount: review.blocking_issues.length,
416
- issues: review.blocking_issues.map(
417
- (x) => `${x.id || "ISSUE"}: ${x.description || "Missing description"}`
418
- ),
419
- provider: reviewerRole.provider,
420
- executorType: "agent"
421
- }
422
- })
423
- );
424
-
425
- if (!review.approved) {
426
- const rejectionResult = await handleReviewerRejection({ review, repeatDetector, config, logger, emitter, eventBase, session, iteration, task, askQuestion, budgetSummary, brainCtx });
427
- if (rejectionResult) return rejectionResult;
428
- }
429
-
430
- return { review };
431
- }