karajan-code 4.70.3 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/ai-surface.js +9 -7
- package/src/checks/config-files.js +8 -7
- 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 -140
- package/src/cli/register-plan.js +9 -100
- 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 -148
- package/src/commands/go.js +76 -55
- package/src/commands/harden.js +105 -86
- 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 +75 -48
- package/src/commands/review-gate.js +422 -339
- 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 +94 -25
- package/src/config/loader.js +34 -17
- package/src/config/overrides.js +2 -1
- package/src/config/secrets.js +36 -0
- package/src/config.js +1 -0
- package/src/environment/adr.js +16 -2
- package/src/environment/board-access.js +11 -9
- package/src/git/karajan-label.js +20 -8
- package/src/guards/main-guard.js +54 -0
- package/src/harden/branch-protection.js +36 -3
- package/src/harden/hook-templates.js +16 -1
- package/src/harden/sentinel/posttooluse.mjs +18 -6
- package/src/harden/sentinel/pretooluse-sentinel.mjs +81 -35
- package/src/harden/sentinel/sentinel-lib.mjs +149 -23
- package/src/harden/sentinel/sentinel-shell.mjs +64 -0
- package/src/harden/sentinel/sessionstart.mjs +3 -2
- package/src/harden/sentinel/stop.mjs +5 -4
- package/src/harden/workflow-engine.js +12 -1
- 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 +15 -7
- 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 +44 -55
- package/src/mcp/handlers/management-handlers.js +2 -42
- package/src/mcp/server-handlers.js +16 -22
- package/src/mcp/tools.js +5 -200
- 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 +56 -43
- package/src/rag/bootstrap-index.js +28 -54
- package/src/rag/migrate.js +1 -1
- package/src/rag/onnx-fallback.js +2 -2
- package/src/rag/pid-lease.js +70 -0
- package/src/rag/project-store.js +2 -12
- package/src/review/card-first.js +57 -46
- package/src/review/dual-review.js +5 -4
- package/src/review/gate-gitignore.js +23 -4
- package/src/review/gate-hook.js +47 -0
- package/src/review/one-shot-review.js +51 -37
- package/src/review/publish-pr.js +18 -3
- package/src/review/repo-docs.js +73 -0
- package/src/review/repo-stack.js +59 -0
- package/src/review/reviewer-fallback.js +34 -3
- 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 +2 -26
- package/src/roles/audit-role.js +106 -125
- package/src/skills/atril-skills.js +5 -4
- 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/agent-home.js +33 -0
- 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,140 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PerfStage — webperf quality gate inside the iteration loop.
|
|
3
|
-
*
|
|
4
|
-
* KJC-TSK-0151. Wraps PerfRole and slots into the existing
|
|
5
|
-
* runQualityGateStages flow alongside Sonar and Impeccable. Designed
|
|
6
|
-
* to be the simplest possible quality gate:
|
|
7
|
-
*
|
|
8
|
-
* - PASS verdict (cwv.pass === true) → return ok, iteration continues.
|
|
9
|
-
* - FAIL verdict → set reviewer feedback with the blocking metrics
|
|
10
|
-
* so the coder receives concrete guidance next iteration. Returns
|
|
11
|
-
* `continue` to retry the iteration loop. No repeat-detector +
|
|
12
|
-
* retry-limit machinery: rerunning Lighthouse on the same URL
|
|
13
|
-
* gives the same result unless the coder changes something, and
|
|
14
|
-
* the iteration limit (max_iterations) is the natural ceiling.
|
|
15
|
-
* - Scanner unavailable (lighthouse missing, URL unreachable, timeout)
|
|
16
|
-
* → log a warn and return ok-skipped. Best-effort, never blocks
|
|
17
|
-
* the pipeline by itself.
|
|
18
|
-
*
|
|
19
|
-
* The role surface (PerfRole) is responsible for persisting the result
|
|
20
|
-
* to ~/.karajan/webperf/<slug>/last.json so subsequent `kj audit` runs
|
|
21
|
-
* pick it up via the auto-discovery added in #602.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import { PerfRole } from "../../roles/perf-role.js";
|
|
25
|
-
import { setReviewerFeedback } from "../../session/mutators.js";
|
|
26
|
-
import { saveSession } from "../../session/store.js";
|
|
27
|
-
import { emitProgress, makeEvent } from "../../utils/events.js";
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Build the human-readable feedback line that goes back to the coder
|
|
31
|
-
* on FAIL. Concrete enough that the LLM can act on it without re-reading
|
|
32
|
-
* the whole report.
|
|
33
|
-
*/
|
|
34
|
-
function buildFeedback(roleResult) {
|
|
35
|
-
const { result } = roleResult;
|
|
36
|
-
const score = typeof result.performanceScore === "number" ? result.performanceScore : null;
|
|
37
|
-
const blocking = (result.cwv?.blocking || []).map(b => `${b.metric.toUpperCase()}=${Math.round(b.value)} (poor>${b.threshold})`);
|
|
38
|
-
const top = (result.issues || []).slice(0, 3).map(i => `${i.id}${i.savingsMs ? ` (~${Math.round(i.savingsMs)}ms)` : ""}`);
|
|
39
|
-
|
|
40
|
-
const lines = [`Webperf gate FAILED${score !== null ? ` (score ${score}/100)` : ""}.`];
|
|
41
|
-
if (blocking.length > 0) lines.push(`Blocking metrics: ${blocking.join(", ")}.`);
|
|
42
|
-
if (top.length > 0) lines.push(`Top opportunities: ${top.join(", ")}.`);
|
|
43
|
-
lines.push("Address the blocking metric(s) before the next iteration; rerunning without code changes will produce the same verdict.");
|
|
44
|
-
return lines.join(" ");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Run the perf gate against config.webperf.url.
|
|
49
|
-
*
|
|
50
|
-
* @returns {Promise<{action: "ok"|"continue", stageResult?: object, summary?: string}>}
|
|
51
|
-
*/
|
|
52
|
-
export async function runPerfStage({ config, logger, emitter, eventBase, session, trackBudget, iteration, task: _task, brainCtx }) {
|
|
53
|
-
if (!session) {
|
|
54
|
-
throw new Error("runPerfStage: `session` is required.");
|
|
55
|
-
}
|
|
56
|
-
logger.setContext({ iteration, stage: "perf" });
|
|
57
|
-
emitProgress(
|
|
58
|
-
emitter,
|
|
59
|
-
makeEvent("perf:start", { ...eventBase, stage: "perf" }, {
|
|
60
|
-
message: "WebPerf gate scanning",
|
|
61
|
-
detail: { url: config?.webperf?.url || null, preset: config?.webperf?.preset || "desktop" },
|
|
62
|
-
})
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const role = new PerfRole({ config, logger, emitter });
|
|
66
|
-
const roleResult = await role.execute();
|
|
67
|
-
|
|
68
|
-
// Track budget — the role doesn't spawn an LLM but it does consume wall
|
|
69
|
-
// time; surface that in the budget summary alongside the agent calls.
|
|
70
|
-
if (trackBudget) {
|
|
71
|
-
try { trackBudget("perf", { tokens_in: 0, tokens_out: 0, cost_usd: 0 }); } catch { /* best-effort */ }
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Scanner unavailable → skip with warn. PerfRole returns ok=false for
|
|
75
|
-
// both "verdict FAIL" and "scanner failed", so we differentiate on the
|
|
76
|
-
// result.error field (set only by the second case).
|
|
77
|
-
if (!roleResult.ok && roleResult.result?.error) {
|
|
78
|
-
logger.warn(`Perf gate skipped: ${roleResult.result.error}`);
|
|
79
|
-
emitProgress(emitter, makeEvent("perf:end", { ...eventBase, stage: "perf" }, {
|
|
80
|
-
status: "warn",
|
|
81
|
-
message: `Perf gate skipped — ${roleResult.result.error}`,
|
|
82
|
-
}));
|
|
83
|
-
return { action: "ok", stageResult: { skipped: true, reason: roleResult.result.error } };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// PASS verdict
|
|
87
|
-
if (roleResult.ok === true) {
|
|
88
|
-
emitProgress(emitter, makeEvent("perf:end", { ...eventBase, stage: "perf" }, {
|
|
89
|
-
status: "ok",
|
|
90
|
-
message: roleResult.summary,
|
|
91
|
-
}));
|
|
92
|
-
return {
|
|
93
|
-
action: "ok",
|
|
94
|
-
stageResult: {
|
|
95
|
-
verdict: "PASS",
|
|
96
|
-
url: roleResult.result?.url,
|
|
97
|
-
performanceScore: roleResult.result?.performanceScore,
|
|
98
|
-
cwv: roleResult.result?.cwv,
|
|
99
|
-
savedPath: roleResult.result?.savedPath,
|
|
100
|
-
summary: roleResult.summary,
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// FAIL verdict → push concrete feedback to the coder for next iteration.
|
|
106
|
-
const feedback = buildFeedback(roleResult);
|
|
107
|
-
setReviewerFeedback(session, feedback);
|
|
108
|
-
await saveSession(session);
|
|
109
|
-
|
|
110
|
-
// Brain: when enabled, surface perf feedback on the queue too.
|
|
111
|
-
if (brainCtx?.enabled) {
|
|
112
|
-
try {
|
|
113
|
-
const { processRoleOutput } = await import("../brain-coordinator.js");
|
|
114
|
-
processRoleOutput(brainCtx, {
|
|
115
|
-
roleName: "perf",
|
|
116
|
-
output: { verdict: "fail", summary: feedback },
|
|
117
|
-
iteration,
|
|
118
|
-
});
|
|
119
|
-
} catch (err) {
|
|
120
|
-
logger.warn(`Perf gate: brain queue push failed (non-blocking): ${err.message}`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
emitProgress(emitter, makeEvent("perf:end", { ...eventBase, stage: "perf" }, {
|
|
125
|
-
status: "fail",
|
|
126
|
-
message: roleResult.summary,
|
|
127
|
-
}));
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
action: "continue",
|
|
131
|
-
stageResult: {
|
|
132
|
-
verdict: "FAIL",
|
|
133
|
-
url: roleResult.result?.url,
|
|
134
|
-
performanceScore: roleResult.result?.performanceScore,
|
|
135
|
-
cwv: roleResult.result?.cwv,
|
|
136
|
-
issues: roleResult.result?.issues,
|
|
137
|
-
summary: feedback,
|
|
138
|
-
},
|
|
139
|
-
};
|
|
140
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Planner stage logic.
|
|
3
|
-
* Extracted from pre-loop-stages.js for maintainability.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { PlannerRole } from "../../roles/planner-role.js";
|
|
7
|
-
import { createAgent } from "../../agents/index.js";
|
|
8
|
-
import { addCheckpoint, markSessionStatus } from "../../session/store.js";
|
|
9
|
-
import { emitProgress, makeEvent, emitAgentOutput } from "../../utils/events.js";
|
|
10
|
-
import { parsePlannerOutput } from "../../prompts/planner.js";
|
|
11
|
-
import { createStallDetector } from "../../utils/stall-detector.js";
|
|
12
|
-
|
|
13
|
-
export async function runPlannerStage({ config, logger, emitter, eventBase, session, plannerRole, researchContext, architectContext = null, triageDecomposition = null, trackBudget }) {
|
|
14
|
-
const task = session.task;
|
|
15
|
-
logger.setContext({ iteration: 0, stage: "planner" });
|
|
16
|
-
emitProgress(
|
|
17
|
-
emitter,
|
|
18
|
-
makeEvent("planner:start", { ...eventBase, stage: "planner" }, {
|
|
19
|
-
message: `Planner (${plannerRole.provider}) running`,
|
|
20
|
-
detail: { planner: plannerRole.provider, provider: plannerRole.provider, executorType: "agent" }
|
|
21
|
-
})
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
const plannerOnOutput = (payload) => emitAgentOutput(emitter, eventBase, "planner", plannerRole.provider, payload);
|
|
25
|
-
const plannerStall = createStallDetector({
|
|
26
|
-
onOutput: plannerOnOutput, emitter, eventBase, stage: "planner", provider: plannerRole.provider
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const planRole = new PlannerRole({ config, logger, emitter, createAgentFn: createAgent });
|
|
30
|
-
planRole.context = { task, research: researchContext, architecture: architectContext, triageDecomposition };
|
|
31
|
-
await planRole.init();
|
|
32
|
-
const plannerStart = Date.now();
|
|
33
|
-
let planResult;
|
|
34
|
-
try {
|
|
35
|
-
planResult = await planRole.execute({ task, onOutput: plannerStall.onOutput });
|
|
36
|
-
} catch (err) {
|
|
37
|
-
logger.warn(`Planner threw: ${err.message}`);
|
|
38
|
-
planResult = { ok: false, result: { error: err.message }, summary: `Planner error: ${err.message}` };
|
|
39
|
-
} finally {
|
|
40
|
-
plannerStall.stop();
|
|
41
|
-
}
|
|
42
|
-
trackBudget({ role: "planner", provider: plannerRole.provider, model: plannerRole.model, result: planResult.result, duration_ms: Date.now() - plannerStart });
|
|
43
|
-
await addCheckpoint(session, {
|
|
44
|
-
stage: "planner",
|
|
45
|
-
iteration: 0,
|
|
46
|
-
ok: planResult.ok,
|
|
47
|
-
provider: plannerRole.provider,
|
|
48
|
-
model: plannerRole.model || null
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
if (!planResult.ok) {
|
|
52
|
-
await markSessionStatus(session, "failed");
|
|
53
|
-
const details = planResult.result?.error || planResult.summary || "unknown error";
|
|
54
|
-
emitProgress(
|
|
55
|
-
emitter,
|
|
56
|
-
makeEvent("planner:end", { ...eventBase, stage: "planner" }, {
|
|
57
|
-
status: "fail",
|
|
58
|
-
message: `Planner failed: ${details}`,
|
|
59
|
-
detail: { provider: plannerRole.provider, executorType: "agent" }
|
|
60
|
-
})
|
|
61
|
-
);
|
|
62
|
-
throw new Error(`Planner failed: ${details}`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const planOutput = planResult.result?.plan || "";
|
|
66
|
-
const plannedTask = planOutput ? `${task}\n\nExecution plan:\n${planOutput}` : task;
|
|
67
|
-
const parsedPlan = parsePlannerOutput(planOutput);
|
|
68
|
-
const stageResult = {
|
|
69
|
-
ok: true,
|
|
70
|
-
title: parsedPlan?.title || null,
|
|
71
|
-
approach: parsedPlan?.approach || null,
|
|
72
|
-
steps: parsedPlan?.steps || [],
|
|
73
|
-
completedSteps: []
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
emitProgress(
|
|
77
|
-
emitter,
|
|
78
|
-
makeEvent("planner:end", { ...eventBase, stage: "planner" }, {
|
|
79
|
-
message: "Planner completed",
|
|
80
|
-
detail: { provider: plannerRole.provider, executorType: "agent" }
|
|
81
|
-
})
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
return { plannedTask, stageResult };
|
|
85
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// KJC-PCS-0049 Camino C — pre-loop RAG retrieval stage.
|
|
2
|
-
// Runs between triage and domainCurator. When `config.rag.preload.enabled`
|
|
3
|
-
// is true and the corpus has chunks, queries the retriever with the
|
|
4
|
-
// task text and returns a markdown block ready to prepend to the task.
|
|
5
|
-
// Failures degrade gracefully (warn + continue); the rest of the pipeline
|
|
6
|
-
// never sees an exception from this stage.
|
|
7
|
-
import { emitProgress, makeEvent } from "../../utils/events.js";
|
|
8
|
-
import { countChunks } from "../../rag/vec-store.js";
|
|
9
|
-
import { makeGovernedEmbedder } from "../../rag/governed-embedder.js";
|
|
10
|
-
import { query } from "../../rag/retriever.js";
|
|
11
|
-
import { openProjectStore } from "../../rag/project-store.js";
|
|
12
|
-
|
|
13
|
-
const DEFAULT_TOP_K = 5;
|
|
14
|
-
const DEFAULT_SCOPE = "all";
|
|
15
|
-
const DEFAULT_SEARCH_MODE = "hybrid";
|
|
16
|
-
const DEFAULT_SEARCH_ALPHA = 0.6;
|
|
17
|
-
const MAX_CHUNK_CHARS = 600;
|
|
18
|
-
|
|
19
|
-
// KJC-TSK-0463 — pull search-time knobs from config so the HU Board
|
|
20
|
-
// modal (rag.search.{mode,alpha,rerank}) actually steers retrieval at
|
|
21
|
-
// pipeline time. Returns the args object query() expects; unset fields
|
|
22
|
-
// fall back to the retriever's own defaults.
|
|
23
|
-
export function resolveSearchOpts(config) {
|
|
24
|
-
const s = config?.rag?.search ?? {};
|
|
25
|
-
const out = {
|
|
26
|
-
mode: typeof s.mode === "string" ? s.mode : DEFAULT_SEARCH_MODE,
|
|
27
|
-
alpha: Number.isFinite(s.alpha) ? s.alpha : DEFAULT_SEARCH_ALPHA,
|
|
28
|
-
};
|
|
29
|
-
if (s.rerank && typeof s.rerank === "object") out.rerankOpts = s.rerank;
|
|
30
|
-
else if (s.rerank === true) out.rerankOpts = {};
|
|
31
|
-
return out;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Runs the RAG preload stage. Returns:
|
|
36
|
-
* { skipped: true, reason } — when disabled / empty / error
|
|
37
|
-
* { skipped: false, contextBlock, hits } — markdown block + raw hits
|
|
38
|
-
*
|
|
39
|
-
* The caller decides whether to mutate `task` with the contextBlock. We
|
|
40
|
-
* keep that responsibility at the call site so this module stays pure.
|
|
41
|
-
*/
|
|
42
|
-
export async function runRagContextStage({ config, logger, emitter, eventBase, task }) {
|
|
43
|
-
const preload = config?.rag?.preload;
|
|
44
|
-
if (!preload?.enabled) return { skipped: true, reason: "disabled" };
|
|
45
|
-
if (typeof task !== "string" || task.length === 0) return { skipped: true, reason: "no-task" };
|
|
46
|
-
try {
|
|
47
|
-
const dim = config?.rag?.embedder?.dim || 768;
|
|
48
|
-
// KJC-TSK-0882: el preload que entra en el prompt del coder solo puede traer
|
|
49
|
-
// codigo de ESTE proyecto: antes abria el indice de la maquina sin filtrar.
|
|
50
|
-
const db = openProjectStore({ projectDir: config?.projectDir || process.cwd(), dim });
|
|
51
|
-
try {
|
|
52
|
-
if (countChunks(db) === 0) {
|
|
53
|
-
logger?.info?.("[rag-preload] corpus is empty, skipping (run `kj rag index` to seed)");
|
|
54
|
-
return { skipped: true, reason: "empty" };
|
|
55
|
-
}
|
|
56
|
-
const topK = preload.topK || DEFAULT_TOP_K;
|
|
57
|
-
const scope = preload.scope || DEFAULT_SCOPE;
|
|
58
|
-
const embedder = makeGovernedEmbedder(config);
|
|
59
|
-
const searchOpts = resolveSearchOpts(config);
|
|
60
|
-
const hits = await query(db, embedder, task, { topK, scope, ...searchOpts });
|
|
61
|
-
if (hits.length === 0) return { skipped: true, reason: "no-hits" };
|
|
62
|
-
const lines = hits.map((h) => {
|
|
63
|
-
const label = h.metadata?.hu_id || h.metadata?.symbol || h.metadata?.headingPath?.join(" > ") || "block";
|
|
64
|
-
const text = h.text.length > MAX_CHUNK_CHARS ? `${h.text.slice(0, MAX_CHUNK_CHARS)}…` : h.text;
|
|
65
|
-
return `### [${h.kind} · ${label}] ${h.source}\n\n${text}`;
|
|
66
|
-
});
|
|
67
|
-
const contextBlock = `## Prior context from RAG (auto-retrieved, top ${hits.length})\n\n${lines.join("\n\n")}`;
|
|
68
|
-
emitProgress(emitter, makeEvent("rag-preload:hits", { ...eventBase, stage: "rag-preload" }, {
|
|
69
|
-
message: `RAG preload: injected ${hits.length} chunk(s) into the task context`,
|
|
70
|
-
detail: { topK, scope, hits: hits.length, mode: searchOpts.mode, alpha: searchOpts.alpha, rerank: Boolean(searchOpts.rerankOpts) },
|
|
71
|
-
}));
|
|
72
|
-
return { skipped: false, contextBlock, hits };
|
|
73
|
-
} finally {
|
|
74
|
-
db.close();
|
|
75
|
-
}
|
|
76
|
-
} catch (err) {
|
|
77
|
-
logger?.warn?.(`[rag-preload] failed (non-blocking): ${err.message}`);
|
|
78
|
-
return { skipped: true, reason: "error", error: err.message };
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// KJC-TSK-0434 — RAG Camino D: Brain decisor heuristic for retrieval.
|
|
2
|
-
// Decides WHETHER to pay the cost of running the RAG preload stage based
|
|
3
|
-
// on signals from triage + task shape, instead of pre-fetching every run.
|
|
4
|
-
//
|
|
5
|
-
// Returns `{ pull: boolean, reason: string }`. The pre-loop driver
|
|
6
|
-
// skips `runRagContextStage` when `pull === false`.
|
|
7
|
-
//
|
|
8
|
-
// Policies (config.rag.preload.policy):
|
|
9
|
-
// - "always" : pull regardless (back-compat with v2.24.0 behaviour)
|
|
10
|
-
// - "never" : never pull (useful for benchmarking, debugging)
|
|
11
|
-
// - "auto" : heuristic — pull only when triage signals complexity,
|
|
12
|
-
// decomposition, or when the task body is long enough
|
|
13
|
-
// to suggest non-trivial scope. Default.
|
|
14
|
-
|
|
15
|
-
const DEFAULT_POLICY = "auto";
|
|
16
|
-
const COMPLEX_LEVELS = new Set(["complex", "high", "epic"]);
|
|
17
|
-
const LONG_TASK_CHARS = 200;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @param {object} params
|
|
21
|
-
* @param {object} [params.triage] - triage stage result (may be null)
|
|
22
|
-
* @param {string} [params.task] - the user task text
|
|
23
|
-
* @param {object} [params.config] - full karajan config
|
|
24
|
-
* @returns {{ pull: boolean, reason: string }}
|
|
25
|
-
*/
|
|
26
|
-
export function shouldPreloadRag({ triage, task, config } = {}) {
|
|
27
|
-
const policy = config?.rag?.preload?.policy || DEFAULT_POLICY;
|
|
28
|
-
|
|
29
|
-
if (policy === "always") return { pull: true, reason: "policy:always" };
|
|
30
|
-
if (policy === "never") return { pull: false, reason: "policy:never" };
|
|
31
|
-
|
|
32
|
-
// policy === "auto" — apply heuristic.
|
|
33
|
-
// Brownfield is an explicit user signal — if onboarding produced a
|
|
34
|
-
// brief and config marks the project as brownfield, prior context is
|
|
35
|
-
// almost always worth pulling.
|
|
36
|
-
if (config?.rag?.preload?.brownfield === true) {
|
|
37
|
-
return { pull: true, reason: "auto:brownfield" };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Triage said this is big enough to decompose → multi-HU run benefits
|
|
41
|
-
// from prior context fed to researcher/architect/planner.
|
|
42
|
-
if (triage?.shouldDecompose === true) {
|
|
43
|
-
return { pull: true, reason: "auto:decompose" };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Triage classified the task as complex / high-effort.
|
|
47
|
-
if (triage?.level && COMPLEX_LEVELS.has(String(triage.level).toLowerCase())) {
|
|
48
|
-
return { pull: true, reason: "auto:complex" };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Long task body usually means a brief with context, motivation and
|
|
52
|
-
// non-trivial scope — worth checking the RAG.
|
|
53
|
-
if (typeof task === "string" && task.length >= LONG_TASK_CHARS) {
|
|
54
|
-
return { pull: true, reason: "auto:long-task" };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return { pull: false, reason: "auto:low-value" };
|
|
58
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Researcher stage logic.
|
|
3
|
-
* Extracted from pre-loop-stages.js for maintainability.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ResearcherRole } from "../../roles/researcher-role.js";
|
|
7
|
-
import { addCheckpoint } from "../../session/store.js";
|
|
8
|
-
import { emitProgress, makeEvent, emitAgentOutput } from "../../utils/events.js";
|
|
9
|
-
import { createStallDetector } from "../../utils/stall-detector.js";
|
|
10
|
-
|
|
11
|
-
export async function runResearcherStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget }) {
|
|
12
|
-
logger.setContext({ iteration: 0, stage: "researcher" });
|
|
13
|
-
|
|
14
|
-
const researcherProvider = config?.roles?.researcher?.provider || coderRole.provider;
|
|
15
|
-
emitProgress(
|
|
16
|
-
emitter,
|
|
17
|
-
makeEvent("researcher:start", { ...eventBase, stage: "researcher" }, {
|
|
18
|
-
message: "Researcher investigating codebase",
|
|
19
|
-
detail: { researcher: researcherProvider, provider: researcherProvider, executorType: "agent" }
|
|
20
|
-
})
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
const researcherOnOutput = (payload) => emitAgentOutput(emitter, eventBase, "researcher", researcherProvider, payload);
|
|
24
|
-
const researcherStall = createStallDetector({
|
|
25
|
-
onOutput: researcherOnOutput, emitter, eventBase, stage: "researcher", provider: researcherProvider
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const researcher = new ResearcherRole({ config, logger, emitter });
|
|
29
|
-
await researcher.init({ task: session.task });
|
|
30
|
-
const researchStart = Date.now();
|
|
31
|
-
let researchOutput;
|
|
32
|
-
try {
|
|
33
|
-
researchOutput = await researcher.run({ task: session.task, onOutput: researcherStall.onOutput });
|
|
34
|
-
} catch (err) {
|
|
35
|
-
logger.warn(`Researcher threw: ${err.message}`);
|
|
36
|
-
researchOutput = { ok: false, summary: `Researcher error: ${err.message}`, result: { error: err.message } };
|
|
37
|
-
} finally {
|
|
38
|
-
researcherStall.stop();
|
|
39
|
-
}
|
|
40
|
-
trackBudget({
|
|
41
|
-
role: "researcher",
|
|
42
|
-
provider: config?.roles?.researcher?.provider || coderRole.provider,
|
|
43
|
-
model: config?.roles?.researcher?.model || coderRole.model,
|
|
44
|
-
result: researchOutput,
|
|
45
|
-
duration_ms: Date.now() - researchStart
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
await addCheckpoint(session, {
|
|
49
|
-
stage: "researcher",
|
|
50
|
-
iteration: 0,
|
|
51
|
-
ok: researchOutput.ok,
|
|
52
|
-
provider: config?.roles?.researcher?.provider || coderRole.provider,
|
|
53
|
-
model: config?.roles?.researcher?.model || coderRole.model || null
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
emitProgress(
|
|
57
|
-
emitter,
|
|
58
|
-
makeEvent("researcher:end", { ...eventBase, stage: "researcher" }, {
|
|
59
|
-
status: researchOutput.ok ? "ok" : "fail",
|
|
60
|
-
message: researchOutput.ok ? "Research completed" : `Research failed: ${researchOutput.summary}`,
|
|
61
|
-
detail: { provider: researcherProvider, executorType: "agent" }
|
|
62
|
-
})
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const stageResult = { ok: researchOutput.ok, summary: researchOutput.summary || null };
|
|
66
|
-
const researchContext = researchOutput.ok ? researchOutput.result : null;
|
|
67
|
-
|
|
68
|
-
return { researchContext, stageResult };
|
|
69
|
-
}
|