@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
|
+
// Claude Code PreToolUse hook (KJC-TSK-0390 commit 2). Reads the JSON
|
|
2
|
+
// payload from stdin, classifies the Bash command, snapshots target
|
|
3
|
+
// paths, prints the decision JSON on stdout. Fail-closed: if snapshot
|
|
4
|
+
// throws, deny the op so Claude never destroys without a recovery copy.
|
|
5
|
+
|
|
6
|
+
import { promises as fs } from "node:fs";
|
|
7
|
+
import { isAbsolute, resolve } from "node:path";
|
|
8
|
+
import process from "node:process";
|
|
9
|
+
import { classifyCommand } from "./destructive-parser.js";
|
|
10
|
+
import { loadManifest, saveManifest } from "./manifest.js";
|
|
11
|
+
import { snapshotFile } from "./snapshot.js";
|
|
12
|
+
import { snapshotGitBundle } from "./git-snapshot.js";
|
|
13
|
+
import { ensureSecureDir, assertOwnedByCurrentUser } from "./permissions.js";
|
|
14
|
+
import { appendLogEntry } from "./logger.js";
|
|
15
|
+
|
|
16
|
+
function reply(decision, reason) {
|
|
17
|
+
return {
|
|
18
|
+
hookSpecificOutput: {
|
|
19
|
+
hookEventName: "PreToolUse",
|
|
20
|
+
permissionDecision: decision,
|
|
21
|
+
permissionDecisionReason: reason,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function readJsonStdin(stdin) {
|
|
27
|
+
let raw = "";
|
|
28
|
+
for await (const chunk of stdin) raw += chunk;
|
|
29
|
+
if (!raw.trim()) return null;
|
|
30
|
+
return JSON.parse(raw);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function snapshotExistingPaths(root, paths, cwd, command) {
|
|
34
|
+
const snapshots = [];
|
|
35
|
+
for (const p of paths) {
|
|
36
|
+
const abs = isAbsolute(p) ? p : resolve(cwd ?? process.cwd(), p);
|
|
37
|
+
try {
|
|
38
|
+
const stat = await fs.lstat(abs);
|
|
39
|
+
if (stat.isDirectory()) continue;
|
|
40
|
+
const entry = await snapshotFile(root, abs, { command, origin: "claude-code" });
|
|
41
|
+
snapshots.push(entry);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
if (err.code === "ENOENT") continue;
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return snapshots;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function snapshotGitRepo(root, cwd, command, kind) {
|
|
51
|
+
if (!cwd) return { snapshots: [], skipped: "no cwd" };
|
|
52
|
+
try {
|
|
53
|
+
const entry = await snapshotGitBundle(root, cwd, {
|
|
54
|
+
command,
|
|
55
|
+
origin: "claude-code",
|
|
56
|
+
label: kind,
|
|
57
|
+
});
|
|
58
|
+
return { snapshots: [entry], skipped: null };
|
|
59
|
+
} catch (err) {
|
|
60
|
+
if (/not a git repo/.test(err.message)) {
|
|
61
|
+
return { snapshots: [], skipped: "cwd is not a git repo" };
|
|
62
|
+
}
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function handleHookPayload(payload, { root, stdin }) {
|
|
68
|
+
const data = payload ?? (await readJsonStdin(stdin));
|
|
69
|
+
if (!data) return reply("allow", "ai-trash: empty payload, deferring");
|
|
70
|
+
if (data.hook_event_name !== "PreToolUse") {
|
|
71
|
+
return reply("allow", `ai-trash: not PreToolUse (${data.hook_event_name})`);
|
|
72
|
+
}
|
|
73
|
+
if (data.tool_name !== "Bash")
|
|
74
|
+
return reply("allow", `ai-trash: tool '${data.tool_name}' not handled`);
|
|
75
|
+
|
|
76
|
+
const command = data.tool_input?.command;
|
|
77
|
+
if (typeof command !== "string" || !command.trim()) {
|
|
78
|
+
return reply("allow", "ai-trash: empty Bash command");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const verdict = classifyCommand(command);
|
|
82
|
+
if (!verdict.destructive) return reply("allow", `ai-trash: ${verdict.kind} (${verdict.reason})`);
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
await ensureSecureDir(root);
|
|
86
|
+
await assertOwnedByCurrentUser(root);
|
|
87
|
+
let snapshots = [];
|
|
88
|
+
let skipped = null;
|
|
89
|
+
if (verdict.kind.startsWith("git-")) {
|
|
90
|
+
({ snapshots, skipped } = await snapshotGitRepo(root, data.cwd, command, verdict.kind));
|
|
91
|
+
} else {
|
|
92
|
+
snapshots = await snapshotExistingPaths(root, verdict.paths, data.cwd, command);
|
|
93
|
+
}
|
|
94
|
+
if (snapshots.length) {
|
|
95
|
+
const m = await loadManifest(root);
|
|
96
|
+
for (const s of snapshots) m.entries.push(s);
|
|
97
|
+
await saveManifest(root, m);
|
|
98
|
+
}
|
|
99
|
+
await appendLogEntry(root, "hook.allow", {
|
|
100
|
+
kind: verdict.kind,
|
|
101
|
+
command,
|
|
102
|
+
cwd: data.cwd ?? null,
|
|
103
|
+
snapshotCount: snapshots.length,
|
|
104
|
+
sessionId: data.session_id ?? null,
|
|
105
|
+
});
|
|
106
|
+
if (snapshots.length) {
|
|
107
|
+
return reply(
|
|
108
|
+
"allow",
|
|
109
|
+
`ai-trash: snapshotted ${snapshots.length} ${verdict.kind.startsWith("git-") ? "git bundle" : "path(s)"} before ${verdict.kind}`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
return reply(
|
|
113
|
+
"allow",
|
|
114
|
+
skipped
|
|
115
|
+
? `ai-trash: ${verdict.kind} (${skipped})`
|
|
116
|
+
: `ai-trash: ${verdict.kind} (no existing paths to snapshot)`
|
|
117
|
+
);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
try {
|
|
120
|
+
await appendLogEntry(root, "hook.deny", {
|
|
121
|
+
kind: verdict.kind,
|
|
122
|
+
command,
|
|
123
|
+
error: err.message,
|
|
124
|
+
sessionId: data.session_id ?? null,
|
|
125
|
+
});
|
|
126
|
+
} catch {
|
|
127
|
+
/* root unwritable; deny is still the right answer */
|
|
128
|
+
}
|
|
129
|
+
return reply("deny", `ai-trash: snapshot failed (${err.message}); blocking ${verdict.kind}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function runHook({ root, stdin = process.stdin, stdout = process.stdout }) {
|
|
134
|
+
const response = await handleHookPayload(null, { root, stdin, stdout });
|
|
135
|
+
stdout.write(JSON.stringify(response) + "\n");
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @karajan/ai-trash — public entry (skeleton).
|
|
2
|
+
// Real surface (snapshot, restore, list, manifest) lands in KJC-TSK-0388
|
|
3
|
+
// commits 2-6 and KJC-TSK-0389 (git ops). For now we expose a single
|
|
4
|
+
// `version` export so consumers / tests can confirm the package loads.
|
|
5
|
+
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
|
|
10
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const pkg = JSON.parse(readFileSync(join(here, "..", "package.json"), "utf8"));
|
|
12
|
+
|
|
13
|
+
export const version = pkg.version;
|
|
14
|
+
export const name = pkg.name;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Claude Code settings patcher (KJC-TSK-0390 commit 3). Idempotently
|
|
2
|
+
// adds a PreToolUse hook entry that pipes Bash commands through
|
|
3
|
+
// `kj-trash hook`. Preserves any unrelated keys and existing hooks so
|
|
4
|
+
// the user's other settings are untouched.
|
|
5
|
+
|
|
6
|
+
import { promises as fs } from "node:fs";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { dirname, join } from "node:path";
|
|
9
|
+
|
|
10
|
+
export const DEFAULT_SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
|
|
11
|
+
// KJC-BUG-0095: the bare command fails SILENTLY when the bin drops off PATH
|
|
12
|
+
// (nvm switch, global reinstall) — the anti-delete net goes down without
|
|
13
|
+
// notice. The installed line fails CLOSED: a missing bin blocks the tool
|
|
14
|
+
// call (exit 2) naming the net and the remedy, never a quiet pass-through.
|
|
15
|
+
export const LEGACY_HOOK_COMMAND = "kj-trash hook";
|
|
16
|
+
export const HOOK_COMMAND =
|
|
17
|
+
"if command -v kj-trash >/dev/null 2>&1; then exec kj-trash hook; fi; " +
|
|
18
|
+
"echo 'kj-trash: bin not on PATH — the anti-delete net is DOWN. Fix: npm i -g karajan-code (or remove this hook from ~/.claude/settings.json).' >&2; exit 2";
|
|
19
|
+
const MATCHER = "Bash";
|
|
20
|
+
|
|
21
|
+
async function readSettings(path) {
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(await fs.readFile(path, "utf8"));
|
|
24
|
+
} catch (err) {
|
|
25
|
+
if (err.code === "ENOENT") return {};
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function hasHookCommand(matcherEntry, command) {
|
|
31
|
+
return (matcherEntry.hooks ?? []).some((h) => h.type === "command" && h.command === command);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function patchSettings(settings, command = HOOK_COMMAND, matcher = MATCHER) {
|
|
35
|
+
const next = { ...settings };
|
|
36
|
+
next.hooks = { ...(next.hooks ?? {}) };
|
|
37
|
+
const preToolUse = Array.isArray(next.hooks.PreToolUse) ? next.hooks.PreToolUse.slice() : [];
|
|
38
|
+
let entry = preToolUse.find((e) => e.matcher === matcher);
|
|
39
|
+
let mutated = false;
|
|
40
|
+
if (!entry) {
|
|
41
|
+
entry = { matcher, hooks: [{ type: "command", command }] };
|
|
42
|
+
preToolUse.push(entry);
|
|
43
|
+
mutated = true;
|
|
44
|
+
} else if (hasHookCommand(entry, LEGACY_HOOK_COMMAND) && command !== LEGACY_HOOK_COMMAND) {
|
|
45
|
+
// KJC-BUG-0095 migration: upgrade the silent legacy line in place —
|
|
46
|
+
// deduped (reviewer catch): an entry already carrying the new line
|
|
47
|
+
// must end up with a single copy, not legacy-turned-duplicate.
|
|
48
|
+
let seen = false;
|
|
49
|
+
entry.hooks = entry.hooks
|
|
50
|
+
.map((h) => (h.type === "command" && h.command === LEGACY_HOOK_COMMAND ? { ...h, command } : h))
|
|
51
|
+
.filter((h) => {
|
|
52
|
+
if (!(h.type === "command" && h.command === command)) return true;
|
|
53
|
+
if (seen) return false;
|
|
54
|
+
seen = true;
|
|
55
|
+
return true;
|
|
56
|
+
});
|
|
57
|
+
mutated = true;
|
|
58
|
+
} else if (!hasHookCommand(entry, command)) {
|
|
59
|
+
entry.hooks = [...(entry.hooks ?? []), { type: "command", command }];
|
|
60
|
+
mutated = true;
|
|
61
|
+
}
|
|
62
|
+
next.hooks.PreToolUse = preToolUse;
|
|
63
|
+
return { settings: next, mutated };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function installClaudeCodeHook({ path = DEFAULT_SETTINGS_PATH, command = HOOK_COMMAND } = {}) {
|
|
67
|
+
const settings = await readSettings(path);
|
|
68
|
+
const { settings: next, mutated } = patchSettings(settings, command);
|
|
69
|
+
if (!mutated) return { path, mutated: false };
|
|
70
|
+
await fs.mkdir(dirname(path), { recursive: true });
|
|
71
|
+
await fs.writeFile(path, JSON.stringify(next, null, 2) + "\n", { encoding: "utf8" });
|
|
72
|
+
return { path, mutated: true };
|
|
73
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Append-only JSONL audit log for the trash store. Events are written one
|
|
2
|
+
// JSON object per line so the file can be `tail -f`-d and parsed
|
|
3
|
+
// line-by-line without holding the whole log in memory.
|
|
4
|
+
|
|
5
|
+
import { promises as fs } from "node:fs";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { lockdownFile } from "./permissions.js";
|
|
9
|
+
|
|
10
|
+
const HOME = homedir();
|
|
11
|
+
|
|
12
|
+
function redactPath(p) {
|
|
13
|
+
if (typeof p !== "string" || !p) return p;
|
|
14
|
+
if (p === HOME) return "~";
|
|
15
|
+
if (p.startsWith(`${HOME}/`)) return `~/${p.slice(HOME.length + 1)}`;
|
|
16
|
+
return p;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function redactPayload(payload) {
|
|
20
|
+
if (!payload || typeof payload !== "object") return payload;
|
|
21
|
+
const out = {};
|
|
22
|
+
for (const [k, v] of Object.entries(payload)) {
|
|
23
|
+
if (typeof v === "string" && (k.includes("Path") || k === "cwd")) {
|
|
24
|
+
out[k] = redactPath(v);
|
|
25
|
+
} else {
|
|
26
|
+
out[k] = v;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function appendLogEntry(rootDir, event, payload = {}) {
|
|
33
|
+
if (!event) throw new Error("ai-trash: log event required");
|
|
34
|
+
const file = join(rootDir, "log.jsonl");
|
|
35
|
+
const line =
|
|
36
|
+
JSON.stringify({
|
|
37
|
+
ts: new Date().toISOString(),
|
|
38
|
+
event,
|
|
39
|
+
...redactPayload(payload),
|
|
40
|
+
}) + "\n";
|
|
41
|
+
await fs.mkdir(rootDir, { recursive: true });
|
|
42
|
+
await fs.appendFile(file, line, { encoding: "utf8", mode: 0o600 });
|
|
43
|
+
await lockdownFile(file);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function readLog(rootDir) {
|
|
47
|
+
const file = join(rootDir, "log.jsonl");
|
|
48
|
+
try {
|
|
49
|
+
const raw = await fs.readFile(file, "utf8");
|
|
50
|
+
return raw
|
|
51
|
+
.split("\n")
|
|
52
|
+
.filter(Boolean)
|
|
53
|
+
.map((l) => JSON.parse(l));
|
|
54
|
+
} catch (err) {
|
|
55
|
+
if (err.code === "ENOENT") return [];
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { redactPath };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { ulid } from "./ulid.js";
|
|
4
|
+
|
|
5
|
+
export const SCHEMA_VERSION = 1;
|
|
6
|
+
|
|
7
|
+
export async function loadManifest(rootDir) {
|
|
8
|
+
const file = join(rootDir, "manifest.json");
|
|
9
|
+
try {
|
|
10
|
+
const raw = await fs.readFile(file, "utf8");
|
|
11
|
+
const parsed = JSON.parse(raw);
|
|
12
|
+
if (parsed?.schemaVersion !== SCHEMA_VERSION) {
|
|
13
|
+
throw new Error(`ai-trash: unsupported manifest schemaVersion ${parsed?.schemaVersion}`);
|
|
14
|
+
}
|
|
15
|
+
if (!Array.isArray(parsed.entries)) parsed.entries = [];
|
|
16
|
+
return parsed;
|
|
17
|
+
} catch (err) {
|
|
18
|
+
if (err.code === "ENOENT") return { schemaVersion: SCHEMA_VERSION, entries: [] };
|
|
19
|
+
throw err;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function saveManifest(rootDir, manifest) {
|
|
24
|
+
const file = join(rootDir, "manifest.json");
|
|
25
|
+
await fs.mkdir(dirname(file), { recursive: true });
|
|
26
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
27
|
+
await fs.writeFile(tmp, JSON.stringify(manifest, null, 2), {
|
|
28
|
+
encoding: "utf8",
|
|
29
|
+
mode: 0o600,
|
|
30
|
+
});
|
|
31
|
+
await fs.rename(tmp, file);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function addEntry(manifest, partial) {
|
|
35
|
+
if (!partial?.sourcePath) throw new Error("ai-trash: sourcePath required");
|
|
36
|
+
if (typeof partial.sizeBytes !== "number" || partial.sizeBytes < 0) {
|
|
37
|
+
throw new Error("ai-trash: sizeBytes must be a non-negative number");
|
|
38
|
+
}
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
const entry = {
|
|
41
|
+
id: ulid(now),
|
|
42
|
+
createdAt: now,
|
|
43
|
+
sourcePath: partial.sourcePath,
|
|
44
|
+
snapshotPath: partial.snapshotPath ?? null,
|
|
45
|
+
sizeBytes: partial.sizeBytes,
|
|
46
|
+
command: partial.command ?? null,
|
|
47
|
+
origin: partial.origin ?? "unknown",
|
|
48
|
+
};
|
|
49
|
+
manifest.entries.push(entry);
|
|
50
|
+
return entry;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function listEntries(manifest) {
|
|
54
|
+
return [...manifest.entries].sort((a, b) => a.id.localeCompare(b.id));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function removeEntry(manifest, id) {
|
|
58
|
+
const idx = manifest.entries.findIndex((e) => e.id === id);
|
|
59
|
+
if (idx < 0) return null;
|
|
60
|
+
return manifest.entries.splice(idx, 1)[0];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function expireBefore(manifest, cutoffMs) {
|
|
64
|
+
const expired = [];
|
|
65
|
+
manifest.entries = manifest.entries.filter((e) => {
|
|
66
|
+
if (e.createdAt < cutoffMs) {
|
|
67
|
+
expired.push(e);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
});
|
|
72
|
+
return expired;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function enforceLruQuota(manifest, maxBytes) {
|
|
76
|
+
if (typeof maxBytes !== "number" || maxBytes < 0) {
|
|
77
|
+
throw new Error("ai-trash: maxBytes must be a non-negative number");
|
|
78
|
+
}
|
|
79
|
+
const sorted = listEntries(manifest);
|
|
80
|
+
const total = sorted.reduce((sum, e) => sum + e.sizeBytes, 0);
|
|
81
|
+
const evicted = [];
|
|
82
|
+
let running = total;
|
|
83
|
+
for (const entry of sorted) {
|
|
84
|
+
if (running <= maxBytes) break;
|
|
85
|
+
evicted.push(entry);
|
|
86
|
+
running -= entry.sizeBytes;
|
|
87
|
+
}
|
|
88
|
+
const evictedIds = new Set(evicted.map((e) => e.id));
|
|
89
|
+
manifest.entries = manifest.entries.filter((e) => !evictedIds.has(e.id));
|
|
90
|
+
return evicted;
|
|
91
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
|
|
3
|
+
const DIR_MODE = 0o700;
|
|
4
|
+
const FILE_MODE = 0o600;
|
|
5
|
+
|
|
6
|
+
export async function ensureSecureDir(path) {
|
|
7
|
+
await fs.mkdir(path, { recursive: true, mode: DIR_MODE });
|
|
8
|
+
await fs.chmod(path, DIR_MODE);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function lockdownFile(path) {
|
|
12
|
+
await fs.chmod(path, FILE_MODE);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function assertOwnedByCurrentUser(path) {
|
|
16
|
+
if (process.platform === "win32") return;
|
|
17
|
+
const stats = await fs.stat(path);
|
|
18
|
+
if (typeof process.getuid !== "function") return;
|
|
19
|
+
if (stats.uid !== process.getuid()) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`ai-trash: ${path} is owned by uid ${stats.uid}, expected ${process.getuid()}`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { DIR_MODE, FILE_MODE };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { basename, join } from "node:path";
|
|
3
|
+
import { ulid } from "./ulid.js";
|
|
4
|
+
import { ensureSecureDir, lockdownFile } from "./permissions.js";
|
|
5
|
+
import { appendLogEntry } from "./logger.js";
|
|
6
|
+
|
|
7
|
+
async function statOrNull(path) {
|
|
8
|
+
try {
|
|
9
|
+
return await fs.lstat(path);
|
|
10
|
+
} catch (err) {
|
|
11
|
+
if (err.code === "ENOENT") return null;
|
|
12
|
+
throw err;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function snapshotFile(rootDir, sourcePath, options = {}) {
|
|
17
|
+
const stat = await statOrNull(sourcePath);
|
|
18
|
+
if (!stat) throw new Error(`ai-trash: source not found: ${sourcePath}`);
|
|
19
|
+
if (stat.isDirectory()) {
|
|
20
|
+
throw new Error("ai-trash: directory snapshots not implemented in MVP");
|
|
21
|
+
}
|
|
22
|
+
const id = ulid();
|
|
23
|
+
const storeDir = join(rootDir, "store", id);
|
|
24
|
+
await ensureSecureDir(storeDir);
|
|
25
|
+
const snapshotPath = join(storeDir, basename(sourcePath));
|
|
26
|
+
await fs.copyFile(sourcePath, snapshotPath);
|
|
27
|
+
await lockdownFile(snapshotPath);
|
|
28
|
+
const entry = {
|
|
29
|
+
id,
|
|
30
|
+
createdAt: Date.now(),
|
|
31
|
+
sourcePath,
|
|
32
|
+
snapshotPath,
|
|
33
|
+
sizeBytes: stat.size,
|
|
34
|
+
command: options.command ?? null,
|
|
35
|
+
origin: options.origin ?? "unknown",
|
|
36
|
+
};
|
|
37
|
+
await appendLogEntry(rootDir, "snapshot.create", {
|
|
38
|
+
id,
|
|
39
|
+
sourcePath,
|
|
40
|
+
snapshotPath,
|
|
41
|
+
sizeBytes: stat.size,
|
|
42
|
+
});
|
|
43
|
+
return entry;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function restoreSnapshot(rootDir, entry, targetPath) {
|
|
47
|
+
const target = targetPath ?? entry.sourcePath;
|
|
48
|
+
const exists = await statOrNull(target);
|
|
49
|
+
if (exists) throw new Error(`ai-trash: refusing to overwrite ${target}`);
|
|
50
|
+
await fs.mkdir(join(target, ".."), { recursive: true });
|
|
51
|
+
await fs.copyFile(entry.snapshotPath, target);
|
|
52
|
+
await appendLogEntry(rootDir, "snapshot.restore", {
|
|
53
|
+
id: entry.id,
|
|
54
|
+
snapshotPath: entry.snapshotPath,
|
|
55
|
+
targetPath: target,
|
|
56
|
+
});
|
|
57
|
+
return target;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function purgeSnapshot(rootDir, entry) {
|
|
61
|
+
await fs.rm(join(rootDir, "store", entry.id), { recursive: true, force: true });
|
|
62
|
+
await appendLogEntry(rootDir, "snapshot.purge", {
|
|
63
|
+
id: entry.id,
|
|
64
|
+
sizeBytes: entry.sizeBytes,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Tiny ULID generator (Crockford base32, 26 chars, monotonic within ms).
|
|
2
|
+
// We keep this self-contained to avoid pulling a runtime dep into the
|
|
3
|
+
// safety-net package — fewer transitive deps = fewer supply-chain surfaces
|
|
4
|
+
// that an attacker could pivot through to reach the trash store.
|
|
5
|
+
|
|
6
|
+
import { randomBytes } from "node:crypto";
|
|
7
|
+
|
|
8
|
+
const ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
9
|
+
|
|
10
|
+
let lastMs = 0;
|
|
11
|
+
let lastRandom = new Uint8Array(10);
|
|
12
|
+
|
|
13
|
+
function encodeTime(ms) {
|
|
14
|
+
let out = "";
|
|
15
|
+
for (let i = 9; i >= 0; i--) {
|
|
16
|
+
out = ENCODING[ms % 32] + out;
|
|
17
|
+
ms = Math.floor(ms / 32);
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function encodeRandom(bytes) {
|
|
23
|
+
let out = "";
|
|
24
|
+
for (let i = 0; i < 16; i++) {
|
|
25
|
+
const byteIndex = Math.floor((i * 5) / 8);
|
|
26
|
+
const bitOffset = (i * 5) % 8;
|
|
27
|
+
const hi = bytes[byteIndex] ?? 0;
|
|
28
|
+
const lo = bytes[byteIndex + 1] ?? 0;
|
|
29
|
+
const value = ((hi << 8) | lo) >> (11 - bitOffset);
|
|
30
|
+
out += ENCODING[value & 31];
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function bumpRandom(buf) {
|
|
36
|
+
for (let i = buf.length - 1; i >= 0; i--) {
|
|
37
|
+
if (buf[i] === 0xff) {
|
|
38
|
+
buf[i] = 0;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
buf[i] += 1;
|
|
42
|
+
return buf;
|
|
43
|
+
}
|
|
44
|
+
throw new Error("ulid: random overflow within the same millisecond");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function ulid(nowMs = Date.now()) {
|
|
48
|
+
if (nowMs === lastMs) {
|
|
49
|
+
lastRandom = bumpRandom(lastRandom);
|
|
50
|
+
} else {
|
|
51
|
+
lastMs = nowMs;
|
|
52
|
+
lastRandom = new Uint8Array(randomBytes(10));
|
|
53
|
+
}
|
|
54
|
+
return encodeTime(nowMs) + encodeRandom(lastRandom);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function decodeTimeFromUlid(id) {
|
|
58
|
+
const slice = id.slice(0, 10);
|
|
59
|
+
let ms = 0;
|
|
60
|
+
for (const ch of slice) {
|
|
61
|
+
const v = ENCODING.indexOf(ch);
|
|
62
|
+
if (v < 0) throw new Error(`ulid: invalid char ${ch}`);
|
|
63
|
+
ms = ms * 32 + v;
|
|
64
|
+
}
|
|
65
|
+
return ms;
|
|
66
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Karajan HU Board
|
|
2
|
+
|
|
3
|
+
A web dashboard that visualizes all HU (User Story) stories managed by Karajan Code. Reads from `~/.karajan/hu-stories/` and `~/.karajan/sessions/`, groups by project, and provides a read-only kanban board with quality metrics and session timelines.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### Without Docker
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd packages/hu-board
|
|
11
|
+
npm install
|
|
12
|
+
npm start
|
|
13
|
+
# Open http://localhost:4000
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### With Docker
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
cd packages/hu-board
|
|
20
|
+
docker compose up -d
|
|
21
|
+
# Open http://localhost:4000
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Development (auto-reload)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm run dev
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Configuration
|
|
31
|
+
|
|
32
|
+
| Variable | Default | Description |
|
|
33
|
+
|----------|---------|-------------|
|
|
34
|
+
| `PORT` | `4000` | Server port (auto-detects next available if busy) |
|
|
35
|
+
| `KJ_HOME` | `~/.karajan` | Path to Karajan data directory |
|
|
36
|
+
|
|
37
|
+
You can also use `--port` flag:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
node src/server.js --port 5000
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Architecture
|
|
44
|
+
|
|
45
|
+
- **Backend**: Node.js + Express serving REST API + static files
|
|
46
|
+
- **Frontend**: Vanilla JS single-page app with hash-based routing
|
|
47
|
+
- **Database**: SQLite (via `better-sqlite3`) at `$KJ_HOME/hu-board.db`
|
|
48
|
+
- **Sync**: Chokidar watches JSON files and syncs to SQLite in real-time
|
|
49
|
+
|
|
50
|
+
The SQLite database is a read index over the JSON source files. If deleted, it rebuilds automatically on next startup.
|
|
51
|
+
|
|
52
|
+
## API Endpoints
|
|
53
|
+
|
|
54
|
+
| Method | Path | Description |
|
|
55
|
+
|--------|------|-------------|
|
|
56
|
+
| GET | `/api/dashboard` | Global statistics |
|
|
57
|
+
| GET | `/api/projects` | List all projects with counts |
|
|
58
|
+
| GET | `/api/projects/:id` | Project detail |
|
|
59
|
+
| GET | `/api/projects/:id/stories` | Stories for a project |
|
|
60
|
+
| GET | `/api/stories/:id` | Story detail with quality, AC, context requests |
|
|
61
|
+
| GET | `/api/projects/:id/sessions` | Sessions for a project |
|
|
62
|
+
| GET | `/api/sessions` | All sessions |
|
|
63
|
+
| GET | `/api/sessions/:id` | Session detail with timeline |
|
|
64
|
+
|
|
65
|
+
## Views
|
|
66
|
+
|
|
67
|
+
1. **Dashboard** - Global stats cards + project overview grid
|
|
68
|
+
2. **Board** - Kanban columns (Pending / Needs Context / Certified / Done)
|
|
69
|
+
3. **Sessions** - Timeline of Karajan pipeline sessions with stages and duration
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@karajan/hu-board",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "HU Story Board dashboard for Karajan Code",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"private": true,
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22.12.0"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node src/server.js",
|
|
12
|
+
"dev": "node --watch src/server.js",
|
|
13
|
+
"test": "vitest run"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"karajan-core": "*",
|
|
17
|
+
"better-sqlite3": "^12.10.0",
|
|
18
|
+
"chokidar": "^5.0.0",
|
|
19
|
+
"express": "^5.1.0",
|
|
20
|
+
"express-rate-limit": "^8.5.0",
|
|
21
|
+
"helmet": "^8.1.0",
|
|
22
|
+
"js-yaml": "^4.2.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"supertest": "^7.1.0",
|
|
26
|
+
"vitest": "^4.0.0"
|
|
27
|
+
}
|
|
28
|
+
}
|