@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,124 @@
|
|
|
1
|
+
export const TELEMETRY_ENDPOINT = "https://karajan-code.web.app/api/telemetry";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Build the exact JSON payload that would be POSTed for an event.
|
|
5
|
+
* Pure function: deterministic given (eventName, data) — exposed so
|
|
6
|
+
* `kj telemetry preview` can render the literal bytes the backend
|
|
7
|
+
* receives without performing any network call.
|
|
8
|
+
*
|
|
9
|
+
* The `data.version` field is folded into `v`; the rest of the
|
|
10
|
+
* event-specific keys ride through `...data` after the common ones,
|
|
11
|
+
* matching the order sent over the wire.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} eventName
|
|
14
|
+
* @param {object} [data]
|
|
15
|
+
* @returns {object}
|
|
16
|
+
*/
|
|
17
|
+
export function buildTelemetryPayload(eventName, data = {}) {
|
|
18
|
+
const { version, ...rest } = data;
|
|
19
|
+
return {
|
|
20
|
+
event: eventName,
|
|
21
|
+
v: version || "unknown",
|
|
22
|
+
os: process.platform,
|
|
23
|
+
node: process.version,
|
|
24
|
+
ts: Date.now(),
|
|
25
|
+
...rest
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Φ0-H (KJC-TSK-0526): aggregate cache-hit ratio per role from the budget
|
|
31
|
+
* summary the orchestrator already builds. Returns `{ cached_pct_coder,
|
|
32
|
+
* cached_pct_reviewer, cached_pct_total }` with values rounded to one
|
|
33
|
+
* decimal, or `null` per slot when there is no measurable input (rather
|
|
34
|
+
* than `0`, so the backend can distinguish "no cache" from "no signal").
|
|
35
|
+
*
|
|
36
|
+
* Provider-agnostic by design: the BudgetTracker entries already
|
|
37
|
+
* normalise `cached_tokens` for Anthropic (`cache_read_input_tokens`),
|
|
38
|
+
* OpenAI / Codex (`prompt_tokens_details.cached_tokens`), Gemini
|
|
39
|
+
* (`cachedContentTokenCount`) and the LiteLLM-routed providers
|
|
40
|
+
* (aider, opencode), so this helper does not need to know which
|
|
41
|
+
* provider produced the run.
|
|
42
|
+
*
|
|
43
|
+
* @param {{ breakdown_by_role?: object, total_cached_tokens?: number } | null | undefined} summary
|
|
44
|
+
* @returns {{ cached_pct_coder: number|null, cached_pct_reviewer: number|null, cached_pct_total: number|null }}
|
|
45
|
+
*/
|
|
46
|
+
export function computeCachedPct(summary) {
|
|
47
|
+
const empty = { cached_pct_coder: null, cached_pct_reviewer: null, cached_pct_total: null };
|
|
48
|
+
if (!summary || typeof summary !== "object") return empty;
|
|
49
|
+
const ratio = (cached, tokensIn) => {
|
|
50
|
+
const c = Number(cached);
|
|
51
|
+
const t = Number(tokensIn);
|
|
52
|
+
if (!Number.isFinite(c) || !Number.isFinite(t) || t <= 0 || c < 0) return null;
|
|
53
|
+
return Math.round((c / t) * 1000) / 10;
|
|
54
|
+
};
|
|
55
|
+
const byRole = summary.breakdown_by_role || {};
|
|
56
|
+
const coder = byRole.coder || null;
|
|
57
|
+
const reviewer = byRole.reviewer || null;
|
|
58
|
+
let totalCached = 0;
|
|
59
|
+
let totalIn = 0;
|
|
60
|
+
for (const role of Object.keys(byRole)) {
|
|
61
|
+
const r = byRole[role];
|
|
62
|
+
totalCached += Number(r?.cached_tokens || 0);
|
|
63
|
+
totalIn += Number(r?.tokens_in || 0);
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
cached_pct_coder: coder ? ratio(coder.cached_tokens, coder.tokens_in) : null,
|
|
67
|
+
cached_pct_reviewer: reviewer ? ratio(reviewer.cached_tokens, reviewer.tokens_in) : null,
|
|
68
|
+
cached_pct_total: ratio(totalCached, totalIn)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Send an anonymous telemetry event. Non-blocking, fire-and-forget.
|
|
74
|
+
* Never throws, never blocks the pipeline.
|
|
75
|
+
*
|
|
76
|
+
* @param {string} eventName - Event name (e.g. "install", "pipeline_complete", "cli_command")
|
|
77
|
+
* @param {object} data - Event-specific data
|
|
78
|
+
* @param {object} [config] - Karajan config (checked for telemetry opt-out)
|
|
79
|
+
*/
|
|
80
|
+
export async function sendTelemetryEvent(eventName, data, config) {
|
|
81
|
+
if (!isTelemetryEnabled(config)) return;
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const payload = buildTelemetryPayload(eventName, data);
|
|
85
|
+
const controller = new AbortController();
|
|
86
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
87
|
+
try {
|
|
88
|
+
await fetch(TELEMETRY_ENDPOINT, {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: { "Content-Type": "application/json" },
|
|
91
|
+
body: JSON.stringify(payload),
|
|
92
|
+
signal: controller.signal
|
|
93
|
+
});
|
|
94
|
+
} finally {
|
|
95
|
+
clearTimeout(timeout);
|
|
96
|
+
}
|
|
97
|
+
} catch (err) {
|
|
98
|
+
// Audit follow-up: was a silent catch{}. Telemetry MUST stay
|
|
99
|
+
// fire-and-forget (never block the user's pipeline, never throw),
|
|
100
|
+
// but completely silent failures hide DNS/network bugs that matter
|
|
101
|
+
// when debugging the telemetry pipeline itself. Surface the error
|
|
102
|
+
// to stderr only when KJ_DEBUG=1 is explicitly set, so normal runs
|
|
103
|
+
// are still silent.
|
|
104
|
+
if (process.env.KJ_DEBUG === "1") {
|
|
105
|
+
// Stderr (not console — telemetry runs from CLI commands and is
|
|
106
|
+
// legitimate user-visible diagnostic output under KJ_DEBUG).
|
|
107
|
+
process.stderr.write(`[telemetry-debug] ${eventName}: ${err.message}\n`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Check if telemetry is enabled (opt-in model).
|
|
114
|
+
*
|
|
115
|
+
* Returns true ONLY when the user explicitly answered "yes" in the
|
|
116
|
+
* `kj init` wizard and we persisted `telemetry: true` to their config.
|
|
117
|
+
* Anything else — undefined, null, missing key, false — disables sending.
|
|
118
|
+
*
|
|
119
|
+
* @param {object} [config] - Karajan config
|
|
120
|
+
* @returns {boolean}
|
|
121
|
+
*/
|
|
122
|
+
export function isTelemetryEnabled(config) {
|
|
123
|
+
return config?.telemetry === true;
|
|
124
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { isSea, getAsset } from "node:sea";
|
|
5
|
+
import { getKarajanHome } from "./paths.js";
|
|
6
|
+
|
|
7
|
+
// npm install / source tree: the real templates/ directory next to src/.
|
|
8
|
+
const SOURCE_ROOT = path.resolve(
|
|
9
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
10
|
+
"..",
|
|
11
|
+
"..",
|
|
12
|
+
"templates",
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const INDEX_ASSET = "templates-index.json";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Root directory of the built-in templates (KJC-BUG-0104).
|
|
19
|
+
*
|
|
20
|
+
* The SEA binary ships only the JS bundle — templates/ never travels as
|
|
21
|
+
* files, and `import.meta.dirname`-relative resolution lands on the
|
|
22
|
+
* binary's own directory (e.g. `$HOME/templates/skills` → ENOENT). In SEA
|
|
23
|
+
* builds the templates travel as SEA assets (see scripts/build-sea.mjs);
|
|
24
|
+
* they are extracted once per version into ~/.karajan/embedded-templates/
|
|
25
|
+
* and served from there, so every fs-based consumer keeps working.
|
|
26
|
+
*/
|
|
27
|
+
export function getTemplatesRoot() {
|
|
28
|
+
if (!isSeaRuntime()) return SOURCE_ROOT;
|
|
29
|
+
const index = JSON.parse(getAsset(INDEX_ASSET, "utf8"));
|
|
30
|
+
const destRoot = path.join(getKarajanHome(), "embedded-templates", index.version);
|
|
31
|
+
return extractEmbeddedTemplates({
|
|
32
|
+
destRoot,
|
|
33
|
+
files: index.files,
|
|
34
|
+
readAsset: (rel) => getAsset(`templates/${rel}`, "utf8"),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isSeaRuntime() {
|
|
39
|
+
try {
|
|
40
|
+
return isSea();
|
|
41
|
+
} catch {
|
|
42
|
+
// isSea() unexpectedly threw ⇒ treat as npm / source tree, never block.
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Extract the embedded template files into destRoot (idempotent: a
|
|
49
|
+
* .complete marker skips re-extraction). Exported for unit testing.
|
|
50
|
+
*/
|
|
51
|
+
export function extractEmbeddedTemplates({ destRoot, files, readAsset }) {
|
|
52
|
+
const marker = path.join(destRoot, ".complete");
|
|
53
|
+
if (fs.existsSync(marker)) return destRoot;
|
|
54
|
+
for (const rel of files) {
|
|
55
|
+
const dest = path.join(destRoot, rel);
|
|
56
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
57
|
+
fs.writeFileSync(dest, readAsset(rel));
|
|
58
|
+
}
|
|
59
|
+
fs.writeFileSync(marker, "");
|
|
60
|
+
return destRoot;
|
|
61
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// KJC-TSK-0375 PR2 — Extract structured tool calls from an agent transcript.
|
|
2
|
+
//
|
|
3
|
+
// The ToolCorrectnessJudgeRole (PR1) consumes a list of `{tool, args}`
|
|
4
|
+
// objects. The coder writes a raw transcript (provider-dependent format) to
|
|
5
|
+
// disk per iteration. This module bridges the two: parse the transcript,
|
|
6
|
+
// return the ordered list of tool invocations.
|
|
7
|
+
//
|
|
8
|
+
// Provider-agnostic interface; Claude stream-json is the only format
|
|
9
|
+
// implemented today. New providers add a branch below — keep parsers
|
|
10
|
+
// pure (no I/O), so the role tests can mock transcripts trivially.
|
|
11
|
+
|
|
12
|
+
const PROVIDER_PARSERS = {
|
|
13
|
+
claude: parseClaudeStreamJson,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Extract tool calls from a transcript string.
|
|
18
|
+
*
|
|
19
|
+
* @param {object} args
|
|
20
|
+
* @param {string} args.transcript - raw agent output (stdout/stderr buffer).
|
|
21
|
+
* @param {string} [args.provider] - "claude" (default). Unknown returns [].
|
|
22
|
+
* @returns {Array<{tool:string, args:object}>}
|
|
23
|
+
*/
|
|
24
|
+
export function extractToolCalls({ transcript, provider = "claude" } = {}) {
|
|
25
|
+
if (typeof transcript !== "string" || transcript.length === 0) return [];
|
|
26
|
+
const parser = PROVIDER_PARSERS[provider];
|
|
27
|
+
if (!parser) return [];
|
|
28
|
+
return parser(transcript);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Claude emits one JSON event per line. We care about `assistant` events
|
|
32
|
+
// whose `message.content` is an array containing `tool_use` blocks with
|
|
33
|
+
// `{type:"tool_use", name, input}`. Lines that fail to parse, that are
|
|
34
|
+
// not `assistant`, or whose content is not an array are silently skipped:
|
|
35
|
+
// the transcript also carries `system`, `result`, `rate_limit_event`, etc.
|
|
36
|
+
function parseClaudeStreamJson(transcript) {
|
|
37
|
+
const out = [];
|
|
38
|
+
for (const raw of transcript.split("\n")) {
|
|
39
|
+
const line = raw.trim();
|
|
40
|
+
if (!line || line[0] !== "{") continue;
|
|
41
|
+
let obj;
|
|
42
|
+
try { obj = JSON.parse(line); } catch { continue; }
|
|
43
|
+
if (obj?.type !== "assistant") continue;
|
|
44
|
+
const content = obj?.message?.content;
|
|
45
|
+
if (!Array.isArray(content)) continue;
|
|
46
|
+
for (const block of content) {
|
|
47
|
+
if (block?.type === "tool_use" && typeof block.name === "string") {
|
|
48
|
+
out.push({
|
|
49
|
+
tool: block.name,
|
|
50
|
+
args: block.input && typeof block.input === "object" ? block.input : {},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tool-governor — resource governance for external tools launched by kj
|
|
3
|
+
* (KJC-TSK-0668), born from a real semgrep CPU storm: single-flight across
|
|
4
|
+
* processes (pid-stamped lockfile, stale locks stolen), jobs cap (half the
|
|
5
|
+
* CPUs), nice +10 best-effort, and hard timeouts that kill the PROCESS TREE
|
|
6
|
+
* (own process group on POSIX). In-process cousin: async-lock.js.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import os from "node:os";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
|
|
14
|
+
const DEFAULT_LOCKS_DIR = path.join(os.homedir(), ".karajan", "locks");
|
|
15
|
+
const NICENESS = 10;
|
|
16
|
+
|
|
17
|
+
/** Parallelism cap for scanner `--jobs` flags: half the CPUs, min 1. */
|
|
18
|
+
export function jobsCap(cpuCount = os.cpus().length) {
|
|
19
|
+
return Math.max(1, Math.floor(cpuCount / 2));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function isPidAlive(pid) {
|
|
23
|
+
try {
|
|
24
|
+
process.kill(pid, 0);
|
|
25
|
+
return true;
|
|
26
|
+
} catch (err) {
|
|
27
|
+
return err.code === "EPERM"; // alive but owned by another user
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Machine-wide lock for `tool` → {release}; ELOCKTIMEOUT if the live holder outlasts `timeoutMs`. */
|
|
32
|
+
export async function acquireToolLock(tool, { locksDir = DEFAULT_LOCKS_DIR, timeoutMs = 180_000, pollMs = 500 } = {}) {
|
|
33
|
+
fs.mkdirSync(locksDir, { recursive: true });
|
|
34
|
+
const lockPath = path.join(locksDir, `${tool}.lock`);
|
|
35
|
+
const deadline = Date.now() + timeoutMs;
|
|
36
|
+
for (;;) {
|
|
37
|
+
try {
|
|
38
|
+
// wx = atomic create-or-fail: the filesystem is the arbiter.
|
|
39
|
+
const fd = fs.openSync(lockPath, "wx");
|
|
40
|
+
fs.writeSync(fd, JSON.stringify({ pid: process.pid, startedAt: new Date().toISOString() }));
|
|
41
|
+
fs.closeSync(fd);
|
|
42
|
+
return { release: () => fs.rmSync(lockPath, { force: true }) };
|
|
43
|
+
} catch (err) {
|
|
44
|
+
if (err.code !== "EEXIST") throw err;
|
|
45
|
+
let holder = null;
|
|
46
|
+
try {
|
|
47
|
+
holder = JSON.parse(fs.readFileSync(lockPath, "utf8"));
|
|
48
|
+
} catch { /* unreadable → stale */ }
|
|
49
|
+
if (!holder || !Number.isInteger(holder.pid) || !isPidAlive(holder.pid)) {
|
|
50
|
+
fs.rmSync(lockPath, { force: true });
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (Date.now() >= deadline) {
|
|
54
|
+
const e = new Error(`${tool} is already running (pid ${holder.pid}, since ${holder.startedAt}) — gave up waiting after ${timeoutMs}ms`);
|
|
55
|
+
e.code = "ELOCKTIMEOUT";
|
|
56
|
+
throw e;
|
|
57
|
+
}
|
|
58
|
+
await new Promise((r) => setTimeout(r, pollMs));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Governed spawn: own process group (POSIX), lowered priority, timeout kills
|
|
65
|
+
* the whole tree. Rejections mirror execFile's contract (err.code /
|
|
66
|
+
* err.killed / err.stdout) so scanner collectors keep their error handling.
|
|
67
|
+
*/
|
|
68
|
+
export function governedExecFile(bin, args, { cwd, timeout = 0, maxBuffer = 16 * 1024 * 1024, niceness = NICENESS } = {}) {
|
|
69
|
+
return new Promise((resolve, reject) => {
|
|
70
|
+
const posix = process.platform !== "win32";
|
|
71
|
+
const child = spawn(bin, args, { cwd, detached: posix, stdio: ["ignore", "pipe", "pipe"] });
|
|
72
|
+
let stdout = "";
|
|
73
|
+
let stderr = "";
|
|
74
|
+
let killedByGovernor = false, timer = null;
|
|
75
|
+
const killTree = () => {
|
|
76
|
+
killedByGovernor = true;
|
|
77
|
+
try {
|
|
78
|
+
if (posix) process.kill(-child.pid, "SIGKILL");
|
|
79
|
+
else child.kill("SIGKILL");
|
|
80
|
+
} catch { /* tree already gone */ }
|
|
81
|
+
};
|
|
82
|
+
if (timeout > 0) timer = setTimeout(killTree, timeout);
|
|
83
|
+
child.on("spawn", () => {
|
|
84
|
+
try {
|
|
85
|
+
os.setPriority(child.pid, niceness);
|
|
86
|
+
} catch { /* best-effort */ }
|
|
87
|
+
});
|
|
88
|
+
const bufferBlown = () => stdout.length + stderr.length > maxBuffer;
|
|
89
|
+
child.stdout.on("data", (d) => { stdout += d; if (bufferBlown()) killTree(); });
|
|
90
|
+
child.stderr.on("data", (d) => { stderr += d; if (bufferBlown()) killTree(); });
|
|
91
|
+
child.on("error", (err) => {
|
|
92
|
+
if (timer) clearTimeout(timer);
|
|
93
|
+
reject(Object.assign(err, { stdout, stderr }));
|
|
94
|
+
});
|
|
95
|
+
child.on("close", (code) => {
|
|
96
|
+
if (timer) clearTimeout(timer);
|
|
97
|
+
if (killedByGovernor) {
|
|
98
|
+
reject(Object.assign(new Error(`${bin} killed by governor after ${timeout}ms (process tree included)`), { killed: true, stdout, stderr }));
|
|
99
|
+
} else if (code === 0) {
|
|
100
|
+
resolve({ stdout, stderr });
|
|
101
|
+
} else {
|
|
102
|
+
reject(Object.assign(new Error(`${bin} exited with code ${code}`), { code, stdout, stderr }));
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Lock + governed exec + guaranteed release. `opts.bin` overrides the executable. */
|
|
109
|
+
export async function runGoverned(tool, args, opts = {}) {
|
|
110
|
+
const lock = await acquireToolLock(tool, opts.lock);
|
|
111
|
+
try {
|
|
112
|
+
return await governedExecFile(opts.bin || tool, args, opts);
|
|
113
|
+
} finally {
|
|
114
|
+
lock.release();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Executor primitives for `kj install-tools` (KJC-TSK-0606).
|
|
2
|
+
//
|
|
3
|
+
// Two ways to run an install step:
|
|
4
|
+
// · runInstallCommand(cmd) — captured: stdout/stderr collected,
|
|
5
|
+
// for non-privileged commands.
|
|
6
|
+
// · runInstallCommand(cmd, {interactive}) — tty inherited: the child owns the
|
|
7
|
+
// terminal so `sudo` prompts the user
|
|
8
|
+
// directly. kj NEVER sees the password.
|
|
9
|
+
//
|
|
10
|
+
// And a downloader for tools shipped as a single static binary (osv-scanner,
|
|
11
|
+
// semgrep) when no package manager is available: fetch → temp file → chmod +x →
|
|
12
|
+
// atomic rename into ~/.local/bin. On any failure it leaves no partial file.
|
|
13
|
+
|
|
14
|
+
import { execFile, spawn } from "node:child_process";
|
|
15
|
+
import { promisify } from "node:util";
|
|
16
|
+
import os from "node:os";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
import fs from "node:fs/promises";
|
|
19
|
+
|
|
20
|
+
const execFileAsync = promisify(execFile);
|
|
21
|
+
|
|
22
|
+
/** Directory where downloaded standalone binaries are placed. */
|
|
23
|
+
export function binDir() {
|
|
24
|
+
return path.join(os.homedir(), ".local", "bin");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Run an install command. Commands here are simple (no nested quoting), so we
|
|
29
|
+
* tokenize on whitespace.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} command
|
|
32
|
+
* @param {{ interactive?: boolean }} [opts]
|
|
33
|
+
* interactive → inherit the parent's stdio so sudo can prompt for the password
|
|
34
|
+
* on the user's own terminal; kj never captures or logs it.
|
|
35
|
+
*/
|
|
36
|
+
export async function runInstallCommand(command, opts = {}) {
|
|
37
|
+
const [bin, ...args] = command.split(/\s+/);
|
|
38
|
+
if (opts.interactive) return runInherited(bin, args);
|
|
39
|
+
try {
|
|
40
|
+
const { stdout, stderr } = await execFileAsync(bin, args, {
|
|
41
|
+
timeout: 300_000,
|
|
42
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
43
|
+
});
|
|
44
|
+
return { ok: true, stdout, stderr };
|
|
45
|
+
} catch (err) {
|
|
46
|
+
return { ok: false, error: err?.shortMessage || err?.message || String(err), stderr: err?.stderr };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function runInherited(bin, args) {
|
|
51
|
+
return new Promise((resolve) => {
|
|
52
|
+
let child;
|
|
53
|
+
try {
|
|
54
|
+
child = spawn(bin, args, { stdio: "inherit", timeout: 600_000 });
|
|
55
|
+
} catch (err) {
|
|
56
|
+
resolve({ ok: false, error: err?.message || String(err) });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
child.on("error", (err) => resolve({ ok: false, error: err?.message || String(err) }));
|
|
60
|
+
child.on("close", (code) => resolve({ ok: code === 0, code }));
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Download a single static binary and place it (executable) into `dir`.
|
|
66
|
+
* Writes to a temp file first and renames atomically; on any failure the temp
|
|
67
|
+
* file is removed so no partial artifact is left behind.
|
|
68
|
+
*
|
|
69
|
+
* @param {{ url: string, name: string, dir?: string }} args
|
|
70
|
+
*/
|
|
71
|
+
export async function downloadBinary({ url, name, dir = binDir() }) {
|
|
72
|
+
let res;
|
|
73
|
+
try {
|
|
74
|
+
res = await fetch(url);
|
|
75
|
+
} catch (err) {
|
|
76
|
+
return { ok: false, error: `download failed: ${err?.message || String(err)}` };
|
|
77
|
+
}
|
|
78
|
+
if (!res.ok) return { ok: false, error: `download failed: HTTP ${res.status}` };
|
|
79
|
+
|
|
80
|
+
await fs.mkdir(dir, { recursive: true });
|
|
81
|
+
const dest = path.join(dir, name);
|
|
82
|
+
const tmp = path.join(dir, `.${name}.download`);
|
|
83
|
+
try {
|
|
84
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
85
|
+
await fs.writeFile(tmp, buf);
|
|
86
|
+
await fs.chmod(tmp, 0o755);
|
|
87
|
+
await fs.rename(tmp, dest);
|
|
88
|
+
return { ok: true, dest };
|
|
89
|
+
} catch (err) {
|
|
90
|
+
await fs.rm(tmp, { force: true }).catch(() => {});
|
|
91
|
+
return { ok: false, error: `install failed: ${err?.message || String(err)}` };
|
|
92
|
+
}
|
|
93
|
+
}
|