karajan-code 4.70.4 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +6 -14
- package/packages/hu-board/package.json +1 -1
- package/packages/hu-board/public/app.js +4 -18
- package/packages/hu-board/public/index.html +5 -2
- package/packages/hu-board/public/styles.css +26 -0
- package/packages/hu-board/public/utils/api.js +0 -74
- package/packages/hu-board/public/utils/board-tour.js +62 -0
- package/packages/hu-board/public/utils/board-view.js +49 -144
- package/packages/hu-board/public/utils/command-launcher.js +8 -70
- package/packages/hu-board/public/utils/formatters.js +10 -0
- package/packages/hu-board/public/utils/governance-view.js +13 -1
- package/packages/hu-board/public/utils/hu-actions.js +17 -68
- package/packages/hu-board/public/utils/init-listeners.js +7 -8
- package/packages/hu-board/public/utils/log-panel.js +3 -16
- package/packages/hu-board/public/utils/maggle-mode.js +2 -12
- package/packages/hu-board/public/utils/modals.js +7 -0
- package/packages/hu-board/public/utils/project-picker-view.js +1 -1
- package/packages/hu-board/public/utils/server-push.js +3 -22
- package/packages/hu-board/public/utils/shared-board-notice.js +33 -0
- package/packages/hu-board/public/utils/story-detail-view.js +5 -19
- package/packages/hu-board/src/cleanup-zombies.js +0 -1
- package/packages/hu-board/src/command-runner.js +36 -25
- package/packages/hu-board/src/db-connection.js +282 -0
- package/packages/hu-board/src/db-paths.js +113 -0
- package/packages/hu-board/src/db-queries.js +188 -0
- package/packages/hu-board/src/db-tombstones.js +51 -0
- package/packages/hu-board/src/db.js +28 -619
- package/packages/hu-board/src/ephemeral-cleaner.js +2 -3
- package/packages/hu-board/src/hu-zombie-reaper.js +5 -1
- package/packages/hu-board/src/plan-mutations.js +3 -153
- package/packages/hu-board/src/plans-service.js +55 -0
- package/packages/hu-board/src/routes/api/commands.js +122 -0
- package/packages/hu-board/src/routes/api/plans.js +55 -0
- package/packages/hu-board/src/routes/api/projects.js +267 -0
- package/packages/hu-board/src/routes/api/prompts.js +135 -0
- package/packages/hu-board/src/routes/api/sessions.js +95 -0
- package/packages/hu-board/src/routes/api/stories.js +183 -0
- package/packages/hu-board/src/routes/api/system.js +241 -0
- package/packages/hu-board/src/routes/api/tombstones.js +38 -0
- package/packages/hu-board/src/routes/api.js +24 -1371
- package/packages/hu-board/src/routes/governance.js +23 -1
- package/packages/hu-board/src/routes/lanes.js +40 -0
- package/packages/hu-board/src/routes/rag.js +4 -3
- package/packages/hu-board/src/server.js +20 -34
- package/packages/hu-board/src/sync-files.js +318 -0
- package/packages/hu-board/src/sync-project.js +99 -0
- package/packages/hu-board/src/sync.js +22 -566
- package/packages/hu-board/src/zombie-reaper.js +1 -1
- package/scripts/dual-publish.mjs +19 -3
- package/scripts/postinstall.js +15 -2
- package/scripts/verify-pack-mcp.mjs +11 -7
- package/scripts/verify-pack.mjs +4 -4
- package/src/audit/audit-history.js +3 -2
- package/src/audit/dead-exports.js +68 -59
- package/src/audit/deterministic-summary.js +33 -13
- package/src/audit/npm-signatures.js +41 -0
- package/src/audit/sbom.js +35 -0
- package/src/checks/agent-token.js +112 -0
- package/src/checks/dir-setup.js +34 -1
- package/src/checks/native-build.js +21 -39
- package/src/checks/runner.js +128 -142
- package/src/cli/advanced-commands.js +6 -6
- package/src/cli/register-meta.js +42 -82
- package/src/cli/register-pipeline.js +8 -143
- package/src/cli/register-plan.js +9 -100
- package/src/cli/register-roles-skills.js +1 -1
- package/src/cli/retired-commands.js +49 -0
- package/src/cli.js +18 -5
- package/src/commands/agent-run.js +40 -26
- package/src/commands/audit.js +127 -124
- package/src/commands/board.js +5 -9
- package/src/commands/check.js +29 -16
- package/src/commands/doctor.js +2 -0
- package/src/commands/env.js +176 -150
- package/src/commands/go.js +71 -53
- package/src/commands/harden.js +90 -81
- package/src/commands/hu-start.js +52 -0
- package/src/commands/hu.js +288 -221
- package/src/commands/identity.js +111 -78
- package/src/commands/init-atril.js +47 -0
- package/src/commands/init.js +11 -40
- package/src/commands/install-tools.js +70 -85
- package/src/commands/main-guard.js +78 -0
- package/src/commands/policy.js +226 -184
- package/src/commands/qmd.js +27 -21
- package/src/commands/rag.js +121 -55
- package/src/commands/review-gate.js +421 -341
- package/src/commands/skills.js +4 -1
- package/src/commands/start.js +4 -5
- package/src/commands/steward.js +96 -47
- package/src/commands/tournament.js +46 -37
- package/src/commands/worktree.js +107 -26
- package/src/config/defaults.js +1 -0
- package/src/config/loader.js +34 -17
- package/src/config/role-resolver.js +1 -0
- package/src/config/schema.js +1 -0
- package/src/config/secrets.js +36 -0
- package/src/config.js +1 -0
- package/src/environment/adr.js +16 -2
- package/src/git/karajan-label.js +20 -8
- package/src/guards/main-guard.js +54 -0
- package/src/harden/hook-templates.js +16 -1
- package/src/harden/sentinel/posttooluse.mjs +18 -6
- package/src/harden/sentinel/pretooluse-sentinel.mjs +64 -36
- package/src/harden/sentinel/sentinel-lib.mjs +129 -26
- package/src/harden/sentinel/sentinel-shell.mjs +5 -16
- package/src/harden/sentinel/sessionstart.mjs +3 -2
- package/src/harden/sentinel/stop.mjs +5 -4
- package/src/harden/workflow-templates.js +1 -1
- package/src/hu/board-lookup.js +29 -0
- package/src/hu/gh-identity.js +23 -0
- package/src/hu/github-board.js +4 -2
- package/src/hu/lane-prune.js +83 -13
- package/src/hu/lane-setup.js +65 -0
- package/src/hu/lanes.js +66 -0
- package/src/hu/team-board-mirror.js +3 -2
- package/src/infrastructure/command-runner.js +1 -1
- package/src/infrastructure/file-system-service.js +1 -1
- package/src/mcp/handlers/direct-handlers.js +2 -292
- package/src/mcp/handlers/hu-handlers.js +1 -35
- package/src/mcp/handlers/management-handlers.js +2 -42
- package/src/mcp/handlers/rag-handler.js +9 -1
- package/src/mcp/server-handlers.js +16 -22
- package/src/mcp/tools.js +1 -196
- package/src/plan/lane-plans.js +54 -0
- package/src/plan/plan-store.js +7 -4
- package/src/policy/add.js +26 -12
- package/src/policy/adr-number-check.js +31 -0
- package/src/prompts/audit.js +299 -339
- package/src/prompts/card-context.js +10 -5
- package/src/prompts/reviewer.js +5 -2
- package/src/rag/auto-update.js +71 -44
- package/src/rag/bootstrap-index.js +46 -54
- package/src/rag/indexer.js +9 -4
- package/src/rag/migrate.js +1 -1
- package/src/rag/onnx-fallback.js +2 -2
- package/src/rag/pid-lease.js +181 -0
- package/src/rag/project-store.js +2 -12
- package/src/review/card-first.js +57 -46
- package/src/review/gate-gitignore.js +23 -4
- package/src/review/gate-hook.js +12 -4
- package/src/review/one-shot-review.js +45 -35
- package/src/review/publish-pr.js +14 -2
- package/src/review/repo-docs.js +73 -0
- package/src/review/repo-stack.js +59 -0
- package/src/review/reviewer-fallback.js +19 -4
- package/src/review/seal-commit.js +29 -0
- package/src/review/sonar-pregate.js +59 -44
- package/src/review/third-party-review.js +90 -16
- package/src/review/third-party-size.js +43 -0
- package/src/review/third-party-skills.js +54 -0
- package/src/review/verify-pr.js +1 -24
- package/src/roles/audit-role.js +106 -125
- package/src/skills/atril-cli.js +19 -1
- package/src/skills/atril-skills.js +5 -4
- package/src/skills/skills-search.js +72 -0
- package/src/skills/translate.js +62 -0
- package/src/sonar/scanner.js +116 -101
- package/src/steward/invariants.js +5 -4
- package/src/steward/phantom-sweep.js +66 -0
- package/src/tournament/judge.js +60 -53
- package/src/utils/gh-account.js +37 -0
- package/src/utils/git.js +0 -13
- package/src/utils/home-migration.js +7 -1
- package/src/utils/main-checkout.js +53 -0
- package/src/utils/qmd-collection.js +3 -1
- package/src/utils/welcome.js +3 -3
- package/templates/{skills → atril/commands}/kj-architect.md +5 -0
- package/templates/{skills → atril/commands}/kj-audit.md +5 -0
- package/templates/{skills → atril/commands}/kj-board.md +5 -0
- package/templates/{skills → atril/commands}/kj-code.md +5 -0
- package/templates/{skills → atril/commands}/kj-csv-transform.md +5 -0
- package/templates/{skills → atril/commands}/kj-data-report.md +5 -0
- package/templates/{skills → atril/commands}/kj-discover.md +5 -0
- package/templates/{skills → atril/commands}/kj-rag-query.md +5 -0
- package/templates/{skills → atril/commands}/kj-review.md +5 -0
- package/templates/{skills → atril/commands}/kj-security.md +5 -0
- package/templates/{skills → atril/commands}/kj-sonar.md +5 -0
- package/templates/{skills → atril/commands}/kj-sql-analysis.md +5 -0
- package/templates/{skills → atril/commands}/kj-test.md +5 -0
- package/packages/hu-board/public/utils/run-launcher.js +0 -169
- package/packages/hu-board/src/run-tracker.js +0 -121
- package/src/activity-log.js +0 -59
- package/src/agents/host-agent.js +0 -38
- package/src/agents/model-registry.js +0 -142
- package/src/audit/plan-adherence.js +0 -224
- package/src/autonomy/arbiter-role.js +0 -71
- package/src/autonomy/arbiter.js +0 -22
- package/src/autonomy/decider.js +0 -18
- package/src/autonomy/decision-resolver.js +0 -58
- package/src/autonomy/outcome-report.js +0 -55
- package/src/autonomy/stage-ask.js +0 -30
- package/src/brain/decision-tracker.js +0 -125
- package/src/brain/decisor.js +0 -243
- package/src/brain/solomon-consult.js +0 -171
- package/src/brain/standby-scheduler.js +0 -8
- package/src/budget/comparison.js +0 -96
- package/src/canvas/parse-md.js +0 -238
- package/src/canvas/schema.js +0 -101
- package/src/canvas/to-flat.js +0 -85
- package/src/canvas/validate.js +0 -163
- package/src/ci/dispatch.js +0 -99
- package/src/ci/index.js +0 -3
- package/src/ci/pr-diff.js +0 -26
- package/src/cli/register-standby.js +0 -26
- package/src/commands/architect.js +0 -111
- package/src/commands/autorun.js +0 -49
- package/src/commands/researcher.js +0 -54
- package/src/commands/resume.js +0 -72
- package/src/commands/review.js +0 -89
- package/src/commands/run.js +0 -185
- package/src/commands/standby.js +0 -117
- package/src/commands/status.js +0 -36
- package/src/commands/triage.js +0 -78
- package/src/commands/undo.js +0 -62
- package/src/domains/domain-loader.js +0 -245
- package/src/domains/domain-registry.js +0 -140
- package/src/domains/domain-synthesizer.js +0 -129
- package/src/git/automation.js +0 -433
- package/src/git/coder-commit-guard.js +0 -40
- package/src/git/hu-automation.js +0 -243
- package/src/git/hu-snapshot.js +0 -10
- package/src/git/symlink-targets.js +0 -57
- package/src/golden/asserter.js +0 -92
- package/src/golden/loader.js +0 -52
- package/src/golden/runner.js +0 -92
- package/src/golden/schema.js +0 -41
- package/src/guards/duplicate-members.js +0 -86
- package/src/guards/intent-guard.js +0 -161
- package/src/guards/perf-guard.js +0 -126
- package/src/guards/policy-guard.js +0 -90
- package/src/guards/policy-resolver.js +0 -85
- package/src/guards/secret-redactor.js +0 -71
- package/src/hu/acceptance-runner.js +0 -138
- package/src/hu/lazy-planner.js +0 -109
- package/src/hu/parallel-executor.js +0 -94
- package/src/hu/routing-metrics.js +0 -17
- package/src/hu/split-validator.js +0 -143
- package/src/hu/splitting-detector.js +0 -158
- package/src/hu/splitting-generator.js +0 -175
- package/src/hu/store.js +0 -394
- package/src/infrastructure/mocks.js +0 -182
- package/src/mcp/handlers/run-handler.js +0 -318
- package/src/mcp/sovereignty-guard.js +0 -113
- package/src/mcp/tool-arg-normalizers.js +0 -16
- package/src/mutate/reviewer-signal.js +0 -76
- package/src/orchestrator/agent-fallback.js +0 -81
- package/src/orchestrator/brain-coordinator.js +0 -186
- package/src/orchestrator/ci-integration.js +0 -139
- package/src/orchestrator/config-init.js +0 -426
- package/src/orchestrator/direct-actions.js +0 -217
- package/src/orchestrator/drivers/error-recovery.js +0 -287
- package/src/orchestrator/drivers/init-context.js +0 -238
- package/src/orchestrator/drivers/iteration-loop.js +0 -382
- package/src/orchestrator/drivers/iteration-phases/coder-and-refactorer.js +0 -69
- package/src/orchestrator/drivers/iteration-phases/guards.js +0 -91
- package/src/orchestrator/drivers/iteration-phases/handle-approved.js +0 -29
- package/src/orchestrator/drivers/iteration-phases/quality-gates.js +0 -125
- package/src/orchestrator/drivers/iteration-phases/reviewer-gate.js +0 -62
- package/src/orchestrator/drivers/post-loop.js +0 -404
- package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +0 -137
- package/src/orchestrator/drivers/pre-loop-phases/config-deprecations.js +0 -47
- package/src/orchestrator/drivers/pre-loop-phases/ensure-addyosmani-skills.js +0 -84
- package/src/orchestrator/drivers/pre-loop-phases/inject-loaded-plan.js +0 -393
- package/src/orchestrator/drivers/pre-loop.js +0 -524
- package/src/orchestrator/drivers/run-hu-batch.js +0 -468
- package/src/orchestrator/feedback-enrichment.js +0 -140
- package/src/orchestrator/feedback-queue.js +0 -151
- package/src/orchestrator/flow-control.js +0 -170
- package/src/orchestrator/flow-runner.js +0 -365
- package/src/orchestrator/fs-leak-detector.js +0 -228
- package/src/orchestrator/hu-scheduler.js +0 -114
- package/src/orchestrator/hu-sub-pipeline.js +0 -642
- package/src/orchestrator/iteration-gate.js +0 -73
- package/src/orchestrator/iteration-stages.js +0 -9
- package/src/orchestrator/parallel-limiter.js +0 -74
- package/src/orchestrator/pipeline-context.js +0 -72
- package/src/orchestrator/post-loop-stages.js +0 -468
- package/src/orchestrator/pre-loop-stages.js +0 -11
- package/src/orchestrator/preflight-checks.js +0 -487
- package/src/orchestrator/repair/repair-detector.js +0 -117
- package/src/orchestrator/repair/repair-runner.js +0 -142
- package/src/orchestrator/reviewer-fallback.js +0 -45
- package/src/orchestrator/role-output-compressor.js +0 -189
- package/src/orchestrator/session-journal.js +0 -308
- package/src/orchestrator/solomon-escalation.js +0 -331
- package/src/orchestrator/solomon-rules.js +0 -212
- package/src/orchestrator/stages/acceptance-coverage-stage.js +0 -47
- package/src/orchestrator/stages/architect-stage.js +0 -172
- package/src/orchestrator/stages/coder-stage.js +0 -506
- package/src/orchestrator/stages/domain-curator-stage.js +0 -82
- package/src/orchestrator/stages/format-stage.js +0 -61
- package/src/orchestrator/stages/hu-reviewer-phases/detect-and-apply-splits.js +0 -127
- package/src/orchestrator/stages/hu-reviewer-stage.js +0 -419
- package/src/orchestrator/stages/perf-stage.js +0 -140
- package/src/orchestrator/stages/planner-stage.js +0 -85
- package/src/orchestrator/stages/rag-context-stage.js +0 -80
- package/src/orchestrator/stages/rag-preload-decisor.js +0 -58
- package/src/orchestrator/stages/research-stage.js +0 -69
- package/src/orchestrator/stages/reviewer-stage.js +0 -431
- package/src/orchestrator/stages/sonar-stage.js +0 -439
- package/src/orchestrator/stages/stage-classes.js +0 -84
- package/src/orchestrator/stages/stage-executor.js +0 -155
- package/src/orchestrator/stages/suite-green-stage.js +0 -62
- package/src/orchestrator/stages/tdd-discipline-stage.js +0 -56
- package/src/orchestrator/stages/tool-judge-stage.js +0 -53
- package/src/orchestrator/stages/triage-stage.js +0 -172
- package/src/orchestrator/standby.js +0 -71
- package/src/orchestrator/verification-gate.js +0 -183
- package/src/orchestrator.js +0 -22
- package/src/plan/adr-generator.js +0 -170
- package/src/plan/adr-loader.js +0 -60
- package/src/plan/plan-executor.js +0 -100
- package/src/plan/plan-validation.js +0 -4
- package/src/prompts/acceptance-coverage.js +0 -32
- package/src/prompts/arbiter.js +0 -38
- package/src/prompts/architect.js +0 -103
- package/src/prompts/hu-reviewer.js +0 -244
- package/src/prompts/tool-correctness-judge.js +0 -31
- package/src/prompts/triage.js +0 -57
- package/src/rag/embedder.js +0 -2
- package/src/rag/embedders/_cloud-base.js +0 -2
- package/src/rag/embedders/cohere.js +0 -2
- package/src/rag/embedders/mistral.js +0 -2
- package/src/rag/embedders/onnx.js +0 -2
- package/src/rag/embedders/openai.js +0 -2
- package/src/rag/embedders/voyage.js +0 -2
- package/src/rag/rerank.js +0 -4
- package/src/rag/where-parser.js +0 -4
- package/src/repeat-detector.js +0 -88
- package/src/review/diff-generator.js +0 -112
- package/src/review/git-stash-helper.js +0 -104
- package/src/review/schema.js +0 -31
- package/src/review/scope-filter.js +0 -152
- package/src/review/snapshot-diff.js +0 -122
- package/src/review/tdd-discipline.js +0 -90
- package/src/review/tdd-policy.js +0 -69
- package/src/roles/acceptance-coverage-role.js +0 -78
- package/src/roles/architect-role.js +0 -77
- package/src/roles/coder-role.js +0 -113
- package/src/roles/commiter-role.js +0 -113
- package/src/roles/domain-curator-role.js +0 -134
- package/src/roles/hu-reviewer-role.js +0 -64
- package/src/roles/impeccable-role.js +0 -85
- package/src/roles/index.js +0 -18
- package/src/roles/karajan-brain-role.js +0 -134
- package/src/roles/perf-role.js +0 -122
- package/src/roles/planner-role.js +0 -151
- package/src/roles/refactorer-role.js +0 -30
- package/src/roles/repairer-role.js +0 -181
- package/src/roles/researcher-role.js +0 -70
- package/src/roles/reviewer-role.js +0 -115
- package/src/roles/security-role.js +0 -73
- package/src/roles/solomon-role.js +0 -271
- package/src/roles/sonar-role.js +0 -72
- package/src/roles/tester-role.js +0 -235
- package/src/roles/tool-correctness-judge-role.js +0 -78
- package/src/roles/triage-role.js +0 -99
- package/src/session/journal/decisions-writer.js +0 -200
- package/src/session/journal/iteration-logger.js +0 -194
- package/src/session/journal/summary-writer.js +0 -320
- package/src/session/journal/tree-writer.js +0 -164
- package/src/session/journal/write-all.js +0 -89
- package/src/session-cleanup.js +0 -116
- package/src/skills/semantic-detector.js +0 -167
- package/src/skills/skill-detector.js +0 -385
- package/src/sonar/cloud-scanner.js +0 -78
- package/src/tracker-bootstrap.js +0 -44
- package/src/types/index.js +0 -38
- package/src/types/policy.js +0 -43
- package/src/types/solomon.js +0 -87
- package/src/utils/async-lock.js +0 -31
- package/src/utils/budget.js +0 -229
- package/src/utils/cwd-confirm.js +0 -39
- package/src/utils/display/event-handlers.js +0 -403
- package/src/utils/display/formatters.js +0 -132
- package/src/utils/display/header.js +0 -47
- package/src/utils/display/session-summary.js +0 -118
- package/src/utils/display/solomon.js +0 -42
- package/src/utils/pricing.js +0 -29
- package/src/utils/quota-simulator.js +0 -56
- package/src/utils/role-assigner.js +0 -137
- package/src/utils/rtk-wrapper.js +0 -87
- package/src/utils/run-registry.js +0 -9
- package/src/utils/status-dashboard.js +0 -254
- package/src/utils/tool-call-extractor.js +0 -56
- package/src/webperf/devtools-detect.js +0 -112
- package/src/webperf/webperf-role-integration.js +0 -66
- 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
|
-
}
|