@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,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic skill detection using the triage classifier.
|
|
3
|
+
*
|
|
4
|
+
* The regex-based detector (skill-detector.js) is fast but shallow: it only
|
|
5
|
+
* catches dependencies that name themselves explicitly. A task like
|
|
6
|
+
* "add a feature flag system" might benefit from an "a/b-testing" skill
|
|
7
|
+
* that regex cannot guess without an exhaustive keyword list.
|
|
8
|
+
*
|
|
9
|
+
* Semantic mode asks the classifier agent to pick skills from a known
|
|
10
|
+
* catalog given the task text and the skills already detected by regex.
|
|
11
|
+
* The catalog is intentionally small and curated — we don't hit the
|
|
12
|
+
* openskills.cc marketplace API (not available). If the classifier is
|
|
13
|
+
* unavailable (missing provider / missing API key), we return [] and the
|
|
14
|
+
* pipeline keeps working with the regex-only result.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { createAgent } from "../agents/index.js";
|
|
18
|
+
import { resolveRole } from "../config.js";
|
|
19
|
+
import { withBrainRecovery } from "../brain/with-brain-recovery.js";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Curated catalog of skills the classifier is allowed to suggest. Keeping
|
|
23
|
+
* this small prevents the model from hallucinating non-existent skills and
|
|
24
|
+
* bounds the tokens spent on the prompt.
|
|
25
|
+
*/
|
|
26
|
+
export const SEMANTIC_CATALOG = [
|
|
27
|
+
"astro", "nextjs", "react", "vue", "svelte", "angular",
|
|
28
|
+
"express", "fastify", "nestjs",
|
|
29
|
+
"java", "kotlin", "go", "rust", "ruby", "php", "dotnet", "elixir",
|
|
30
|
+
"python", "python-data", "python-ml", "pytest-patterns",
|
|
31
|
+
"django", "flask", "fastapi",
|
|
32
|
+
"sql-analysis", "prisma", "mongodb",
|
|
33
|
+
"owasp-top-10", "security-checklist",
|
|
34
|
+
"java-code-review", "python-code-review",
|
|
35
|
+
"frontend-design", "csv-transform", "data-report",
|
|
36
|
+
"vitest-patterns", "jest-patterns", "playwright-patterns", "cypress-patterns",
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const PROMPT = (task, catalog, alreadyDetected) => `You are a classifier that picks which domain skills would help solve a task.
|
|
40
|
+
|
|
41
|
+
Task:
|
|
42
|
+
"""${task}"""
|
|
43
|
+
|
|
44
|
+
Already detected skills (do NOT repeat, but consider the task context they imply):
|
|
45
|
+
${alreadyDetected.length > 0 ? alreadyDetected.join(", ") : "(none)"}
|
|
46
|
+
|
|
47
|
+
From this exact catalog, output a JSON array with the names of 0 to 5 additional skills that would meaningfully help. Output ONLY the JSON array, no prose.
|
|
48
|
+
|
|
49
|
+
Catalog (pick strict matches only):
|
|
50
|
+
${catalog.join(", ")}
|
|
51
|
+
|
|
52
|
+
Rules:
|
|
53
|
+
- Only names from the catalog. Do NOT invent.
|
|
54
|
+
- Prefer precision over recall: empty array is a valid answer when nothing fits.
|
|
55
|
+
- Do NOT include already-detected skills.
|
|
56
|
+
- Respond with a single JSON array, e.g. ["python-data","sql-analysis"]
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
function tryParseArray(raw) {
|
|
60
|
+
if (!raw) return [];
|
|
61
|
+
try {
|
|
62
|
+
const m = String(raw).match(/\[[^\]]*\]/);
|
|
63
|
+
if (!m) return [];
|
|
64
|
+
const parsed = JSON.parse(m[0]);
|
|
65
|
+
if (!Array.isArray(parsed)) return [];
|
|
66
|
+
return parsed.filter((s) => typeof s === "string");
|
|
67
|
+
} catch {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Ask the classifier for additional skills.
|
|
74
|
+
*
|
|
75
|
+
* @param {Object} args
|
|
76
|
+
* @param {string} args.task
|
|
77
|
+
* @param {string[]} args.alreadyDetected
|
|
78
|
+
* @param {Object} args.config - Karajan config
|
|
79
|
+
* @param {Object} [args.logger]
|
|
80
|
+
* @returns {Promise<string[]>}
|
|
81
|
+
*/
|
|
82
|
+
export async function refineSkillsSemantically({ task, alreadyDetected = [], config, logger }) {
|
|
83
|
+
if (!task || typeof task !== "string") return [];
|
|
84
|
+
let provider;
|
|
85
|
+
try {
|
|
86
|
+
provider = resolveRole(config, "triage")?.provider
|
|
87
|
+
|| resolveRole(config, "planner")?.provider
|
|
88
|
+
|| resolveRole(config, "coder")?.provider;
|
|
89
|
+
} catch {
|
|
90
|
+
provider = null;
|
|
91
|
+
}
|
|
92
|
+
if (!provider) {
|
|
93
|
+
logger?.debug?.("semantic-detector: no classifier provider — skipping");
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let agent;
|
|
98
|
+
try {
|
|
99
|
+
agent = createAgent(provider, config, logger);
|
|
100
|
+
} catch (err) {
|
|
101
|
+
logger?.debug?.(`semantic-detector: classifier unavailable (${err.message}) — skipping`);
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
if (!agent || typeof agent.runTask !== "function") {
|
|
105
|
+
logger?.debug?.("semantic-detector: classifier agent has no runTask() — skipping");
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const prompt = PROMPT(task, SEMANTIC_CATALOG, alreadyDetected);
|
|
110
|
+
// KJC-TSK-0413 step D: wrap with Brain Recovery. semantic-detector usa
|
|
111
|
+
// signature legacy `runTask(prompt, opts)` — adapter normaliza al estándar
|
|
112
|
+
// `runTask({ prompt, timeoutMs })` que withBrainRecovery espera.
|
|
113
|
+
const adapter = {
|
|
114
|
+
provider: agent.provider,
|
|
115
|
+
runTask: (args) => agent.runTask(args.prompt, { timeoutMs: args.timeoutMs }),
|
|
116
|
+
};
|
|
117
|
+
let res;
|
|
118
|
+
try {
|
|
119
|
+
res = await withBrainRecovery({
|
|
120
|
+
agent: adapter,
|
|
121
|
+
taskArgs: { prompt, timeoutMs: 30_000 },
|
|
122
|
+
role: "semantic-detector",
|
|
123
|
+
logger,
|
|
124
|
+
});
|
|
125
|
+
} catch (err) {
|
|
126
|
+
logger?.warn?.(`semantic-detector: classifier call failed (${err.message}) — skipping`);
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
if (!res?.ok) {
|
|
130
|
+
// En test env el sleep es no-op así que abort viene rápido. Skip-on-fail
|
|
131
|
+
// sigue siendo el comportamiento — semantic detection es best-effort.
|
|
132
|
+
logger?.debug?.(`semantic-detector: classifier returned not-ok (${res?.recovery?.class || "unknown"}) — skipping`);
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const suggested = tryParseArray(res.output || res.result?.raw || "");
|
|
137
|
+
const allowed = new Set(SEMANTIC_CATALOG);
|
|
138
|
+
const alreadySet = new Set(alreadyDetected.map((s) => s.toLowerCase()));
|
|
139
|
+
return suggested
|
|
140
|
+
.map((s) => String(s).trim())
|
|
141
|
+
.filter((s) => s && allowed.has(s) && !alreadySet.has(s.toLowerCase()))
|
|
142
|
+
.slice(0, 5);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Resolve the effective skills mode from config + flags.
|
|
147
|
+
* Precedence: flags.skillsMode > config.skills.mode > config.testHarness.defaultSkillsMode > "auto".
|
|
148
|
+
*
|
|
149
|
+
* The testHarness default lets the test harness opt out of semantic
|
|
150
|
+
* detection without each orchestrator test having to mock this module.
|
|
151
|
+
* Production code reads `config.testHarness.defaultSkillsMode` only;
|
|
152
|
+
* the legacy global override is documented and exclusively read in
|
|
153
|
+
* src/config/test-harness.js (ESLint rule #557 blocks any reintroduction
|
|
154
|
+
* of `globalThis.__KJ_*` outside that one file). Legacy callers without
|
|
155
|
+
* a fully-loaded config still work because `config.testHarness` is
|
|
156
|
+
* undefined → falls through to `"auto"`.
|
|
157
|
+
*
|
|
158
|
+
* @param {Object} config
|
|
159
|
+
* @param {Object} [flags]
|
|
160
|
+
* @returns {"auto"|"regex"|"semantic"|"none"}
|
|
161
|
+
*/
|
|
162
|
+
export function resolveSkillsMode(config, flags = {}) {
|
|
163
|
+
const defaultMode = config?.testHarness?.defaultSkillsMode || "auto";
|
|
164
|
+
const candidate = flags.skillsMode ?? config?.skills?.mode ?? defaultMode;
|
|
165
|
+
const valid = new Set(["auto", "regex", "semantic", "none"]);
|
|
166
|
+
return valid.has(candidate) ? candidate : "auto";
|
|
167
|
+
}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects needed skills from task description and project files,
|
|
3
|
+
* then auto-installs them via OpenSkills if available.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from "node:fs/promises";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { loadAvailableSkills } from "./skill-loader.js";
|
|
9
|
+
import { isOpenSkillsAvailable, installSkill, removeSkill } from "./openskills-client.js";
|
|
10
|
+
import { isFresh as isCacheFresh, recordInstall as recordSkillInstall } from "./skills-cache.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Known frameworks detectable from package.json dependencies.
|
|
14
|
+
* Maps dependency name to the skill name to search for.
|
|
15
|
+
*/
|
|
16
|
+
const PKG_JSON_FRAMEWORKS = {
|
|
17
|
+
astro: "astro",
|
|
18
|
+
next: "nextjs",
|
|
19
|
+
react: "react",
|
|
20
|
+
"react-dom": "react",
|
|
21
|
+
vue: "vue",
|
|
22
|
+
svelte: "svelte",
|
|
23
|
+
"@angular/core": "angular",
|
|
24
|
+
express: "express",
|
|
25
|
+
fastify: "fastify",
|
|
26
|
+
"@nestjs/core": "nestjs",
|
|
27
|
+
// DB / ORM
|
|
28
|
+
prisma: "prisma",
|
|
29
|
+
"@prisma/client": "prisma",
|
|
30
|
+
knex: "sql-analysis",
|
|
31
|
+
sequelize: "sql-analysis",
|
|
32
|
+
typeorm: "sql-analysis",
|
|
33
|
+
mongoose: "mongodb",
|
|
34
|
+
"better-sqlite3": "sql-analysis",
|
|
35
|
+
// Testing
|
|
36
|
+
vitest: "vitest-patterns",
|
|
37
|
+
jest: "jest-patterns",
|
|
38
|
+
"@playwright/test": "playwright-patterns",
|
|
39
|
+
cypress: "cypress-patterns",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Python dependency names (from requirements.txt or pyproject.toml) mapping
|
|
44
|
+
* to their canonical skill.
|
|
45
|
+
*/
|
|
46
|
+
const PYTHON_DEPS = {
|
|
47
|
+
pandas: "python-data",
|
|
48
|
+
numpy: "python-data",
|
|
49
|
+
scipy: "python-data",
|
|
50
|
+
"scikit-learn": "python-ml",
|
|
51
|
+
sklearn: "python-ml",
|
|
52
|
+
tensorflow: "python-ml",
|
|
53
|
+
torch: "python-ml",
|
|
54
|
+
pytorch: "python-ml",
|
|
55
|
+
pytest: "pytest-patterns",
|
|
56
|
+
django: "python-django",
|
|
57
|
+
flask: "python-flask",
|
|
58
|
+
fastapi: "python-fastapi",
|
|
59
|
+
sqlalchemy: "sql-analysis",
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Language markers: file presence maps to a skill name.
|
|
64
|
+
* Reuses the same concept as src/utils/project-detect.js LANGUAGE_MARKERS.
|
|
65
|
+
*/
|
|
66
|
+
const LANGUAGE_FILE_MARKERS = [
|
|
67
|
+
{ file: "pom.xml", skill: "java" },
|
|
68
|
+
{ file: "build.gradle", skill: "java" },
|
|
69
|
+
{ file: "build.gradle.kts", skill: "kotlin" },
|
|
70
|
+
{ file: "go.mod", skill: "go" },
|
|
71
|
+
{ file: "Cargo.toml", skill: "rust" },
|
|
72
|
+
{ file: "pyproject.toml", skill: "python" },
|
|
73
|
+
{ file: "requirements.txt", skill: "python" },
|
|
74
|
+
{ file: "setup.py", skill: "python" },
|
|
75
|
+
{ file: "Gemfile", skill: "ruby" },
|
|
76
|
+
{ file: "pubspec.yaml", skill: "flutter" },
|
|
77
|
+
{ file: "Package.swift", skill: "swift" },
|
|
78
|
+
{ file: "phpunit.xml", skill: "php" },
|
|
79
|
+
{ file: "composer.json", skill: "php" },
|
|
80
|
+
{ file: "mix.exs", skill: "elixir" },
|
|
81
|
+
{ file: "rebar.config", skill: "erlang" },
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* File EXTENSIONS whose presence anywhere under projectDir adds a skill.
|
|
86
|
+
* Uses a shallow-recursive glob with a cutoff to avoid walking node_modules.
|
|
87
|
+
*/
|
|
88
|
+
const EXTENSION_MARKERS = [
|
|
89
|
+
{ ext: ".csproj", skill: "dotnet" },
|
|
90
|
+
{ ext: ".sln", skill: "dotnet" },
|
|
91
|
+
{ ext: ".ipynb", skill: "python-data" },
|
|
92
|
+
{ ext: ".prisma", skill: "prisma" },
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Files detected as "SQL / database schema" when they exist at repo root.
|
|
97
|
+
* Used in addition to EXTENSION_MARKERS for *.sql anywhere in the repo.
|
|
98
|
+
*/
|
|
99
|
+
const SQL_MARKER_FILES = [
|
|
100
|
+
"schema.sql",
|
|
101
|
+
"schema.prisma",
|
|
102
|
+
"migrations",
|
|
103
|
+
"db/migrate",
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const DIRECTORIES_TO_SKIP = new Set([
|
|
107
|
+
"node_modules", ".git", ".kj", ".karajan", "dist", "build", ".next", "out",
|
|
108
|
+
"target", ".venv", "venv", "__pycache__", ".vitest-cache", "coverage",
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Patterns to detect framework/skill mentions in the task text.
|
|
113
|
+
* Each entry: regex pattern (case-insensitive) -> skill name.
|
|
114
|
+
*/
|
|
115
|
+
const TASK_TEXT_PATTERNS = [
|
|
116
|
+
{ pattern: /\bastro\b/i, skill: "astro" },
|
|
117
|
+
{ pattern: /\bnext\.?js\b/i, skill: "nextjs" },
|
|
118
|
+
{ pattern: /\breact\b/i, skill: "react" },
|
|
119
|
+
{ pattern: /\bvue\b/i, skill: "vue" },
|
|
120
|
+
{ pattern: /\bsvelte\b/i, skill: "svelte" },
|
|
121
|
+
{ pattern: /\bangular\b/i, skill: "angular" },
|
|
122
|
+
{ pattern: /\bexpress\b/i, skill: "express" },
|
|
123
|
+
{ pattern: /\bfastify\b/i, skill: "fastify" },
|
|
124
|
+
{ pattern: /\bnest\.?js\b/i, skill: "nestjs" },
|
|
125
|
+
{ pattern: /\bjava\b/i, skill: "java" },
|
|
126
|
+
{ pattern: /\bkotlin\b/i, skill: "kotlin" },
|
|
127
|
+
{ pattern: /\bgo(?:lang)?\b/i, skill: "go" },
|
|
128
|
+
{ pattern: /\brust\b/i, skill: "rust" },
|
|
129
|
+
{ pattern: /\bpython\b/i, skill: "python" },
|
|
130
|
+
{ pattern: /\bdjango\b/i, skill: "python" },
|
|
131
|
+
{ pattern: /\bflask\b/i, skill: "python" },
|
|
132
|
+
{ pattern: /\bruby\b/i, skill: "ruby" },
|
|
133
|
+
{ pattern: /\bflutter\b/i, skill: "flutter" },
|
|
134
|
+
{ pattern: /\bswift\b/i, skill: "swift" },
|
|
135
|
+
{ pattern: /\bphp\b/i, skill: "php" },
|
|
136
|
+
{ pattern: /\bSQL\b/i, skill: "sql-analysis" },
|
|
137
|
+
{ pattern: /\bquer(?:y|ies)\b/i, skill: "sql-analysis" },
|
|
138
|
+
{ pattern: /\bdatabase\b/i, skill: "sql-analysis" },
|
|
139
|
+
{ pattern: /\bCSV\b/i, skill: "csv-transform" },
|
|
140
|
+
{ pattern: /\btransform\b/i, skill: "csv-transform" },
|
|
141
|
+
{ pattern: /\bparse\b/i, skill: "csv-transform" },
|
|
142
|
+
{ pattern: /\breport\b/i, skill: "data-report" },
|
|
143
|
+
{ pattern: /\banalysis\b/i, skill: "data-report" },
|
|
144
|
+
{ pattern: /\bfindings\b/i, skill: "data-report" },
|
|
145
|
+
// Frontend/backend broad categories
|
|
146
|
+
{ pattern: /\bfrontend\b/i, skill: "frontend-design" },
|
|
147
|
+
{ pattern: /\bCSS\b/i, skill: "frontend-design" },
|
|
148
|
+
{ pattern: /\bHTML\b/i, skill: "frontend-design" },
|
|
149
|
+
{ pattern: /\bbackend\b/i, skill: "express" },
|
|
150
|
+
{ pattern: /\bnode\.?js\b/i, skill: "express" },
|
|
151
|
+
{ pattern: /\bAPI\b/, skill: "express" },
|
|
152
|
+
{ pattern: /\bwebsocket\b/i, skill: "express" },
|
|
153
|
+
{ pattern: /\breal[- ]time\b/i, skill: "express" },
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Analyze the task and project to determine what skills might be needed.
|
|
158
|
+
*
|
|
159
|
+
* @param {string} task - The task description text.
|
|
160
|
+
* @param {string} projectDir - Absolute path to project root.
|
|
161
|
+
* @param {{ includeExtensions?: boolean, maxDepth?: number }} [options]
|
|
162
|
+
* - includeExtensions: scan for file extensions (.csproj, .ipynb, .sql...)
|
|
163
|
+
* that signal a stack. Default true. Disable to avoid the shallow walk
|
|
164
|
+
* in very large repos or in tests.
|
|
165
|
+
* - maxDepth: bound the walk (default 3 directories deep).
|
|
166
|
+
* @returns {Promise<string[]>} Array of unique skill names to search for.
|
|
167
|
+
*/
|
|
168
|
+
export async function detectNeededSkills(task, projectDir, options = {}) {
|
|
169
|
+
const { includeExtensions = true, maxDepth = 3 } = options;
|
|
170
|
+
const needed = new Set();
|
|
171
|
+
|
|
172
|
+
// 1. Scan package.json for known frameworks and JS-ecosystem deps
|
|
173
|
+
if (projectDir) {
|
|
174
|
+
try {
|
|
175
|
+
const pkgRaw = await fs.readFile(path.join(projectDir, "package.json"), "utf8");
|
|
176
|
+
const pkg = JSON.parse(pkgRaw);
|
|
177
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
178
|
+
for (const [dep, skill] of Object.entries(PKG_JSON_FRAMEWORKS)) {
|
|
179
|
+
if (allDeps[dep]) {
|
|
180
|
+
needed.add(skill);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
} catch { /* no package.json or parse error — skip */ }
|
|
184
|
+
|
|
185
|
+
// 2. Language marker files at repo root
|
|
186
|
+
for (const marker of LANGUAGE_FILE_MARKERS) {
|
|
187
|
+
try {
|
|
188
|
+
await fs.access(path.join(projectDir, marker.file));
|
|
189
|
+
needed.add(marker.skill);
|
|
190
|
+
} catch { /* file not found — skip */ }
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// 3. Python deps from requirements.txt / pyproject.toml
|
|
194
|
+
await collectPythonDeps(projectDir, needed);
|
|
195
|
+
|
|
196
|
+
// 4. File extension markers (.csproj, .ipynb, .prisma, *.sql)
|
|
197
|
+
if (includeExtensions) {
|
|
198
|
+
await collectExtensionMarkers(projectDir, maxDepth, needed);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// 5. SQL / DB schema markers at well-known paths
|
|
202
|
+
for (const candidate of SQL_MARKER_FILES) {
|
|
203
|
+
try {
|
|
204
|
+
await fs.access(path.join(projectDir, candidate));
|
|
205
|
+
needed.add("sql-analysis");
|
|
206
|
+
} catch { /* skip */ }
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// 6. Task text patterns
|
|
211
|
+
if (task) {
|
|
212
|
+
for (const { pattern, skill } of TASK_TEXT_PATTERNS) {
|
|
213
|
+
if (pattern.test(task)) {
|
|
214
|
+
needed.add(skill);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return Array.from(needed);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async function collectPythonDeps(projectDir, needed) {
|
|
223
|
+
// requirements.txt — each non-comment line is "name==ver" or "name>=ver"
|
|
224
|
+
try {
|
|
225
|
+
const raw = await fs.readFile(path.join(projectDir, "requirements.txt"), "utf8");
|
|
226
|
+
for (const line of raw.split("\n")) {
|
|
227
|
+
const trimmed = line.trim().split("#")[0].trim();
|
|
228
|
+
if (!trimmed) continue;
|
|
229
|
+
const name = trimmed.split(/[<>=!~[\s]/)[0].toLowerCase();
|
|
230
|
+
const skill = PYTHON_DEPS[name];
|
|
231
|
+
if (skill) needed.add(skill);
|
|
232
|
+
}
|
|
233
|
+
} catch { /* no requirements.txt */ }
|
|
234
|
+
|
|
235
|
+
// pyproject.toml — simple heuristic scan for dependency names. A full TOML
|
|
236
|
+
// parse would need a dep; we just look for quoted names, which is fine.
|
|
237
|
+
try {
|
|
238
|
+
const raw = await fs.readFile(path.join(projectDir, "pyproject.toml"), "utf8");
|
|
239
|
+
const lower = raw.toLowerCase();
|
|
240
|
+
for (const [name, skill] of Object.entries(PYTHON_DEPS)) {
|
|
241
|
+
if (lower.includes(`"${name}"`) || lower.includes(`'${name}'`)) {
|
|
242
|
+
needed.add(skill);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
} catch { /* no pyproject.toml */ }
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async function collectExtensionMarkers(projectDir, maxDepth, needed) {
|
|
249
|
+
// Build a lookup by extension for fast decisions.
|
|
250
|
+
const byExt = new Map(EXTENSION_MARKERS.map((m) => [m.ext, m.skill]));
|
|
251
|
+
const extensions = new Set(byExt.keys());
|
|
252
|
+
extensions.add(".sql");
|
|
253
|
+
let sqlFound = false;
|
|
254
|
+
|
|
255
|
+
async function walk(dir, depth) {
|
|
256
|
+
if (depth > maxDepth) return;
|
|
257
|
+
let entries;
|
|
258
|
+
try {
|
|
259
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
260
|
+
} catch {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
for (const entry of entries) {
|
|
264
|
+
if (entry.isDirectory()) {
|
|
265
|
+
if (DIRECTORIES_TO_SKIP.has(entry.name)) continue;
|
|
266
|
+
if (entry.name.startsWith(".")) continue;
|
|
267
|
+
await walk(path.join(dir, entry.name), depth + 1);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (!entry.isFile()) continue;
|
|
271
|
+
const ext = path.extname(entry.name).toLowerCase();
|
|
272
|
+
if (!extensions.has(ext)) continue;
|
|
273
|
+
if (ext === ".sql") {
|
|
274
|
+
sqlFound = true;
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const skill = byExt.get(ext);
|
|
278
|
+
if (skill) needed.add(skill);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
await walk(projectDir, 0);
|
|
283
|
+
if (sqlFound) needed.add("sql-analysis");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Auto-install needed skills that are not yet installed.
|
|
288
|
+
*
|
|
289
|
+
* When the `openskills` CLI is not available, this function degrades
|
|
290
|
+
* gracefully: it returns `osAvailable: false` and `wouldHaveUsed` with the
|
|
291
|
+
* list of skills that would have been installed if the CLI had been present.
|
|
292
|
+
* Callers (e.g. the orchestrator) can surface this info in the session
|
|
293
|
+
* report without blocking execution.
|
|
294
|
+
*
|
|
295
|
+
* @param {string[]} neededSkills - Skill names to ensure are installed.
|
|
296
|
+
* @param {string} projectDir - Absolute path to project root.
|
|
297
|
+
* @returns {Promise<{
|
|
298
|
+
* installed: string[],
|
|
299
|
+
* failed: string[],
|
|
300
|
+
* alreadyInstalled: string[],
|
|
301
|
+
* wouldHaveUsed: string[],
|
|
302
|
+
* osAvailable: boolean
|
|
303
|
+
* }>}
|
|
304
|
+
*/
|
|
305
|
+
export async function autoInstallSkills(neededSkills, projectDir) {
|
|
306
|
+
const result = { installed: [], failed: [], alreadyInstalled: [], wouldHaveUsed: [], osAvailable: true };
|
|
307
|
+
|
|
308
|
+
if (!neededSkills || neededSkills.length === 0) {
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Check which skills are already installed locally
|
|
313
|
+
const existingSkills = await loadAvailableSkills(projectDir);
|
|
314
|
+
const existingNames = new Set(existingSkills.map(s => s.name.toLowerCase()));
|
|
315
|
+
|
|
316
|
+
// Check if OpenSkills is available
|
|
317
|
+
const osAvailable = await isOpenSkillsAvailable();
|
|
318
|
+
if (!osAvailable) {
|
|
319
|
+
result.osAvailable = false;
|
|
320
|
+
// Report what we would have installed so the session report can surface
|
|
321
|
+
// the recommendation — "install openskills globally to enable: X, Y, Z".
|
|
322
|
+
result.wouldHaveUsed = neededSkills.filter((s) => !existingNames.has(s.toLowerCase()));
|
|
323
|
+
return result;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
for (const skillName of neededSkills) {
|
|
327
|
+
if (existingNames.has(skillName.toLowerCase())) {
|
|
328
|
+
result.alreadyInstalled.push(skillName);
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Cache short-circuit: if we installed this skill in the last 7 days,
|
|
333
|
+
// assume it's still good and skip the `npx openskills install` call
|
|
334
|
+
// (which can take 10-30s). Running sessions can opt out by clearing
|
|
335
|
+
// the cache with `kj skills clear-cache`.
|
|
336
|
+
if (await isCacheFresh(skillName)) {
|
|
337
|
+
result.alreadyInstalled.push(skillName);
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
const installResult = await installSkill(skillName, { projectDir });
|
|
343
|
+
if (installResult.ok) {
|
|
344
|
+
const installedName = installResult.name || skillName;
|
|
345
|
+
result.installed.push(installedName);
|
|
346
|
+
await recordSkillInstall(installedName, { source: skillName }).catch(() => {});
|
|
347
|
+
} else {
|
|
348
|
+
result.failed.push(skillName);
|
|
349
|
+
}
|
|
350
|
+
} catch { /* skill install threw */
|
|
351
|
+
result.failed.push(skillName);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return result;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Remove skills that were auto-installed during this session.
|
|
360
|
+
* @param {string[]} skillNames - Skill names to remove.
|
|
361
|
+
* @param {string} projectDir - Absolute path to project root.
|
|
362
|
+
* @returns {Promise<{removed: string[], failed: string[]}>}
|
|
363
|
+
*/
|
|
364
|
+
export async function cleanupAutoInstalledSkills(skillNames, projectDir) {
|
|
365
|
+
const result = { removed: [], failed: [] };
|
|
366
|
+
|
|
367
|
+
if (!skillNames || skillNames.length === 0) {
|
|
368
|
+
return result;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
for (const name of skillNames) {
|
|
372
|
+
try {
|
|
373
|
+
const removeResult = await removeSkill(name, { projectDir });
|
|
374
|
+
if (removeResult.ok) {
|
|
375
|
+
result.removed.push(name);
|
|
376
|
+
} else {
|
|
377
|
+
result.failed.push(name);
|
|
378
|
+
}
|
|
379
|
+
} catch { /* skill removal threw */
|
|
380
|
+
result.failed.push(name);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
return result;
|
|
385
|
+
}
|