@karajan-family/code 4.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +98 -0
- package/bin/karajan-mcp.js +2 -0
- package/bin/kj-rag-mcp.js +75 -0
- package/bin/kj-tail +361 -0
- package/bin/kj.js +2 -0
- package/docs/README.es.md +80 -0
- package/docs/karajan-code-logo-small.png +0 -0
- package/library/logical-clocks-lamport.md +40 -0
- package/package.json +140 -0
- package/packages/ai-trash/README.md +37 -0
- package/packages/ai-trash/bin/kj-trash.js +10 -0
- package/packages/ai-trash/package.json +43 -0
- package/packages/ai-trash/src/cli.js +200 -0
- package/packages/ai-trash/src/destructive-parser.js +74 -0
- package/packages/ai-trash/src/git-snapshot.js +128 -0
- package/packages/ai-trash/src/hook.js +137 -0
- package/packages/ai-trash/src/index.js +14 -0
- package/packages/ai-trash/src/install.js +73 -0
- package/packages/ai-trash/src/logger.js +60 -0
- package/packages/ai-trash/src/manifest.js +91 -0
- package/packages/ai-trash/src/permissions.js +26 -0
- package/packages/ai-trash/src/snapshot.js +66 -0
- package/packages/ai-trash/src/ulid.js +66 -0
- package/packages/hu-board/README.md +69 -0
- package/packages/hu-board/package.json +28 -0
- package/packages/hu-board/public/app.js +259 -0
- package/packages/hu-board/public/index.html +77 -0
- package/packages/hu-board/public/pipeline.css +132 -0
- package/packages/hu-board/public/pipeline.html +48 -0
- package/packages/hu-board/public/pipeline.js +200 -0
- package/packages/hu-board/public/rag.html +21 -0
- package/packages/hu-board/public/rag.js +39 -0
- package/packages/hu-board/public/styles.css +973 -0
- package/packages/hu-board/public/utils/api.js +139 -0
- package/packages/hu-board/public/utils/board-view.js +473 -0
- package/packages/hu-board/public/utils/command-launcher.js +213 -0
- package/packages/hu-board/public/utils/config-editor.js +181 -0
- package/packages/hu-board/public/utils/dashboard-view.js +103 -0
- package/packages/hu-board/public/utils/formatters.js +300 -0
- package/packages/hu-board/public/utils/graph-view.js +216 -0
- package/packages/hu-board/public/utils/hu-actions.js +224 -0
- package/packages/hu-board/public/utils/init-listeners.js +180 -0
- package/packages/hu-board/public/utils/log-panel.js +222 -0
- package/packages/hu-board/public/utils/modals.js +309 -0
- package/packages/hu-board/public/utils/plan-rollup-view.js +53 -0
- package/packages/hu-board/public/utils/preflight-view.js +89 -0
- package/packages/hu-board/public/utils/project-actions.js +143 -0
- package/packages/hu-board/public/utils/project-picker-view.js +139 -0
- package/packages/hu-board/public/utils/run-launcher.js +169 -0
- package/packages/hu-board/public/utils/server-push.js +252 -0
- package/packages/hu-board/public/utils/sessions-view.js +199 -0
- package/packages/hu-board/public/utils/story-detail-view.js +324 -0
- package/packages/hu-board/public/utils/story-edit-form.js +271 -0
- package/packages/hu-board/public/wiki.html +32 -0
- package/packages/hu-board/public/wiki.js +53 -0
- package/packages/hu-board/src/auth.js +92 -0
- package/packages/hu-board/src/boot-info.js +16 -0
- package/packages/hu-board/src/cleanup-zombies.js +145 -0
- package/packages/hu-board/src/command-runner.js +133 -0
- package/packages/hu-board/src/config-yaml.js +531 -0
- package/packages/hu-board/src/db.js +963 -0
- package/packages/hu-board/src/ephemeral-cleaner.js +196 -0
- package/packages/hu-board/src/event-bus.js +58 -0
- package/packages/hu-board/src/format.js +207 -0
- package/packages/hu-board/src/hu-zombie-reaper.js +103 -0
- package/packages/hu-board/src/journal-parser.js +180 -0
- package/packages/hu-board/src/plan-mutations.js +424 -0
- package/packages/hu-board/src/preflight.js +286 -0
- package/packages/hu-board/src/routes/api.js +1374 -0
- package/packages/hu-board/src/routes/pipeline.js +45 -0
- package/packages/hu-board/src/routes/rag.js +42 -0
- package/packages/hu-board/src/routes/wiki.js +43 -0
- package/packages/hu-board/src/run-tracker.js +121 -0
- package/packages/hu-board/src/server.js +438 -0
- package/packages/hu-board/src/sync.js +732 -0
- package/packages/hu-board/src/token-store.js +56 -0
- package/packages/hu-board/src/zombie-reaper.js +206 -0
- package/scripts/ai-attribution-guard.yml +84 -0
- package/scripts/audit-test-diet.mjs +151 -0
- package/scripts/build-sea.mjs +150 -0
- package/scripts/diet-baseline.mjs +170 -0
- package/scripts/dual-publish.mjs +67 -0
- package/scripts/esbuild-sea.config.mjs +273 -0
- package/scripts/git-hooks/post-merge +18 -0
- package/scripts/install-binary.ps1 +174 -0
- package/scripts/install-binary.sh +159 -0
- package/scripts/install-guard-all-repos.sh +85 -0
- package/scripts/install-kj.sh +193 -0
- package/scripts/install.js +901 -0
- package/scripts/install.sh +7 -0
- package/scripts/postinstall.js +117 -0
- package/scripts/protect-all-repos.sh +88 -0
- package/scripts/quickstart-gate.mjs +97 -0
- package/scripts/regen-arch-stats.sh +71 -0
- package/scripts/setup-multi-instance.sh +150 -0
- package/scripts/verify-pack.mjs +278 -0
- package/src/activity-log.js +59 -0
- package/src/agents/agy-agent.js +62 -0
- package/src/agents/aider-agent.js +78 -0
- package/src/agents/availability.js +52 -0
- package/src/agents/base-agent.js +134 -0
- package/src/agents/claude-agent.js +413 -0
- package/src/agents/codex-agent.js +112 -0
- package/src/agents/copilot-agent.js +65 -0
- package/src/agents/gemini-agent.js +85 -0
- package/src/agents/host-agent.js +38 -0
- package/src/agents/index.js +59 -0
- package/src/agents/kimi-agent.js +45 -0
- package/src/agents/model-registry.js +137 -0
- package/src/agents/opencode-agent.js +72 -0
- package/src/agents/qwen-agent.js +20 -0
- package/src/agents/resolve-bin.js +73 -0
- package/src/audit/agent-readiness.js +259 -0
- package/src/audit/ai-slop-findings.js +102 -0
- package/src/audit/audit-fallback.js +66 -0
- package/src/audit/audit-history-display.js +61 -0
- package/src/audit/audit-history.js +102 -0
- package/src/audit/basal-cost.js +281 -0
- package/src/audit/circular-deps.js +144 -0
- package/src/audit/dead-exports.js +186 -0
- package/src/audit/deterministic-summary.js +327 -0
- package/src/audit/harness-scorecard.js +100 -0
- package/src/audit/harness-section.js +81 -0
- package/src/audit/infra-findings.js +100 -0
- package/src/audit/injection-findings.js +114 -0
- package/src/audit/issue-filter.js +133 -0
- package/src/audit/osv-findings.js +167 -0
- package/src/audit/plan-adherence.js +224 -0
- package/src/audit/semgrep-findings.js +129 -0
- package/src/audit/sonar-findings.js +93 -0
- package/src/audit/webperf-input.js +133 -0
- package/src/autonomy/arbiter-role.js +71 -0
- package/src/autonomy/arbiter.js +22 -0
- package/src/autonomy/decider.js +18 -0
- package/src/autonomy/decision-resolver.js +58 -0
- package/src/autonomy/outcome-report.js +55 -0
- package/src/autonomy/policy.js +41 -0
- package/src/autonomy/stage-ask.js +30 -0
- package/src/bootstrap.js +276 -0
- package/src/brain/agent-error-classifier.js +116 -0
- package/src/brain/decision-tracker.js +125 -0
- package/src/brain/decisor.js +243 -0
- package/src/brain/solomon-consult.js +171 -0
- package/src/brain/standby-scheduler.js +8 -0
- package/src/brain/standby-store.js +12 -0
- package/src/brain/with-brain-recovery.js +235 -0
- package/src/budget/comparison.js +96 -0
- package/src/canvas/parse-md.js +238 -0
- package/src/canvas/schema.js +101 -0
- package/src/canvas/to-flat.js +85 -0
- package/src/canvas/validate.js +163 -0
- package/src/checks/ai-surface.js +79 -0
- package/src/checks/ai-trash.js +34 -0
- package/src/checks/binaries.js +207 -0
- package/src/checks/ci.js +105 -0
- package/src/checks/config-files.js +217 -0
- package/src/checks/dir-setup.js +103 -0
- package/src/checks/guarantee-level.js +38 -0
- package/src/checks/hardware.js +150 -0
- package/src/checks/harness-scorecard.js +41 -0
- package/src/checks/mcp-health.js +169 -0
- package/src/checks/method.js +73 -0
- package/src/checks/native-build.js +67 -0
- package/src/checks/node.js +70 -0
- package/src/checks/ollama.js +41 -0
- package/src/checks/orphans.js +77 -0
- package/src/checks/ports.js +188 -0
- package/src/checks/project-checks.js +245 -0
- package/src/checks/qmd.js +41 -0
- package/src/checks/rag-hooks.js +54 -0
- package/src/checks/release-check.js +102 -0
- package/src/checks/rtk.js +36 -0
- package/src/checks/runner.js +326 -0
- package/src/checks/skills.js +53 -0
- package/src/checks/sonar.js +67 -0
- package/src/checks/squeezr.js +36 -0
- package/src/checks/system.js +53 -0
- package/src/checks/tokens.js +172 -0
- package/src/checks/types.js +103 -0
- package/src/ci/dispatch.js +99 -0
- package/src/ci/index.js +3 -0
- package/src/ci/pr-diff.js +26 -0
- package/src/ci/repo.js +45 -0
- package/src/cli/_shared.js +30 -0
- package/src/cli/advanced-commands.js +61 -0
- package/src/cli/register-meta.js +772 -0
- package/src/cli/register-pipeline.js +335 -0
- package/src/cli/register-plan.js +224 -0
- package/src/cli/register-roles-skills.js +54 -0
- package/src/cli/register-sonar.js +28 -0
- package/src/cli/register-standby.js +26 -0
- package/src/cli.js +155 -0
- package/src/commands/advanced.js +31 -0
- package/src/commands/agent-run.js +63 -0
- package/src/commands/agents.js +105 -0
- package/src/commands/architect.js +123 -0
- package/src/commands/audit.js +430 -0
- package/src/commands/autorun.js +49 -0
- package/src/commands/board.js +458 -0
- package/src/commands/check.js +40 -0
- package/src/commands/clean.js +145 -0
- package/src/commands/code.js +45 -0
- package/src/commands/config.js +74 -0
- package/src/commands/discover.js +105 -0
- package/src/commands/doctor.js +251 -0
- package/src/commands/env.js +207 -0
- package/src/commands/harden.js +203 -0
- package/src/commands/hu.js +210 -0
- package/src/commands/identity.js +60 -0
- package/src/commands/init.js +950 -0
- package/src/commands/install-tools.js +432 -0
- package/src/commands/mutate.js +94 -0
- package/src/commands/ollama.js +44 -0
- package/src/commands/onboard.js +45 -0
- package/src/commands/plan/_shared.js +55 -0
- package/src/commands/plan/add-hu.js +23 -0
- package/src/commands/plan/delete.js +9 -0
- package/src/commands/plan/fix.js +99 -0
- package/src/commands/plan/generate.js +532 -0
- package/src/commands/plan/index.js +13 -0
- package/src/commands/plan/list.js +21 -0
- package/src/commands/plan/migrate-result.js +41 -0
- package/src/commands/plan/ready.js +46 -0
- package/src/commands/plan/remove-hu.js +17 -0
- package/src/commands/plan/share.js +85 -0
- package/src/commands/plan/show.js +81 -0
- package/src/commands/plan/unshare.js +41 -0
- package/src/commands/plan/validate.js +20 -0
- package/src/commands/plan.js +17 -0
- package/src/commands/policy.js +164 -0
- package/src/commands/privacy.js +45 -0
- package/src/commands/qmd.js +86 -0
- package/src/commands/rag-mcp.js +18 -0
- package/src/commands/rag.js +173 -0
- package/src/commands/report-issue.js +77 -0
- package/src/commands/report.js +469 -0
- package/src/commands/researcher.js +54 -0
- package/src/commands/resume.js +68 -0
- package/src/commands/review-gate.js +355 -0
- package/src/commands/review.js +89 -0
- package/src/commands/roles.js +116 -0
- package/src/commands/run.js +185 -0
- package/src/commands/scan.js +18 -0
- package/src/commands/skills.js +86 -0
- package/src/commands/sonar.js +53 -0
- package/src/commands/standby.js +117 -0
- package/src/commands/start.js +121 -0
- package/src/commands/status.js +36 -0
- package/src/commands/sync.js +103 -0
- package/src/commands/telemetry.js +70 -0
- package/src/commands/tournament.js +85 -0
- package/src/commands/triage.js +78 -0
- package/src/commands/undo.js +62 -0
- package/src/commands/watch.js +46 -0
- package/src/commands/webperf.js +162 -0
- package/src/commands/worktree.js +76 -0
- package/src/config/defaults.js +270 -0
- package/src/config/loader.js +204 -0
- package/src/config/overrides.js +220 -0
- package/src/config/role-resolver.js +171 -0
- package/src/config/schema.js +299 -0
- package/src/config/test-harness.js +78 -0
- package/src/config.js +34 -0
- package/src/domains/domain-loader.js +245 -0
- package/src/domains/domain-registry.js +140 -0
- package/src/domains/domain-synthesizer.js +129 -0
- package/src/environment/adr.js +45 -0
- package/src/environment/board-access.js +97 -0
- package/src/environment/board-select.js +59 -0
- package/src/environment/briefs.js +129 -0
- package/src/environment/issue-report.js +72 -0
- package/src/environment/mcp-wiring.js +44 -0
- package/src/environment/playbook.js +127 -0
- package/src/git/automation.js +334 -0
- package/src/git/hu-automation.js +171 -0
- package/src/git/hu-snapshot.js +10 -0
- package/src/golden/asserter.js +92 -0
- package/src/golden/loader.js +52 -0
- package/src/golden/runner.js +92 -0
- package/src/golden/schema.js +41 -0
- package/src/guards/intent-guard.js +161 -0
- package/src/guards/output-guard.js +149 -0
- package/src/guards/perf-guard.js +126 -0
- package/src/guards/policy-guard.js +90 -0
- package/src/guards/policy-resolver.js +85 -0
- package/src/guards/secret-redactor.js +71 -0
- package/src/harden/advisory.js +203 -0
- package/src/harden/alternatives.js +50 -0
- package/src/harden/check.js +81 -0
- package/src/harden/config-engine.js +128 -0
- package/src/harden/config-templates.js +122 -0
- package/src/harden/guidelines-engine.js +48 -0
- package/src/harden/guidelines-templates.js +36 -0
- package/src/harden/harden-engine.js +80 -0
- package/src/harden/harness-hooks.js +107 -0
- package/src/harden/hook-commands.js +25 -0
- package/src/harden/hook-templates.js +183 -0
- package/src/harden/interactive.js +76 -0
- package/src/harden/sentinel-hooks.js +721 -0
- package/src/harden/stack-roots.js +105 -0
- package/src/harden/test-on-push.js +38 -0
- package/src/harden/workflow-engine.js +116 -0
- package/src/harden/workflow-templates.js +285 -0
- package/src/hu/acceptance-runner.js +138 -0
- package/src/hu/auto-generator.js +358 -0
- package/src/hu/graph.js +71 -0
- package/src/hu/lazy-planner.js +109 -0
- package/src/hu/model-router.js +108 -0
- package/src/hu/parallel-executor.js +94 -0
- package/src/hu/split-validator.js +143 -0
- package/src/hu/splitting-detector.js +158 -0
- package/src/hu/splitting-generator.js +175 -0
- package/src/hu/store.js +392 -0
- package/src/hu/worktree-bootstrap.js +59 -0
- package/src/identity/bootstrap.js +48 -0
- package/src/identity/compare.js +38 -0
- package/src/identity/detect.js +51 -0
- package/src/identity/store.js +66 -0
- package/src/infrastructure/command-runner.js +44 -0
- package/src/infrastructure/environment.js +38 -0
- package/src/infrastructure/file-system-service.js +63 -0
- package/src/infrastructure/mocks.js +182 -0
- package/src/lang/chunk-go.js +94 -0
- package/src/lang/chunk-java.js +90 -0
- package/src/lang/chunk-python.js +88 -0
- package/src/lang/chunk-rust.js +102 -0
- package/src/lang/go.js +14 -0
- package/src/lang/java.js +16 -0
- package/src/lang/js.js +8 -0
- package/src/lang/python.js +14 -0
- package/src/lang/registry.js +79 -0
- package/src/lang/rust.js +14 -0
- package/src/lang/tree-sitter-loader.js +45 -0
- package/src/mcp/direct-role-runner.js +112 -0
- package/src/mcp/error-classifiers.js +66 -0
- package/src/mcp/handlers/direct-handlers.js +486 -0
- package/src/mcp/handlers/hu-handlers.js +93 -0
- package/src/mcp/handlers/management-handlers.js +265 -0
- package/src/mcp/handlers/rag-handler.js +52 -0
- package/src/mcp/handlers/run-handler.js +313 -0
- package/src/mcp/orphan-guard.js +131 -0
- package/src/mcp/preflight.js +47 -0
- package/src/mcp/progress.js +149 -0
- package/src/mcp/response-compressor.js +81 -0
- package/src/mcp/run-kj.js +135 -0
- package/src/mcp/server-handlers.js +79 -0
- package/src/mcp/server.js +66 -0
- package/src/mcp/shared-helpers.js +297 -0
- package/src/mcp/sovereignty-guard.js +112 -0
- package/src/mcp/suggest-handler.js +92 -0
- package/src/mcp/tool-arg-normalizers.js +16 -0
- package/src/mcp/tools.js +432 -0
- package/src/mutate/diff-scope.js +105 -0
- package/src/mutate/reviewer-signal.js +76 -0
- package/src/mutate/runner.js +72 -0
- package/src/mutate/tool-registry.js +90 -0
- package/src/onboarder/cache.js +24 -0
- package/src/onboarder/collectors/framework-multilang.js +64 -0
- package/src/onboarder/collectors/index.js +136 -0
- package/src/orchestrator/agent-fallback.js +81 -0
- package/src/orchestrator/brain-coordinator.js +186 -0
- package/src/orchestrator/ci-integration.js +139 -0
- package/src/orchestrator/config-init.js +510 -0
- package/src/orchestrator/direct-actions.js +217 -0
- package/src/orchestrator/drivers/error-recovery.js +287 -0
- package/src/orchestrator/drivers/init-context.js +227 -0
- package/src/orchestrator/drivers/iteration-loop.js +380 -0
- package/src/orchestrator/drivers/iteration-phases/coder-and-refactorer.js +69 -0
- package/src/orchestrator/drivers/iteration-phases/guards.js +84 -0
- package/src/orchestrator/drivers/iteration-phases/handle-approved.js +29 -0
- package/src/orchestrator/drivers/iteration-phases/quality-gates.js +114 -0
- package/src/orchestrator/drivers/iteration-phases/reviewer-gate.js +60 -0
- package/src/orchestrator/drivers/post-loop.js +383 -0
- package/src/orchestrator/drivers/pre-loop-phases/auto-hu-batch.js +136 -0
- package/src/orchestrator/drivers/pre-loop-phases/config-deprecations.js +47 -0
- package/src/orchestrator/drivers/pre-loop-phases/ensure-addyosmani-skills.js +84 -0
- package/src/orchestrator/drivers/pre-loop-phases/inject-loaded-plan.js +391 -0
- package/src/orchestrator/drivers/pre-loop.js +507 -0
- package/src/orchestrator/drivers/run-hu-batch.js +427 -0
- package/src/orchestrator/feedback-enrichment.js +140 -0
- package/src/orchestrator/feedback-queue.js +151 -0
- package/src/orchestrator/flow-control.js +170 -0
- package/src/orchestrator/flow-runner.js +364 -0
- package/src/orchestrator/fs-leak-detector.js +210 -0
- package/src/orchestrator/hu-scheduler.js +114 -0
- package/src/orchestrator/hu-sub-pipeline.js +616 -0
- package/src/orchestrator/integrations.js +81 -0
- package/src/orchestrator/iteration-gate.js +73 -0
- package/src/orchestrator/iteration-stages.js +9 -0
- package/src/orchestrator/parallel-limiter.js +74 -0
- package/src/orchestrator/pipeline-context.js +72 -0
- package/src/orchestrator/post-loop-stages.js +468 -0
- package/src/orchestrator/pre-loop-stages.js +11 -0
- package/src/orchestrator/preflight-checks.js +462 -0
- package/src/orchestrator/repair/repair-detector.js +117 -0
- package/src/orchestrator/repair/repair-runner.js +142 -0
- package/src/orchestrator/reviewer-fallback.js +45 -0
- package/src/orchestrator/role-output-compressor.js +189 -0
- package/src/orchestrator/session-journal.js +308 -0
- package/src/orchestrator/solomon-escalation.js +305 -0
- package/src/orchestrator/solomon-rules.js +212 -0
- package/src/orchestrator/stages/architect-stage.js +172 -0
- package/src/orchestrator/stages/coder-stage.js +480 -0
- package/src/orchestrator/stages/domain-curator-stage.js +82 -0
- package/src/orchestrator/stages/hu-reviewer-phases/detect-and-apply-splits.js +127 -0
- package/src/orchestrator/stages/hu-reviewer-stage.js +394 -0
- package/src/orchestrator/stages/perf-stage.js +140 -0
- package/src/orchestrator/stages/planner-stage.js +85 -0
- package/src/orchestrator/stages/rag-context-stage.js +77 -0
- package/src/orchestrator/stages/rag-preload-decisor.js +58 -0
- package/src/orchestrator/stages/research-stage.js +69 -0
- package/src/orchestrator/stages/reviewer-stage.js +422 -0
- package/src/orchestrator/stages/sonar-stage.js +421 -0
- package/src/orchestrator/stages/stage-classes.js +84 -0
- package/src/orchestrator/stages/stage-executor.js +155 -0
- package/src/orchestrator/stages/tdd-discipline-stage.js +56 -0
- package/src/orchestrator/stages/tool-judge-stage.js +53 -0
- package/src/orchestrator/stages/triage-stage.js +172 -0
- package/src/orchestrator/standby.js +71 -0
- package/src/orchestrator/verification-gate.js +183 -0
- package/src/orchestrator.js +22 -0
- package/src/plan/adr-generator.js +170 -0
- package/src/plan/adr-loader.js +60 -0
- package/src/plan/plan-executor.js +100 -0
- package/src/plan/plan-fixer.js +192 -0
- package/src/plan/plan-hu-ops.js +16 -0
- package/src/plan/plan-id.js +4 -0
- package/src/plan/plan-migrate-result.js +24 -0
- package/src/plan/plan-reviewer.js +236 -0
- package/src/plan/plan-schema.js +334 -0
- package/src/plan/plan-store.js +260 -0
- package/src/plan/plan-structural-pass.js +122 -0
- package/src/plan/plan-validation.js +4 -0
- package/src/plan/preflight-hu.js +105 -0
- package/src/plan/spec-detector.js +61 -0
- package/src/plan/tests-synthesizer.js +131 -0
- package/src/planning-game/adapter.js +108 -0
- package/src/planning-game/architect-adrs.js +45 -0
- package/src/planning-game/client.js +108 -0
- package/src/planning-game/decomposition.js +87 -0
- package/src/planning-game/pipeline-adapter.js +251 -0
- package/src/plugins/loader.js +67 -0
- package/src/policy/add.js +111 -0
- package/src/policy/decisions.js +42 -0
- package/src/policy/engine.js +82 -0
- package/src/policy/exceptions.js +60 -0
- package/src/privacy/onboarding.js +35 -0
- package/src/privacy/scan.js +120 -0
- package/src/prompts/arbiter.js +38 -0
- package/src/prompts/architect.js +103 -0
- package/src/prompts/audit.js +474 -0
- package/src/prompts/coder.js +287 -0
- package/src/prompts/diff-clip.js +27 -0
- package/src/prompts/discover.js +222 -0
- package/src/prompts/hu-reviewer.js +219 -0
- package/src/prompts/planner.js +312 -0
- package/src/prompts/prompt-layout.js +80 -0
- package/src/prompts/prompt-resolver.js +120 -0
- package/src/prompts/reviewer.js +75 -0
- package/src/prompts/rtk-snippet.js +25 -0
- package/src/prompts/spec-reviewer.js +66 -0
- package/src/prompts/split-signal.js +82 -0
- package/src/prompts/start-decision.js +52 -0
- package/src/prompts/tool-correctness-judge.js +31 -0
- package/src/prompts/triage.js +57 -0
- package/src/rag/auto-update.js +72 -0
- package/src/rag/chunker-ast.js +56 -0
- package/src/rag/chunker.js +132 -0
- package/src/rag/embedder.js +2 -0
- package/src/rag/embedders/_cloud-base.js +2 -0
- package/src/rag/embedders/cohere.js +2 -0
- package/src/rag/embedders/factory.js +2 -0
- package/src/rag/embedders/mistral.js +2 -0
- package/src/rag/embedders/onnx.js +2 -0
- package/src/rag/embedders/openai.js +2 -0
- package/src/rag/embedders/voyage.js +2 -0
- package/src/rag/eval.js +61 -0
- package/src/rag/governed-embedder.js +39 -0
- package/src/rag/indexer.js +199 -0
- package/src/rag/library.js +62 -0
- package/src/rag/ollama-capability.js +59 -0
- package/src/rag/ollama-manager.js +98 -0
- package/src/rag/onnx-fallback.js +69 -0
- package/src/rag/rerank.js +4 -0
- package/src/rag/retriever.js +2 -0
- package/src/rag/vec-store.js +17 -0
- package/src/rag/watcher.js +62 -0
- package/src/rag/where-parser.js +4 -0
- package/src/repeat-detector.js +88 -0
- package/src/review/card-first.js +99 -0
- package/src/review/card-verify.js +83 -0
- package/src/review/diff-generator.js +112 -0
- package/src/review/gate-gitignore.js +77 -0
- package/src/review/git-stash-helper.js +104 -0
- package/src/review/mutation-pregate.js +48 -0
- package/src/review/one-shot-review.js +122 -0
- package/src/review/parser.js +80 -0
- package/src/review/policy-gate.js +26 -0
- package/src/review/profiles.js +66 -0
- package/src/review/reviewer-fallback.js +125 -0
- package/src/review/schema.js +31 -0
- package/src/review/scope-filter.js +152 -0
- package/src/review/snapshot-diff.js +122 -0
- package/src/review/solomon-arbitration.js +113 -0
- package/src/review/sonar-pregate.js +63 -0
- package/src/review/tdd-discipline.js +90 -0
- package/src/review/tdd-policy.js +69 -0
- package/src/review/tests-with-code.js +33 -0
- package/src/review/verdict-store.js +87 -0
- package/src/review/workspace.js +21 -0
- package/src/roles/agent-role.js +194 -0
- package/src/roles/architect-role.js +77 -0
- package/src/roles/audit-role.js +258 -0
- package/src/roles/base-role.js +165 -0
- package/src/roles/coder-role.js +107 -0
- package/src/roles/commiter-role.js +110 -0
- package/src/roles/discover-role.js +81 -0
- package/src/roles/domain-curator-role.js +141 -0
- package/src/roles/hu-reviewer-role.js +64 -0
- package/src/roles/impeccable-role.js +85 -0
- package/src/roles/index.js +18 -0
- package/src/roles/karajan-brain-role.js +134 -0
- package/src/roles/onboarder-role.js +61 -0
- package/src/roles/perf-role.js +122 -0
- package/src/roles/planner-role.js +151 -0
- package/src/roles/refactorer-role.js +30 -0
- package/src/roles/repairer-role.js +181 -0
- package/src/roles/researcher-role.js +70 -0
- package/src/roles/reviewer-role.js +104 -0
- package/src/roles/security-role.js +73 -0
- package/src/roles/solomon-role.js +265 -0
- package/src/roles/sonar-role.js +70 -0
- package/src/roles/spec-reviewer-role.js +106 -0
- package/src/roles/tester-role.js +235 -0
- package/src/roles/tool-correctness-judge-role.js +78 -0
- package/src/roles/triage-role.js +99 -0
- package/src/session/journal/decisions-writer.js +200 -0
- package/src/session/journal/iteration-logger.js +194 -0
- package/src/session/journal/summary-writer.js +320 -0
- package/src/session/journal/tree-writer.js +164 -0
- package/src/session/journal/write-all.js +89 -0
- package/src/session/mutators.js +339 -0
- package/src/session/runtime-overrides.js +59 -0
- package/src/session/store.js +106 -0
- package/src/session-cleanup.js +116 -0
- package/src/skills/addyosmani-catalog.js +315 -0
- package/src/skills/addyosmani-role-map.js +139 -0
- package/src/skills/openskills-client.js +157 -0
- package/src/skills/semantic-detector.js +167 -0
- package/src/skills/skill-detector.js +385 -0
- package/src/skills/skill-loader.js +219 -0
- package/src/skills/skills-cache.js +128 -0
- package/src/sonar/api.js +128 -0
- package/src/sonar/cloud-scanner.js +78 -0
- package/src/sonar/config-resolver.js +88 -0
- package/src/sonar/credentials.js +60 -0
- package/src/sonar/discovery.js +124 -0
- package/src/sonar/enforcer.js +19 -0
- package/src/sonar/issue-filter.js +12 -0
- package/src/sonar/manager.js +181 -0
- package/src/sonar/project-key.js +120 -0
- package/src/sonar/scanner.js +307 -0
- package/src/sonar/token-bootstrap.js +205 -0
- package/src/sonar/token-recovery.js +67 -0
- package/src/spec-review/refine-loop.js +58 -0
- package/src/spec-review/run-spec-review.js +119 -0
- package/src/start/assessment.js +74 -0
- package/src/start/maturity.js +73 -0
- package/src/start/start-decider-role.js +79 -0
- package/src/start/sweep.js +157 -0
- package/src/sync/apply-canvas-patch.js +55 -0
- package/src/sync/detect-drift.js +113 -0
- package/src/tournament/crown.js +88 -0
- package/src/tournament/judge.js +150 -0
- package/src/tournament/run.js +142 -0
- package/src/tournament/scoreboard.js +124 -0
- package/src/tracker-bootstrap.js +44 -0
- package/src/types/agent.js +55 -0
- package/src/types/config.js +114 -0
- package/src/types/hu.js +47 -0
- package/src/types/index.js +38 -0
- package/src/types/policy.js +43 -0
- package/src/types/session.js +75 -0
- package/src/types/solomon.js +87 -0
- package/src/types/stage.js +68 -0
- package/src/utils/agent-detect.js +93 -0
- package/src/utils/ai-trash.js +48 -0
- package/src/utils/async-lock.js +31 -0
- package/src/utils/atomic-write.js +6 -0
- package/src/utils/banner.js +66 -0
- package/src/utils/binary-sources.js +70 -0
- package/src/utils/board-prompt-bridge.js +108 -0
- package/src/utils/budget.js +229 -0
- package/src/utils/cli-ask-question.js +93 -0
- package/src/utils/cli-progress.js +220 -0
- package/src/utils/cli-run-log.js +83 -0
- package/src/utils/cwd-confirm.js +39 -0
- package/src/utils/derive-project-name-from-cwd.js +119 -0
- package/src/utils/display/event-handlers.js +403 -0
- package/src/utils/display/formatters.js +132 -0
- package/src/utils/display/header.js +47 -0
- package/src/utils/display/resume-hint.js +41 -0
- package/src/utils/display/session-summary.js +118 -0
- package/src/utils/display/solomon.js +42 -0
- package/src/utils/display/spec-findings.js +44 -0
- package/src/utils/doc-links.js +29 -0
- package/src/utils/docker-install.js +34 -0
- package/src/utils/escape-regexp.js +15 -0
- package/src/utils/events.js +35 -0
- package/src/utils/fs.js +19 -0
- package/src/utils/garbage-collector.js +481 -0
- package/src/utils/git.js +279 -0
- package/src/utils/home-migration.js +87 -0
- package/src/utils/injection-guard.js +186 -0
- package/src/utils/install-hints.js +180 -0
- package/src/utils/json-extract.js +64 -0
- package/src/utils/locale.js +59 -0
- package/src/utils/logger.js +96 -0
- package/src/utils/managed-markers.js +93 -0
- package/src/utils/manifest-sniff.js +82 -0
- package/src/utils/messages.js +61 -0
- package/src/utils/model-selector.js +107 -0
- package/src/utils/os-detect.js +79 -0
- package/src/utils/paths.js +13 -0
- package/src/utils/pending-user-action.js +95 -0
- package/src/utils/port-check.js +6 -0
- package/src/utils/port-occupant.js +96 -0
- package/src/utils/pricing.js +29 -0
- package/src/utils/process.js +4 -0
- package/src/utils/project-detect.js +160 -0
- package/src/utils/prompt-project-name.js +35 -0
- package/src/utils/provider-env.js +116 -0
- package/src/utils/qmd-collection.js +72 -0
- package/src/utils/qmd-detect.js +18 -0
- package/src/utils/qmd-install.js +37 -0
- package/src/utils/quota-simulator.js +56 -0
- package/src/utils/rate-limit-detector.js +181 -0
- package/src/utils/repo-cleaner.js +79 -0
- package/src/utils/retry.js +88 -0
- package/src/utils/role-assigner.js +137 -0
- package/src/utils/role-env.js +58 -0
- package/src/utils/rtk-detect.js +18 -0
- package/src/utils/rtk-install.js +38 -0
- package/src/utils/rtk-wrapper.js +87 -0
- package/src/utils/run-context.js +75 -0
- package/src/utils/run-log.js +217 -0
- package/src/utils/run-registry.js +9 -0
- package/src/utils/shared-paths.js +12 -0
- package/src/utils/squeezr-detect.js +21 -0
- package/src/utils/squeezr-install.js +37 -0
- package/src/utils/stack-detect.js +135 -0
- package/src/utils/stall-detector.js +159 -0
- package/src/utils/status-dashboard.js +254 -0
- package/src/utils/task-file.js +109 -0
- package/src/utils/telemetry.js +124 -0
- package/src/utils/templates-root.js +61 -0
- package/src/utils/tool-call-extractor.js +56 -0
- package/src/utils/tool-governor.js +116 -0
- package/src/utils/tool-installer.js +93 -0
- package/src/utils/update-check.js +280 -0
- package/src/utils/vector-store-orphans.js +89 -0
- package/src/utils/welcome.js +47 -0
- package/src/utils/with-timeout.js +42 -0
- package/src/utils/wizard.js +47 -0
- package/src/webperf/cwv-gate.js +94 -0
- package/src/webperf/devtools-detect.js +112 -0
- package/src/webperf/scanner.js +209 -0
- package/src/webperf/webperf-role-integration.js +66 -0
- package/templates/coder-rules.md +45 -0
- package/templates/docker-compose.sonar.yml +60 -0
- package/templates/domains/example-dental.md +57 -0
- package/templates/kj.config.yml +128 -0
- package/templates/review-rules.md +17 -0
- package/templates/roles/architect/anthropic.md +74 -0
- package/templates/roles/architect/default.md +72 -0
- package/templates/roles/architect/google.md +61 -0
- package/templates/roles/architect/openai.md +60 -0
- package/templates/roles/architect/opencode.md +59 -0
- package/templates/roles/architect.md +76 -0
- package/templates/roles/audit.md +68 -0
- package/templates/roles/coder/anthropic.md +81 -0
- package/templates/roles/coder/default.md +78 -0
- package/templates/roles/coder/google.md +87 -0
- package/templates/roles/coder/openai.md +68 -0
- package/templates/roles/coder/opencode.md +58 -0
- package/templates/roles/coder.md +152 -0
- package/templates/roles/commiter.md +44 -0
- package/templates/roles/discover.md +167 -0
- package/templates/roles/domain-curator.md +52 -0
- package/templates/roles/hu-reviewer.md +236 -0
- package/templates/roles/impeccable-design.md +87 -0
- package/templates/roles/impeccable.md +125 -0
- package/templates/roles/karajan-brain.md +95 -0
- package/templates/roles/onboarder.md +45 -0
- package/templates/roles/planner/anthropic.md +59 -0
- package/templates/roles/planner/default.md +57 -0
- package/templates/roles/planner/google.md +75 -0
- package/templates/roles/planner/openai.md +55 -0
- package/templates/roles/planner/opencode.md +62 -0
- package/templates/roles/planner.md +61 -0
- package/templates/roles/refactorer.md +48 -0
- package/templates/roles/repairer.md +103 -0
- package/templates/roles/researcher.md +41 -0
- package/templates/roles/reviewer/anthropic.md +61 -0
- package/templates/roles/reviewer/default.md +62 -0
- package/templates/roles/reviewer/google.md +63 -0
- package/templates/roles/reviewer/openai.md +57 -0
- package/templates/roles/reviewer/opencode.md +42 -0
- package/templates/roles/reviewer-paranoid.md +38 -0
- package/templates/roles/reviewer-relaxed.md +34 -0
- package/templates/roles/reviewer-strict.md +37 -0
- package/templates/roles/reviewer.md +62 -0
- package/templates/roles/security.md +54 -0
- package/templates/roles/solomon/anthropic.md +71 -0
- package/templates/roles/solomon/default.md +83 -0
- package/templates/roles/solomon/google.md +61 -0
- package/templates/roles/solomon/openai.md +53 -0
- package/templates/roles/solomon/opencode.md +55 -0
- package/templates/roles/solomon.md +83 -0
- package/templates/roles/sonar.md +49 -0
- package/templates/roles/spec-reviewer.md +47 -0
- package/templates/roles/tester.md +50 -0
- package/templates/roles/triage.md +69 -0
- package/templates/skills/kj-architect.md +45 -0
- package/templates/skills/kj-audit.md +63 -0
- package/templates/skills/kj-board.md +16 -0
- package/templates/skills/kj-code.md +51 -0
- package/templates/skills/kj-csv-transform.md +40 -0
- package/templates/skills/kj-data-report.md +44 -0
- package/templates/skills/kj-discover.md +24 -0
- package/templates/skills/kj-rag-query.md +50 -0
- package/templates/skills/kj-review.md +47 -0
- package/templates/skills/kj-run.md +73 -0
- package/templates/skills/kj-security.md +49 -0
- package/templates/skills/kj-sonar.md +41 -0
- package/templates/skills/kj-sql-analysis.md +40 -0
- package/templates/skills/kj-test.md +40 -0
- package/templates/workflows/automerge.yml +30 -0
- package/templates/workflows/houston-override.yml +46 -0
- package/templates/workflows/kj-ci-gateway.yml +58 -0
- package/vendor/tree-sitter-grammars/README.md +21 -0
- package/vendor/tree-sitter-grammars/go.wasm +0 -0
- package/vendor/tree-sitter-grammars/java.wasm +0 -0
- package/vendor/tree-sitter-grammars/python.wasm +0 -0
- package/vendor/tree-sitter-grammars/rust.wasm +0 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI-flag overrides applied on top of a loaded config.
|
|
3
|
+
*
|
|
4
|
+
* `applyRunOverrides(config, flags)` takes the merged config from the
|
|
5
|
+
* loader plus the CLI flags (also forwarded from MCP tool args) and
|
|
6
|
+
* produces the final config the orchestrator operates on. Overrides are
|
|
7
|
+
* declarative where possible (ROLE_PROVIDER_FLAGS, ROLE_MODEL_FLAGS,
|
|
8
|
+
* PIPELINE_ENABLE_FLAGS, SCALAR_FLAGS, UNDEF_CHECK_FLAGS) and imperative
|
|
9
|
+
* only where the mapping is not 1:1 (methodology, CI, output mode,
|
|
10
|
+
* deprecated flags like `--no-sonar`).
|
|
11
|
+
*
|
|
12
|
+
* Extracted from `src/config.js` in TSK-0332 (Oleada 2 of the v2.7.4
|
|
13
|
+
* audit refactor). Public API: `applyRunOverrides`. The apply* helpers
|
|
14
|
+
* are internal.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { mergeDeep } from "./loader.js";
|
|
18
|
+
import { DEFAULTS } from "./defaults.js";
|
|
19
|
+
import { safeParseConfig, formatConfigIssues } from "./schema.js";
|
|
20
|
+
|
|
21
|
+
const ROLE_PROVIDER_FLAGS = [
|
|
22
|
+
["planner", "planner"], ["coder", "coder"], ["reviewer", "reviewer"],
|
|
23
|
+
["refactorer", "refactorer"], ["solomon", "solomon"], ["researcher", "researcher"],
|
|
24
|
+
["tester", "tester"], ["security", "security"], ["triage", "triage"],
|
|
25
|
+
["discover", "discover"], ["architect", "architect"]
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
// Role model flags: [flagName, roleName] — truthy check, String coercion
|
|
29
|
+
const ROLE_MODEL_FLAGS = [
|
|
30
|
+
["plannerModel", "planner"], ["coderModel", "coder"], ["reviewerModel", "reviewer"],
|
|
31
|
+
["refactorerModel", "refactorer"], ["solomonModel", "solomon"], ["discoverModel", "discover"],
|
|
32
|
+
["architectModel", "architect"]
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
// Pipeline enable flags: [flagName, pipelineKey] — !== undefined check, Boolean coercion
|
|
36
|
+
const PIPELINE_ENABLE_FLAGS = [
|
|
37
|
+
["enablePlanner", "planner"], ["enableRefactorer", "refactorer"],
|
|
38
|
+
["enableSolomon", "solomon"], ["enableResearcher", "researcher"],
|
|
39
|
+
["enableTester", "tester"], ["enableSecurity", "security"], ["enableImpeccable", "impeccable"],
|
|
40
|
+
["enablePerf", "perf"],
|
|
41
|
+
["enableTriage", "triage"], ["enableDiscover", "discover"],
|
|
42
|
+
["enableArchitect", "architect"],
|
|
43
|
+
["enableHuReviewer", "hu_reviewer"]
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const AUTO_SIMPLIFY_FLAG = "autoSimplify";
|
|
47
|
+
|
|
48
|
+
// Scalar flags: [flagName, setter] — truthy check.
|
|
49
|
+
// Note: max_iterations was previously here but `0` was silently ignored
|
|
50
|
+
// (truthy check skipped it). It now lives in UNDEF_CHECK_FLAGS so
|
|
51
|
+
// `--max-iterations 0` reaches the schema validator and errors cleanly
|
|
52
|
+
// instead of falling through to the default (KJC-TSK-0318).
|
|
53
|
+
const SCALAR_FLAGS = [
|
|
54
|
+
["mode", (out, v) => { out.review_mode = v; }],
|
|
55
|
+
["maxIterationMinutes", (out, v) => { out.session.max_iteration_minutes = Number(v); }],
|
|
56
|
+
["maxTotalMinutes", (out, v) => { out.session.max_total_minutes = Number(v); }],
|
|
57
|
+
["checkpointInterval", (out, v) => { out.session.checkpoint_interval_minutes = Number(v); }],
|
|
58
|
+
["parallel", (out, v) => { out.session.max_parallel_hus = Number(v); }],
|
|
59
|
+
["baseBranch", (out, v) => { out.base_branch = v; }],
|
|
60
|
+
["coderFallback", (out, v) => { out.coder_options.fallback_coder = v; }],
|
|
61
|
+
["reviewerFallback", (out, v) => { out.reviewer_options.fallback_reviewer = v; }],
|
|
62
|
+
["taskType", (out, v) => { out.taskType = String(v); }],
|
|
63
|
+
["branchPrefix", (out, v) => { out.git.branch_prefix = String(v); }]
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// Boolean/undefined-check flags: [flagName, setter] — !== undefined check.
|
|
67
|
+
// These preserve falsy values (false, 0) so --no-rebase correctly sets
|
|
68
|
+
// auto_rebase=false and --reviewer-retries 0 correctly disables retries.
|
|
69
|
+
const UNDEF_CHECK_FLAGS = [
|
|
70
|
+
["maxIterations", (out, v) => { out.max_iterations = Number(v); }],
|
|
71
|
+
["reviewerRetries", (out, v) => { out.reviewer_options.retries = Number(v); }],
|
|
72
|
+
["autoCommit", (out, v) => { out.git.auto_commit = Boolean(v); }],
|
|
73
|
+
["autoPush", (out, v) => { out.git.auto_push = Boolean(v); }],
|
|
74
|
+
["autoPr", (out, v) => { out.git.auto_pr = Boolean(v); }],
|
|
75
|
+
["autoRebase", (out, v) => { out.git.auto_rebase = Boolean(v); }],
|
|
76
|
+
["enableSerena", (out, v) => { out.serena.enabled = Boolean(v); }]
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
function applyRoleOverrides(out, flags) {
|
|
80
|
+
// A provider override is always a string (`--security codex`). A bare
|
|
81
|
+
// boolean means the flag belongs to the command itself (`kj audit
|
|
82
|
+
// --security`, KJC-TSK-0695) and must not become a provider.
|
|
83
|
+
for (const [flag, role] of ROLE_PROVIDER_FLAGS) {
|
|
84
|
+
if (typeof flags[flag] === "string" && flags[flag]) {
|
|
85
|
+
// A model pin belongs to the provider it was written for — switching
|
|
86
|
+
// provider by flag drops it (KJC-TSK-0729: codex's pinned mini reached
|
|
87
|
+
// agy, which answered with its model list instead of a verdict). An
|
|
88
|
+
// explicit --<role>-model flag re-pins below, after this loop.
|
|
89
|
+
if (out.roles[role].provider && out.roles[role].provider !== flags[flag]) out.roles[role].model = null;
|
|
90
|
+
out.roles[role].provider = flags[flag];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// coder/reviewer also update top-level aliases
|
|
94
|
+
if (flags.coder) out.coder = flags.coder;
|
|
95
|
+
if (flags.reviewer) out.reviewer = flags.reviewer;
|
|
96
|
+
|
|
97
|
+
for (const [flag, role] of ROLE_MODEL_FLAGS) {
|
|
98
|
+
if (flags[flag]) out.roles[role].model = String(flags[flag]);
|
|
99
|
+
}
|
|
100
|
+
// reviewerModel also updates reviewer_options
|
|
101
|
+
if (flags.reviewerModel) out.reviewer_options.model = String(flags.reviewerModel);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function applyPipelineOverrides(out, flags) {
|
|
105
|
+
for (const [flag, key] of PIPELINE_ENABLE_FLAGS) {
|
|
106
|
+
if (flags[flag] !== undefined) out.pipeline[key].enabled = Boolean(flags[flag]);
|
|
107
|
+
}
|
|
108
|
+
if (flags.enableReviewer !== undefined) {
|
|
109
|
+
out.pipeline.reviewer = out.pipeline.reviewer || {};
|
|
110
|
+
out.pipeline.reviewer.enabled = Boolean(flags.enableReviewer);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function applyScalarAndBooleanOverrides(out, flags) {
|
|
115
|
+
for (const [flag, setter] of SCALAR_FLAGS) {
|
|
116
|
+
if (flags[flag]) setter(out, flags[flag]);
|
|
117
|
+
}
|
|
118
|
+
for (const [flag, setter] of UNDEF_CHECK_FLAGS) {
|
|
119
|
+
if (flags[flag] !== undefined) setter(out, flags[flag]);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function applyMethodologyOverride(out, flags) {
|
|
124
|
+
if (!flags.methodology) return;
|
|
125
|
+
const methodology = String(flags.methodology).toLowerCase();
|
|
126
|
+
out.development.methodology = methodology;
|
|
127
|
+
out.development.require_test_changes = methodology === "tdd";
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function applyCiOverride(out, flags) {
|
|
131
|
+
out.ci = out.ci || { enabled: false };
|
|
132
|
+
if (flags.enableCi === undefined) return;
|
|
133
|
+
out.ci.enabled = Boolean(flags.enableCi);
|
|
134
|
+
// CI requires git automation (commit + push + PR)
|
|
135
|
+
if (out.ci.enabled) {
|
|
136
|
+
out.git.auto_commit = true;
|
|
137
|
+
out.git.auto_push = true;
|
|
138
|
+
out.git.auto_pr = true;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function applyOutputModeOverrides(out, flags) {
|
|
143
|
+
out.output = out.output || {};
|
|
144
|
+
// --verbose explicitly overrides quiet
|
|
145
|
+
if (flags.verbose === true) {
|
|
146
|
+
out.output.quiet = false;
|
|
147
|
+
} else if (flags.quiet === true) {
|
|
148
|
+
out.output.quiet = true;
|
|
149
|
+
}
|
|
150
|
+
// quiet defaults to true (set in DEFAULTS)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function applyMiscOverrides(out, flags) {
|
|
154
|
+
if (flags[AUTO_SIMPLIFY_FLAG] !== undefined) out.pipeline.auto_simplify = Boolean(flags[AUTO_SIMPLIFY_FLAG]);
|
|
155
|
+
// `--no-sonar` and `sonarqube.enabled: false` are deprecated since v2.7.4.
|
|
156
|
+
// Sonar is intrinsic to Karajan for code tasks (sw/refactor/add-tests) and
|
|
157
|
+
// skipped for non-code tasks (audit/doc/infra/analysis/no-code) by policy.
|
|
158
|
+
// The flag is still accepted to avoid breaking scripts; it now emits a
|
|
159
|
+
// warning at run start and is otherwise ignored. See preflight-checks.js
|
|
160
|
+
// and flow-runner.js for the actual gate (resolvedPolicies.sonar).
|
|
161
|
+
// --step: per-iteration supervision gate (KJC-TSK-0628).
|
|
162
|
+
if (flags.step === true) out.session.iteration_gate = true;
|
|
163
|
+
|
|
164
|
+
if (flags.noSonar || flags.sonar === false) {
|
|
165
|
+
out._deprecated = out._deprecated || {};
|
|
166
|
+
out._deprecated.noSonarFlag = true;
|
|
167
|
+
}
|
|
168
|
+
out.sonarcloud = out.sonarcloud || {};
|
|
169
|
+
if (flags.enableSonarcloud === true) out.sonarcloud.enabled = true;
|
|
170
|
+
if (flags.noSonarcloud === true || flags.sonarcloud === false) out.sonarcloud.enabled = false;
|
|
171
|
+
|
|
172
|
+
out.planning_game = out.planning_game || {};
|
|
173
|
+
if (flags.pgTask) out.planning_game.enabled = true;
|
|
174
|
+
if (flags.pgProject) out.planning_game.project_id = flags.pgProject;
|
|
175
|
+
|
|
176
|
+
out.model_selection = out.model_selection || { enabled: true, tiers: {}, role_overrides: {} };
|
|
177
|
+
if (flags.smartModels === true) out.model_selection.enabled = true;
|
|
178
|
+
if (flags.smartModels === false || flags.noSmartModels === true) out.model_selection.enabled = false;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function applyRunOverrides(config, flags) {
|
|
182
|
+
const out = mergeDeep(config, {});
|
|
183
|
+
out.coder_options = out.coder_options || {};
|
|
184
|
+
out.reviewer_options = out.reviewer_options || {};
|
|
185
|
+
out.session = out.session || {};
|
|
186
|
+
out.git = out.git || {};
|
|
187
|
+
out.development = out.development || {};
|
|
188
|
+
out.sonarqube = out.sonarqube || {};
|
|
189
|
+
// Precedence: explicit top-level value (including null = opt-out) wins;
|
|
190
|
+
// the legacy session.max_budget_usd location next; the shipped default
|
|
191
|
+
// (KJC-TSK-0621: 5) last. When top-level still carries the default, a
|
|
192
|
+
// session-level value — including an explicit null — takes over.
|
|
193
|
+
if (out.max_budget_usd === undefined) {
|
|
194
|
+
out.max_budget_usd = out.session.max_budget_usd !== undefined ? out.session.max_budget_usd : DEFAULTS.max_budget_usd;
|
|
195
|
+
} else if (out.max_budget_usd === DEFAULTS.max_budget_usd && out.session.max_budget_usd !== undefined) {
|
|
196
|
+
out.max_budget_usd = out.session.max_budget_usd;
|
|
197
|
+
}
|
|
198
|
+
out.budget = mergeDeep(DEFAULTS.budget, out.budget || {});
|
|
199
|
+
out.roles = mergeDeep(DEFAULTS.roles, out.roles || {});
|
|
200
|
+
out.pipeline = mergeDeep(DEFAULTS.pipeline, out.pipeline || {});
|
|
201
|
+
out.serena = out.serena || { enabled: false };
|
|
202
|
+
|
|
203
|
+
applyRoleOverrides(out, flags);
|
|
204
|
+
applyPipelineOverrides(out, flags);
|
|
205
|
+
applyScalarAndBooleanOverrides(out, flags);
|
|
206
|
+
applyMethodologyOverride(out, flags);
|
|
207
|
+
applyCiOverride(out, flags);
|
|
208
|
+
applyMiscOverrides(out, flags);
|
|
209
|
+
applyOutputModeOverrides(out, flags);
|
|
210
|
+
|
|
211
|
+
// KJC-TSK-0318 — re-run schema validation after overrides so CLI flags
|
|
212
|
+
// that would produce an invalid config (e.g. --max-iterations 0) fail
|
|
213
|
+
// fast with the same clear message loadConfig would have produced.
|
|
214
|
+
const validation = safeParseConfig(out);
|
|
215
|
+
if (!validation.success) {
|
|
216
|
+
throw new Error(`Invalid Karajan config after CLI overrides:\n${formatConfigIssues(validation.issues)}`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return out;
|
|
220
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role provider/model resolution + config validation.
|
|
3
|
+
*
|
|
4
|
+
* `resolveRole(config, role)` returns `{ provider, model }` for a role
|
|
5
|
+
* given the fully-overridden config, respecting legacy single-provider
|
|
6
|
+
* shortcuts (`coder: "claude"`) and per-role overrides
|
|
7
|
+
* (`roles.coder.provider`). Handles model compatibility (gemini models
|
|
8
|
+
* are dropped from a claude provider, etc.) so the agent subprocess
|
|
9
|
+
* never sees an incompatible `--model` flag.
|
|
10
|
+
*
|
|
11
|
+
* `validateConfig(config, commandName)` is the run-time guard called by
|
|
12
|
+
* every CLI command before spawning agents: it asserts every required
|
|
13
|
+
* role has a provider, otherwise throws with an actionable message
|
|
14
|
+
* ("Set 'roles.planner.provider' or pass '--planner <name>'").
|
|
15
|
+
*
|
|
16
|
+
* Extracted from `src/config.js` in TSK-0332 (Oleada 2 of the v2.7.4
|
|
17
|
+
* audit refactor). Public API: `resolveRole`, `validateConfig`. The
|
|
18
|
+
* inference helpers are internal.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Check if a model string is compatible with an agent provider.
|
|
23
|
+
* Only returns false when the model clearly belongs to a DIFFERENT family.
|
|
24
|
+
* Returns true if we can't determine or if the model is ambiguous.
|
|
25
|
+
*
|
|
26
|
+
* KJC-BUG-0144: exported and family-based — an agent may serve another
|
|
27
|
+
* family's models (agy is Google's Antigravity, gemini family), and the
|
|
28
|
+
* same check now guards BaseAgent.getRoleModel so per-role defaults
|
|
29
|
+
* (e.g. start's haiku) never reach a provider from another family.
|
|
30
|
+
*/
|
|
31
|
+
const AGENT_MODEL_SIGNATURES = {
|
|
32
|
+
claude: ["claude", "sonnet", "opus", "haiku"],
|
|
33
|
+
codex: ["o4-", "o3-", "gpt-", "codex"],
|
|
34
|
+
gemini: ["gemini", "flash-"]
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Single-family CLIs: they only serve their own vendor's models. Agents NOT
|
|
38
|
+
// in this map (aider, opencode, copilot, kimi...) are multi-model hosts —
|
|
39
|
+
// they route to arbitrary models, so any model name is allowed there.
|
|
40
|
+
const AGENT_FAMILY = { claude: "claude", codex: "codex", gemini: "gemini", agy: "gemini" };
|
|
41
|
+
|
|
42
|
+
function modelFamily(model) {
|
|
43
|
+
const lower = model.toLowerCase();
|
|
44
|
+
for (const [family, signatures] of Object.entries(AGENT_MODEL_SIGNATURES)) {
|
|
45
|
+
if (signatures.some(s => lower.includes(s))) return family;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function isModelCompatible(agent, model) {
|
|
51
|
+
if (!model || !agent) return true;
|
|
52
|
+
const agentFamily = AGENT_FAMILY[agent];
|
|
53
|
+
if (!agentFamily) return true; // multi-model host — bring your own model
|
|
54
|
+
const family = modelFamily(model);
|
|
55
|
+
if (!family) return true; // ambiguous/custom/local — allow it
|
|
56
|
+
return family === agentFamily;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Roles that inherit provider/model from the coder when not explicitly configured
|
|
60
|
+
const CODER_INHERITED_ROLES = new Set([
|
|
61
|
+
"planner", "refactorer", "solomon", "researcher", "tester", "security",
|
|
62
|
+
"impeccable", "triage", "discover", "architect", "audit",
|
|
63
|
+
"hu_reviewer", "hu-reviewer",
|
|
64
|
+
"spec_reviewer", "spec-reviewer",
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
function resolveProvider(roleConfig, role, roles, legacyCoder, legacyReviewer) {
|
|
68
|
+
if (roleConfig.provider) return roleConfig.provider;
|
|
69
|
+
|
|
70
|
+
// If model has "provider/model" format (e.g. "gemini/pro"), extract the provider
|
|
71
|
+
if (roleConfig.model && roleConfig.model.includes("/")) {
|
|
72
|
+
const inferredProvider = roleConfig.model.split("/")[0].toLowerCase();
|
|
73
|
+
if (AGENT_MODEL_SIGNATURES[inferredProvider]) return inferredProvider;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (role === "coder") return legacyCoder;
|
|
77
|
+
if (role === "reviewer") return legacyReviewer;
|
|
78
|
+
if (CODER_INHERITED_ROLES.has(role)) return roles.coder?.provider || legacyCoder;
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function resolveModel(roleConfig, role, config) {
|
|
83
|
+
if (roleConfig.model) {
|
|
84
|
+
// Strip "provider/" prefix from models like "gemini/pro" → "pro"
|
|
85
|
+
const model = roleConfig.model.includes("/")
|
|
86
|
+
? roleConfig.model.split("/").slice(1).join("/")
|
|
87
|
+
: roleConfig.model;
|
|
88
|
+
return { model, inherited: false };
|
|
89
|
+
}
|
|
90
|
+
if (role === "coder") return { model: config?.coder_options?.model ?? null, inherited: false };
|
|
91
|
+
if (role === "reviewer") return { model: config?.reviewer_options?.model ?? null, inherited: false };
|
|
92
|
+
if (CODER_INHERITED_ROLES.has(role)) {
|
|
93
|
+
const model = config?.coder_options?.model ?? null;
|
|
94
|
+
return { model, inherited: !!model };
|
|
95
|
+
}
|
|
96
|
+
return { model: null, inherited: false };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function resolveRole(config, role) {
|
|
100
|
+
const roles = config?.roles || {};
|
|
101
|
+
const roleConfig = roles[role] || {};
|
|
102
|
+
const legacyCoder = config?.coder || null;
|
|
103
|
+
const legacyReviewer = config?.reviewer || null;
|
|
104
|
+
|
|
105
|
+
const provider = resolveProvider(roleConfig, role, roles, legacyCoder, legacyReviewer);
|
|
106
|
+
let { model } = resolveModel(roleConfig, role, config);
|
|
107
|
+
|
|
108
|
+
// Drop model if incompatible with the resolved provider (inherited or explicit)
|
|
109
|
+
if (provider && model && !isModelCompatible(provider, model)) {
|
|
110
|
+
model = null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return { provider, model };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Pipeline roles checked when commandName is "run": [pipelineKey, roleName]
|
|
117
|
+
const RUN_PIPELINE_ROLES = [
|
|
118
|
+
["reviewer", "reviewer"], ["triage", "triage"], ["planner", "planner"],
|
|
119
|
+
["refactorer", "refactorer"], ["researcher", "researcher"],
|
|
120
|
+
["tester", "tester"], ["security", "security"], ["impeccable", "impeccable"]
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
// Direct command-to-role mapping for non-"run" commands
|
|
124
|
+
const COMMAND_ROLE_MAP = {
|
|
125
|
+
discover: ["discover"],
|
|
126
|
+
plan: ["planner"],
|
|
127
|
+
code: ["coder"],
|
|
128
|
+
review: ["reviewer"]
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
function requiredRolesFor(commandName, config) {
|
|
132
|
+
if (commandName !== "run") {
|
|
133
|
+
return COMMAND_ROLE_MAP[commandName] || [];
|
|
134
|
+
}
|
|
135
|
+
const required = ["coder"];
|
|
136
|
+
for (const [pipelineKey, roleName] of RUN_PIPELINE_ROLES) {
|
|
137
|
+
const pipelineEntry = config?.pipeline?.[pipelineKey];
|
|
138
|
+
// reviewer defaults to enabled (only excluded if explicitly false)
|
|
139
|
+
const isEnabled = pipelineKey === "reviewer"
|
|
140
|
+
? pipelineEntry?.enabled !== false
|
|
141
|
+
: Boolean(pipelineEntry?.enabled);
|
|
142
|
+
if (isEnabled) required.push(roleName);
|
|
143
|
+
}
|
|
144
|
+
return required;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function validateConfig(config, commandName = "run") {
|
|
148
|
+
const errors = [];
|
|
149
|
+
if (!new Set(["paranoid", "strict", "standard", "relaxed", "custom"]).has(config.review_mode)) {
|
|
150
|
+
errors.push(`Invalid review_mode: ${config.review_mode}`);
|
|
151
|
+
}
|
|
152
|
+
if (!new Set(["tdd", "standard"]).has(config.development?.methodology)) {
|
|
153
|
+
errors.push(`Invalid development.methodology: ${config.development?.methodology}`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const requiredRoles = requiredRolesFor(commandName, config);
|
|
157
|
+
for (const role of requiredRoles) {
|
|
158
|
+
const { provider } = resolveRole(config, role);
|
|
159
|
+
if (!provider) {
|
|
160
|
+
errors.push(
|
|
161
|
+
`Missing provider for required role '${role}'. Set 'roles.${role}.provider' or pass '--${role} <name>'`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (errors.length > 0) {
|
|
167
|
+
throw new Error(errors.join("\n"));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return config;
|
|
171
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central Valibot schema for Karajan's configuration surface (KJC-TSK-0318).
|
|
3
|
+
*
|
|
4
|
+
* Origin: this schema is based on Jorge del Casar's original work in PR #379
|
|
5
|
+
* (closed). The full 650-line mirror-of-DEFAULTS approach he proposed drifted
|
|
6
|
+
* heavily against `main` by the time it was reviewed, so this file takes the
|
|
7
|
+
* same intent — validating Karajan config at load time with Valibot — but
|
|
8
|
+
* narrows the scope to the handful of fields where validation actually
|
|
9
|
+
* catches real bugs (review_mode, methodology, max_iterations, percentage
|
|
10
|
+
* budgets, port numbers). Everything else is defined with `v.looseObject` /
|
|
11
|
+
* `v.unknown()` so existing consumers who touch undeclared keys keep working.
|
|
12
|
+
*
|
|
13
|
+
* The runtime DEFAULTS object still lives in src/config.js — it is the source
|
|
14
|
+
* of truth for default values. This schema exists to reject invalid input
|
|
15
|
+
* early (e.g. `max_iterations: 0`, `review_mode: "yolo"`) with a clear error,
|
|
16
|
+
* and to give downstream consumers a typed handle via `KarajanConfig`.
|
|
17
|
+
*
|
|
18
|
+
* @typedef {import("valibot").InferOutput<typeof ConfigSchema>} KarajanConfig
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import * as v from "valibot";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Positive integer (>= 1). Used where 0 / negative would be a clear bug
|
|
25
|
+
* (max_iterations, port, most timeout knobs when they gate the loop itself).
|
|
26
|
+
*/
|
|
27
|
+
const PositiveInt = v.pipe(
|
|
28
|
+
v.number("must be a number"),
|
|
29
|
+
v.integer("must be an integer"),
|
|
30
|
+
v.minValue(1, "must be >= 1")
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Non-negative integer (>= 0). Used for retry counts where 0 is a valid
|
|
35
|
+
* "don't retry" signal.
|
|
36
|
+
*/
|
|
37
|
+
const NonNegativeInt = v.pipe(
|
|
38
|
+
v.number("must be a number"),
|
|
39
|
+
v.integer("must be an integer"),
|
|
40
|
+
v.minValue(0, "must be >= 0")
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* review_mode picklist — anything outside this set is a typo.
|
|
45
|
+
*/
|
|
46
|
+
const ReviewMode = v.picklist(
|
|
47
|
+
["paranoid", "strict", "standard", "relaxed", "custom"],
|
|
48
|
+
"review_mode must be one of: paranoid | strict | standard | relaxed | custom"
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const Methodology = v.picklist(
|
|
52
|
+
["tdd", "standard"],
|
|
53
|
+
"development.methodology must be one of: tdd | standard"
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* KJC-TSK-0415: fallback chain. Cuando provider primario hits
|
|
58
|
+
* QUOTA_EXHAUSTED_* con cooldown > max_wait_hours, switch a fallback.
|
|
59
|
+
* Recursivo — el fallback puede tener su propio fallback.
|
|
60
|
+
*/
|
|
61
|
+
const RoleFallback = v.looseObject({
|
|
62
|
+
provider: v.string("fallback.provider required (claude|codex|gemini|opencode|aider)"),
|
|
63
|
+
model: v.optional(v.nullable(v.string())),
|
|
64
|
+
max_wait_hours: v.optional(v.pipe(v.number(), v.minValue(0)), 12),
|
|
65
|
+
// Recursivo. Schema permite cualquier shape compatible con RoleFallback.
|
|
66
|
+
fallback: v.optional(v.lazy(() => RoleFallback)),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Role entry — provider + model, both nullable. Extra keys allowed.
|
|
71
|
+
* KJC-TSK-0415: campo fallback opcional para Plan B en quota exhausted.
|
|
72
|
+
*/
|
|
73
|
+
const RoleEntry = v.looseObject({
|
|
74
|
+
provider: v.optional(v.nullable(v.string())),
|
|
75
|
+
model: v.optional(v.nullable(v.string())),
|
|
76
|
+
fallback: v.optional(RoleFallback),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const RolesMap = v.optional(v.looseObject({
|
|
80
|
+
planner: v.optional(RoleEntry),
|
|
81
|
+
coder: v.optional(RoleEntry),
|
|
82
|
+
reviewer: v.optional(RoleEntry),
|
|
83
|
+
refactorer: v.optional(RoleEntry),
|
|
84
|
+
solomon: v.optional(RoleEntry),
|
|
85
|
+
researcher: v.optional(RoleEntry),
|
|
86
|
+
tester: v.optional(RoleEntry),
|
|
87
|
+
security: v.optional(RoleEntry),
|
|
88
|
+
impeccable: v.optional(RoleEntry),
|
|
89
|
+
triage: v.optional(RoleEntry),
|
|
90
|
+
discover: v.optional(RoleEntry),
|
|
91
|
+
architect: v.optional(RoleEntry),
|
|
92
|
+
hu_reviewer: v.optional(RoleEntry),
|
|
93
|
+
start: v.optional(RoleEntry),
|
|
94
|
+
}));
|
|
95
|
+
|
|
96
|
+
const PipelineEntry = v.looseObject({
|
|
97
|
+
enabled: v.optional(v.boolean()),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const PipelineMap = v.optional(v.looseObject({
|
|
101
|
+
planner: v.optional(PipelineEntry),
|
|
102
|
+
refactorer: v.optional(PipelineEntry),
|
|
103
|
+
solomon: v.optional(PipelineEntry),
|
|
104
|
+
researcher: v.optional(PipelineEntry),
|
|
105
|
+
tester: v.optional(PipelineEntry),
|
|
106
|
+
security: v.optional(PipelineEntry),
|
|
107
|
+
impeccable: v.optional(PipelineEntry),
|
|
108
|
+
perf: v.optional(PipelineEntry),
|
|
109
|
+
triage: v.optional(PipelineEntry),
|
|
110
|
+
discover: v.optional(PipelineEntry),
|
|
111
|
+
architect: v.optional(PipelineEntry),
|
|
112
|
+
hu_reviewer: v.optional(PipelineEntry),
|
|
113
|
+
auto_simplify: v.optional(v.boolean()),
|
|
114
|
+
}));
|
|
115
|
+
|
|
116
|
+
const Development = v.optional(v.looseObject({
|
|
117
|
+
methodology: v.optional(Methodology),
|
|
118
|
+
require_test_changes: v.optional(v.boolean()),
|
|
119
|
+
// KJC-TSK-0398: opt-in flag; module lands in PR1, integration in PR3.
|
|
120
|
+
require_red_then_green: v.optional(v.boolean()),
|
|
121
|
+
test_file_patterns: v.optional(v.array(v.string())),
|
|
122
|
+
source_file_extensions: v.optional(v.array(v.string())),
|
|
123
|
+
}));
|
|
124
|
+
|
|
125
|
+
const Git = v.optional(v.looseObject({
|
|
126
|
+
auto_commit: v.optional(v.boolean()),
|
|
127
|
+
auto_push: v.optional(v.boolean()),
|
|
128
|
+
auto_pr: v.optional(v.boolean()),
|
|
129
|
+
auto_rebase: v.optional(v.boolean()),
|
|
130
|
+
branch_prefix: v.optional(v.string()),
|
|
131
|
+
}));
|
|
132
|
+
|
|
133
|
+
const ReviewerOptions = v.optional(v.looseObject({
|
|
134
|
+
output_format: v.optional(v.string()),
|
|
135
|
+
require_schema: v.optional(v.boolean()),
|
|
136
|
+
model: v.optional(v.nullable(v.string())),
|
|
137
|
+
deterministic: v.optional(v.boolean()),
|
|
138
|
+
retries: v.optional(NonNegativeInt, 1),
|
|
139
|
+
fallback_reviewer: v.optional(v.nullable(v.string())),
|
|
140
|
+
}));
|
|
141
|
+
|
|
142
|
+
const CoderOptions = v.optional(v.looseObject({
|
|
143
|
+
model: v.optional(v.nullable(v.string())),
|
|
144
|
+
auto_approve: v.optional(v.boolean()),
|
|
145
|
+
fallback_coder: v.optional(v.nullable(v.string())),
|
|
146
|
+
}));
|
|
147
|
+
|
|
148
|
+
const HuBoard = v.optional(v.looseObject({
|
|
149
|
+
enabled: v.optional(v.boolean()),
|
|
150
|
+
port: v.optional(v.pipe(
|
|
151
|
+
v.number("hu_board.port must be a number"),
|
|
152
|
+
v.integer(),
|
|
153
|
+
v.minValue(1, "hu_board.port must be >= 1"),
|
|
154
|
+
v.maxValue(65535, "hu_board.port must be <= 65535")
|
|
155
|
+
)),
|
|
156
|
+
auto_start: v.optional(v.boolean()),
|
|
157
|
+
}));
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Budget warn threshold: 0-100 percent. Anything outside is nonsense.
|
|
161
|
+
*/
|
|
162
|
+
const Budget = v.optional(v.looseObject({
|
|
163
|
+
warn_threshold_pct: v.optional(v.pipe(
|
|
164
|
+
v.number(),
|
|
165
|
+
v.minValue(0, "budget.warn_threshold_pct must be 0-100"),
|
|
166
|
+
v.maxValue(100, "budget.warn_threshold_pct must be 0-100")
|
|
167
|
+
)),
|
|
168
|
+
currency: v.optional(v.string()),
|
|
169
|
+
exchange_rate_eur: v.optional(v.number()),
|
|
170
|
+
pricing: v.optional(v.unknown()),
|
|
171
|
+
}));
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* skills.addyosmani subtree (KJC-TSK-0327). Governs the addyosmani/agent-skills
|
|
175
|
+
* catalog provider: enabled flag, refresh TTL and repo URL.
|
|
176
|
+
*/
|
|
177
|
+
const SkillsAddyosmani = v.looseObject({
|
|
178
|
+
enabled: v.optional(v.boolean()),
|
|
179
|
+
refreshDays: v.optional(v.pipe(
|
|
180
|
+
v.number(),
|
|
181
|
+
v.minValue(0, "skills.addyosmani.refreshDays must be >= 0")
|
|
182
|
+
)),
|
|
183
|
+
repoUrl: v.optional(v.string()),
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* skills.* subtree. `sources` controls which providers Karajan consults and in
|
|
188
|
+
* what order (addyosmani → openskills → local by default). `mode` is the
|
|
189
|
+
* existing regex/semantic/auto/none knob from semantic-detector.js.
|
|
190
|
+
*/
|
|
191
|
+
const Skills = v.optional(v.looseObject({
|
|
192
|
+
mode: v.optional(v.picklist(["auto", "regex", "semantic", "none"], "skills.mode must be one of: auto | regex | semantic | none")),
|
|
193
|
+
sources: v.optional(v.array(v.string())),
|
|
194
|
+
addyosmani: v.optional(SkillsAddyosmani),
|
|
195
|
+
}));
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* KJC-TSK-0407: routing automático de modelos por HU según complexity.
|
|
199
|
+
* - by_provider: override de tiers per provider (claude/codex/gemini).
|
|
200
|
+
* Cada provider mapea level → modelo. Sobreescribe defaults del router.
|
|
201
|
+
* - fixed.coder / fixed.reviewer: si presentes, override TOTAL — todas
|
|
202
|
+
* las HUs usan esos modelos independientemente del score. Útil para
|
|
203
|
+
* forzar Sonnet en todo el proyecto, por ejemplo.
|
|
204
|
+
*/
|
|
205
|
+
const ModelRouting = v.optional(v.looseObject({
|
|
206
|
+
by_provider: v.optional(v.record(
|
|
207
|
+
v.string(),
|
|
208
|
+
v.looseObject({
|
|
209
|
+
trivial: v.optional(v.string()),
|
|
210
|
+
simple: v.optional(v.string()),
|
|
211
|
+
medium: v.optional(v.string()),
|
|
212
|
+
complex: v.optional(v.string()),
|
|
213
|
+
})
|
|
214
|
+
)),
|
|
215
|
+
fixed: v.optional(v.looseObject({
|
|
216
|
+
coder: v.optional(v.nullable(v.string())),
|
|
217
|
+
reviewer: v.optional(v.nullable(v.string())),
|
|
218
|
+
})),
|
|
219
|
+
}));
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Main config schema. `looseObject` lets every consumer that reads an
|
|
223
|
+
* undeclared key keep working while the schema catches the bugs we care
|
|
224
|
+
* about.
|
|
225
|
+
*/
|
|
226
|
+
export const ConfigSchema = v.looseObject({
|
|
227
|
+
coder: v.optional(v.string()),
|
|
228
|
+
reviewer: v.optional(v.string()),
|
|
229
|
+
roles: RolesMap,
|
|
230
|
+
pipeline: PipelineMap,
|
|
231
|
+
review_mode: v.optional(ReviewMode),
|
|
232
|
+
max_iterations: v.optional(PositiveInt, 5),
|
|
233
|
+
hu_max_iterations: v.optional(PositiveInt, 3),
|
|
234
|
+
max_budget_usd: v.optional(v.nullable(v.pipe(
|
|
235
|
+
v.number(),
|
|
236
|
+
v.minValue(0, "max_budget_usd must be >= 0")
|
|
237
|
+
))),
|
|
238
|
+
// ENV-D1 (KJC-TSK-0642): where work items live — the integrated HU Board
|
|
239
|
+
// or the user's Planning Game. The v4 playbook renders per backend.
|
|
240
|
+
state_backend: v.optional(v.picklist(
|
|
241
|
+
// KJC-TSK-0709 caught the drift: "external" shipped in v4.5.0 (any
|
|
242
|
+
// board via the agent's own MCP/tools) but this picklist never learned it.
|
|
243
|
+
["hu-board", "planning-game", "external"],
|
|
244
|
+
"state_backend must be \"hu-board\", \"planning-game\" or \"external\""
|
|
245
|
+
)),
|
|
246
|
+
review_rules: v.optional(v.string()),
|
|
247
|
+
coder_rules: v.optional(v.string()),
|
|
248
|
+
base_branch: v.optional(v.string()),
|
|
249
|
+
coder_options: CoderOptions,
|
|
250
|
+
reviewer_options: ReviewerOptions,
|
|
251
|
+
development: Development,
|
|
252
|
+
git: Git,
|
|
253
|
+
hu_board: HuBoard,
|
|
254
|
+
budget: Budget,
|
|
255
|
+
language: v.optional(v.string()),
|
|
256
|
+
hu_language: v.optional(v.string()),
|
|
257
|
+
policies: v.optional(v.record(v.string(), v.unknown())),
|
|
258
|
+
telemetry: v.optional(v.boolean()),
|
|
259
|
+
skills: Skills,
|
|
260
|
+
model_routing: ModelRouting,
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Parse a raw merged config against the schema. Returns the normalized
|
|
265
|
+
* config or throws a Valibot ValiError. Call sites should wrap this in a
|
|
266
|
+
* try/catch that re-throws with a friendlier prefix.
|
|
267
|
+
*
|
|
268
|
+
* @param {unknown} input
|
|
269
|
+
* @returns {KarajanConfig}
|
|
270
|
+
*/
|
|
271
|
+
export function parseConfig(input) {
|
|
272
|
+
return v.parse(ConfigSchema, input);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Safe variant — returns { success, data } | { success: false, issues } so
|
|
277
|
+
* callers can decide how to report errors without catching ValiError.
|
|
278
|
+
* @param {unknown} input
|
|
279
|
+
*/
|
|
280
|
+
export function safeParseConfig(input) {
|
|
281
|
+
const result = v.safeParse(ConfigSchema, input);
|
|
282
|
+
if (result.success) return { success: true, data: result.output };
|
|
283
|
+
return {
|
|
284
|
+
success: false,
|
|
285
|
+
issues: result.issues.map(i => ({
|
|
286
|
+
path: (i.path || []).map(p => p.key).join("."),
|
|
287
|
+
message: i.message,
|
|
288
|
+
})),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Aggregate Valibot issues into a single readable string. Used by loadConfig
|
|
294
|
+
* to produce actionable error messages instead of the default ValiError dump.
|
|
295
|
+
* @param {Array<{path: string, message: string}>} issues
|
|
296
|
+
*/
|
|
297
|
+
export function formatConfigIssues(issues) {
|
|
298
|
+
return issues.map(i => (i.path ? `${i.path}: ${i.message}` : i.message)).join("\n");
|
|
299
|
+
}
|