kodelyth-ecc 1.2.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/.agent/rules/README.md +108 -0
- package/.agent/rules/agents.md +94 -0
- package/.agent/rules/code-review.md +124 -0
- package/.agent/rules/coding-style.md +122 -0
- package/.agent/rules/design-quality.md +63 -0
- package/.agent/rules/development-workflow.md +44 -0
- package/.agent/rules/git-mastery.md +366 -0
- package/.agent/rules/git-workflow.md +24 -0
- package/.agent/rules/hooks.md +25 -0
- package/.agent/rules/kodelyth-always-on.md +63 -0
- package/.agent/rules/kodelyth-quickstart.md +207 -0
- package/.agent/rules/observability.md +390 -0
- package/.agent/rules/patterns.md +50 -0
- package/.agent/rules/performance.md +178 -0
- package/.agent/rules/security.md +58 -0
- package/.agent/rules/smart-debug.md +241 -0
- package/.agent/rules/soul.md +32 -0
- package/.agent/rules/testing.md +46 -0
- package/.agent/skills/api-guardian.md +279 -0
- package/.agent/skills/architect.md +211 -0
- package/.agent/skills/build-error-resolver.md +114 -0
- package/.agent/skills/chief-of-staff.md +151 -0
- package/.agent/skills/code-architect.md +71 -0
- package/.agent/skills/code-explorer.md +69 -0
- package/.agent/skills/code-reviewer.md +237 -0
- package/.agent/skills/code-simplifier.md +47 -0
- package/.agent/skills/comment-analyzer.md +45 -0
- package/.agent/skills/conversation-analyzer.md +52 -0
- package/.agent/skills/cpp-build-resolver.md +90 -0
- package/.agent/skills/cpp-reviewer.md +72 -0
- package/.agent/skills/csharp-reviewer.md +101 -0
- package/.agent/skills/dart-build-resolver.md +201 -0
- package/.agent/skills/database-reviewer.md +91 -0
- package/.agent/skills/debug-detective.md +409 -0
- package/.agent/skills/doc-updater.md +107 -0
- package/.agent/skills/docs-lookup.md +68 -0
- package/.agent/skills/e2e-runner.md +107 -0
- package/.agent/skills/flutter-reviewer.md +243 -0
- package/.agent/skills/gan-evaluator.md +209 -0
- package/.agent/skills/gan-generator.md +131 -0
- package/.agent/skills/gan-planner.md +99 -0
- package/.agent/skills/go-build-resolver.md +94 -0
- package/.agent/skills/go-reviewer.md +76 -0
- package/.agent/skills/harness-optimizer.md +35 -0
- package/.agent/skills/healthcare-reviewer.md +83 -0
- package/.agent/skills/java-build-resolver.md +153 -0
- package/.agent/skills/java-reviewer.md +92 -0
- package/.agent/skills/kodelyth-advisor.md +172 -0
- package/.agent/skills/kotlin-build-resolver.md +118 -0
- package/.agent/skills/kotlin-reviewer.md +159 -0
- package/.agent/skills/loop-operator.md +36 -0
- package/.agent/skills/migration-guide.md +368 -0
- package/.agent/skills/opensource-forker.md +198 -0
- package/.agent/skills/opensource-packager.md +249 -0
- package/.agent/skills/opensource-sanitizer.md +188 -0
- package/.agent/skills/pair-programmer.md +260 -0
- package/.agent/skills/performance-optimizer.md +446 -0
- package/.agent/skills/planner.md +212 -0
- package/.agent/skills/pr-test-analyzer.md +45 -0
- package/.agent/skills/python-reviewer.md +98 -0
- package/.agent/skills/pytorch-build-resolver.md +120 -0
- package/.agent/skills/refactor-cleaner.md +85 -0
- package/.agent/skills/rust-build-resolver.md +148 -0
- package/.agent/skills/rust-reviewer.md +94 -0
- package/.agent/skills/security-reviewer.md +108 -0
- package/.agent/skills/seo-specialist.md +62 -0
- package/.agent/skills/silent-failure-hunter.md +50 -0
- package/.agent/skills/tdd-guide.md +91 -0
- package/.agent/skills/type-design-analyzer.md +41 -0
- package/.agent/skills/typescript-reviewer.md +112 -0
- package/.agent/skills/ux-reviewer.md +483 -0
- package/.agent/workflows/agent-sort.md +23 -0
- package/.agent/workflows/aside.md +164 -0
- package/.agent/workflows/build-fix.md +62 -0
- package/.agent/workflows/checkpoint.md +74 -0
- package/.agent/workflows/claw.md +23 -0
- package/.agent/workflows/code-review.md +289 -0
- package/.agent/workflows/context-budget.md +23 -0
- package/.agent/workflows/cpp-build.md +173 -0
- package/.agent/workflows/cpp-review.md +132 -0
- package/.agent/workflows/cpp-test.md +251 -0
- package/.agent/workflows/devfleet.md +23 -0
- package/.agent/workflows/docs.md +23 -0
- package/.agent/workflows/e2e.md +268 -0
- package/.agent/workflows/eval.md +23 -0
- package/.agent/workflows/evolve.md +178 -0
- package/.agent/workflows/feature-dev.md +49 -0
- package/.agent/workflows/flutter-build.md +164 -0
- package/.agent/workflows/flutter-review.md +116 -0
- package/.agent/workflows/flutter-test.md +144 -0
- package/.agent/workflows/gan-build.md +99 -0
- package/.agent/workflows/gan-design.md +35 -0
- package/.agent/workflows/go-build.md +183 -0
- package/.agent/workflows/go-review.md +148 -0
- package/.agent/workflows/go-test.md +268 -0
- package/.agent/workflows/gradle-build.md +70 -0
- package/.agent/workflows/harness-audit.md +73 -0
- package/.agent/workflows/hookify-configure.md +14 -0
- package/.agent/workflows/hookify-help.md +46 -0
- package/.agent/workflows/hookify-list.md +21 -0
- package/.agent/workflows/hookify.md +50 -0
- package/.agent/workflows/instinct-export.md +66 -0
- package/.agent/workflows/instinct-import.md +114 -0
- package/.agent/workflows/instinct-status.md +59 -0
- package/.agent/workflows/jira.md +106 -0
- package/.agent/workflows/kotlin-build.md +174 -0
- package/.agent/workflows/kotlin-review.md +140 -0
- package/.agent/workflows/kotlin-test.md +312 -0
- package/.agent/workflows/learn-eval.md +116 -0
- package/.agent/workflows/learn.md +70 -0
- package/.agent/workflows/loop-start.md +32 -0
- package/.agent/workflows/loop-status.md +24 -0
- package/.agent/workflows/model-route.md +26 -0
- package/.agent/workflows/multi-backend.md +158 -0
- package/.agent/workflows/multi-execute.md +315 -0
- package/.agent/workflows/multi-frontend.md +158 -0
- package/.agent/workflows/multi-plan.md +268 -0
- package/.agent/workflows/multi-workflow.md +191 -0
- package/.agent/workflows/orchestrate.md +135 -0
- package/.agent/workflows/plan.md +117 -0
- package/.agent/workflows/pm2.md +272 -0
- package/.agent/workflows/projects.md +39 -0
- package/.agent/workflows/promote.md +41 -0
- package/.agent/workflows/prompt-optimize.md +23 -0
- package/.agent/workflows/prp-commit.md +112 -0
- package/.agent/workflows/prp-implement.md +385 -0
- package/.agent/workflows/prp-plan.md +502 -0
- package/.agent/workflows/prp-pr.md +184 -0
- package/.agent/workflows/prp-prd.md +447 -0
- package/.agent/workflows/prune.md +31 -0
- package/.agent/workflows/python-review.md +297 -0
- package/.agent/workflows/quality-gate.md +29 -0
- package/.agent/workflows/refactor-clean.md +80 -0
- package/.agent/workflows/resume-session.md +156 -0
- package/.agent/workflows/review-pr.md +37 -0
- package/.agent/workflows/rules-distill.md +20 -0
- package/.agent/workflows/rust-build.md +187 -0
- package/.agent/workflows/rust-review.md +142 -0
- package/.agent/workflows/rust-test.md +308 -0
- package/.agent/workflows/santa-loop.md +175 -0
- package/.agent/workflows/save-session.md +275 -0
- package/.agent/workflows/sessions.md +333 -0
- package/.agent/workflows/setup-pm.md +80 -0
- package/.agent/workflows/skill-create.md +174 -0
- package/.agent/workflows/skill-health.md +54 -0
- package/.agent/workflows/tdd.md +231 -0
- package/.agent/workflows/test-coverage.md +69 -0
- package/.agent/workflows/update-codemaps.md +72 -0
- package/.agent/workflows/update-docs.md +84 -0
- package/.agent/workflows/verify.md +23 -0
- package/.github/workflows/ci.yml +46 -0
- package/.github/workflows/publish.yml +41 -0
- package/AGENTS.md +209 -0
- package/CHANGELOG.md +236 -0
- package/CLAUDE.md +90 -0
- package/CONTRIBUTING.md +255 -0
- package/KODELYTH.md +74 -0
- package/LICENSE +21 -0
- package/README.md +414 -0
- package/SECURITY.md +77 -0
- package/SOUL.md +32 -0
- package/VERSION +1 -0
- package/agents/api-guardian.md +279 -0
- package/agents/architect.md +211 -0
- package/agents/build-error-resolver.md +114 -0
- package/agents/chief-of-staff.md +151 -0
- package/agents/code-architect.md +71 -0
- package/agents/code-explorer.md +69 -0
- package/agents/code-reviewer.md +237 -0
- package/agents/code-simplifier.md +47 -0
- package/agents/comment-analyzer.md +45 -0
- package/agents/conversation-analyzer.md +52 -0
- package/agents/cpp-build-resolver.md +90 -0
- package/agents/cpp-reviewer.md +72 -0
- package/agents/csharp-reviewer.md +101 -0
- package/agents/dart-build-resolver.md +201 -0
- package/agents/database-reviewer.md +91 -0
- package/agents/debug-detective.md +409 -0
- package/agents/doc-updater.md +107 -0
- package/agents/docs-lookup.md +68 -0
- package/agents/e2e-runner.md +107 -0
- package/agents/flutter-reviewer.md +243 -0
- package/agents/gan-evaluator.md +209 -0
- package/agents/gan-generator.md +131 -0
- package/agents/gan-planner.md +99 -0
- package/agents/go-build-resolver.md +94 -0
- package/agents/go-reviewer.md +76 -0
- package/agents/harness-optimizer.md +35 -0
- package/agents/healthcare-reviewer.md +83 -0
- package/agents/java-build-resolver.md +153 -0
- package/agents/java-reviewer.md +92 -0
- package/agents/kodelyth-advisor.md +172 -0
- package/agents/kotlin-build-resolver.md +118 -0
- package/agents/kotlin-reviewer.md +159 -0
- package/agents/loop-operator.md +36 -0
- package/agents/migration-guide.md +368 -0
- package/agents/opensource-forker.md +198 -0
- package/agents/opensource-packager.md +249 -0
- package/agents/opensource-sanitizer.md +188 -0
- package/agents/pair-programmer.md +260 -0
- package/agents/performance-optimizer.md +446 -0
- package/agents/planner.md +212 -0
- package/agents/pr-test-analyzer.md +45 -0
- package/agents/python-reviewer.md +98 -0
- package/agents/pytorch-build-resolver.md +120 -0
- package/agents/refactor-cleaner.md +85 -0
- package/agents/rust-build-resolver.md +148 -0
- package/agents/rust-reviewer.md +94 -0
- package/agents/security-reviewer.md +108 -0
- package/agents/seo-specialist.md +62 -0
- package/agents/silent-failure-hunter.md +50 -0
- package/agents/tdd-guide.md +91 -0
- package/agents/type-design-analyzer.md +41 -0
- package/agents/typescript-reviewer.md +112 -0
- package/agents/ux-reviewer.md +483 -0
- package/bin/kodelyth-ecc.js +87 -0
- package/commands/agent-sort.md +23 -0
- package/commands/aside.md +164 -0
- package/commands/build-fix.md +62 -0
- package/commands/checkpoint.md +74 -0
- package/commands/claw.md +23 -0
- package/commands/code-review.md +289 -0
- package/commands/context-budget.md +23 -0
- package/commands/cpp-build.md +173 -0
- package/commands/cpp-review.md +132 -0
- package/commands/cpp-test.md +251 -0
- package/commands/devfleet.md +23 -0
- package/commands/docs.md +23 -0
- package/commands/e2e.md +268 -0
- package/commands/eval.md +23 -0
- package/commands/evolve.md +178 -0
- package/commands/feature-dev.md +49 -0
- package/commands/flutter-build.md +164 -0
- package/commands/flutter-review.md +116 -0
- package/commands/flutter-test.md +144 -0
- package/commands/gan-build.md +99 -0
- package/commands/gan-design.md +35 -0
- package/commands/go-build.md +183 -0
- package/commands/go-review.md +148 -0
- package/commands/go-test.md +268 -0
- package/commands/gradle-build.md +70 -0
- package/commands/harness-audit.md +73 -0
- package/commands/hookify-configure.md +14 -0
- package/commands/hookify-help.md +46 -0
- package/commands/hookify-list.md +21 -0
- package/commands/hookify.md +50 -0
- package/commands/instinct-export.md +66 -0
- package/commands/instinct-import.md +114 -0
- package/commands/instinct-status.md +59 -0
- package/commands/jira.md +106 -0
- package/commands/kotlin-build.md +174 -0
- package/commands/kotlin-review.md +140 -0
- package/commands/kotlin-test.md +312 -0
- package/commands/learn-eval.md +116 -0
- package/commands/learn.md +70 -0
- package/commands/loop-start.md +32 -0
- package/commands/loop-status.md +24 -0
- package/commands/model-route.md +26 -0
- package/commands/multi-backend.md +158 -0
- package/commands/multi-execute.md +315 -0
- package/commands/multi-frontend.md +158 -0
- package/commands/multi-plan.md +268 -0
- package/commands/multi-workflow.md +191 -0
- package/commands/orchestrate.md +135 -0
- package/commands/plan.md +117 -0
- package/commands/pm2.md +272 -0
- package/commands/projects.md +39 -0
- package/commands/promote.md +41 -0
- package/commands/prompt-optimize.md +23 -0
- package/commands/prp-commit.md +112 -0
- package/commands/prp-implement.md +385 -0
- package/commands/prp-plan.md +502 -0
- package/commands/prp-pr.md +184 -0
- package/commands/prp-prd.md +447 -0
- package/commands/prune.md +31 -0
- package/commands/python-review.md +297 -0
- package/commands/quality-gate.md +29 -0
- package/commands/refactor-clean.md +80 -0
- package/commands/resume-session.md +156 -0
- package/commands/review-pr.md +37 -0
- package/commands/rules-distill.md +20 -0
- package/commands/rust-build.md +187 -0
- package/commands/rust-review.md +142 -0
- package/commands/rust-test.md +308 -0
- package/commands/santa-loop.md +175 -0
- package/commands/save-session.md +275 -0
- package/commands/sessions.md +333 -0
- package/commands/setup-pm.md +80 -0
- package/commands/skill-create.md +174 -0
- package/commands/skill-health.md +54 -0
- package/commands/tdd.md +231 -0
- package/commands/test-coverage.md +69 -0
- package/commands/update-codemaps.md +72 -0
- package/commands/update-docs.md +84 -0
- package/commands/verify.md +23 -0
- package/contexts/dev.md +20 -0
- package/contexts/research.md +26 -0
- package/contexts/review.md +22 -0
- package/dashboard/lib/agent-tracker.js +366 -0
- package/dashboard/lib/aggregator.js +118 -0
- package/dashboard/lib/cost-calculator.js +50 -0
- package/dashboard/lib/platform-detector.js +89 -0
- package/dashboard/lib/readers/antigravity-reader.js +113 -0
- package/dashboard/lib/readers/claude-reader.js +135 -0
- package/dashboard/lib/readers/codex-reader.js +192 -0
- package/dashboard/lib/readers/cursor-reader.js +135 -0
- package/dashboard/lib/readers/opencode-reader.js +201 -0
- package/dashboard/lib/readers/windsurf-reader.js +126 -0
- package/dashboard/package.json +24 -0
- package/dashboard/public/index.html +1147 -0
- package/dashboard/server.js +119 -0
- package/hooks/README.md +220 -0
- package/hooks/hooks.json +420 -0
- package/install.ps1 +190 -0
- package/install.sh +583 -0
- package/package.json +33 -0
- package/rules/README.md +111 -0
- package/rules/common/agents.md +50 -0
- package/rules/common/code-review.md +124 -0
- package/rules/common/coding-style.md +122 -0
- package/rules/common/development-workflow.md +44 -0
- package/rules/common/git-workflow.md +24 -0
- package/rules/common/hooks.md +30 -0
- package/rules/common/patterns.md +31 -0
- package/rules/common/performance.md +178 -0
- package/rules/common/security.md +29 -0
- package/rules/common/testing.md +57 -0
- package/rules/cpp/coding-style.md +44 -0
- package/rules/cpp/hooks.md +39 -0
- package/rules/cpp/patterns.md +51 -0
- package/rules/cpp/security.md +51 -0
- package/rules/cpp/testing.md +44 -0
- package/rules/csharp/coding-style.md +72 -0
- package/rules/csharp/hooks.md +25 -0
- package/rules/csharp/patterns.md +50 -0
- package/rules/csharp/security.md +58 -0
- package/rules/csharp/testing.md +46 -0
- package/rules/dart/coding-style.md +159 -0
- package/rules/dart/hooks.md +66 -0
- package/rules/dart/patterns.md +261 -0
- package/rules/dart/security.md +135 -0
- package/rules/dart/testing.md +215 -0
- package/rules/golang/coding-style.md +32 -0
- package/rules/golang/hooks.md +17 -0
- package/rules/golang/patterns.md +45 -0
- package/rules/golang/security.md +34 -0
- package/rules/golang/testing.md +31 -0
- package/rules/java/coding-style.md +114 -0
- package/rules/java/hooks.md +18 -0
- package/rules/java/patterns.md +146 -0
- package/rules/java/security.md +100 -0
- package/rules/java/testing.md +131 -0
- package/rules/kotlin/coding-style.md +86 -0
- package/rules/kotlin/hooks.md +17 -0
- package/rules/kotlin/patterns.md +146 -0
- package/rules/kotlin/security.md +82 -0
- package/rules/kotlin/testing.md +128 -0
- package/rules/perl/coding-style.md +46 -0
- package/rules/perl/hooks.md +22 -0
- package/rules/perl/patterns.md +76 -0
- package/rules/perl/security.md +69 -0
- package/rules/perl/testing.md +54 -0
- package/rules/php/coding-style.md +40 -0
- package/rules/php/hooks.md +24 -0
- package/rules/php/patterns.md +33 -0
- package/rules/php/security.md +37 -0
- package/rules/php/testing.md +39 -0
- package/rules/python/coding-style.md +42 -0
- package/rules/python/hooks.md +19 -0
- package/rules/python/patterns.md +39 -0
- package/rules/python/security.md +30 -0
- package/rules/python/testing.md +38 -0
- package/rules/rust/coding-style.md +151 -0
- package/rules/rust/hooks.md +16 -0
- package/rules/rust/patterns.md +168 -0
- package/rules/rust/security.md +141 -0
- package/rules/rust/testing.md +154 -0
- package/rules/swift/coding-style.md +47 -0
- package/rules/swift/hooks.md +20 -0
- package/rules/swift/patterns.md +66 -0
- package/rules/swift/security.md +33 -0
- package/rules/swift/testing.md +45 -0
- package/rules/typescript/coding-style.md +199 -0
- package/rules/typescript/hooks.md +22 -0
- package/rules/typescript/patterns.md +52 -0
- package/rules/typescript/security.md +28 -0
- package/rules/typescript/testing.md +18 -0
- package/rules/web/coding-style.md +96 -0
- package/rules/web/design-quality.md +63 -0
- package/rules/web/hooks.md +120 -0
- package/rules/web/patterns.md +79 -0
- package/rules/web/performance.md +64 -0
- package/rules/web/security.md +57 -0
- package/rules/web/testing.md +55 -0
- package/rules/zh/README.md +108 -0
- package/rules/zh/agents.md +50 -0
- package/rules/zh/code-review.md +124 -0
- package/rules/zh/coding-style.md +48 -0
- package/rules/zh/development-workflow.md +44 -0
- package/rules/zh/git-workflow.md +24 -0
- package/rules/zh/hooks.md +30 -0
- package/rules/zh/patterns.md +31 -0
- package/rules/zh/performance.md +55 -0
- package/rules/zh/security.md +29 -0
- package/rules/zh/testing.md +29 -0
- package/scripts/agent-tracker-hook.js +81 -0
- package/scripts/build-opencode.js +26 -0
- package/scripts/catalog.js +186 -0
- package/scripts/ci/catalog.js +648 -0
- package/scripts/ci/check-unicode-safety.js +246 -0
- package/scripts/ci/validate-agents.js +81 -0
- package/scripts/ci/validate-commands.js +136 -0
- package/scripts/ci/validate-hooks.js +239 -0
- package/scripts/ci/validate-install-manifests.js +214 -0
- package/scripts/ci/validate-no-personal-paths.js +63 -0
- package/scripts/ci/validate-rules.js +81 -0
- package/scripts/ci/validate-skills.js +56 -0
- package/scripts/claw.js +468 -0
- package/scripts/codemaps/generate.ts +330 -0
- package/scripts/codex/check-codex-global-state.sh +250 -0
- package/scripts/codex/install-global-git-hooks.sh +65 -0
- package/scripts/codex/merge-codex-config.js +317 -0
- package/scripts/codex/merge-mcp-config.js +335 -0
- package/scripts/codex-git-hooks/pre-commit +77 -0
- package/scripts/codex-git-hooks/pre-push +124 -0
- package/scripts/doctor.js +111 -0
- package/scripts/ecc.js +216 -0
- package/scripts/gan-harness.sh +299 -0
- package/scripts/harness-audit.js +735 -0
- package/scripts/hooks/auto-tmux-dev.js +88 -0
- package/scripts/hooks/branch-name-check.js +163 -0
- package/scripts/hooks/check-console-log.js +71 -0
- package/scripts/hooks/check-hook-enabled.js +12 -0
- package/scripts/hooks/config-protection.js +140 -0
- package/scripts/hooks/cost-tracker.js +78 -0
- package/scripts/hooks/design-quality-check.js +131 -0
- package/scripts/hooks/desktop-notify.js +168 -0
- package/scripts/hooks/doc-file-warning.js +90 -0
- package/scripts/hooks/evaluate-session.js +100 -0
- package/scripts/hooks/governance-capture.js +334 -0
- package/scripts/hooks/mcp-health-check.js +619 -0
- package/scripts/hooks/post-bash-build-complete.js +27 -0
- package/scripts/hooks/post-bash-command-log.js +73 -0
- package/scripts/hooks/post-bash-pr-created.js +36 -0
- package/scripts/hooks/post-edit-accumulator.js +78 -0
- package/scripts/hooks/post-edit-console-warn.js +54 -0
- package/scripts/hooks/post-edit-format.js +109 -0
- package/scripts/hooks/post-edit-typecheck.js +96 -0
- package/scripts/hooks/pre-bash-commit-quality.js +405 -0
- package/scripts/hooks/pre-bash-dev-server-block.js +187 -0
- package/scripts/hooks/pre-bash-git-push-reminder.js +28 -0
- package/scripts/hooks/pre-bash-tmux-reminder.js +33 -0
- package/scripts/hooks/pre-compact.js +48 -0
- package/scripts/hooks/pre-write-doc-warn.js +9 -0
- package/scripts/hooks/quality-gate.js +168 -0
- package/scripts/hooks/run-with-flags-shell.sh +36 -0
- package/scripts/hooks/run-with-flags.js +181 -0
- package/scripts/hooks/session-end-marker.js +67 -0
- package/scripts/hooks/session-end.js +301 -0
- package/scripts/hooks/session-start-bootstrap.js +161 -0
- package/scripts/hooks/session-start.js +492 -0
- package/scripts/hooks/smart-suggest.js +138 -0
- package/scripts/hooks/stop-format-typecheck.js +209 -0
- package/scripts/hooks/suggest-compact.js +80 -0
- package/scripts/hooks/test-reminder.js +128 -0
- package/scripts/install-apply.js +150 -0
- package/scripts/install-plan.js +266 -0
- package/scripts/lib/agent-compress.js +244 -0
- package/scripts/lib/hook-flags.js +74 -0
- package/scripts/lib/inspection.js +212 -0
- package/scripts/lib/install/apply.js +265 -0
- package/scripts/lib/install/config.js +89 -0
- package/scripts/lib/install/request.js +120 -0
- package/scripts/lib/install/runtime.js +54 -0
- package/scripts/lib/install-executor.js +672 -0
- package/scripts/lib/install-lifecycle.js +1226 -0
- package/scripts/lib/install-manifests.js +551 -0
- package/scripts/lib/install-state.js +313 -0
- package/scripts/lib/install-targets/antigravity-project.js +85 -0
- package/scripts/lib/install-targets/claude-home.js +10 -0
- package/scripts/lib/install-targets/codebuddy-project.js +50 -0
- package/scripts/lib/install-targets/codex-home.js +10 -0
- package/scripts/lib/install-targets/cursor-project.js +50 -0
- package/scripts/lib/install-targets/gemini-project.js +10 -0
- package/scripts/lib/install-targets/helpers.js +340 -0
- package/scripts/lib/install-targets/opencode-home.js +10 -0
- package/scripts/lib/install-targets/registry.js +70 -0
- package/scripts/lib/mcp-config.js +56 -0
- package/scripts/lib/observer-sessions.js +175 -0
- package/scripts/lib/orchestration-session.js +299 -0
- package/scripts/lib/package-manager.d.ts +119 -0
- package/scripts/lib/package-manager.js +431 -0
- package/scripts/lib/project-detect.js +428 -0
- package/scripts/lib/resolve-ecc-root.js +118 -0
- package/scripts/lib/resolve-formatter.js +185 -0
- package/scripts/lib/session-adapters/canonical-session.js +531 -0
- package/scripts/lib/session-adapters/claude-history.js +160 -0
- package/scripts/lib/session-adapters/dmux-tmux.js +90 -0
- package/scripts/lib/session-adapters/registry.js +127 -0
- package/scripts/lib/session-aliases.d.ts +136 -0
- package/scripts/lib/session-aliases.js +481 -0
- package/scripts/lib/session-manager.d.ts +132 -0
- package/scripts/lib/session-manager.js +533 -0
- package/scripts/lib/shell-split.js +86 -0
- package/scripts/lib/skill-evolution/dashboard.js +401 -0
- package/scripts/lib/skill-evolution/health.js +263 -0
- package/scripts/lib/skill-evolution/index.js +20 -0
- package/scripts/lib/skill-evolution/provenance.js +187 -0
- package/scripts/lib/skill-evolution/tracker.js +146 -0
- package/scripts/lib/skill-evolution/versioning.js +237 -0
- package/scripts/lib/skill-improvement/amendify.js +89 -0
- package/scripts/lib/skill-improvement/evaluate.js +59 -0
- package/scripts/lib/skill-improvement/health.js +118 -0
- package/scripts/lib/skill-improvement/observations.js +108 -0
- package/scripts/lib/state-store/index.js +191 -0
- package/scripts/lib/state-store/migrations.js +178 -0
- package/scripts/lib/state-store/queries.js +697 -0
- package/scripts/lib/state-store/schema.js +92 -0
- package/scripts/lib/tmux-worktree-orchestrator.js +598 -0
- package/scripts/lib/utils.d.ts +196 -0
- package/scripts/lib/utils.js +629 -0
- package/scripts/list-installed.js +91 -0
- package/scripts/orchestrate-codex-worker.sh +107 -0
- package/scripts/orchestrate-worktrees.js +108 -0
- package/scripts/orchestration-status.js +62 -0
- package/scripts/release.sh +83 -0
- package/scripts/repair.js +98 -0
- package/scripts/session-inspect.js +150 -0
- package/scripts/sessions-cli.js +178 -0
- package/scripts/setup-package-manager.js +204 -0
- package/scripts/skill-create-output.js +244 -0
- package/scripts/skills-health.js +132 -0
- package/scripts/status.js +177 -0
- package/scripts/sync-ecc-to-codex.sh +534 -0
- package/scripts/uninstall.js +97 -0
- package/skills/agent-eval/SKILL.md +145 -0
- package/skills/agent-harness-construction/SKILL.md +73 -0
- package/skills/agent-introspection-debugging/SKILL.md +153 -0
- package/skills/agent-payment-x402/SKILL.md +178 -0
- package/skills/agent-sort/SKILL.md +215 -0
- package/skills/agentic-engineering/SKILL.md +63 -0
- package/skills/ai-first-engineering/SKILL.md +51 -0
- package/skills/ai-regression-testing/SKILL.md +385 -0
- package/skills/android-clean-architecture/SKILL.md +339 -0
- package/skills/api-connector-builder/SKILL.md +121 -0
- package/skills/api-design/SKILL.md +523 -0
- package/skills/architecture-decision-records/SKILL.md +179 -0
- package/skills/article-writing/SKILL.md +79 -0
- package/skills/automation-audit-ops/SKILL.md +142 -0
- package/skills/autonomous-agent-harness/SKILL.md +267 -0
- package/skills/autonomous-loops/SKILL.md +610 -0
- package/skills/backend-patterns/SKILL.md +598 -0
- package/skills/benchmark/SKILL.md +93 -0
- package/skills/blueprint/SKILL.md +105 -0
- package/skills/brand-voice/SKILL.md +97 -0
- package/skills/brand-voice/references/voice-profile-schema.md +55 -0
- package/skills/browser-qa/SKILL.md +87 -0
- package/skills/bun-runtime/SKILL.md +84 -0
- package/skills/canary-watch/SKILL.md +99 -0
- package/skills/carrier-relationship-management/SKILL.md +212 -0
- package/skills/ck/SKILL.md +147 -0
- package/skills/ck/commands/forget.mjs +44 -0
- package/skills/ck/commands/info.mjs +24 -0
- package/skills/ck/commands/init.mjs +143 -0
- package/skills/ck/commands/list.mjs +40 -0
- package/skills/ck/commands/migrate.mjs +202 -0
- package/skills/ck/commands/resume.mjs +36 -0
- package/skills/ck/commands/save.mjs +210 -0
- package/skills/ck/commands/shared.mjs +387 -0
- package/skills/ck/hooks/session-start.mjs +224 -0
- package/skills/claude-api/SKILL.md +337 -0
- package/skills/claude-devfleet/SKILL.md +103 -0
- package/skills/click-path-audit/SKILL.md +244 -0
- package/skills/clickhouse-io/SKILL.md +439 -0
- package/skills/code-tour/SKILL.md +236 -0
- package/skills/codebase-onboarding/SKILL.md +233 -0
- package/skills/coding-standards/SKILL.md +549 -0
- package/skills/compose-multiplatform-patterns/SKILL.md +299 -0
- package/skills/configure-ecc/SKILL.md +367 -0
- package/skills/connections-optimizer/SKILL.md +189 -0
- package/skills/content-engine/SKILL.md +131 -0
- package/skills/content-hash-cache-pattern/SKILL.md +161 -0
- package/skills/context-budget/SKILL.md +135 -0
- package/skills/continuous-agent-loop/SKILL.md +45 -0
- package/skills/continuous-learning/SKILL.md +123 -0
- package/skills/continuous-learning/config.json +18 -0
- package/skills/continuous-learning/evaluate-session.sh +69 -0
- package/skills/continuous-learning-v2/SKILL.md +365 -0
- package/skills/continuous-learning-v2/agents/observer-loop.sh +271 -0
- package/skills/continuous-learning-v2/agents/observer.md +198 -0
- package/skills/continuous-learning-v2/agents/session-guardian.sh +150 -0
- package/skills/continuous-learning-v2/agents/start-observer.sh +244 -0
- package/skills/continuous-learning-v2/config.json +8 -0
- package/skills/continuous-learning-v2/hooks/observe.sh +428 -0
- package/skills/continuous-learning-v2/scripts/detect-project.sh +228 -0
- package/skills/continuous-learning-v2/scripts/instinct-cli.py +1426 -0
- package/skills/continuous-learning-v2/scripts/test_parse_instinct.py +984 -0
- package/skills/cost-aware-llm-pipeline/SKILL.md +183 -0
- package/skills/council/SKILL.md +203 -0
- package/skills/cpp-coding-standards/SKILL.md +723 -0
- package/skills/cpp-testing/SKILL.md +324 -0
- package/skills/crosspost/SKILL.md +111 -0
- package/skills/csharp-testing/SKILL.md +321 -0
- package/skills/customer-billing-ops/SKILL.md +140 -0
- package/skills/customs-trade-compliance/SKILL.md +263 -0
- package/skills/dart-flutter-patterns/SKILL.md +563 -0
- package/skills/dashboard-builder/SKILL.md +109 -0
- package/skills/data-scraper-agent/SKILL.md +764 -0
- package/skills/database-migrations/SKILL.md +429 -0
- package/skills/deep-research/SKILL.md +155 -0
- package/skills/defi-amm-security/SKILL.md +160 -0
- package/skills/deployment-patterns/SKILL.md +427 -0
- package/skills/design-system/SKILL.md +82 -0
- package/skills/django-patterns/SKILL.md +734 -0
- package/skills/django-security/SKILL.md +593 -0
- package/skills/django-tdd/SKILL.md +729 -0
- package/skills/django-verification/SKILL.md +469 -0
- package/skills/dmux-workflows/SKILL.md +191 -0
- package/skills/docker-patterns/SKILL.md +364 -0
- package/skills/documentation-lookup/SKILL.md +90 -0
- package/skills/dotnet-patterns/SKILL.md +321 -0
- package/skills/e2e-testing/SKILL.md +326 -0
- package/skills/ecc-tools-cost-audit/SKILL.md +160 -0
- package/skills/email-ops/SKILL.md +121 -0
- package/skills/energy-procurement/SKILL.md +228 -0
- package/skills/enterprise-agent-ops/SKILL.md +50 -0
- package/skills/eval-harness/SKILL.md +270 -0
- package/skills/evm-token-decimals/SKILL.md +130 -0
- package/skills/exa-search/SKILL.md +103 -0
- package/skills/fal-ai-media/SKILL.md +284 -0
- package/skills/finance-billing-ops/SKILL.md +127 -0
- package/skills/flutter-dart-code-review/SKILL.md +435 -0
- package/skills/foundation-models-on-device/SKILL.md +243 -0
- package/skills/frontend-design/SKILL.md +145 -0
- package/skills/frontend-patterns/SKILL.md +642 -0
- package/skills/frontend-slides/SKILL.md +184 -0
- package/skills/frontend-slides/STYLE_PRESETS.md +330 -0
- package/skills/gan-style-harness/SKILL.md +278 -0
- package/skills/git-mastery/SKILL.md +366 -0
- package/skills/git-workflow/SKILL.md +715 -0
- package/skills/github-ops/SKILL.md +144 -0
- package/skills/golang-patterns/SKILL.md +674 -0
- package/skills/golang-testing/SKILL.md +720 -0
- package/skills/google-workspace-ops/SKILL.md +95 -0
- package/skills/healthcare-cdss-patterns/SKILL.md +245 -0
- package/skills/healthcare-emr-patterns/SKILL.md +159 -0
- package/skills/healthcare-eval-harness/SKILL.md +207 -0
- package/skills/healthcare-phi-compliance/SKILL.md +145 -0
- package/skills/hexagonal-architecture/SKILL.md +276 -0
- package/skills/hipaa-compliance/SKILL.md +78 -0
- package/skills/hookify-rules/SKILL.md +128 -0
- package/skills/inventory-demand-planning/SKILL.md +247 -0
- package/skills/investor-materials/SKILL.md +96 -0
- package/skills/investor-outreach/SKILL.md +91 -0
- package/skills/iterative-retrieval/SKILL.md +211 -0
- package/skills/java-coding-standards/SKILL.md +147 -0
- package/skills/jira-integration/SKILL.md +293 -0
- package/skills/jpa-patterns/SKILL.md +151 -0
- package/skills/knowledge-ops/SKILL.md +154 -0
- package/skills/kodelyth-quickstart/SKILL.md +207 -0
- package/skills/kotlin-coroutines-flows/SKILL.md +284 -0
- package/skills/kotlin-exposed-patterns/SKILL.md +719 -0
- package/skills/kotlin-ktor-patterns/SKILL.md +689 -0
- package/skills/kotlin-patterns/SKILL.md +711 -0
- package/skills/kotlin-testing/SKILL.md +824 -0
- package/skills/laravel-patterns/SKILL.md +415 -0
- package/skills/laravel-plugin-discovery/SKILL.md +229 -0
- package/skills/laravel-security/SKILL.md +285 -0
- package/skills/laravel-tdd/SKILL.md +283 -0
- package/skills/laravel-verification/SKILL.md +179 -0
- package/skills/lead-intelligence/SKILL.md +321 -0
- package/skills/lead-intelligence/agents/enrichment-agent.md +85 -0
- package/skills/lead-intelligence/agents/mutual-mapper.md +75 -0
- package/skills/lead-intelligence/agents/outreach-drafter.md +98 -0
- package/skills/lead-intelligence/agents/signal-scorer.md +60 -0
- package/skills/liquid-glass-design/SKILL.md +279 -0
- package/skills/llm-trading-agent-security/SKILL.md +146 -0
- package/skills/logistics-exception-management/SKILL.md +222 -0
- package/skills/manim-video/SKILL.md +89 -0
- package/skills/manim-video/assets/network_graph_scene.py +52 -0
- package/skills/market-research/SKILL.md +75 -0
- package/skills/mcp-server-patterns/SKILL.md +67 -0
- package/skills/messages-ops/SKILL.md +104 -0
- package/skills/nanoclaw-repl/SKILL.md +33 -0
- package/skills/nestjs-patterns/SKILL.md +230 -0
- package/skills/nextjs-turbopack/SKILL.md +44 -0
- package/skills/nodejs-keccak256/SKILL.md +102 -0
- package/skills/nutrient-document-processing/SKILL.md +167 -0
- package/skills/nuxt4-patterns/SKILL.md +100 -0
- package/skills/observability/SKILL.md +390 -0
- package/skills/openclaw-persona-forge/SKILL.md +296 -0
- package/skills/openclaw-persona-forge/gacha.py +224 -0
- package/skills/openclaw-persona-forge/gacha.sh +5 -0
- package/skills/openclaw-persona-forge/references/avatar-style.md +124 -0
- package/skills/openclaw-persona-forge/references/boundary-rules.md +53 -0
- package/skills/openclaw-persona-forge/references/error-handling.md +53 -0
- package/skills/openclaw-persona-forge/references/identity-tension.md +48 -0
- package/skills/openclaw-persona-forge/references/naming-system.md +39 -0
- package/skills/openclaw-persona-forge/references/output-template.md +166 -0
- package/skills/opensource-pipeline/SKILL.md +255 -0
- package/skills/perl-patterns/SKILL.md +504 -0
- package/skills/perl-security/SKILL.md +503 -0
- package/skills/perl-testing/SKILL.md +475 -0
- package/skills/plankton-code-quality/SKILL.md +236 -0
- package/skills/postgres-patterns/SKILL.md +147 -0
- package/skills/product-capability/SKILL.md +141 -0
- package/skills/product-lens/SKILL.md +92 -0
- package/skills/production-scheduling/SKILL.md +238 -0
- package/skills/project-flow-ops/SKILL.md +111 -0
- package/skills/prompt-optimizer/SKILL.md +397 -0
- package/skills/python-patterns/SKILL.md +750 -0
- package/skills/python-testing/SKILL.md +816 -0
- package/skills/pytorch-patterns/SKILL.md +396 -0
- package/skills/quality-nonconformance/SKILL.md +260 -0
- package/skills/ralphinho-rfc-pipeline/SKILL.md +67 -0
- package/skills/regex-vs-llm-structured-text/SKILL.md +220 -0
- package/skills/remotion-video-creation/SKILL.md +43 -0
- package/skills/remotion-video-creation/rules/3d.md +86 -0
- package/skills/remotion-video-creation/rules/animations.md +29 -0
- package/skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx +173 -0
- package/skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx +100 -0
- package/skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/skills/remotion-video-creation/rules/assets.md +78 -0
- package/skills/remotion-video-creation/rules/audio.md +172 -0
- package/skills/remotion-video-creation/rules/calculate-metadata.md +104 -0
- package/skills/remotion-video-creation/rules/can-decode.md +75 -0
- package/skills/remotion-video-creation/rules/charts.md +58 -0
- package/skills/remotion-video-creation/rules/compositions.md +146 -0
- package/skills/remotion-video-creation/rules/display-captions.md +126 -0
- package/skills/remotion-video-creation/rules/extract-frames.md +229 -0
- package/skills/remotion-video-creation/rules/fonts.md +152 -0
- package/skills/remotion-video-creation/rules/get-audio-duration.md +58 -0
- package/skills/remotion-video-creation/rules/get-video-dimensions.md +68 -0
- package/skills/remotion-video-creation/rules/get-video-duration.md +58 -0
- package/skills/remotion-video-creation/rules/gifs.md +138 -0
- package/skills/remotion-video-creation/rules/images.md +130 -0
- package/skills/remotion-video-creation/rules/import-srt-captions.md +67 -0
- package/skills/remotion-video-creation/rules/lottie.md +67 -0
- package/skills/remotion-video-creation/rules/measuring-dom-nodes.md +34 -0
- package/skills/remotion-video-creation/rules/measuring-text.md +143 -0
- package/skills/remotion-video-creation/rules/sequencing.md +106 -0
- package/skills/remotion-video-creation/rules/tailwind.md +11 -0
- package/skills/remotion-video-creation/rules/text-animations.md +20 -0
- package/skills/remotion-video-creation/rules/timing.md +179 -0
- package/skills/remotion-video-creation/rules/transcribe-captions.md +19 -0
- package/skills/remotion-video-creation/rules/transitions.md +122 -0
- package/skills/remotion-video-creation/rules/trimming.md +52 -0
- package/skills/remotion-video-creation/rules/videos.md +171 -0
- package/skills/repo-scan/SKILL.md +78 -0
- package/skills/research-ops/SKILL.md +112 -0
- package/skills/returns-reverse-logistics/SKILL.md +240 -0
- package/skills/rules-distill/SKILL.md +264 -0
- package/skills/rules-distill/scripts/scan-rules.sh +58 -0
- package/skills/rules-distill/scripts/scan-skills.sh +129 -0
- package/skills/rust-patterns/SKILL.md +499 -0
- package/skills/rust-testing/SKILL.md +500 -0
- package/skills/safety-guard/SKILL.md +75 -0
- package/skills/santa-method/SKILL.md +306 -0
- package/skills/search-first/SKILL.md +161 -0
- package/skills/security-bounty-hunter/SKILL.md +99 -0
- package/skills/security-review/SKILL.md +495 -0
- package/skills/security-review/cloud-infrastructure-security.md +361 -0
- package/skills/security-scan/SKILL.md +165 -0
- package/skills/seo/SKILL.md +154 -0
- package/skills/skill-comply/SKILL.md +58 -0
- package/skills/skill-comply/fixtures/compliant_trace.jsonl +5 -0
- package/skills/skill-comply/fixtures/noncompliant_trace.jsonl +3 -0
- package/skills/skill-comply/fixtures/tdd_spec.yaml +44 -0
- package/skills/skill-comply/prompts/classifier.md +24 -0
- package/skills/skill-comply/prompts/scenario_generator.md +62 -0
- package/skills/skill-comply/prompts/spec_generator.md +42 -0
- package/skills/skill-comply/pyproject.toml +15 -0
- package/skills/skill-comply/scripts/__init__.py +0 -0
- package/skills/skill-comply/scripts/classifier.py +85 -0
- package/skills/skill-comply/scripts/grader.py +122 -0
- package/skills/skill-comply/scripts/parser.py +107 -0
- package/skills/skill-comply/scripts/report.py +170 -0
- package/skills/skill-comply/scripts/run.py +127 -0
- package/skills/skill-comply/scripts/runner.py +161 -0
- package/skills/skill-comply/scripts/scenario_generator.py +70 -0
- package/skills/skill-comply/scripts/spec_generator.py +72 -0
- package/skills/skill-comply/scripts/utils.py +13 -0
- package/skills/skill-comply/tests/test_grader.py +137 -0
- package/skills/skill-comply/tests/test_parser.py +90 -0
- package/skills/skill-stocktake/SKILL.md +193 -0
- package/skills/skill-stocktake/scripts/quick-diff.sh +87 -0
- package/skills/skill-stocktake/scripts/save-results.sh +56 -0
- package/skills/skill-stocktake/scripts/scan.sh +170 -0
- package/skills/smart-debug/SKILL.md +241 -0
- package/skills/social-graph-ranker/SKILL.md +154 -0
- package/skills/springboot-patterns/SKILL.md +314 -0
- package/skills/springboot-security/SKILL.md +272 -0
- package/skills/springboot-tdd/SKILL.md +158 -0
- package/skills/springboot-verification/SKILL.md +231 -0
- package/skills/strategic-compact/SKILL.md +131 -0
- package/skills/strategic-compact/suggest-compact.sh +54 -0
- package/skills/swift-actor-persistence/SKILL.md +143 -0
- package/skills/swift-concurrency-6-2/SKILL.md +216 -0
- package/skills/swift-protocol-di-testing/SKILL.md +190 -0
- package/skills/swiftui-patterns/SKILL.md +259 -0
- package/skills/tdd-workflow/SKILL.md +463 -0
- package/skills/team-builder/SKILL.md +168 -0
- package/skills/terminal-ops/SKILL.md +109 -0
- package/skills/token-budget-advisor/SKILL.md +133 -0
- package/skills/ui-demo/SKILL.md +465 -0
- package/skills/unified-notifications-ops/SKILL.md +187 -0
- package/skills/verification-loop/SKILL.md +126 -0
- package/skills/video-editing/SKILL.md +310 -0
- package/skills/videodb/SKILL.md +374 -0
- package/skills/videodb/reference/api-reference.md +550 -0
- package/skills/videodb/reference/capture-reference.md +407 -0
- package/skills/videodb/reference/capture.md +101 -0
- package/skills/videodb/reference/editor.md +443 -0
- package/skills/videodb/reference/generative.md +331 -0
- package/skills/videodb/reference/rtstream-reference.md +564 -0
- package/skills/videodb/reference/rtstream.md +65 -0
- package/skills/videodb/reference/search.md +230 -0
- package/skills/videodb/reference/streaming.md +406 -0
- package/skills/videodb/reference/use-cases.md +118 -0
- package/skills/videodb/scripts/ws_listener.py +282 -0
- package/skills/visa-doc-translate/README.md +86 -0
- package/skills/visa-doc-translate/SKILL.md +117 -0
- package/skills/workspace-surface-audit/SKILL.md +125 -0
- package/skills/x-api/SKILL.md +230 -0
- package/social/card-agents.svg +96 -0
- package/social/card-install.svg +99 -0
- package/social/card-main.svg +133 -0
- package/social/github-social-preview.svg +147 -0
- package/social/readme-agents.svg +139 -0
- package/social/readme-hero.svg +131 -0
- package/social/readme-lens.svg +140 -0
- package/social/readme-savings.svg +56 -0
- package/social/x-card-agents-grid.svg +94 -0
- package/social/x-card-free.svg +95 -0
- package/social/x-card-hook.svg +77 -0
- package/tests/hooks/branch-name-check.test.js +184 -0
- package/tests/hooks/smart-suggest.test.js +149 -0
- package/tests/hooks/test-reminder.test.js +181 -0
- package/tests/run-all.js +55 -0
- package/wiki/Agent-Reference.md +199 -0
- package/wiki/FAQ.md +142 -0
- package/wiki/Home.md +50 -0
- package/wiki/Hook-Reference.md +101 -0
- package/wiki/Installation-Guide.md +126 -0
- package/wiki/Platform-Support.md +106 -0
- package/wiki/Skill-Reference.md +103 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Desktop Notification Hook (Stop)
|
|
4
|
+
*
|
|
5
|
+
* Sends a native desktop notification with the task summary when Claude
|
|
6
|
+
* finishes responding. Supports:
|
|
7
|
+
* - macOS: osascript (native)
|
|
8
|
+
* - WSL: PowerShell 7 or Windows PowerShell + BurntToast module
|
|
9
|
+
*
|
|
10
|
+
* On WSL, if BurntToast is not installed, logs a tip for installation.
|
|
11
|
+
*
|
|
12
|
+
* Hook ID : stop:desktop-notify
|
|
13
|
+
* Profiles: standard, strict
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
const { spawnSync } = require('child_process');
|
|
19
|
+
const { isMacOS, log } = require('../lib/utils');
|
|
20
|
+
|
|
21
|
+
const TITLE = 'Claude Code';
|
|
22
|
+
const MAX_BODY_LENGTH = 100;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Memoized WSL detection at module load (avoids repeated /proc/version reads).
|
|
26
|
+
*/
|
|
27
|
+
let isWSL = false;
|
|
28
|
+
if (process.platform === 'linux') {
|
|
29
|
+
try {
|
|
30
|
+
isWSL = require('fs').readFileSync('/proc/version', 'utf8').toLowerCase().includes('microsoft');
|
|
31
|
+
} catch {
|
|
32
|
+
isWSL = false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Find available PowerShell executable on WSL.
|
|
38
|
+
* Returns first accessible path, or null if none found.
|
|
39
|
+
*/
|
|
40
|
+
function findPowerShell() {
|
|
41
|
+
if (!isWSL) return null;
|
|
42
|
+
|
|
43
|
+
const candidates = [
|
|
44
|
+
'pwsh.exe', // WSL interop resolves from Windows PATH
|
|
45
|
+
'powershell.exe', // WSL interop for Windows PowerShell
|
|
46
|
+
'/mnt/c/Program Files/PowerShell/7/pwsh.exe', // PowerShell 7 (default install)
|
|
47
|
+
'/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe', // Windows PowerShell
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
for (const path of candidates) {
|
|
51
|
+
try {
|
|
52
|
+
const result = spawnSync(path, ['-Command', 'exit 0'],
|
|
53
|
+
{ stdio: ['ignore', 'pipe', 'ignore'], timeout: 3000 });
|
|
54
|
+
if (result.status === 0) {
|
|
55
|
+
return path;
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
// continue
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Send a Windows Toast notification via PowerShell BurntToast.
|
|
66
|
+
* Returns { success: boolean, reason: string|null }.
|
|
67
|
+
* reason is null on success, or contains error detail on failure.
|
|
68
|
+
*/
|
|
69
|
+
function notifyWindows(pwshPath, title, body) {
|
|
70
|
+
const safeBody = body.replace(/'/g, "''");
|
|
71
|
+
const safeTitle = title.replace(/'/g, "''");
|
|
72
|
+
const command = `Import-Module BurntToast; New-BurntToastNotification -Text '${safeTitle}', '${safeBody}'`;
|
|
73
|
+
const result = spawnSync(pwshPath, ['-Command', command],
|
|
74
|
+
{ stdio: ['ignore', 'pipe', 'pipe'], timeout: 5000 });
|
|
75
|
+
if (result.status === 0) {
|
|
76
|
+
return { success: true, reason: null };
|
|
77
|
+
}
|
|
78
|
+
const errorMsg = result.error ? result.error.message : result.stderr?.toString();
|
|
79
|
+
return { success: false, reason: errorMsg || `exit ${result.status}` };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Extract a short summary from the last assistant message.
|
|
84
|
+
* Takes the first non-empty line and truncates to MAX_BODY_LENGTH chars.
|
|
85
|
+
*/
|
|
86
|
+
function extractSummary(message) {
|
|
87
|
+
if (!message || typeof message !== 'string') return 'Done';
|
|
88
|
+
|
|
89
|
+
const firstLine = message
|
|
90
|
+
.split('\n')
|
|
91
|
+
.map(l => l.trim())
|
|
92
|
+
.find(l => l.length > 0);
|
|
93
|
+
|
|
94
|
+
if (!firstLine) return 'Done';
|
|
95
|
+
|
|
96
|
+
return firstLine.length > MAX_BODY_LENGTH
|
|
97
|
+
? `${firstLine.slice(0, MAX_BODY_LENGTH)}...`
|
|
98
|
+
: firstLine;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Send a macOS notification via osascript.
|
|
103
|
+
* AppleScript strings do not support backslash escapes, so we replace
|
|
104
|
+
* double quotes with curly quotes and strip backslashes before embedding.
|
|
105
|
+
*/
|
|
106
|
+
function notifyMacOS(title, body) {
|
|
107
|
+
const safeBody = body.replace(/\\/g, '').replace(/"/g, '\u201C');
|
|
108
|
+
const safeTitle = title.replace(/\\/g, '').replace(/"/g, '\u201C');
|
|
109
|
+
const script = `display notification "${safeBody}" with title "${safeTitle}"`;
|
|
110
|
+
const result = spawnSync('osascript', ['-e', script], { stdio: 'ignore', timeout: 5000 });
|
|
111
|
+
if (result.error || result.status !== 0) {
|
|
112
|
+
log(`[DesktopNotify] osascript failed: ${result.error ? result.error.message : `exit ${result.status}`}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Fast-path entry point for run-with-flags.js (avoids extra process spawn).
|
|
118
|
+
*/
|
|
119
|
+
function run(raw) {
|
|
120
|
+
try {
|
|
121
|
+
const input = raw.trim() ? JSON.parse(raw) : {};
|
|
122
|
+
const summary = extractSummary(input.last_assistant_message);
|
|
123
|
+
|
|
124
|
+
if (isMacOS) {
|
|
125
|
+
notifyMacOS(TITLE, summary);
|
|
126
|
+
} else if (isWSL) {
|
|
127
|
+
const ps = findPowerShell();
|
|
128
|
+
if (ps) {
|
|
129
|
+
const { success, reason } = notifyWindows(ps, TITLE, summary);
|
|
130
|
+
if (success) {
|
|
131
|
+
// notification sent successfully
|
|
132
|
+
} else if (reason && reason.toLowerCase().includes('burnttoast')) {
|
|
133
|
+
// BurntToast module not found
|
|
134
|
+
log('[DesktopNotify] Tip: Install BurntToast module to enable notifications');
|
|
135
|
+
} else if (reason) {
|
|
136
|
+
// Other PowerShell/notification error - log for debugging
|
|
137
|
+
log(`[DesktopNotify] Notification failed: ${reason}`);
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
// No PowerShell found
|
|
141
|
+
log('[DesktopNotify] Tip: Install BurntToast module in PowerShell for notifications');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} catch (err) {
|
|
145
|
+
log(`[DesktopNotify] Error: ${err.message}`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return raw;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
module.exports = { run };
|
|
152
|
+
|
|
153
|
+
// Legacy stdin path (when invoked directly rather than via run-with-flags)
|
|
154
|
+
if (require.main === module) {
|
|
155
|
+
const MAX_STDIN = 1024 * 1024;
|
|
156
|
+
let data = '';
|
|
157
|
+
|
|
158
|
+
process.stdin.setEncoding('utf8');
|
|
159
|
+
process.stdin.on('data', chunk => {
|
|
160
|
+
if (data.length < MAX_STDIN) {
|
|
161
|
+
data += chunk.substring(0, MAX_STDIN - data.length);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
process.stdin.on('end', () => {
|
|
165
|
+
const output = run(data);
|
|
166
|
+
if (output) process.stdout.write(output);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Doc file warning hook (PreToolUse - Write)
|
|
4
|
+
*
|
|
5
|
+
* Uses a denylist approach: only warn on known ad-hoc documentation
|
|
6
|
+
* filenames (NOTES, TODO, SCRATCH, etc.) outside structured directories.
|
|
7
|
+
* This avoids false positives for legitimate markdown-heavy workflows
|
|
8
|
+
* (specs, ADRs, command definitions, skill files, etc.).
|
|
9
|
+
*
|
|
10
|
+
* Policy ported from the intent of PR #962 into the current hook architecture.
|
|
11
|
+
* Exit code 0 always (warns only, never blocks).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
const path = require('path');
|
|
17
|
+
|
|
18
|
+
const MAX_STDIN = 1024 * 1024;
|
|
19
|
+
let data = '';
|
|
20
|
+
|
|
21
|
+
// Known ad-hoc filenames that indicate impulse/scratch files (case-sensitive, uppercase only)
|
|
22
|
+
const ADHOC_FILENAMES = /^(NOTES|TODO|SCRATCH|TEMP|DRAFT|BRAINSTORM|SPIKE|DEBUG|WIP)\.(md|txt)$/;
|
|
23
|
+
|
|
24
|
+
// Structured directories where even ad-hoc names are intentional
|
|
25
|
+
const STRUCTURED_DIRS = /(^|\/)(docs|\.claude|\.github|commands|skills|benchmarks|templates|\.history|memory)\//;
|
|
26
|
+
|
|
27
|
+
function isSuspiciousDocPath(filePath) {
|
|
28
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
29
|
+
const basename = path.basename(normalized);
|
|
30
|
+
|
|
31
|
+
// Only inspect .md and .txt files (case-sensitive, consistent with ADHOC_FILENAMES)
|
|
32
|
+
if (!/\.(md|txt)$/.test(basename)) return false;
|
|
33
|
+
|
|
34
|
+
// Only flag known ad-hoc filenames
|
|
35
|
+
if (!ADHOC_FILENAMES.test(basename)) return false;
|
|
36
|
+
|
|
37
|
+
// Allow ad-hoc names inside structured directories (intentional usage)
|
|
38
|
+
if (STRUCTURED_DIRS.test(normalized)) return false;
|
|
39
|
+
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Exportable run() for in-process execution via run-with-flags.js.
|
|
45
|
+
* Avoids the ~50-100ms spawnSync overhead when available.
|
|
46
|
+
*/
|
|
47
|
+
function run(inputOrRaw, _options = {}) {
|
|
48
|
+
let input;
|
|
49
|
+
try {
|
|
50
|
+
input = typeof inputOrRaw === 'string'
|
|
51
|
+
? (inputOrRaw.trim() ? JSON.parse(inputOrRaw) : {})
|
|
52
|
+
: (inputOrRaw || {});
|
|
53
|
+
} catch {
|
|
54
|
+
return { exitCode: 0 };
|
|
55
|
+
}
|
|
56
|
+
const filePath = String(input?.tool_input?.file_path || '');
|
|
57
|
+
|
|
58
|
+
if (filePath && isSuspiciousDocPath(filePath)) {
|
|
59
|
+
return {
|
|
60
|
+
exitCode: 0,
|
|
61
|
+
stderr:
|
|
62
|
+
'[Hook] WARNING: Ad-hoc documentation filename detected\n' +
|
|
63
|
+
`[Hook] File: ${filePath}\n` +
|
|
64
|
+
'[Hook] Consider using a structured path (e.g. docs/, .claude/, skills/, .github/, benchmarks/, templates/)',
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return { exitCode: 0 };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = { run };
|
|
72
|
+
|
|
73
|
+
// Stdin fallback for spawnSync execution
|
|
74
|
+
process.stdin.setEncoding('utf8');
|
|
75
|
+
process.stdin.on('data', c => {
|
|
76
|
+
if (data.length < MAX_STDIN) {
|
|
77
|
+
const remaining = MAX_STDIN - data.length;
|
|
78
|
+
data += c.substring(0, remaining);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
process.stdin.on('end', () => {
|
|
83
|
+
const result = run(data);
|
|
84
|
+
|
|
85
|
+
if (result.stderr) {
|
|
86
|
+
process.stderr.write(result.stderr + '\n');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
process.stdout.write(data);
|
|
90
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Continuous Learning - Session Evaluator
|
|
4
|
+
*
|
|
5
|
+
* Cross-platform (Windows, macOS, Linux)
|
|
6
|
+
*
|
|
7
|
+
* Runs on Stop hook to extract reusable patterns from Claude Code sessions.
|
|
8
|
+
* Reads transcript_path from stdin JSON (Claude Code hook input).
|
|
9
|
+
*
|
|
10
|
+
* Why Stop hook instead of UserPromptSubmit:
|
|
11
|
+
* - Stop runs once at session end (lightweight)
|
|
12
|
+
* - UserPromptSubmit runs every message (heavy, adds latency)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const {
|
|
18
|
+
getLearnedSkillsDir,
|
|
19
|
+
ensureDir,
|
|
20
|
+
readFile,
|
|
21
|
+
countInFile,
|
|
22
|
+
log
|
|
23
|
+
} = require('../lib/utils');
|
|
24
|
+
|
|
25
|
+
// Read hook input from stdin (Claude Code provides transcript_path via stdin JSON)
|
|
26
|
+
const MAX_STDIN = 1024 * 1024;
|
|
27
|
+
let stdinData = '';
|
|
28
|
+
process.stdin.setEncoding('utf8');
|
|
29
|
+
|
|
30
|
+
process.stdin.on('data', chunk => {
|
|
31
|
+
if (stdinData.length < MAX_STDIN) {
|
|
32
|
+
const remaining = MAX_STDIN - stdinData.length;
|
|
33
|
+
stdinData += chunk.substring(0, remaining);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
process.stdin.on('end', () => {
|
|
38
|
+
main().catch(err => {
|
|
39
|
+
console.error('[ContinuousLearning] Error:', err.message);
|
|
40
|
+
process.exit(0);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
async function main() {
|
|
45
|
+
// Parse stdin JSON to get transcript_path
|
|
46
|
+
let transcriptPath = null;
|
|
47
|
+
try {
|
|
48
|
+
const input = JSON.parse(stdinData);
|
|
49
|
+
transcriptPath = input.transcript_path;
|
|
50
|
+
} catch {
|
|
51
|
+
// Fallback: try env var for backwards compatibility
|
|
52
|
+
transcriptPath = process.env.CLAUDE_TRANSCRIPT_PATH;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Get script directory to find config
|
|
56
|
+
const scriptDir = __dirname;
|
|
57
|
+
const configFile = path.join(scriptDir, '..', '..', 'skills', 'continuous-learning', 'config.json');
|
|
58
|
+
|
|
59
|
+
// Default configuration
|
|
60
|
+
let minSessionLength = 10;
|
|
61
|
+
let learnedSkillsPath = getLearnedSkillsDir();
|
|
62
|
+
|
|
63
|
+
// Load config if exists
|
|
64
|
+
const configContent = readFile(configFile);
|
|
65
|
+
if (configContent) {
|
|
66
|
+
try {
|
|
67
|
+
const config = JSON.parse(configContent);
|
|
68
|
+
minSessionLength = config.min_session_length ?? 10;
|
|
69
|
+
|
|
70
|
+
if (config.learned_skills_path) {
|
|
71
|
+
// Handle ~ in path
|
|
72
|
+
learnedSkillsPath = config.learned_skills_path.replace(/^~/, require('os').homedir());
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
log(`[ContinuousLearning] Failed to parse config: ${err.message}, using defaults`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Ensure learned skills directory exists
|
|
80
|
+
ensureDir(learnedSkillsPath);
|
|
81
|
+
|
|
82
|
+
if (!transcriptPath || !fs.existsSync(transcriptPath)) {
|
|
83
|
+
process.exit(0);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Count user messages in session (allow optional whitespace around colon)
|
|
87
|
+
const messageCount = countInFile(transcriptPath, /"type"\s*:\s*"user"/g);
|
|
88
|
+
|
|
89
|
+
// Skip short sessions
|
|
90
|
+
if (messageCount < minSessionLength) {
|
|
91
|
+
log(`[ContinuousLearning] Session too short (${messageCount} messages), skipping`);
|
|
92
|
+
process.exit(0);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Signal to Claude that session should be evaluated for extractable patterns
|
|
96
|
+
log(`[ContinuousLearning] Session has ${messageCount} messages - evaluate for extractable patterns`);
|
|
97
|
+
log(`[ContinuousLearning] Save learned skills to: ${learnedSkillsPath}`);
|
|
98
|
+
|
|
99
|
+
process.exit(0);
|
|
100
|
+
}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Governance Event Capture Hook
|
|
4
|
+
*
|
|
5
|
+
* PreToolUse/PostToolUse hook that detects governance-relevant events
|
|
6
|
+
* and writes them to the governance_events table in the state store.
|
|
7
|
+
*
|
|
8
|
+
* Captured event types:
|
|
9
|
+
* - secret_detected: Hardcoded secrets in tool input/output
|
|
10
|
+
* - policy_violation: Actions that violate configured policies
|
|
11
|
+
* - security_finding: Security-relevant tool invocations
|
|
12
|
+
* - approval_requested: Operations requiring explicit approval
|
|
13
|
+
* - hook_input_truncated: Hook input exceeded the safe inspection limit
|
|
14
|
+
*
|
|
15
|
+
* Enable: Set ECC_GOVERNANCE_CAPTURE=1
|
|
16
|
+
* Configure session: Set ECC_SESSION_ID for session correlation
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
'use strict';
|
|
20
|
+
|
|
21
|
+
const crypto = require('crypto');
|
|
22
|
+
|
|
23
|
+
const MAX_STDIN = 1024 * 1024;
|
|
24
|
+
|
|
25
|
+
// Patterns that indicate potential hardcoded secrets
|
|
26
|
+
const SECRET_PATTERNS = [
|
|
27
|
+
{ name: 'aws_key', pattern: /(?:AKIA|ASIA)[A-Z0-9]{16}/i },
|
|
28
|
+
{ name: 'generic_secret', pattern: /(?:secret|password|token|api[_-]?key)\s*[:=]\s*["'][^"']{8,}/i },
|
|
29
|
+
{ name: 'private_key', pattern: /-----BEGIN (?:RSA |EC |DSA )?PRIVATE KEY-----/ },
|
|
30
|
+
{ name: 'jwt', pattern: /eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/ },
|
|
31
|
+
{ name: 'github_token', pattern: /gh[pousr]_[A-Za-z0-9_]{36,}/ },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// Tool names that represent security-relevant operations
|
|
35
|
+
const SECURITY_RELEVANT_TOOLS = new Set([
|
|
36
|
+
'Bash', // Could execute arbitrary commands
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
// Commands that require governance approval
|
|
40
|
+
const APPROVAL_COMMANDS = [
|
|
41
|
+
/git\s+push\s+.*--force/,
|
|
42
|
+
/git\s+reset\s+--hard/,
|
|
43
|
+
/rm\s+-rf?\s/,
|
|
44
|
+
/DROP\s+(?:TABLE|DATABASE)/i,
|
|
45
|
+
/DELETE\s+FROM\s+\w+\s*(?:;|$)/i,
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
// File patterns that indicate policy-sensitive paths
|
|
49
|
+
const SENSITIVE_PATHS = [
|
|
50
|
+
/\.env(?:\.|$)/,
|
|
51
|
+
/credentials/i,
|
|
52
|
+
/secrets?\./i,
|
|
53
|
+
/\.pem$/,
|
|
54
|
+
/\.key$/,
|
|
55
|
+
/id_rsa/,
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Generate a unique event ID.
|
|
60
|
+
*/
|
|
61
|
+
function generateEventId() {
|
|
62
|
+
return `gov-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Scan text content for hardcoded secrets.
|
|
67
|
+
* Returns array of { name, match } for each detected secret.
|
|
68
|
+
*/
|
|
69
|
+
function detectSecrets(text) {
|
|
70
|
+
if (!text || typeof text !== 'string') return [];
|
|
71
|
+
|
|
72
|
+
const findings = [];
|
|
73
|
+
for (const { name, pattern } of SECRET_PATTERNS) {
|
|
74
|
+
if (pattern.test(text)) {
|
|
75
|
+
findings.push({ name });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return findings;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Check if a command requires governance approval.
|
|
83
|
+
*/
|
|
84
|
+
function detectApprovalRequired(command) {
|
|
85
|
+
if (!command || typeof command !== 'string') return [];
|
|
86
|
+
|
|
87
|
+
const findings = [];
|
|
88
|
+
for (const pattern of APPROVAL_COMMANDS) {
|
|
89
|
+
if (pattern.test(command)) {
|
|
90
|
+
findings.push({ pattern: pattern.source });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return findings;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Check if a file path is policy-sensitive.
|
|
98
|
+
*/
|
|
99
|
+
function detectSensitivePath(filePath) {
|
|
100
|
+
if (!filePath || typeof filePath !== 'string') return false;
|
|
101
|
+
|
|
102
|
+
return SENSITIVE_PATHS.some(pattern => pattern.test(filePath));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function fingerprintCommand(command) {
|
|
106
|
+
if (!command || typeof command !== 'string') return null;
|
|
107
|
+
return crypto.createHash('sha256').update(command).digest('hex').slice(0, 12);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function summarizeCommand(command) {
|
|
111
|
+
if (!command || typeof command !== 'string') {
|
|
112
|
+
return {
|
|
113
|
+
commandName: null,
|
|
114
|
+
commandFingerprint: null,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const trimmed = command.trim();
|
|
119
|
+
if (!trimmed) {
|
|
120
|
+
return {
|
|
121
|
+
commandName: null,
|
|
122
|
+
commandFingerprint: null,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
commandName: trimmed.split(/\s+/)[0] || null,
|
|
128
|
+
commandFingerprint: fingerprintCommand(trimmed),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function emitGovernanceEvent(event) {
|
|
133
|
+
process.stderr.write(`[governance] ${JSON.stringify(event)}\n`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Analyze a hook input payload and return governance events to capture.
|
|
138
|
+
*
|
|
139
|
+
* @param {Object} input - Parsed hook input (tool_name, tool_input, tool_output)
|
|
140
|
+
* @param {Object} [context] - Additional context (sessionId, hookPhase)
|
|
141
|
+
* @returns {Array<Object>} Array of governance event objects
|
|
142
|
+
*/
|
|
143
|
+
function analyzeForGovernanceEvents(input, context = {}) {
|
|
144
|
+
const events = [];
|
|
145
|
+
const toolName = input.tool_name || '';
|
|
146
|
+
const toolInput = input.tool_input || {};
|
|
147
|
+
const toolOutput = typeof input.tool_output === 'string' ? input.tool_output : '';
|
|
148
|
+
const sessionId = context.sessionId || null;
|
|
149
|
+
const hookPhase = context.hookPhase || 'unknown';
|
|
150
|
+
|
|
151
|
+
// 1. Secret detection in tool input content
|
|
152
|
+
const inputText = typeof toolInput === 'object'
|
|
153
|
+
? JSON.stringify(toolInput)
|
|
154
|
+
: String(toolInput);
|
|
155
|
+
|
|
156
|
+
const inputSecrets = detectSecrets(inputText);
|
|
157
|
+
const outputSecrets = detectSecrets(toolOutput);
|
|
158
|
+
const allSecrets = [...inputSecrets, ...outputSecrets];
|
|
159
|
+
|
|
160
|
+
if (allSecrets.length > 0) {
|
|
161
|
+
events.push({
|
|
162
|
+
id: generateEventId(),
|
|
163
|
+
sessionId,
|
|
164
|
+
eventType: 'secret_detected',
|
|
165
|
+
payload: {
|
|
166
|
+
toolName,
|
|
167
|
+
hookPhase,
|
|
168
|
+
secretTypes: allSecrets.map(s => s.name),
|
|
169
|
+
location: inputSecrets.length > 0 ? 'input' : 'output',
|
|
170
|
+
severity: 'critical',
|
|
171
|
+
},
|
|
172
|
+
resolvedAt: null,
|
|
173
|
+
resolution: null,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 2. Approval-required commands (Bash only)
|
|
178
|
+
if (toolName === 'Bash') {
|
|
179
|
+
const command = toolInput.command || '';
|
|
180
|
+
const approvalFindings = detectApprovalRequired(command);
|
|
181
|
+
const commandSummary = summarizeCommand(command);
|
|
182
|
+
|
|
183
|
+
if (approvalFindings.length > 0) {
|
|
184
|
+
events.push({
|
|
185
|
+
id: generateEventId(),
|
|
186
|
+
sessionId,
|
|
187
|
+
eventType: 'approval_requested',
|
|
188
|
+
payload: {
|
|
189
|
+
toolName,
|
|
190
|
+
hookPhase,
|
|
191
|
+
...commandSummary,
|
|
192
|
+
matchedPatterns: approvalFindings.map(f => f.pattern),
|
|
193
|
+
severity: 'high',
|
|
194
|
+
},
|
|
195
|
+
resolvedAt: null,
|
|
196
|
+
resolution: null,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// 3. Policy violation: writing to sensitive paths
|
|
202
|
+
const filePath = toolInput.file_path || toolInput.path || '';
|
|
203
|
+
if (filePath && detectSensitivePath(filePath)) {
|
|
204
|
+
events.push({
|
|
205
|
+
id: generateEventId(),
|
|
206
|
+
sessionId,
|
|
207
|
+
eventType: 'policy_violation',
|
|
208
|
+
payload: {
|
|
209
|
+
toolName,
|
|
210
|
+
hookPhase,
|
|
211
|
+
filePath: filePath.slice(0, 200),
|
|
212
|
+
reason: 'sensitive_file_access',
|
|
213
|
+
severity: 'warning',
|
|
214
|
+
},
|
|
215
|
+
resolvedAt: null,
|
|
216
|
+
resolution: null,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 4. Security-relevant tool usage tracking
|
|
221
|
+
if (SECURITY_RELEVANT_TOOLS.has(toolName) && hookPhase === 'post') {
|
|
222
|
+
const command = toolInput.command || '';
|
|
223
|
+
const hasElevated = /sudo\s/.test(command) || /chmod\s/.test(command) || /chown\s/.test(command);
|
|
224
|
+
const commandSummary = summarizeCommand(command);
|
|
225
|
+
|
|
226
|
+
if (hasElevated) {
|
|
227
|
+
events.push({
|
|
228
|
+
id: generateEventId(),
|
|
229
|
+
sessionId,
|
|
230
|
+
eventType: 'security_finding',
|
|
231
|
+
payload: {
|
|
232
|
+
toolName,
|
|
233
|
+
hookPhase,
|
|
234
|
+
...commandSummary,
|
|
235
|
+
reason: 'elevated_privilege_command',
|
|
236
|
+
severity: 'medium',
|
|
237
|
+
},
|
|
238
|
+
resolvedAt: null,
|
|
239
|
+
resolution: null,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return events;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Core hook logic — exported so run-with-flags.js can call directly.
|
|
249
|
+
*
|
|
250
|
+
* @param {string} rawInput - Raw JSON string from stdin
|
|
251
|
+
* @returns {string} The original input (pass-through)
|
|
252
|
+
*/
|
|
253
|
+
function run(rawInput, options = {}) {
|
|
254
|
+
// Gate on feature flag
|
|
255
|
+
if (String(process.env.ECC_GOVERNANCE_CAPTURE || '').toLowerCase() !== '1') {
|
|
256
|
+
return rawInput;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const sessionId = process.env.ECC_SESSION_ID || null;
|
|
260
|
+
const hookPhase = process.env.CLAUDE_HOOK_EVENT_NAME || 'unknown';
|
|
261
|
+
|
|
262
|
+
if (options.truncated) {
|
|
263
|
+
emitGovernanceEvent({
|
|
264
|
+
id: generateEventId(),
|
|
265
|
+
sessionId,
|
|
266
|
+
eventType: 'hook_input_truncated',
|
|
267
|
+
payload: {
|
|
268
|
+
hookPhase: hookPhase.startsWith('Pre') ? 'pre' : 'post',
|
|
269
|
+
sizeLimitBytes: options.maxStdin || MAX_STDIN,
|
|
270
|
+
severity: 'warning',
|
|
271
|
+
},
|
|
272
|
+
resolvedAt: null,
|
|
273
|
+
resolution: null,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
const input = JSON.parse(rawInput);
|
|
279
|
+
|
|
280
|
+
const events = analyzeForGovernanceEvents(input, {
|
|
281
|
+
sessionId,
|
|
282
|
+
hookPhase: hookPhase.startsWith('Pre') ? 'pre' : 'post',
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
if (events.length > 0) {
|
|
286
|
+
for (const event of events) {
|
|
287
|
+
emitGovernanceEvent(event);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
} catch {
|
|
291
|
+
// Silently ignore parse errors — never block the tool pipeline.
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return rawInput;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// ── stdin entry point ────────────────────────────────
|
|
298
|
+
if (require.main === module) {
|
|
299
|
+
let raw = '';
|
|
300
|
+
let truncated = /^(1|true|yes)$/i.test(String(process.env.ECC_HOOK_INPUT_TRUNCATED || ''));
|
|
301
|
+
process.stdin.setEncoding('utf8');
|
|
302
|
+
process.stdin.on('data', chunk => {
|
|
303
|
+
if (raw.length < MAX_STDIN) {
|
|
304
|
+
const remaining = MAX_STDIN - raw.length;
|
|
305
|
+
raw += chunk.substring(0, remaining);
|
|
306
|
+
if (chunk.length > remaining) {
|
|
307
|
+
truncated = true;
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
truncated = true;
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
process.stdin.on('end', () => {
|
|
315
|
+
const result = run(raw, {
|
|
316
|
+
truncated,
|
|
317
|
+
maxStdin: Number(process.env.ECC_HOOK_INPUT_MAX_BYTES) || MAX_STDIN,
|
|
318
|
+
});
|
|
319
|
+
process.stdout.write(result);
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
module.exports = {
|
|
324
|
+
APPROVAL_COMMANDS,
|
|
325
|
+
SECRET_PATTERNS,
|
|
326
|
+
SECURITY_RELEVANT_TOOLS,
|
|
327
|
+
SENSITIVE_PATHS,
|
|
328
|
+
analyzeForGovernanceEvents,
|
|
329
|
+
detectApprovalRequired,
|
|
330
|
+
detectSecrets,
|
|
331
|
+
detectSensitivePath,
|
|
332
|
+
generateEventId,
|
|
333
|
+
run,
|
|
334
|
+
};
|