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.
- 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/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 +75 -48
- package/src/commands/review-gate.js +421 -341
- 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/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 +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 +1 -35
- package/src/mcp/handlers/management-handlers.js +2 -42
- 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 +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/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-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/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,524 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pre-loop driver — extracted from src/orchestrator/flow-runner.js in
|
|
3
|
-
* TSK-0335 (Oleada 3 of the v2.7.4 audit refactor).
|
|
4
|
-
*
|
|
5
|
-
* Everything that runs BEFORE the coder/reviewer iteration loop:
|
|
6
|
-
*
|
|
7
|
-
* - runPreLoopStages: the main pre-loop orchestration
|
|
8
|
-
* (HU-reviewer → intent → discover → triage →
|
|
9
|
-
* Brain decisor → domain → auto-simplify →
|
|
10
|
-
* PG decomposition → TDD detect → preflight →
|
|
11
|
-
* plan injection → planning phases →
|
|
12
|
-
* .gitignore update → auto-HU → skill
|
|
13
|
-
* auto-install).
|
|
14
|
-
* - runPlanningPhases: researcher → architect → planner.
|
|
15
|
-
* - emitConfigDeprecations: one-shot warnings for ignored config keys.
|
|
16
|
-
* - ensureAddyosmaniSkills: refresh + resolve addyosmani/agent-skills.
|
|
17
|
-
* - maybeGenerateAutoHuBatch: auto-generate HUs when triage recommends
|
|
18
|
-
* decomposition and no manual huFile was passed.
|
|
19
|
-
*
|
|
20
|
-
* Extracted verbatim; no behavior change. flow-runner.js now imports these
|
|
21
|
-
* instead of defining them. initFlowContext lives in ./init-context.js to
|
|
22
|
-
* keep each driver under the 600-LOC ceiling. Part of breaking up the
|
|
23
|
-
* 2254-LOC god-module — see docs/ARCHITECTURE.md and the TSK-0335
|
|
24
|
-
* acceptance criteria.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import { emitProgress, makeEvent } from "../../utils/events.js";
|
|
28
|
-
import { resolveRole } from "../../config.js";
|
|
29
|
-
import { classifyIntent } from "../../guards/intent-guard.js";
|
|
30
|
-
import { persistInlineDomain } from "../../domains/domain-loader.js";
|
|
31
|
-
import { detectTestFramework } from "../../utils/project-detect.js";
|
|
32
|
-
import { detectNeededSkills, autoInstallSkills } from "../../skills/skill-detector.js";
|
|
33
|
-
import { refineSkillsSemantically, resolveSkillsMode } from "../../skills/semantic-detector.js";
|
|
34
|
-
import { saveSession } from "../../session/store.js";
|
|
35
|
-
import {
|
|
36
|
-
setPreflight, setAutoInstalledSkills, setSkillsRecommended,
|
|
37
|
-
setStageResult, setStageBundle,
|
|
38
|
-
} from "../../session/mutators.js";
|
|
39
|
-
import {
|
|
40
|
-
runResearcherStage, runArchitectStage, runPlannerStage,
|
|
41
|
-
runDiscoverStage, runHuReviewerStage,
|
|
42
|
-
} from "../pre-loop-stages.js";
|
|
43
|
-
import { runRagContextStage } from "../stages/rag-context-stage.js";
|
|
44
|
-
import { shouldPreloadRag } from "../stages/rag-preload-decisor.js";
|
|
45
|
-
// TSK-0336: triage goes through the StageRegistry / StageExecutor contract
|
|
46
|
-
// so canRun / execute / onFailure are actually exercised in production.
|
|
47
|
-
// The registry is a singleton with TriageStage / CoderStage / ReviewerStage
|
|
48
|
-
// pre-registered; `runStage` returns null when `canRun` vetoes execution.
|
|
49
|
-
import { stageRegistry } from "../stages/stage-classes.js";
|
|
50
|
-
import { runStage } from "../stages/stage-executor.js";
|
|
51
|
-
import { runDomainCuratorStage } from "../stages/domain-curator-stage.js";
|
|
52
|
-
import { runPreflightChecks } from "../preflight-checks.js";
|
|
53
|
-
import { injectLoadedPlan } from "./pre-loop-phases/inject-loaded-plan.js";
|
|
54
|
-
import { emitConfigDeprecations } from "./pre-loop-phases/config-deprecations.js";
|
|
55
|
-
import { ensureAddyosmaniSkills } from "./pre-loop-phases/ensure-addyosmani-skills.js";
|
|
56
|
-
import { maybeGenerateAutoHuBatch } from "./pre-loop-phases/auto-hu-batch.js";
|
|
57
|
-
|
|
58
|
-
import {
|
|
59
|
-
applyTriageOverrides, applyAutoSimplify, applyFlagOverrides,
|
|
60
|
-
resolvePipelinePolicies,
|
|
61
|
-
} from "../config-init.js";
|
|
62
|
-
import { tryCiComment } from "../ci-integration.js";
|
|
63
|
-
import { getIntegration } from "../integrations.js";
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* KJC-BUG-0332 (#2092, root of #2090/#2091): a plan run implements the plan's
|
|
67
|
-
* certified HUs. Triaging the plan's original task auto-generated other HUs
|
|
68
|
-
* (HU-01..) that ran instead, and could call it analysis-only, skipping the
|
|
69
|
-
* coder and approving an empty diff. In a plan run there is no triage; each HU
|
|
70
|
-
* carries its own task type, which the HU batch applies.
|
|
71
|
-
*/
|
|
72
|
-
export async function triageForRun({ flags, runTriage }) {
|
|
73
|
-
if (flags?.plan) {
|
|
74
|
-
return {
|
|
75
|
-
roleOverrides: {}, // applyTriageOverrides reads its keys: no override, never null
|
|
76
|
-
stageResult: { ok: true, taskType: "sw", level: null, roles: [], shouldDecompose: false, subtasks: [], fromPlan: flags.plan, summary: "plan run: the plan's HUs are the work" },
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
return (await runTriage()) ?? { roleOverrides: null, stageResult: null };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export async function runPreLoopStages({ config, logger, emitter, eventBase, session, flags, pipelineFlags, coderRole, trackBudget, task, askQuestion, pgTaskId, pgProject, stageResults, brainCtx }) {
|
|
83
|
-
// KJC-BUG-0058: on `kj resume` `stageResults` is rehydrated from
|
|
84
|
-
// `session.stage_results`. Persist after every successful pre-loop stage
|
|
85
|
-
// and skip the work when the slot is already populated. Cost: one
|
|
86
|
-
// `await saveSession` per stage; equivalent to the writes the post-loop
|
|
87
|
-
// path already makes for security / acceptance results.
|
|
88
|
-
const persistStage = async (name, result) => {
|
|
89
|
-
if (!result) return;
|
|
90
|
-
stageResults[name] = result;
|
|
91
|
-
setStageResult(session, name, result);
|
|
92
|
-
try { await saveSession(session); } catch (err) {
|
|
93
|
-
logger.warn(`Could not persist '${name}' stage result: ${err.message}`);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
const resumeSkip = (name) => {
|
|
97
|
-
if (!stageResults[name]) return false;
|
|
98
|
-
logger.info(`[resume] skipping pre-loop stage '${name}' — completed in previous session`);
|
|
99
|
-
emitProgress(emitter, makeEvent("stage:skipped", { ...eventBase, stage: name }, {
|
|
100
|
-
status: "ok",
|
|
101
|
-
message: `Stage '${name}' skipped — already completed on previous run`,
|
|
102
|
-
detail: { cached: true }
|
|
103
|
-
}));
|
|
104
|
-
return true;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
// --- HU Reviewer (first stage, before everything else, opt-in) ---
|
|
108
|
-
const huFile = flags.huFile || null;
|
|
109
|
-
if (flags.enableHuReviewer !== undefined) pipelineFlags.huReviewerEnabled = Boolean(flags.enableHuReviewer);
|
|
110
|
-
if (pipelineFlags.huReviewerEnabled && huFile && !resumeSkip("huReviewer")) {
|
|
111
|
-
const huResult = await runHuReviewerStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget, huFile, askQuestion, pgStories: null });
|
|
112
|
-
await persistStage("huReviewer", huResult.stageResult);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// --- Intent classifier (deterministic pre-triage, opt-in) ---
|
|
116
|
-
if (config.guards?.intent?.enabled && !resumeSkip("intent")) {
|
|
117
|
-
const intentResult = classifyIntent(task, config);
|
|
118
|
-
await persistStage("intent", intentResult);
|
|
119
|
-
if (intentResult.classified) {
|
|
120
|
-
emitProgress(emitter, makeEvent("intent:classified", { ...eventBase, stage: "intent" }, {
|
|
121
|
-
message: `Intent classified: ${intentResult.taskType} (${intentResult.level}) — ${intentResult.message}`,
|
|
122
|
-
detail: intentResult
|
|
123
|
-
}));
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// --- Discover (pre-triage, opt-in) ---
|
|
128
|
-
if (flags.enableDiscover !== undefined) pipelineFlags.discoverEnabled = Boolean(flags.enableDiscover);
|
|
129
|
-
if (pipelineFlags.discoverEnabled && !resumeSkip("discover")) {
|
|
130
|
-
const discoverResult = await runDiscoverStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget });
|
|
131
|
-
await persistStage("discover", discoverResult.stageResult);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// --- Triage (always on) — routed through StageRegistry (TSK-0336) ---
|
|
135
|
-
// KJC-BUG-0058: NOT skipped on resume. Triage is cheap and emits
|
|
136
|
-
// `roleOverrides` that downstream stages depend on (Brain decisor + the
|
|
137
|
-
// pipelineFlags). Re-running it on resume is the safe path; the heavy
|
|
138
|
-
// stages it gates (researcher, architect, planner) ARE skipped if
|
|
139
|
-
// already complete.
|
|
140
|
-
const triageCtx = { config, logger, emitter, eventBase, session, coderRole, trackBudget, pipelineFlags };
|
|
141
|
-
const triageResult = await triageForRun({ flags, runTriage: () => runStage(stageRegistry.get("triage"), triageCtx) });
|
|
142
|
-
if (triageResult.stageResult?.fromPlan) logger.info(`Triage skipped: plan ${flags.plan} runs its own certified HUs`);
|
|
143
|
-
applyTriageOverrides(pipelineFlags, triageResult.roleOverrides);
|
|
144
|
-
await persistStage("triage", triageResult.stageResult);
|
|
145
|
-
|
|
146
|
-
// --- RAG preload (KJC-PCS-0049 Camino C, opt-in) ---
|
|
147
|
-
// Runs only when config.rag.preload.enabled === true. Queries the local
|
|
148
|
-
// vector store with the task description, prepends the top-K chunks to
|
|
149
|
-
// the task as a markdown block so researcher/architect/planner/coder
|
|
150
|
-
// all see prior context without having to call kj_rag_query themselves.
|
|
151
|
-
// Empty store / network / etc. degrade to no-op via the stage itself.
|
|
152
|
-
if (!resumeSkip("ragPreload")) {
|
|
153
|
-
// KJC-TSK-0434 (Camino D): Brain decisor heuristic — skip retrieval
|
|
154
|
-
// when triage + task shape say it would be low-value. Defaults to
|
|
155
|
-
// policy=auto; `always`/`never` are escape hatches.
|
|
156
|
-
const decision = shouldPreloadRag({ triage: triageResult.stageResult, task, config });
|
|
157
|
-
if (!decision.pull) {
|
|
158
|
-
await persistStage("ragPreload", { skipped: true, reason: decision.reason });
|
|
159
|
-
} else {
|
|
160
|
-
const ragRes = await runRagContextStage({ config, logger, emitter, eventBase, task });
|
|
161
|
-
if (!ragRes.skipped && ragRes.contextBlock) {
|
|
162
|
-
task = `${task}\n\n${ragRes.contextBlock}`;
|
|
163
|
-
await persistStage("ragPreload", {
|
|
164
|
-
hits: ragRes.hits.length,
|
|
165
|
-
scope: config?.rag?.preload?.scope || "all",
|
|
166
|
-
decisor: decision.reason,
|
|
167
|
-
});
|
|
168
|
-
} else {
|
|
169
|
-
await persistStage("ragPreload", { skipped: true, reason: ragRes.reason, decisor: decision.reason });
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// --- Brain decisor (opt-in, intent-driven routing) ---
|
|
175
|
-
//
|
|
176
|
-
// When enabled, translates triage output + task text + CLI overrides into a
|
|
177
|
-
// structured Decision and applies it as pipelineFlags overrides. The rest
|
|
178
|
-
// of the orchestrator continues to branch on pipelineFlags as before — the
|
|
179
|
-
// Brain is a router that adjusts WHICH roles run, not HOW they run.
|
|
180
|
-
//
|
|
181
|
-
// Flag precedence:
|
|
182
|
-
// 1. flags.brain === "off" → forced off
|
|
183
|
-
// 2. flags.brain === "on" → forced on
|
|
184
|
-
// 3. config.brain.decisor.enabled (if set)
|
|
185
|
-
// 4. config.testHarness.defaultBrainDecisor (test harness = false)
|
|
186
|
-
// 5. true in production
|
|
187
|
-
const brainDefault = config?.testHarness?.defaultBrainDecisor ?? true;
|
|
188
|
-
let brainDecisorEnabled = config?.brain?.decisor?.enabled ?? brainDefault;
|
|
189
|
-
if (flags?.brain === "off") brainDecisorEnabled = false;
|
|
190
|
-
if (flags?.brain === "on") brainDecisorEnabled = true;
|
|
191
|
-
if (brainDecisorEnabled) {
|
|
192
|
-
try {
|
|
193
|
-
const { buildDecision, applyDecisionToFlags } = await import("../../brain/decisor.js");
|
|
194
|
-
const { createTracker, recordDecision, checkLimits } = await import("../../brain/decision-tracker.js");
|
|
195
|
-
const tracker = createTracker(session, { max: config?.brain?.decisor?.maxDecisions });
|
|
196
|
-
const limitStatus = checkLimits(tracker);
|
|
197
|
-
if (limitStatus.status === "ok") {
|
|
198
|
-
let decision = buildDecision({
|
|
199
|
-
triage: triageResult.stageResult,
|
|
200
|
-
task,
|
|
201
|
-
config,
|
|
202
|
-
overrides: {
|
|
203
|
-
// Commander variadic --force-role a b → flags.forceRole = ["a","b"].
|
|
204
|
-
// Back-compat: accept both singular (commander) and plural (legacy / API).
|
|
205
|
-
forceRoles: flags?.forceRole || flags?.forceRoles || [],
|
|
206
|
-
skipRoles: flags?.skipRole || flags?.skipRoles || [],
|
|
207
|
-
},
|
|
208
|
-
});
|
|
209
|
-
// If the decision is low-confidence or ambiguous, consult Solomon
|
|
210
|
-
// for a refined routing suggestion. Solomon's ruling is advisory —
|
|
211
|
-
// if it fails or returns nothing useful, the baseline decision stands.
|
|
212
|
-
if (decision.consultSolomon) {
|
|
213
|
-
try {
|
|
214
|
-
const { consultSolomonForRouting } = await import("../../brain/solomon-consult.js");
|
|
215
|
-
decision = await consultSolomonForRouting({
|
|
216
|
-
decision, triage: triageResult.stageResult, task, config, logger,
|
|
217
|
-
emitter, eventBase, session,
|
|
218
|
-
});
|
|
219
|
-
} catch (err) {
|
|
220
|
-
logger.warn(`Brain → Solomon consult failed (non-blocking): ${err.message}`);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
const newFlags = applyDecisionToFlags(decision, pipelineFlags);
|
|
224
|
-
Object.assign(pipelineFlags, newFlags);
|
|
225
|
-
recordDecision(tracker, decision, {
|
|
226
|
-
taskType: triageResult.stageResult?.taskType,
|
|
227
|
-
level: triageResult.stageResult?.level,
|
|
228
|
-
});
|
|
229
|
-
emitProgress(emitter, makeEvent("brain:decision", { ...eventBase, stage: "brain" }, {
|
|
230
|
-
status: "ok",
|
|
231
|
-
message: `Brain routing: ${decision.rolesOn.length} role(s) active — ${decision.rationale}`,
|
|
232
|
-
detail: {
|
|
233
|
-
rolesOn: decision.rolesOn,
|
|
234
|
-
rolesOff: decision.rolesOff,
|
|
235
|
-
confidence: decision.confidence,
|
|
236
|
-
consultSolomon: decision.consultSolomon,
|
|
237
|
-
appliedOverrides: decision.appliedOverrides,
|
|
238
|
-
},
|
|
239
|
-
}));
|
|
240
|
-
} else {
|
|
241
|
-
logger.warn(`Brain decisor skipped: ${limitStatus.detail}`);
|
|
242
|
-
emitProgress(emitter, makeEvent("brain:decision", { ...eventBase, stage: "brain" }, {
|
|
243
|
-
status: "warn",
|
|
244
|
-
message: `Brain decisor skipped: ${limitStatus.status}`,
|
|
245
|
-
detail: limitStatus,
|
|
246
|
-
}));
|
|
247
|
-
}
|
|
248
|
-
} catch (err) {
|
|
249
|
-
logger.warn(`Brain decisor failed (non-blocking): ${err.message}`);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// --- Persist inline domain if provided via --domain flag ---
|
|
254
|
-
if (flags?.domain) {
|
|
255
|
-
try {
|
|
256
|
-
await persistInlineDomain(flags.domain, config.projectDir || process.cwd());
|
|
257
|
-
} catch (err) {
|
|
258
|
-
logger.warn(`Failed to persist inline domain: ${err.message}`);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// --- Domain Curator (after triage + skill auto-install, before planning phases) ---
|
|
263
|
-
const domainHints = triageResult.stageResult?.domainHints || [];
|
|
264
|
-
if ((domainHints.length > 0 || config.projectDir) && !resumeSkip("domainCurator")) {
|
|
265
|
-
try {
|
|
266
|
-
const { domainContext, stageResult: dcStageResult } = await runDomainCuratorStage({
|
|
267
|
-
config, logger, emitter, eventBase, session, trackBudget,
|
|
268
|
-
domainHints, askQuestion
|
|
269
|
-
});
|
|
270
|
-
await persistStage("domainCurator", dcStageResult);
|
|
271
|
-
if (domainContext) {
|
|
272
|
-
config = { ...config, domainContext };
|
|
273
|
-
}
|
|
274
|
-
} catch (err) {
|
|
275
|
-
logger.warn(`Domain Curator failed (non-blocking): ${err.message}`);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// --- HU Reviewer auto-activation from triage (post-triage, no huFile needed) ---
|
|
280
|
-
const triageRoles = new Set(triageResult.stageResult?.roles || []);
|
|
281
|
-
if (triageRoles.has("hu-reviewer") && !stageResults.huReviewer) {
|
|
282
|
-
pipelineFlags.huReviewerEnabled = true;
|
|
283
|
-
// Feed tracker card structured data to hu-reviewer when available
|
|
284
|
-
let pgStories = null;
|
|
285
|
-
if (pgTaskId && pgProject && session.pg_card) {
|
|
286
|
-
pgStories = getIntegration("tracker")?.buildHuStoriesFromCard?.(session.pg_card) ?? null;
|
|
287
|
-
}
|
|
288
|
-
const huResult = await runHuReviewerStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget, huFile: null, askQuestion, pgStories });
|
|
289
|
-
await persistStage("huReviewer", huResult.stageResult);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// --- Auto-simplify pipeline for simple tasks (before explicit flag overrides) ---
|
|
293
|
-
const simplified = applyAutoSimplify({
|
|
294
|
-
pipelineFlags,
|
|
295
|
-
triageLevel: triageResult.stageResult?.level || null,
|
|
296
|
-
config, flags, logger, emitter, eventBase
|
|
297
|
-
});
|
|
298
|
-
if (simplified) stageResults.triage.autoSimplified = true;
|
|
299
|
-
|
|
300
|
-
await getIntegration("tracker")?.handleDecomposition?.({ triageResult, pgTaskId, pgProject, config, askQuestion, emitter, eventBase, session, stageResults, logger });
|
|
301
|
-
|
|
302
|
-
applyFlagOverrides(pipelineFlags, flags);
|
|
303
|
-
|
|
304
|
-
// --- Auto-detect TDD applicability when methodology not explicitly set ---
|
|
305
|
-
if (!flags.methodology) {
|
|
306
|
-
const projectDir = config.projectDir || process.cwd();
|
|
307
|
-
const detection = await detectTestFramework(projectDir);
|
|
308
|
-
if (!detection.hasTests) {
|
|
309
|
-
config = { ...config, development: { ...config.development, methodology: "standard", require_test_changes: false } };
|
|
310
|
-
logger.info("No test framework detected — using standard methodology");
|
|
311
|
-
} else {
|
|
312
|
-
config = { ...config, development: { ...config.development, methodology: "tdd", require_test_changes: true } };
|
|
313
|
-
logger.info(`Test framework detected (${detection.framework}) — using TDD methodology`);
|
|
314
|
-
}
|
|
315
|
-
emitProgress(emitter, makeEvent("tdd:auto-detect", { ...eventBase, stage: "pre-loop" }, {
|
|
316
|
-
message: detection.hasTests
|
|
317
|
-
? `TDD auto-detected: ${detection.framework}`
|
|
318
|
-
: "TDD skipped: no test framework found",
|
|
319
|
-
detail: detection
|
|
320
|
-
}));
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
let updatedConfig = resolvePipelinePolicies({ flags, config, stageResults, emitter, eventBase, session, pipelineFlags });
|
|
324
|
-
|
|
325
|
-
// Deprecation warnings recorded at config load time. Done here, after
|
|
326
|
-
// policies are resolved, so the message lands in context: if the user's
|
|
327
|
-
// legacy `sonarqube.enabled: false` is being ignored, this is the right
|
|
328
|
-
// moment for them to see it.
|
|
329
|
-
emitConfigDeprecations(updatedConfig, logger, emitter, eventBase);
|
|
330
|
-
|
|
331
|
-
// --- Preflight environment checks ---
|
|
332
|
-
const preflightResult = await runPreflightChecks({
|
|
333
|
-
config: updatedConfig, logger, emitter, eventBase,
|
|
334
|
-
resolvedPolicies: session.resolved_policies,
|
|
335
|
-
securityEnabled: pipelineFlags.securityEnabled
|
|
336
|
-
});
|
|
337
|
-
setPreflight(session, preflightResult);
|
|
338
|
-
await saveSession(session);
|
|
339
|
-
|
|
340
|
-
// Hard fail if blocking checks failed (SonarQube enabled but not available)
|
|
341
|
-
if (!preflightResult.ok) {
|
|
342
|
-
const errorLines = (preflightResult.errors || [])
|
|
343
|
-
.map(e => ` - ${e.message}${e.fix ? `\n Fix: ${e.fix}` : ""}`)
|
|
344
|
-
.join("\n");
|
|
345
|
-
throw new Error(
|
|
346
|
-
`Preflight FAILED — environment changed during session. Fix the issues and retry:\n${errorLines}`
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
if (preflightResult.configOverrides.securityDisabled) {
|
|
351
|
-
pipelineFlags.securityEnabled = false;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// --- Plan injection: skip researcher/architect/planner if a persisted plan is loaded ---
|
|
355
|
-
// Extracted to pre-loop-phases/inject-loaded-plan.js (PR-K).
|
|
356
|
-
// 189 LOC of plan-load + tests-gate + auto-certify + assertRunnable +
|
|
357
|
-
// huBatch + --hu filter + callback wiring + plannedTask build.
|
|
358
|
-
const planInjection = await injectLoadedPlan({
|
|
359
|
-
flags, updatedConfig, session, stageResults, eventBase, emitter, logger, task,
|
|
360
|
-
});
|
|
361
|
-
if (planInjection.handled) {
|
|
362
|
-
return { plannedTask: planInjection.plannedTask, updatedConfig };
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
// --- Researcher → Planner ---
|
|
367
|
-
const { plannedTask } = await runPlanningPhases({ config: updatedConfig, logger, emitter, eventBase, session, stageResults, pipelineFlags, coderRole, trackBudget, task, askQuestion, brainCtx, persistStage, resumeSkip });
|
|
368
|
-
|
|
369
|
-
// --- Update .gitignore with stack-specific entries based on planner/architect output ---
|
|
370
|
-
const projectDir = updatedConfig.projectDir || process.cwd();
|
|
371
|
-
|
|
372
|
-
// --- Auto-HU: when triage recommended decomposition and no manual huFile, generate HU batch ---
|
|
373
|
-
await maybeGenerateAutoHuBatch({
|
|
374
|
-
flags, stageResults, task, plannedTask, logger, emitter, eventBase, projectDir, session
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
// --- Auto-install skills based on task + planner output + project detection ---
|
|
378
|
-
// Runs AFTER triage and planner so that the planned task text (which includes
|
|
379
|
-
// planner output like implementation steps) is available for keyword detection.
|
|
380
|
-
// This ensures greenfield projects with no package.json still get correct skills.
|
|
381
|
-
//
|
|
382
|
-
// Detection runs UNCONDITIONALLY — even when the openskills CLI is missing —
|
|
383
|
-
// so the session report can recommend which skills would have been used. The
|
|
384
|
-
// actual install is skipped inside autoInstallSkills when unavailable.
|
|
385
|
-
const skillProjectDir = updatedConfig.projectDir || process.cwd();
|
|
386
|
-
try {
|
|
387
|
-
const skillsMode = resolveSkillsMode(updatedConfig, flags);
|
|
388
|
-
if (skillsMode === "none") {
|
|
389
|
-
// User explicitly opted out. Skip detection entirely.
|
|
390
|
-
return { plannedTask, updatedConfig };
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// FIRST source: addyosmani/agent-skills (process skills per role).
|
|
394
|
-
// This runs BEFORE OpenSkills detection because process skills are the
|
|
395
|
-
// canonical workflows (TDD, code-review, security, performance...) that
|
|
396
|
-
// should shape every role's prompt; stack skills come second.
|
|
397
|
-
await ensureAddyosmaniSkills({
|
|
398
|
-
task: plannedTask,
|
|
399
|
-
config: updatedConfig,
|
|
400
|
-
logger,
|
|
401
|
-
session,
|
|
402
|
-
emitter,
|
|
403
|
-
eventBase,
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
let neededSkills = skillsMode === "semantic"
|
|
407
|
-
? []
|
|
408
|
-
: await detectNeededSkills(plannedTask, skillProjectDir);
|
|
409
|
-
// Semantic mode augments regex detection with a classifier call.
|
|
410
|
-
// "auto" = regex always + semantic when budget allows (v1: always when mode=auto and classifier reachable).
|
|
411
|
-
if (skillsMode === "auto" || skillsMode === "semantic") {
|
|
412
|
-
const extra = await refineSkillsSemantically({
|
|
413
|
-
task: plannedTask,
|
|
414
|
-
alreadyDetected: neededSkills,
|
|
415
|
-
config: updatedConfig,
|
|
416
|
-
logger,
|
|
417
|
-
});
|
|
418
|
-
if (extra.length > 0) {
|
|
419
|
-
logger.info(`Semantic skill detection added: ${extra.join(", ")}`);
|
|
420
|
-
neededSkills = Array.from(new Set([...neededSkills, ...extra]));
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
if (neededSkills.length > 0) {
|
|
424
|
-
const skillResult = await autoInstallSkills(neededSkills, skillProjectDir);
|
|
425
|
-
if (skillResult.installed.length > 0) {
|
|
426
|
-
setAutoInstalledSkills(session, skillResult.installed);
|
|
427
|
-
}
|
|
428
|
-
if (skillResult.osAvailable === false && skillResult.wouldHaveUsed.length > 0) {
|
|
429
|
-
setSkillsRecommended(session, skillResult.wouldHaveUsed);
|
|
430
|
-
logger.warn(`OpenSkills CLI not available — would have used: ${skillResult.wouldHaveUsed.join(", ")}. Install openskills globally to auto-inject them next time.`);
|
|
431
|
-
emitProgress(emitter, makeEvent("skills:unavailable", { ...eventBase, stage: "skills" }, {
|
|
432
|
-
message: `OpenSkills CLI not available — would have used: ${skillResult.wouldHaveUsed.join(", ")}`,
|
|
433
|
-
detail: {
|
|
434
|
-
wouldHaveUsed: skillResult.wouldHaveUsed,
|
|
435
|
-
hint: "Install openskills globally: npm install -g openskills",
|
|
436
|
-
},
|
|
437
|
-
}));
|
|
438
|
-
}
|
|
439
|
-
emitProgress(emitter, makeEvent("skills:auto-install", { ...eventBase, stage: "skills" }, {
|
|
440
|
-
message: skillResult.installed.length > 0
|
|
441
|
-
? `Auto-installed ${skillResult.installed.length} skill(s): ${skillResult.installed.join(", ")}`
|
|
442
|
-
: `Skills detected (${neededSkills.join(", ")}) — all already installed or unavailable`,
|
|
443
|
-
detail: skillResult,
|
|
444
|
-
}));
|
|
445
|
-
}
|
|
446
|
-
} catch (err) {
|
|
447
|
-
logger.warn(`Skill auto-install failed (non-blocking): ${err.message}`);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
return { plannedTask, updatedConfig };
|
|
451
|
-
}
|
|
452
|
-
async function runPlanningPhases({ config, logger, emitter, eventBase, session, stageResults, pipelineFlags, coderRole, trackBudget, task, askQuestion, brainCtx, persistStage, resumeSkip }) {
|
|
453
|
-
let researchContext = null;
|
|
454
|
-
let plannedTask = task;
|
|
455
|
-
|
|
456
|
-
// Brain: track compression across pre-loop roles
|
|
457
|
-
const brainCompress = brainCtx?.enabled
|
|
458
|
-
? (await import("../brain-coordinator.js")).processRoleOutput
|
|
459
|
-
: null;
|
|
460
|
-
|
|
461
|
-
// KJC-BUG-0058: on resume, rehydrate cross-stage context from session.
|
|
462
|
-
// researchContext / architectContext / plannedTask live ONLY in memory
|
|
463
|
-
// after their owning stage runs; without these the post-loop coder
|
|
464
|
-
// would lose context even though we skipped the upstream LLM call.
|
|
465
|
-
const bundles = session?.stage_bundles || {};
|
|
466
|
-
|
|
467
|
-
if (pipelineFlags.researcherEnabled) {
|
|
468
|
-
if (resumeSkip("researcher")) {
|
|
469
|
-
researchContext = bundles.researcher?.researchContext || null;
|
|
470
|
-
} else {
|
|
471
|
-
const researcherResult = await runResearcherStage({ config, logger, emitter, eventBase, session, coderRole, trackBudget });
|
|
472
|
-
researchContext = researcherResult.researchContext;
|
|
473
|
-
setStageBundle(session, "researcher", { stageResult: researcherResult.stageResult, researchContext });
|
|
474
|
-
await persistStage("researcher", researcherResult.stageResult);
|
|
475
|
-
if (brainCompress) brainCompress(brainCtx, { roleName: "researcher", output: researcherResult.stageResult, iteration: 0 });
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// --- Architect (between researcher and planner) ---
|
|
480
|
-
let architectContext = null;
|
|
481
|
-
if (pipelineFlags.architectEnabled) {
|
|
482
|
-
if (resumeSkip("architect")) {
|
|
483
|
-
architectContext = bundles.architect?.architectContext || null;
|
|
484
|
-
} else {
|
|
485
|
-
const architectResult = await runArchitectStage({
|
|
486
|
-
config, logger, emitter, eventBase, session, coderRole, trackBudget,
|
|
487
|
-
researchContext,
|
|
488
|
-
discoverResult: stageResults.discover || null,
|
|
489
|
-
triageLevel: stageResults.triage?.level || null,
|
|
490
|
-
askQuestion
|
|
491
|
-
});
|
|
492
|
-
architectContext = architectResult.architectContext;
|
|
493
|
-
setStageBundle(session, "architect", { stageResult: architectResult.stageResult, architectContext });
|
|
494
|
-
await persistStage("architect", architectResult.stageResult);
|
|
495
|
-
if (brainCompress) brainCompress(brainCtx, { roleName: "architect", output: architectResult.stageResult, iteration: 0 });
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
const triageDecomposition = stageResults.triage?.shouldDecompose ? stageResults.triage.subtasks : null;
|
|
500
|
-
if (pipelineFlags.plannerEnabled) {
|
|
501
|
-
if (resumeSkip("planner")) {
|
|
502
|
-
plannedTask = bundles.planner?.plannedTask || task;
|
|
503
|
-
} else {
|
|
504
|
-
const plannerRole = resolveRole(config, "planner");
|
|
505
|
-
const plannerResult = await runPlannerStage({ config, logger, emitter, eventBase, session, plannerRole, researchContext, architectContext, triageDecomposition, trackBudget });
|
|
506
|
-
plannedTask = plannerResult.plannedTask;
|
|
507
|
-
setStageBundle(session, "planner", { stageResult: plannerResult.stageResult, plannedTask });
|
|
508
|
-
await persistStage("planner", plannerResult.stageResult);
|
|
509
|
-
if (brainCompress) brainCompress(brainCtx, { roleName: "planner", output: plannerResult.stageResult, iteration: 0 });
|
|
510
|
-
|
|
511
|
-
await tryCiComment({
|
|
512
|
-
config, session, logger,
|
|
513
|
-
agent: "Planner",
|
|
514
|
-
body: `Plan: ${plannerResult.stageResult?.summary || plannedTask}`
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
return { plannedTask };
|
|
520
|
-
}
|
|
521
|
-
// `emitConfigDeprecations`, `ensureAddyosmaniSkills` and
|
|
522
|
-
// `maybeGenerateAutoHuBatch` were extracted to ./pre-loop-phases/ in
|
|
523
|
-
// TSK-0337 to keep this driver under the 600-LOC ceiling. Imports at
|
|
524
|
-
// the top of this file pull them back in; behaviour is unchanged.
|