@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,137 @@
|
|
|
1
|
+
// Smart role assignment based on available AI agents.
|
|
2
|
+
// Used by both kj init (interactive) and auto-init (non-interactive).
|
|
3
|
+
|
|
4
|
+
import { detectAvailableAgents } from "./agent-detect.js";
|
|
5
|
+
|
|
6
|
+
// Agent capability tiers (higher = more capable for complex reasoning)
|
|
7
|
+
const CAPABILITY_TIERS = {
|
|
8
|
+
claude: 5, // Best for reasoning, orchestration, complex tasks
|
|
9
|
+
codex: 4, // Strong coder, good reviewer
|
|
10
|
+
gemini: 3, // Good general purpose
|
|
11
|
+
aider: 2, // Good coder, limited reasoning
|
|
12
|
+
opencode: 2 // Similar to aider
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Role requirements: what capability level is ideal for each role
|
|
16
|
+
const ROLE_PREFERENCES = {
|
|
17
|
+
brain: { minTier: 4, prefer: "claude", description: "Karajan Brain (orchestrator)" },
|
|
18
|
+
// KJC-BUG-0113: Solomon preferred gemini, but Google retired the Gemini
|
|
19
|
+
// Code Assist CLI for individuals — a binary that answers --version yet
|
|
20
|
+
// dies with IneligibleTierError on every real call. Any machine with the
|
|
21
|
+
// stale CLI on PATH got a judge that could never rule. Claude matches
|
|
22
|
+
// the brain default; diversifyReviewer still picks a different agent
|
|
23
|
+
// when more than one healthy option exists.
|
|
24
|
+
solomon: { minTier: 3, prefer: "claude", description: "Solomon (judge/arbiter)" },
|
|
25
|
+
coder: { minTier: 2, prefer: "claude", description: "Coder" },
|
|
26
|
+
reviewer: { minTier: 3, prefer: "codex", description: "Reviewer" },
|
|
27
|
+
planner: { minTier: 4, prefer: "claude", description: "Planner" },
|
|
28
|
+
researcher: { minTier: 3, prefer: "claude", description: "Researcher" },
|
|
29
|
+
architect: { minTier: 4, prefer: "claude", description: "Architect" },
|
|
30
|
+
tester: { minTier: 3, prefer: "claude", description: "Tester" },
|
|
31
|
+
security: { minTier: 3, prefer: "claude", description: "Security" },
|
|
32
|
+
triage: { minTier: 3, prefer: "claude", description: "Triage" }
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Assign the best available agent to a role.
|
|
37
|
+
* Prefers the role's preferred agent if available, then falls back by capability tier.
|
|
38
|
+
*/
|
|
39
|
+
function assignRole(roleName, availableAgents) {
|
|
40
|
+
const pref = ROLE_PREFERENCES[roleName];
|
|
41
|
+
if (!pref) return availableAgents[0]?.name || "claude";
|
|
42
|
+
|
|
43
|
+
// Preferred agent available?
|
|
44
|
+
if (availableAgents.find(a => a.name === pref.prefer)) {
|
|
45
|
+
return pref.prefer;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Sort by capability tier (descending) and pick the best available
|
|
49
|
+
const sorted = [...availableAgents].sort(
|
|
50
|
+
(a, b) => (CAPABILITY_TIERS[b.name] || 1) - (CAPABILITY_TIERS[a.name] || 1)
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return sorted[0]?.name || "claude";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Try to diversify: if possible, use a different agent for reviewer than coder.
|
|
58
|
+
*/
|
|
59
|
+
function diversifyReviewer(coderAgent, availableAgents) {
|
|
60
|
+
const alternatives = availableAgents.filter(a => a.name !== coderAgent);
|
|
61
|
+
if (alternatives.length === 0) return coderAgent;
|
|
62
|
+
|
|
63
|
+
const sorted = [...alternatives].sort(
|
|
64
|
+
(a, b) => (CAPABILITY_TIERS[b.name] || 1) - (CAPABILITY_TIERS[a.name] || 1)
|
|
65
|
+
);
|
|
66
|
+
return sorted[0].name;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Auto-assign all roles based on detected agents. Non-interactive.
|
|
71
|
+
* Returns a config-ready object with role assignments.
|
|
72
|
+
*/
|
|
73
|
+
export async function autoAssignRoles(logger) {
|
|
74
|
+
const agents = await detectAvailableAgents();
|
|
75
|
+
const available = agents.filter(a => a.available);
|
|
76
|
+
|
|
77
|
+
if (available.length === 0) {
|
|
78
|
+
logger?.warn?.("No AI agents detected. Using claude as default for all roles.");
|
|
79
|
+
return { assignments: getDefaultAssignments("claude"), agents, available: [] };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
logger?.info?.(`Detected ${available.length} AI agent(s): ${available.map(a => `${a.name} (${a.version})`).join(", ")}`);
|
|
83
|
+
|
|
84
|
+
const coder = assignRole("coder", available);
|
|
85
|
+
const reviewer = available.length > 1 ? diversifyReviewer(coder, available) : coder;
|
|
86
|
+
const brain = assignRole("brain", available);
|
|
87
|
+
const solomon = available.length > 1 ? diversifyReviewer(brain, available) : brain;
|
|
88
|
+
|
|
89
|
+
const assignments = {
|
|
90
|
+
brain,
|
|
91
|
+
solomon,
|
|
92
|
+
coder,
|
|
93
|
+
reviewer,
|
|
94
|
+
planner: assignRole("planner", available),
|
|
95
|
+
researcher: assignRole("researcher", available),
|
|
96
|
+
architect: assignRole("architect", available),
|
|
97
|
+
tester: assignRole("tester", available),
|
|
98
|
+
security: assignRole("security", available),
|
|
99
|
+
triage: assignRole("triage", available)
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
logger?.info?.(`Role assignments: Brain=${brain}, Solomon=${solomon}, Coder=${coder}, Reviewer=${reviewer}`);
|
|
103
|
+
|
|
104
|
+
return { assignments, agents, available };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function getDefaultAssignments(agent) {
|
|
108
|
+
return {
|
|
109
|
+
brain: agent, solomon: agent, coder: agent, reviewer: agent,
|
|
110
|
+
planner: agent, researcher: agent, architect: agent,
|
|
111
|
+
tester: agent, security: agent, triage: agent
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Apply role assignments to a Karajan config object.
|
|
117
|
+
*/
|
|
118
|
+
export function applyRoleAssignments(config, assignments) {
|
|
119
|
+
config.coder = assignments.coder;
|
|
120
|
+
config.reviewer = assignments.reviewer;
|
|
121
|
+
|
|
122
|
+
const roleNames = ["coder", "reviewer", "planner", "researcher", "architect",
|
|
123
|
+
"tester", "security", "triage", "solomon"];
|
|
124
|
+
|
|
125
|
+
for (const role of roleNames) {
|
|
126
|
+
config.roles = config.roles || {};
|
|
127
|
+
config.roles[role] = config.roles[role] || {};
|
|
128
|
+
config.roles[role].provider = assignments[role] || assignments.coder;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Brain is a new top-level config (not in roles yet — will be when KarajanBrainRole is implemented)
|
|
132
|
+
config.brain = { provider: assignments.brain };
|
|
133
|
+
|
|
134
|
+
return config;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { CAPABILITY_TIERS };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* role-env — env allowlist for agent subprocesses (KJC-TSK-0693).
|
|
3
|
+
*
|
|
4
|
+
* Agents inherit only what their function requires: system essentials, the
|
|
5
|
+
* spawned CLI's own auth/config vars, and KJ_* lane vars. Long-lived secrets
|
|
6
|
+
* that no agent needs (cloud keys, registry tokens, DB URLs) never reach the
|
|
7
|
+
* child, so a compromised agent or an injected prompt cannot exfiltrate them.
|
|
8
|
+
* Escapes: `security.env_passthrough` (exact names or trailing-* globs) and
|
|
9
|
+
* `security.env_allowlist: false` to disable filtering entirely.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const EXACT = new Set([
|
|
13
|
+
"PATH", "Path", "HOME", "USER", "LOGNAME", "SHELL", "TERM", "COLORTERM", "LANG",
|
|
14
|
+
"TZ", "TMPDIR", "TMP", "TEMP", "EDITOR", "CI", "OLLAMA_HOST",
|
|
15
|
+
// Windows child-process essentials: executable resolution and profile dirs.
|
|
16
|
+
"SystemRoot", "SYSTEMROOT", "windir", "COMSPEC", "ComSpec", "PATHEXT",
|
|
17
|
+
"USERPROFILE", "HOMEDRIVE", "HOMEPATH", "APPDATA", "LOCALAPPDATA", "PROGRAMDATA",
|
|
18
|
+
// SSH agent socket: local-only handle, needed for git fetch/pull over SSH
|
|
19
|
+
// inside worktrees. Unusable off-machine, unlike a long-lived token.
|
|
20
|
+
"SSH_AUTH_SOCK", "SSH_AGENT_PID",
|
|
21
|
+
"HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY",
|
|
22
|
+
"http_proxy", "https_proxy", "no_proxy",
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
// Per-CLI auth/config families. GOOGLE_ covers GOOGLE_APPLICATION_CREDENTIALS
|
|
26
|
+
// (gemini via Vertex); npm_ covers npm_config_* that Node tooling reads.
|
|
27
|
+
const PREFIXES = [
|
|
28
|
+
"LC_", "XDG_", "KJ_", "NODE_", "npm_",
|
|
29
|
+
"ANTHROPIC_", "CLAUDE", "OPENAI_", "CODEX", "GEMINI", "GOOGLE_",
|
|
30
|
+
"QWEN", "DASHSCOPE_", "OPENCODE", "AIDER_", "OPENROUTER_",
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
// Vars only ONE agent authenticates with — granting them globally would
|
|
34
|
+
// defeat the point (the coder does not need your GitHub token; copilot does).
|
|
35
|
+
export const AGENT_EXTRAS = {
|
|
36
|
+
copilot: ["GITHUB_", "GH_"],
|
|
37
|
+
kimi: ["KIMI_", "MOONSHOT_"],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const matches = (pattern, key) =>
|
|
41
|
+
pattern.endsWith("*") ? key.startsWith(pattern.slice(0, -1)) : key === pattern;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Filter an environment down to what the given agent's subprocess needs.
|
|
45
|
+
* @param {Record<string,string|undefined>} base - env to filter
|
|
46
|
+
* @param {{agent?: string|null, passthrough?: string[]}} [opts]
|
|
47
|
+
* @returns {Record<string,string|undefined>}
|
|
48
|
+
*/
|
|
49
|
+
export function buildAgentEnv(base = process.env, { agent = null, passthrough = [] } = {}) {
|
|
50
|
+
const prefixes = [...PREFIXES, ...(AGENT_EXTRAS[agent] || [])];
|
|
51
|
+
const out = {};
|
|
52
|
+
for (const [key, value] of Object.entries(base)) {
|
|
53
|
+
if (EXACT.has(key) || prefixes.some((p) => key.startsWith(p)) || passthrough.some((p) => matches(p, key))) {
|
|
54
|
+
out[key] = value;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { runCommand } from "./process.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Detect whether RTK (Rust Token Killer) is installed and available.
|
|
5
|
+
* @returns {Promise<{ available: boolean, version: string|null }>}
|
|
6
|
+
*/
|
|
7
|
+
export async function detectRtk() {
|
|
8
|
+
try {
|
|
9
|
+
const result = await runCommand("rtk", ["--version"]);
|
|
10
|
+
if (result.exitCode === 0) {
|
|
11
|
+
const version = (result.stdout || "").trim() || null;
|
|
12
|
+
return { available: true, version };
|
|
13
|
+
}
|
|
14
|
+
return { available: false, version: null };
|
|
15
|
+
} catch { /* rtk binary not found */
|
|
16
|
+
return { available: false, version: null };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { runCommand } from "./process.js";
|
|
2
|
+
import { getInstallCommand } from "./os-detect.js";
|
|
3
|
+
import { detectRtk } from "./rtk-detect.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Install RTK (Rust Token Killer) using the OS-appropriate command.
|
|
7
|
+
* @param {object} logger - Logger with info/warn methods
|
|
8
|
+
* @returns {Promise<{ ok: boolean, version: string|null, error: string|null }>}
|
|
9
|
+
*/
|
|
10
|
+
export async function installRtk(logger) {
|
|
11
|
+
const command = getInstallCommand("rtk");
|
|
12
|
+
|
|
13
|
+
logger.info("Installing RTK (Rust Token Killer)...");
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const result = await runCommand("sh", ["-c", command], { timeout: 120_000 });
|
|
17
|
+
|
|
18
|
+
if (result.exitCode !== 0) {
|
|
19
|
+
const error = (result.stderr || "").trim() || `exit code ${result.exitCode}`;
|
|
20
|
+
logger.warn(`RTK install failed: ${error}`);
|
|
21
|
+
return { ok: false, version: null, error };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Verify installation
|
|
25
|
+
const check = await detectRtk();
|
|
26
|
+
if (check.available) {
|
|
27
|
+
logger.info(`RTK ${check.version || ""} installed successfully.`);
|
|
28
|
+
return { ok: true, version: check.version, error: null };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
logger.warn("RTK install command succeeded but rtk binary not found in PATH.");
|
|
32
|
+
return { ok: false, version: null, error: "Binary not found after install" };
|
|
33
|
+
} catch (err) {
|
|
34
|
+
const error = err.message || String(err);
|
|
35
|
+
logger.warn(`RTK install failed: ${error}`);
|
|
36
|
+
return { ok: false, version: null, error };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { runCommand } from "./process.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Commands that RTK can safely wrap for token-optimized output.
|
|
5
|
+
*/
|
|
6
|
+
export const RTK_SUPPORTED_COMMANDS = [
|
|
7
|
+
"git", "ls", "find", "grep", "cat", "head", "tail",
|
|
8
|
+
"wc", "diff", "tree", "du", "file"
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
const supportedSet = new Set(RTK_SUPPORTED_COMMANDS);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Wrap a command with RTK if available and the command is in the whitelist.
|
|
15
|
+
* @param {string} command
|
|
16
|
+
* @param {string[]} args
|
|
17
|
+
* @param {boolean} rtkAvailable
|
|
18
|
+
* @returns {{ command: string, args: string[] }}
|
|
19
|
+
*/
|
|
20
|
+
export function wrapWithRtk(command, args, rtkAvailable) {
|
|
21
|
+
if (rtkAvailable && supportedSet.has(command)) {
|
|
22
|
+
return { command: "rtk", args: [command, ...args] };
|
|
23
|
+
}
|
|
24
|
+
return { command, args };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Session-level accumulator for RTK byte savings.
|
|
29
|
+
*/
|
|
30
|
+
export class RtkSavingsTracker {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.originalBytes = 0;
|
|
33
|
+
this.rtkBytes = 0;
|
|
34
|
+
this.callCount = 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
record(originalSize, rtkSize) {
|
|
38
|
+
this.originalBytes += originalSize;
|
|
39
|
+
this.rtkBytes += rtkSize;
|
|
40
|
+
this.callCount += 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
summary() {
|
|
44
|
+
const savedBytes = this.originalBytes - this.rtkBytes;
|
|
45
|
+
const savedPct = this.originalBytes > 0
|
|
46
|
+
? Number(((savedBytes / this.originalBytes) * 100).toFixed(1))
|
|
47
|
+
: 0;
|
|
48
|
+
const estimatedTokensSaved = Math.floor(savedBytes / 4);
|
|
49
|
+
return {
|
|
50
|
+
originalBytes: this.originalBytes,
|
|
51
|
+
rtkBytes: this.rtkBytes,
|
|
52
|
+
savedBytes,
|
|
53
|
+
savedPct,
|
|
54
|
+
estimatedTokensSaved,
|
|
55
|
+
callCount: this.callCount
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Returns true if any commands were recorded. */
|
|
60
|
+
hasData() {
|
|
61
|
+
return this.callCount > 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Create a runner function that transparently wraps supported commands with RTK.
|
|
67
|
+
* @param {boolean} rtkAvailable
|
|
68
|
+
* @param {RtkSavingsTracker} [tracker] - Optional savings tracker
|
|
69
|
+
* @returns {(command: string, args?: string[], options?: object) => Promise<object>}
|
|
70
|
+
*/
|
|
71
|
+
export function createRtkRunner(rtkAvailable, tracker = null) {
|
|
72
|
+
return async (command, args = [], options = {}) => {
|
|
73
|
+
const wrapped = wrapWithRtk(command, args, rtkAvailable);
|
|
74
|
+
const result = await runCommand(wrapped.command, wrapped.args, options);
|
|
75
|
+
|
|
76
|
+
if (tracker && rtkAvailable && supportedSet.has(command)) {
|
|
77
|
+
const outputSize = Buffer.byteLength(result.stdout || "", "utf8");
|
|
78
|
+
// For RTK-wrapped calls, the output is already compressed.
|
|
79
|
+
// We estimate the original size as outputSize (conservative — real savings
|
|
80
|
+
// would require running the command without RTK, which defeats the purpose).
|
|
81
|
+
// The tracker is useful when the caller provides real estimates externally.
|
|
82
|
+
tracker.record(outputSize, outputSize);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return result;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-run context store — makes module-level state in `utils/git.js`,
|
|
3
|
+
* `review/diff-generator.js`, etc. safe under concurrent `runFlow` calls.
|
|
4
|
+
*
|
|
5
|
+
* Pre-v2.7.5 the orchestrator mutated module-scope variables at pipeline
|
|
6
|
+
* start:
|
|
7
|
+
* setDiffRunner(rtkRunner); setDiffProjectDir(diffScope);
|
|
8
|
+
* setGitRunner(rtkRunner);
|
|
9
|
+
* // …later…
|
|
10
|
+
* // every git/diff op reads those globals
|
|
11
|
+
*
|
|
12
|
+
* That is fine for a single-threaded CLI invocation but corrupts when the
|
|
13
|
+
* MCP server fields two `kj_run` tool calls in parallel: each run would
|
|
14
|
+
* overwrite the others' runner/projectDir during setup, and subsequent
|
|
15
|
+
* reads would see a mix.
|
|
16
|
+
*
|
|
17
|
+
* TSK-0338 isolates that state to a per-run AsyncLocalStorage scope.
|
|
18
|
+
* `runFlow` wraps its execution in `withRunContext(ctx, fn)`, and the
|
|
19
|
+
* read paths in git.js / diff-generator.js look up
|
|
20
|
+
* `getRunContext()?.runner` before falling back to the module-level
|
|
21
|
+
* `_runner` (kept as a back-compat entry for callers outside a
|
|
22
|
+
* `runFlow` — CLI helpers, tests — that set state directly).
|
|
23
|
+
*
|
|
24
|
+
* What lives here vs. elsewhere:
|
|
25
|
+
* - `runContext` (this module) — runner, projectDir, snapshot — the
|
|
26
|
+
* pieces git/diff touches synchronously on every op.
|
|
27
|
+
* - `PipelineContext` (src/orchestrator/pipeline-context.js) — the
|
|
28
|
+
* richer structure ferried between stages. The two could merge
|
|
29
|
+
* eventually, but PipelineContext is created after preflight, and
|
|
30
|
+
* the runner/projectDir must be in scope BEFORE preflight runs
|
|
31
|
+
* (which itself calls git commands).
|
|
32
|
+
*
|
|
33
|
+
* The invariant `tests/orchestrator/concurrent-runs.test.js` exercises
|
|
34
|
+
* the isolation: two parallel `withRunContext(A, …)` and
|
|
35
|
+
* `withRunContext(B, …)` see their own runner, not each other's.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @typedef {Object} RunContext
|
|
42
|
+
* @property {((command: string, args?: string[], options?: object) => Promise<object>)|null} [runner]
|
|
43
|
+
* Pipeline-scoped command runner. When present, git.js + diff-generator.js
|
|
44
|
+
* route commands through it instead of the default `runCommand`.
|
|
45
|
+
* @property {string|null} [projectDir]
|
|
46
|
+
* Directory scope for `git diff`. Prevents leaking unrelated subdir
|
|
47
|
+
* changes when `kj run` is invoked from a subpath of a monorepo.
|
|
48
|
+
* @property {Map<string, string>|null} [snapshot]
|
|
49
|
+
* Pre-coder filesystem snapshot for snapshot-based diff when git is
|
|
50
|
+
* unavailable (greenfield projects with no initial commit).
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
const runStore = new AsyncLocalStorage();
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Run `fn` with `ctx` as the active RunContext. All reads of
|
|
57
|
+
* `getRunContext()` inside (including from awaited callees) see `ctx`.
|
|
58
|
+
* Concurrent `withRunContext` invocations are fully isolated from each
|
|
59
|
+
* other — that's what AsyncLocalStorage guarantees.
|
|
60
|
+
*
|
|
61
|
+
* @param {RunContext} ctx
|
|
62
|
+
* @param {() => Promise<any>} fn
|
|
63
|
+
* @returns {Promise<any>}
|
|
64
|
+
*/
|
|
65
|
+
export function withRunContext(ctx, fn) {
|
|
66
|
+
return runStore.run(ctx ?? {}, fn);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @returns {RunContext|undefined} the active RunContext, or undefined when
|
|
71
|
+
* called outside any `withRunContext` scope (legacy CLI paths, tests).
|
|
72
|
+
*/
|
|
73
|
+
export function getRunContext() {
|
|
74
|
+
return runStore.getStore();
|
|
75
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-based run logger.
|
|
3
|
+
*
|
|
4
|
+
* Writes progress events to a known file so that external tools
|
|
5
|
+
* (tail -f, kj_status, another Claude process) can monitor what
|
|
6
|
+
* Karajan is doing in real time.
|
|
7
|
+
*
|
|
8
|
+
* Log location: <projectDir>/.kj/run.log (overwritten each run)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
|
|
14
|
+
const LOG_FILENAME = "run.log";
|
|
15
|
+
|
|
16
|
+
function resolveLogDir(baseDir) {
|
|
17
|
+
return path.join(baseDir || process.cwd(), ".kj");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function resolveLogPath(baseDir) {
|
|
21
|
+
return path.join(resolveLogDir(baseDir), LOG_FILENAME);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function ensureDir(dir) {
|
|
25
|
+
try {
|
|
26
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
27
|
+
} catch { /* already exists */ }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function formatLine(event) {
|
|
31
|
+
const ts = new Date().toISOString().slice(11, 23);
|
|
32
|
+
const stage = event.stage || event.detail?.stage || "";
|
|
33
|
+
const type = event.type || "info";
|
|
34
|
+
const msg = event.message || "";
|
|
35
|
+
const extra = [];
|
|
36
|
+
|
|
37
|
+
if (event.detail?.provider) extra.push(`agent=${event.detail.provider}`);
|
|
38
|
+
if (event.detail?.lineCount !== undefined) extra.push(`lines=${event.detail.lineCount}`);
|
|
39
|
+
if (event.detail?.elapsedMs !== undefined) extra.push(`elapsed=${Math.round(event.detail.elapsedMs / 1000)}s`);
|
|
40
|
+
if (event.detail?.silenceMs !== undefined) extra.push(`silence=${Math.round(event.detail.silenceMs / 1000)}s`);
|
|
41
|
+
if (event.detail?.severity) extra.push(`severity=${event.detail.severity}`);
|
|
42
|
+
if (event.detail?.stream) extra.push(`stream=${event.detail.stream}`);
|
|
43
|
+
if (event.detail?.cooldownUntil) extra.push(`until=${event.detail.cooldownUntil}`);
|
|
44
|
+
if (event.detail?.retryCount !== undefined) extra.push(`retry=${event.detail.retryCount}/${event.detail.maxRetries || "?"}`);
|
|
45
|
+
if (event.detail?.remainingMs !== undefined) extra.push(`remaining=${Math.round(event.detail.remainingMs / 1000)}s`);
|
|
46
|
+
|
|
47
|
+
const extraStr = extra.length ? ` (${extra.join(", ")})` : "";
|
|
48
|
+
const stageStr = stage ? `[${stage}] ` : "";
|
|
49
|
+
return `${ts} [${type}] ${stageStr}${msg}${extraStr}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function createRunLog(projectDir) {
|
|
53
|
+
const logPath = resolveLogPath(projectDir);
|
|
54
|
+
const logDir = resolveLogDir(projectDir);
|
|
55
|
+
ensureDir(logDir);
|
|
56
|
+
|
|
57
|
+
// Truncate/create the log file
|
|
58
|
+
fs.writeFileSync(logPath, `--- Karajan run started at ${new Date().toISOString()} ---\n`);
|
|
59
|
+
|
|
60
|
+
// Audit recommendation (perf-LOW): suggested createWriteStream + queue.
|
|
61
|
+
// Tried it; broke the contract. `readRunLog` (used by `kj_status`,
|
|
62
|
+
// `kj-tail`, and the HU board's chokidar tick) reads the file with
|
|
63
|
+
// `fs.readFileSync` and expects every prior write to be visible the
|
|
64
|
+
// moment the writer's `logEvent()` returns — which is what
|
|
65
|
+
// `fs.writeSync(fd, ...)` guarantees and `stream.write()` does NOT.
|
|
66
|
+
//
|
|
67
|
+
// The current shape is already opened-once: `fs.openSync(logPath, "a")`
|
|
68
|
+
// returns an fd that every subsequent `fs.writeSync` reuses (no extra
|
|
69
|
+
// open/close per call). The hot-path complaint was about the FALLBACK
|
|
70
|
+
// `fs.appendFileSync` line, which only fires when openSync itself
|
|
71
|
+
// fails (rare; FS error or RO mount).
|
|
72
|
+
let fd = null;
|
|
73
|
+
try {
|
|
74
|
+
fd = fs.openSync(logPath, "a");
|
|
75
|
+
} catch {
|
|
76
|
+
// If we can't open for append, use writeFile fallback
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function write(line) {
|
|
80
|
+
try {
|
|
81
|
+
if (fd === null) {
|
|
82
|
+
fs.appendFileSync(logPath, line + "\n");
|
|
83
|
+
} else {
|
|
84
|
+
fs.writeSync(fd, line + "\n");
|
|
85
|
+
}
|
|
86
|
+
} catch { /* best-effort */ }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function logEvent(event) {
|
|
90
|
+
write(formatLine(event));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function logText(text) {
|
|
94
|
+
const ts = new Date().toISOString().slice(11, 23);
|
|
95
|
+
write(`${ts} ${text}`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function close() {
|
|
99
|
+
try {
|
|
100
|
+
if (fd !== null) {
|
|
101
|
+
fs.closeSync(fd);
|
|
102
|
+
fd = null;
|
|
103
|
+
}
|
|
104
|
+
} catch { /* best-effort */ }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
logEvent,
|
|
109
|
+
logText,
|
|
110
|
+
close,
|
|
111
|
+
get path() { return logPath; }
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const KJ_TOOLS = ["kj_run", "kj_code", "kj_plan"];
|
|
116
|
+
|
|
117
|
+
function detectRunStart(line, status) {
|
|
118
|
+
const started = KJ_TOOLS.some(t => line.includes(`[${t}] started`));
|
|
119
|
+
if (!started) return;
|
|
120
|
+
status.isRunning = true;
|
|
121
|
+
status.currentStage = KJ_TOOLS.find(t => line.includes(t));
|
|
122
|
+
const tsMatch = /^(\d{2}:\d{2}:\d{2}\.\d{3})/.exec(line);
|
|
123
|
+
if (tsMatch) status.startedAt = tsMatch[1];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function detectRunFinish(line, status) {
|
|
127
|
+
const isToolFinish = KJ_TOOLS.some(t => line.includes(`[${t}] finished`) || line.includes(`[${t}]`));
|
|
128
|
+
if (line.includes("finished") && isToolFinish) {
|
|
129
|
+
status.isRunning = false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function detectStageTransitions(line, status) {
|
|
134
|
+
const stageStart = /\[(\w+):start\]/.exec(line);
|
|
135
|
+
if (stageStart) status.currentStage = stageStart[1];
|
|
136
|
+
|
|
137
|
+
const stageDone = /\[(\w+):done\]|\[(\w+)\] finished/.exec(line);
|
|
138
|
+
if (stageDone) {
|
|
139
|
+
const doneName = stageDone[1] || stageDone[2];
|
|
140
|
+
if (doneName === status.currentStage) status.currentStage = "idle";
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function detectMetadata(line, status) {
|
|
145
|
+
const agentMatch = /agent=(\w+)/.exec(line);
|
|
146
|
+
if (agentMatch) status.currentAgent = agentMatch[1];
|
|
147
|
+
|
|
148
|
+
const iterMatch = /[Ii]teration\s+(\d+)/.exec(line);
|
|
149
|
+
if (iterMatch) status.iteration = Number.parseInt(iterMatch[1], 10);
|
|
150
|
+
|
|
151
|
+
if (/\[.*:fail\]|\[.*error\]/i.test(line) || line.includes("ERROR")) {
|
|
152
|
+
status.errors.push(line.trim());
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (line.includes("[standby]") || line.includes("standby")) {
|
|
156
|
+
status.currentStage = "standby";
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Parse the run log to extract current status information.
|
|
162
|
+
*/
|
|
163
|
+
function parseRunStatus(lines) {
|
|
164
|
+
const status = {
|
|
165
|
+
currentStage: null,
|
|
166
|
+
currentAgent: null,
|
|
167
|
+
startedAt: null,
|
|
168
|
+
isRunning: false,
|
|
169
|
+
lastEvent: null,
|
|
170
|
+
iteration: null,
|
|
171
|
+
errors: []
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
for (const line of lines) {
|
|
175
|
+
detectRunStart(line, status);
|
|
176
|
+
detectRunFinish(line, status);
|
|
177
|
+
detectStageTransitions(line, status);
|
|
178
|
+
detectMetadata(line, status);
|
|
179
|
+
status.lastEvent = line.trim();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (status.errors.length > 3) status.errors = status.errors.slice(-3);
|
|
183
|
+
return status;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Read the current run log contents.
|
|
188
|
+
* Returns the last N lines (default 50) plus a parsed status summary.
|
|
189
|
+
*/
|
|
190
|
+
export function readRunLog(projectDir, maxLines = 50) {
|
|
191
|
+
const logPath = resolveLogPath(projectDir);
|
|
192
|
+
try {
|
|
193
|
+
const content = fs.readFileSync(logPath, "utf8");
|
|
194
|
+
const lines = content.split("\n").filter(Boolean);
|
|
195
|
+
const total = lines.length;
|
|
196
|
+
const shown = lines.slice(-maxLines);
|
|
197
|
+
const status = parseRunStatus(lines);
|
|
198
|
+
const MAX_LINE_CHARS = 2000;
|
|
199
|
+
const truncated = shown.map(l => l.length > MAX_LINE_CHARS ? l.slice(0, MAX_LINE_CHARS) + "… [truncated]" : l);
|
|
200
|
+
return {
|
|
201
|
+
ok: true,
|
|
202
|
+
path: logPath,
|
|
203
|
+
totalLines: total,
|
|
204
|
+
status,
|
|
205
|
+
lines: truncated,
|
|
206
|
+
summary: truncated.join("\n")
|
|
207
|
+
};
|
|
208
|
+
} catch (err) {
|
|
209
|
+
return {
|
|
210
|
+
ok: false,
|
|
211
|
+
path: logPath,
|
|
212
|
+
error: err.code === "ENOENT"
|
|
213
|
+
? "No active run log found. Start a run with kj_run first."
|
|
214
|
+
: `Failed to read log: ${err.message}`
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Shim: run-registry now lives in karajan-core/run-registry so the
|
|
2
|
+
// hu-board workspace can consume it without a relative dep on the CLI
|
|
3
|
+
// src tree. KJC-TSK-0511 PR3.
|
|
4
|
+
export {
|
|
5
|
+
runsDir,
|
|
6
|
+
registerRun,
|
|
7
|
+
unregisterRun,
|
|
8
|
+
listActiveRuns,
|
|
9
|
+
} from "karajan-core/run-registry";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Shim — the real implementation now lives in karajan-core/shared-paths.
|
|
2
|
+
// Kept here so CLI callers (src/**/*.js) keep importing
|
|
3
|
+
// "../utils/shared-paths.js" without churn during KJC-TSK-0511 (decouple
|
|
4
|
+
// @karajan/hu-board). Will be retired once every consumer migrates to
|
|
5
|
+
// the karajan-core import.
|
|
6
|
+
export {
|
|
7
|
+
SHARED_DIR_NAME,
|
|
8
|
+
getSharedRoot,
|
|
9
|
+
getSharedPlansDir,
|
|
10
|
+
getSharedHuStoriesDir,
|
|
11
|
+
isSharedPath,
|
|
12
|
+
} from "karajan-core/shared-paths";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { runCommand } from "./process.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Detect whether Squeezr is installed and available.
|
|
5
|
+
* @returns {Promise<{ available: boolean, version: string|null }>}
|
|
6
|
+
*/
|
|
7
|
+
export async function detectSqueezr() {
|
|
8
|
+
try {
|
|
9
|
+
const result = await runCommand("squeezr", ["--version"]);
|
|
10
|
+
if (result.exitCode === 0) {
|
|
11
|
+
// `squeezr --version` may append an "update available" banner box; keep
|
|
12
|
+
// just the semver so callers never render that noise (KJC-BUG-0088).
|
|
13
|
+
const raw = (result.stdout || "").trim();
|
|
14
|
+
const version = raw.match(/\d+\.\d+\.\d+[\w.-]*/)?.[0] || raw.split("\n")[0].trim() || null;
|
|
15
|
+
return { available: true, version };
|
|
16
|
+
}
|
|
17
|
+
return { available: false, version: null };
|
|
18
|
+
} catch { /* squeezr binary not found */
|
|
19
|
+
return { available: false, version: null };
|
|
20
|
+
}
|
|
21
|
+
}
|