@paths.design/caws-cli 10.2.0 → 11.0.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/README.md +125 -374
- package/dist/index.js +43 -785
- package/dist/shell/binding/resolve-binding.d.ts +4 -0
- package/dist/shell/binding/resolve-binding.d.ts.map +1 -0
- package/dist/shell/binding/resolve-binding.js +228 -0
- package/dist/shell/binding/resolve-binding.js.map +1 -0
- package/dist/shell/binding/types.d.ts +42 -0
- package/dist/shell/binding/types.d.ts.map +1 -0
- package/dist/shell/binding/types.js +21 -0
- package/dist/shell/binding/types.js.map +1 -0
- package/dist/shell/commands/claim.d.ts +14 -0
- package/dist/shell/commands/claim.d.ts.map +1 -0
- package/dist/shell/commands/claim.js +197 -0
- package/dist/shell/commands/claim.js.map +1 -0
- package/dist/shell/commands/doctor.d.ts +13 -0
- package/dist/shell/commands/doctor.d.ts.map +1 -0
- package/dist/shell/commands/doctor.js +97 -0
- package/dist/shell/commands/doctor.js.map +1 -0
- package/dist/shell/commands/evidence.d.ts +28 -0
- package/dist/shell/commands/evidence.d.ts.map +1 -0
- package/dist/shell/commands/evidence.js +166 -0
- package/dist/shell/commands/evidence.js.map +1 -0
- package/dist/shell/commands/gates.d.ts +19 -0
- package/dist/shell/commands/gates.d.ts.map +1 -0
- package/dist/shell/commands/gates.js +181 -0
- package/dist/shell/commands/gates.js.map +1 -0
- package/dist/shell/commands/init.d.ts +8 -0
- package/dist/shell/commands/init.d.ts.map +1 -0
- package/dist/shell/commands/init.js +64 -0
- package/dist/shell/commands/init.js.map +1 -0
- package/dist/shell/commands/scope.d.ts +11 -0
- package/dist/shell/commands/scope.d.ts.map +1 -0
- package/dist/shell/commands/scope.js +92 -0
- package/dist/shell/commands/scope.js.map +1 -0
- package/dist/shell/commands/status.d.ts +15 -0
- package/dist/shell/commands/status.d.ts.map +1 -0
- package/dist/shell/commands/status.js +106 -0
- package/dist/shell/commands/status.js.map +1 -0
- package/dist/shell/commands/waiver.d.ts +38 -0
- package/dist/shell/commands/waiver.d.ts.map +1 -0
- package/dist/shell/commands/waiver.js +240 -0
- package/dist/shell/commands/waiver.js.map +1 -0
- package/dist/shell/gates/disposition.d.ts +23 -0
- package/dist/shell/gates/disposition.d.ts.map +1 -0
- package/dist/shell/gates/disposition.js +87 -0
- package/dist/shell/gates/disposition.js.map +1 -0
- package/dist/shell/gates/gate-result-contract.d.ts +39 -0
- package/dist/shell/gates/gate-result-contract.d.ts.map +1 -0
- package/dist/shell/gates/gate-result-contract.js +150 -0
- package/dist/shell/gates/gate-result-contract.js.map +1 -0
- package/dist/shell/gates/quality-gates-adapter.d.ts +55 -0
- package/dist/shell/gates/quality-gates-adapter.d.ts.map +1 -0
- package/dist/shell/gates/quality-gates-adapter.js +161 -0
- package/dist/shell/gates/quality-gates-adapter.js.map +1 -0
- package/dist/shell/gates/waiver-filter.d.ts +58 -0
- package/dist/shell/gates/waiver-filter.d.ts.map +1 -0
- package/dist/shell/gates/waiver-filter.js +119 -0
- package/dist/shell/gates/waiver-filter.js.map +1 -0
- package/dist/shell/index.d.ts +50 -0
- package/dist/shell/index.d.ts.map +1 -0
- package/dist/shell/index.js +73 -0
- package/dist/shell/index.js.map +1 -0
- package/dist/shell/register.d.ts +11 -0
- package/dist/shell/register.d.ts.map +1 -0
- package/dist/shell/register.js +274 -0
- package/dist/shell/register.js.map +1 -0
- package/dist/shell/render/claim.d.ts +22 -0
- package/dist/shell/render/claim.d.ts.map +1 -0
- package/dist/shell/render/claim.js +75 -0
- package/dist/shell/render/claim.js.map +1 -0
- package/dist/shell/render/decision.d.ts +15 -0
- package/dist/shell/render/decision.d.ts.map +1 -0
- package/dist/shell/render/decision.js +66 -0
- package/dist/shell/render/decision.js.map +1 -0
- package/dist/shell/render/diagnostic.d.ts +19 -0
- package/dist/shell/render/diagnostic.d.ts.map +1 -0
- package/dist/shell/render/diagnostic.js +76 -0
- package/dist/shell/render/diagnostic.js.map +1 -0
- package/dist/shell/render/finding.d.ts +15 -0
- package/dist/shell/render/finding.d.ts.map +1 -0
- package/dist/shell/render/finding.js +57 -0
- package/dist/shell/render/finding.js.map +1 -0
- package/dist/shell/render/gates.d.ts +3 -0
- package/dist/shell/render/gates.d.ts.map +1 -0
- package/dist/shell/render/gates.js +56 -0
- package/dist/shell/render/gates.js.map +1 -0
- package/dist/shell/render/init.d.ts +11 -0
- package/dist/shell/render/init.d.ts.map +1 -0
- package/dist/shell/render/init.js +32 -0
- package/dist/shell/render/init.js.map +1 -0
- package/dist/shell/render/status.d.ts +26 -0
- package/dist/shell/render/status.d.ts.map +1 -0
- package/dist/shell/render/status.js +143 -0
- package/dist/shell/render/status.js.map +1 -0
- package/dist/shell/render/waiver.d.ts +21 -0
- package/dist/shell/render/waiver.d.ts.map +1 -0
- package/dist/shell/render/waiver.js +94 -0
- package/dist/shell/render/waiver.js.map +1 -0
- package/dist/shell/rules.d.ts +37 -0
- package/dist/shell/rules.d.ts.map +1 -0
- package/dist/shell/rules.js +51 -0
- package/dist/shell/rules.js.map +1 -0
- package/dist/shell/session/actor.d.ts +14 -0
- package/dist/shell/session/actor.d.ts.map +1 -0
- package/dist/shell/session/actor.js +34 -0
- package/dist/shell/session/actor.js.map +1 -0
- package/dist/shell/session/resolve-session.d.ts +5 -0
- package/dist/shell/session/resolve-session.d.ts.map +1 -0
- package/dist/shell/session/resolve-session.js +239 -0
- package/dist/shell/session/resolve-session.js.map +1 -0
- package/dist/shell/session/types.d.ts +56 -0
- package/dist/shell/session/types.d.ts.map +1 -0
- package/dist/shell/session/types.js +15 -0
- package/dist/shell/session/types.js.map +1 -0
- package/dist/store/agents-store.d.ts +3 -0
- package/dist/store/agents-store.d.ts.map +1 -0
- package/dist/store/agents-store.js +63 -0
- package/dist/store/agents-store.js.map +1 -0
- package/dist/store/apply-patch.d.ts +16 -0
- package/dist/store/apply-patch.d.ts.map +1 -0
- package/dist/store/apply-patch.js +191 -0
- package/dist/store/apply-patch.js.map +1 -0
- package/dist/store/atomic-write.d.ts +16 -0
- package/dist/store/atomic-write.d.ts.map +1 -0
- package/dist/store/atomic-write.js +132 -0
- package/dist/store/atomic-write.js.map +1 -0
- package/dist/store/doctor-snapshot.d.ts +20 -0
- package/dist/store/doctor-snapshot.d.ts.map +1 -0
- package/dist/store/doctor-snapshot.js +176 -0
- package/dist/store/doctor-snapshot.js.map +1 -0
- package/dist/store/events-store.d.ts +33 -0
- package/dist/store/events-store.d.ts.map +1 -0
- package/dist/store/events-store.js +297 -0
- package/dist/store/events-store.js.map +1 -0
- package/dist/store/index.d.ts +21 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +47 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/init-store.d.ts +21 -0
- package/dist/store/init-store.d.ts.map +1 -0
- package/dist/store/init-store.js +295 -0
- package/dist/store/init-store.js.map +1 -0
- package/dist/store/json-store.d.ts +3 -0
- package/dist/store/json-store.d.ts.map +1 -0
- package/dist/store/json-store.js +65 -0
- package/dist/store/json-store.js.map +1 -0
- package/dist/store/policy-store.d.ts +3 -0
- package/dist/store/policy-store.d.ts.map +1 -0
- package/dist/store/policy-store.js +65 -0
- package/dist/store/policy-store.js.map +1 -0
- package/dist/store/repo-root.d.ts +46 -0
- package/dist/store/repo-root.d.ts.map +1 -0
- package/dist/store/repo-root.js +145 -0
- package/dist/store/repo-root.js.map +1 -0
- package/dist/store/rules.d.ts +53 -0
- package/dist/store/rules.d.ts.map +1 -0
- package/dist/store/rules.js +78 -0
- package/dist/store/rules.js.map +1 -0
- package/dist/store/specs-store.d.ts +3 -0
- package/dist/store/specs-store.d.ts.map +1 -0
- package/dist/store/specs-store.js +131 -0
- package/dist/store/specs-store.js.map +1 -0
- package/dist/store/types.d.ts +84 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +14 -0
- package/dist/store/types.js.map +1 -0
- package/dist/store/waivers-store.d.ts +25 -0
- package/dist/store/waivers-store.d.ts.map +1 -0
- package/dist/store/waivers-store.js +232 -0
- package/dist/store/waivers-store.js.map +1 -0
- package/dist/store/worktrees-store.d.ts +3 -0
- package/dist/store/worktrees-store.d.ts.map +1 -0
- package/dist/store/worktrees-store.js +62 -0
- package/dist/store/worktrees-store.js.map +1 -0
- package/dist/store/yaml-store.d.ts +9 -0
- package/dist/store/yaml-store.d.ts.map +1 -0
- package/dist/store/yaml-store.js +121 -0
- package/dist/store/yaml-store.js.map +1 -0
- package/package.json +15 -13
- package/dist/budget-derivation.js +0 -751
- package/dist/cicd-optimizer.js +0 -504
- package/dist/commands/agents.js +0 -124
- package/dist/commands/archive.js +0 -500
- package/dist/commands/burnup.js +0 -198
- package/dist/commands/diagnose.js +0 -525
- package/dist/commands/evaluate.js +0 -314
- package/dist/commands/gates.js +0 -149
- package/dist/commands/init.js +0 -857
- package/dist/commands/iterate.js +0 -417
- package/dist/commands/mode.js +0 -269
- package/dist/commands/parallel.js +0 -242
- package/dist/commands/plan.js +0 -438
- package/dist/commands/provenance.js +0 -1143
- package/dist/commands/quality-monitor.js +0 -284
- package/dist/commands/scope.js +0 -264
- package/dist/commands/session.js +0 -312
- package/dist/commands/sidecar.js +0 -74
- package/dist/commands/specs.js +0 -1656
- package/dist/commands/status.js +0 -1172
- package/dist/commands/templates.js +0 -237
- package/dist/commands/tool.js +0 -136
- package/dist/commands/tutorial.js +0 -480
- package/dist/commands/validate.js +0 -357
- package/dist/commands/verify-acs.js +0 -443
- package/dist/commands/waivers.js +0 -599
- package/dist/commands/workflow.js +0 -243
- package/dist/commands/worktree.js +0 -502
- package/dist/config/lite-scope.js +0 -158
- package/dist/config/modes.js +0 -347
- package/dist/constants/spec-types.js +0 -65
- package/dist/gates/budget-limit.js +0 -121
- package/dist/gates/feedback.js +0 -260
- package/dist/gates/format.js +0 -179
- package/dist/gates/god-object.js +0 -117
- package/dist/gates/pipeline.js +0 -167
- package/dist/gates/scope-boundary.js +0 -112
- package/dist/gates/spec-completeness.js +0 -109
- package/dist/gates/todo-detection.js +0 -205
- package/dist/generators/jest-config-generator.js +0 -242
- package/dist/generators/working-spec.js +0 -237
- package/dist/minimal-cli.js +0 -88
- package/dist/parallel/parallel-manager.js +0 -433
- package/dist/policy/PolicyManager.js +0 -470
- package/dist/scaffold/claude-hooks.js +0 -443
- package/dist/scaffold/cursor-hooks.js +0 -177
- package/dist/scaffold/git-hooks.js +0 -928
- package/dist/scaffold/index.js +0 -794
- package/dist/session/session-manager.js +0 -653
- package/dist/sidecars/index.js +0 -33
- package/dist/sidecars/listeners.js +0 -40
- package/dist/sidecars/provenance-summary.js +0 -238
- package/dist/sidecars/quality-gaps.js +0 -258
- package/dist/sidecars/schema.js +0 -149
- package/dist/sidecars/spec-drift.js +0 -151
- package/dist/sidecars/waiver-draft.js +0 -176
- package/dist/spec/SpecFileManager.js +0 -419
- package/dist/templates/.caws/schemas/policy.schema.json +0 -117
- package/dist/templates/.caws/schemas/scope.schema.json +0 -52
- package/dist/templates/.caws/schemas/waivers.schema.json +0 -106
- package/dist/templates/.caws/schemas/working-spec.schema.json +0 -340
- package/dist/templates/.caws/schemas/worktrees.schema.json +0 -38
- package/dist/templates/.caws/templates/working-spec.template.yml +0 -80
- package/dist/templates/.caws/tools/README.md +0 -18
- package/dist/templates/.caws/tools/scope-guard.js +0 -203
- package/dist/templates/.caws/tools-allow.json +0 -331
- package/dist/templates/.caws/waivers.yml +0 -19
- package/dist/templates/.claude/README.md +0 -190
- package/dist/templates/.claude/hooks/audit.sh +0 -121
- package/dist/templates/.claude/hooks/block-dangerous.sh +0 -203
- package/dist/templates/.claude/hooks/classify_command.py +0 -592
- package/dist/templates/.claude/hooks/doc-frontmatter-check.sh +0 -173
- package/dist/templates/.claude/hooks/lite-sprawl-check.sh +0 -145
- package/dist/templates/.claude/hooks/naming-check.sh +0 -100
- package/dist/templates/.claude/hooks/protected-paths.sh +0 -39
- package/dist/templates/.claude/hooks/quality-check.sh +0 -81
- package/dist/templates/.claude/hooks/scan-secrets.sh +0 -85
- package/dist/templates/.claude/hooks/scope-guard.sh +0 -381
- package/dist/templates/.claude/hooks/session-caws-status.sh +0 -117
- package/dist/templates/.claude/hooks/session-log.sh +0 -634
- package/dist/templates/.claude/hooks/simplification-guard.sh +0 -92
- package/dist/templates/.claude/hooks/stop-worktree-check.sh +0 -46
- package/dist/templates/.claude/hooks/test_classify_command.py +0 -370
- package/dist/templates/.claude/hooks/test_wrapper_smoke.sh +0 -96
- package/dist/templates/.claude/hooks/validate-spec.sh +0 -76
- package/dist/templates/.claude/hooks/worktree-guard.sh +0 -220
- package/dist/templates/.claude/hooks/worktree-write-guard.sh +0 -190
- package/dist/templates/.claude/rules/git-safety.md +0 -26
- package/dist/templates/.claude/rules/worktree-isolation.md +0 -101
- package/dist/templates/.claude/settings.json +0 -141
- package/dist/templates/.cursor/README.md +0 -299
- package/dist/templates/.cursor/hooks/audit.sh +0 -55
- package/dist/templates/.cursor/hooks/block-dangerous.sh +0 -84
- package/dist/templates/.cursor/hooks/caws-quality-check.sh +0 -52
- package/dist/templates/.cursor/hooks/caws-scope-guard.sh +0 -130
- package/dist/templates/.cursor/hooks/format.sh +0 -38
- package/dist/templates/.cursor/hooks/naming-check.sh +0 -64
- package/dist/templates/.cursor/hooks/scan-secrets.sh +0 -51
- package/dist/templates/.cursor/hooks/scope-guard.sh +0 -52
- package/dist/templates/.cursor/hooks/session-log.sh +0 -924
- package/dist/templates/.cursor/hooks/validate-spec.sh +0 -83
- package/dist/templates/.cursor/hooks.json +0 -76
- package/dist/templates/.cursor/rules/00-claims-verification.mdc +0 -144
- package/dist/templates/.cursor/rules/01-working-style.mdc +0 -50
- package/dist/templates/.cursor/rules/02-quality-gates.mdc +0 -368
- package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +0 -33
- package/dist/templates/.cursor/rules/04-logging-language-style.mdc +0 -23
- package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +0 -23
- package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +0 -36
- package/dist/templates/.cursor/rules/07-process-ops.mdc +0 -20
- package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +0 -16
- package/dist/templates/.cursor/rules/09-docstrings.mdc +0 -89
- package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +0 -385
- package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +0 -381
- package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +0 -516
- package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +0 -578
- package/dist/templates/.cursor/rules/README.md +0 -148
- package/dist/templates/.github/copilot-instructions.md +0 -82
- package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +0 -5
- package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +0 -5
- package/dist/templates/.junie/guidelines.md +0 -73
- package/dist/templates/.vscode/launch.json +0 -17
- package/dist/templates/.vscode/settings.json +0 -95
- package/dist/templates/.windsurf/rules/caws-quality-standards.md +0 -54
- package/dist/templates/.windsurf/workflows/caws-guided-development.md +0 -92
- package/dist/templates/CLAUDE.md +0 -196
- package/dist/templates/COMMIT_CONVENTIONS.md +0 -86
- package/dist/templates/OIDC_SETUP.md +0 -300
- package/dist/templates/agents.md +0 -171
- package/dist/templates/codemod/README.md +0 -1
- package/dist/templates/codemod/test.js +0 -93
- package/dist/templates/docs/README.md +0 -151
- package/dist/templates/scripts/new_feature.sh +0 -80
- package/dist/templates/scripts/quality-gates/check-god-objects.js +0 -146
- package/dist/templates/scripts/quality-gates/run-quality-gates.js +0 -50
- package/dist/templates/scripts/v3/analysis/todo_analyzer.py +0 -1997
- package/dist/test-analysis.js +0 -786
- package/dist/tool-interface.js +0 -314
- package/dist/tool-loader.js +0 -303
- package/dist/tool-validator.js +0 -393
- package/dist/utils/agent-display.js +0 -210
- package/dist/utils/agent-session.js +0 -344
- package/dist/utils/async-utils.js +0 -188
- package/dist/utils/command-wrapper.js +0 -200
- package/dist/utils/event-log.js +0 -584
- package/dist/utils/event-renderer.js +0 -521
- package/dist/utils/finalization.js +0 -230
- package/dist/utils/git-lock.js +0 -119
- package/dist/utils/gitignore-updater.js +0 -158
- package/dist/utils/ide-detection.js +0 -133
- package/dist/utils/lifecycle-events.js +0 -94
- package/dist/utils/project-analysis.js +0 -367
- package/dist/utils/promise-utils.js +0 -72
- package/dist/utils/quality-gates-errors.js +0 -520
- package/dist/utils/quality-gates-utils.js +0 -387
- package/dist/utils/schema-validator.js +0 -50
- package/dist/utils/spec-resolver.js +0 -711
- package/dist/utils/typescript-detector.js +0 -369
- package/dist/utils/working-state.js +0 -530
- package/dist/utils/yaml-validation.js +0 -156
- package/dist/validation/spec-validation.js +0 -924
- package/dist/waivers-manager.js +0 -732
- package/dist/worktree/worktree-manager.js +0 -1735
- package/templates/.caws/schemas/policy.schema.json +0 -117
- package/templates/.caws/schemas/scope.schema.json +0 -52
- package/templates/.caws/schemas/waivers.schema.json +0 -106
- package/templates/.caws/schemas/working-spec.schema.json +0 -340
- package/templates/.caws/schemas/worktrees.schema.json +0 -38
- package/templates/.caws/templates/working-spec.template.yml +0 -80
- package/templates/.caws/tools/README.md +0 -18
- package/templates/.caws/tools/scope-guard.js +0 -203
- package/templates/.caws/tools-allow.json +0 -331
- package/templates/.caws/waivers.yml +0 -19
- package/templates/.claude/README.md +0 -190
- package/templates/.claude/hooks/audit.sh +0 -121
- package/templates/.claude/hooks/block-dangerous.sh +0 -203
- package/templates/.claude/hooks/classify_command.py +0 -592
- package/templates/.claude/hooks/doc-frontmatter-check.sh +0 -173
- package/templates/.claude/hooks/lite-sprawl-check.sh +0 -145
- package/templates/.claude/hooks/naming-check.sh +0 -100
- package/templates/.claude/hooks/protected-paths.sh +0 -39
- package/templates/.claude/hooks/quality-check.sh +0 -81
- package/templates/.claude/hooks/scan-secrets.sh +0 -85
- package/templates/.claude/hooks/scope-guard.sh +0 -381
- package/templates/.claude/hooks/session-caws-status.sh +0 -117
- package/templates/.claude/hooks/session-log.sh +0 -634
- package/templates/.claude/hooks/simplification-guard.sh +0 -92
- package/templates/.claude/hooks/stop-worktree-check.sh +0 -46
- package/templates/.claude/hooks/test_classify_command.py +0 -370
- package/templates/.claude/hooks/test_wrapper_smoke.sh +0 -96
- package/templates/.claude/hooks/validate-spec.sh +0 -76
- package/templates/.claude/hooks/worktree-guard.sh +0 -220
- package/templates/.claude/hooks/worktree-write-guard.sh +0 -190
- package/templates/.claude/rules/git-safety.md +0 -26
- package/templates/.claude/rules/worktree-isolation.md +0 -101
- package/templates/.claude/settings.json +0 -141
- package/templates/.cursor/README.md +0 -299
- package/templates/.cursor/hooks/audit.sh +0 -55
- package/templates/.cursor/hooks/block-dangerous.sh +0 -84
- package/templates/.cursor/hooks/caws-quality-check.sh +0 -52
- package/templates/.cursor/hooks/caws-scope-guard.sh +0 -130
- package/templates/.cursor/hooks/format.sh +0 -38
- package/templates/.cursor/hooks/naming-check.sh +0 -64
- package/templates/.cursor/hooks/scan-secrets.sh +0 -51
- package/templates/.cursor/hooks/scope-guard.sh +0 -52
- package/templates/.cursor/hooks/session-log.sh +0 -924
- package/templates/.cursor/hooks/validate-spec.sh +0 -83
- package/templates/.cursor/hooks.json +0 -76
- package/templates/.cursor/rules/00-claims-verification.mdc +0 -144
- package/templates/.cursor/rules/01-working-style.mdc +0 -50
- package/templates/.cursor/rules/02-quality-gates.mdc +0 -368
- package/templates/.cursor/rules/03-naming-and-refactor.mdc +0 -33
- package/templates/.cursor/rules/04-logging-language-style.mdc +0 -23
- package/templates/.cursor/rules/05-safe-defaults-guards.mdc +0 -23
- package/templates/.cursor/rules/06-typescript-conventions.mdc +0 -36
- package/templates/.cursor/rules/07-process-ops.mdc +0 -20
- package/templates/.cursor/rules/08-solid-and-architecture.mdc +0 -16
- package/templates/.cursor/rules/09-docstrings.mdc +0 -89
- package/templates/.cursor/rules/10-documentation-quality-standards.mdc +0 -385
- package/templates/.cursor/rules/11-scope-management-waivers.mdc +0 -381
- package/templates/.cursor/rules/12-implementation-completeness.mdc +0 -516
- package/templates/.cursor/rules/13-language-agnostic-standards.mdc +0 -578
- package/templates/.cursor/rules/README.md +0 -148
- package/templates/.github/copilot-instructions.md +0 -82
- package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +0 -5
- package/templates/.idea/runConfigurations/CAWS_Validate.xml +0 -5
- package/templates/.junie/guidelines.md +0 -73
- package/templates/.vscode/launch.json +0 -17
- package/templates/.vscode/settings.json +0 -95
- package/templates/.windsurf/rules/caws-quality-standards.md +0 -54
- package/templates/.windsurf/workflows/caws-guided-development.md +0 -92
- package/templates/CLAUDE.md +0 -196
- package/templates/COMMIT_CONVENTIONS.md +0 -86
- package/templates/OIDC_SETUP.md +0 -300
- package/templates/agents.md +0 -171
- package/templates/codemod/README.md +0 -1
- package/templates/codemod/test.js +0 -93
- package/templates/docs/README.md +0 -151
- package/templates/scripts/new_feature.sh +0 -80
- package/templates/scripts/quality-gates/check-god-objects.js +0 -146
- package/templates/scripts/quality-gates/run-quality-gates.js +0 -50
- package/templates/scripts/v3/analysis/todo_analyzer.py +0 -1997
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Claude Code Hooks Scaffolding
|
|
3
|
-
* Functions for setting up Claude Code hooks for CAWS projects
|
|
4
|
-
* @author @darianrosebrook
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const fs = require('fs-extra');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const chalk = require('chalk');
|
|
10
|
-
|
|
11
|
-
// Import detection utilities
|
|
12
|
-
const { detectCAWSSetup, findPackageRoot } = require('../utils/detection');
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Scaffold Claude Code hooks for a CAWS project
|
|
16
|
-
* Creates .claude/settings.json with hooks and .claude/hooks/ directory with scripts
|
|
17
|
-
*
|
|
18
|
-
* @param {string} projectDir - Project directory path
|
|
19
|
-
* @param {string[]} levels - Hook levels to enable: 'safety', 'quality', 'scope', 'audit'
|
|
20
|
-
*/
|
|
21
|
-
async function scaffoldClaudeHooks(projectDir, levels = ['safety', 'quality', 'scope', 'audit']) {
|
|
22
|
-
try {
|
|
23
|
-
const claudeDir = path.join(projectDir, '.claude');
|
|
24
|
-
const claudeHooksDir = path.join(claudeDir, 'hooks');
|
|
25
|
-
|
|
26
|
-
// Create .claude directory structure
|
|
27
|
-
await fs.ensureDir(claudeDir);
|
|
28
|
-
await fs.ensureDir(claudeHooksDir);
|
|
29
|
-
|
|
30
|
-
// Determine template directory - prefer bundled templates
|
|
31
|
-
const setup = detectCAWSSetup(projectDir);
|
|
32
|
-
|
|
33
|
-
// Find package root using shared utility
|
|
34
|
-
const packageRoot = findPackageRoot(__dirname);
|
|
35
|
-
|
|
36
|
-
// Try templates relative to package root first (works in both dev and global install)
|
|
37
|
-
const bundledTemplateDir = path.join(packageRoot, 'templates');
|
|
38
|
-
const fallbackTemplateDir = path.join(__dirname, '../../templates');
|
|
39
|
-
const templateDir = fs.existsSync(bundledTemplateDir)
|
|
40
|
-
? bundledTemplateDir
|
|
41
|
-
: fs.existsSync(fallbackTemplateDir)
|
|
42
|
-
? fallbackTemplateDir
|
|
43
|
-
: setup.templateDir || path.resolve(__dirname, '../templates');
|
|
44
|
-
|
|
45
|
-
const claudeTemplateDir = path.join(templateDir, '.claude');
|
|
46
|
-
const claudeHooksTemplateDir = path.join(claudeTemplateDir, 'hooks');
|
|
47
|
-
|
|
48
|
-
if (!fs.existsSync(claudeTemplateDir)) {
|
|
49
|
-
console.warn(chalk.yellow('Claude Code hooks templates not found'));
|
|
50
|
-
console.warn(chalk.blue('Skipping Claude Code hooks setup'));
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Map levels to hook scripts
|
|
55
|
-
const hookMapping = {
|
|
56
|
-
safety: ['block-dangerous.sh', 'scan-secrets.sh', 'worktree-guard.sh', 'worktree-write-guard.sh', 'stop-worktree-check.sh', 'session-caws-status.sh'],
|
|
57
|
-
quality: ['quality-check.sh', 'validate-spec.sh', 'doc-frontmatter-check.sh'],
|
|
58
|
-
scope: ['scope-guard.sh', 'naming-check.sh'],
|
|
59
|
-
audit: ['audit.sh', 'session-log.sh'],
|
|
60
|
-
lite: ['block-dangerous.sh', 'scope-guard.sh', 'lite-sprawl-check.sh', 'simplification-guard.sh'],
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// Determine which hooks to enable
|
|
64
|
-
const enabledHooks = new Set();
|
|
65
|
-
levels.forEach((level) => {
|
|
66
|
-
const hooks = hookMapping[level] || [];
|
|
67
|
-
hooks.forEach((hook) => enabledHooks.add(hook));
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Always enable audit.sh if any hooks are enabled
|
|
71
|
-
if (enabledHooks.size > 0) {
|
|
72
|
-
enabledHooks.add('audit.sh');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Copy enabled hook scripts
|
|
76
|
-
const allHookScripts = [
|
|
77
|
-
'audit.sh',
|
|
78
|
-
'validate-spec.sh',
|
|
79
|
-
'quality-check.sh',
|
|
80
|
-
'scan-secrets.sh',
|
|
81
|
-
'block-dangerous.sh',
|
|
82
|
-
'scope-guard.sh',
|
|
83
|
-
'naming-check.sh',
|
|
84
|
-
'doc-frontmatter-check.sh',
|
|
85
|
-
'lite-sprawl-check.sh',
|
|
86
|
-
'simplification-guard.sh',
|
|
87
|
-
'worktree-guard.sh',
|
|
88
|
-
'worktree-write-guard.sh',
|
|
89
|
-
'stop-worktree-check.sh',
|
|
90
|
-
'session-caws-status.sh',
|
|
91
|
-
'session-log.sh',
|
|
92
|
-
];
|
|
93
|
-
|
|
94
|
-
// Copy supporting scripts (not hooks themselves, but used by hooks)
|
|
95
|
-
const supportingScripts = [
|
|
96
|
-
'classify_command.py',
|
|
97
|
-
'test_classify_command.py',
|
|
98
|
-
'test_wrapper_smoke.sh',
|
|
99
|
-
];
|
|
100
|
-
|
|
101
|
-
for (const script of supportingScripts) {
|
|
102
|
-
const sourcePath = path.join(claudeHooksTemplateDir, script);
|
|
103
|
-
const destPath = path.join(claudeHooksDir, script);
|
|
104
|
-
|
|
105
|
-
if (fs.existsSync(sourcePath)) {
|
|
106
|
-
await fs.copy(sourcePath, destPath);
|
|
107
|
-
await fs.chmod(destPath, 0o755);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
for (const script of allHookScripts) {
|
|
112
|
-
if (enabledHooks.has(script)) {
|
|
113
|
-
const sourcePath = path.join(claudeHooksTemplateDir, script);
|
|
114
|
-
const destPath = path.join(claudeHooksDir, script);
|
|
115
|
-
|
|
116
|
-
if (fs.existsSync(sourcePath)) {
|
|
117
|
-
await fs.copy(sourcePath, destPath);
|
|
118
|
-
// Make executable
|
|
119
|
-
await fs.chmod(destPath, 0o755);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Generate settings.json with hooks configuration
|
|
125
|
-
const settings = generateClaudeSettings(levels, enabledHooks);
|
|
126
|
-
|
|
127
|
-
// Check for existing settings and merge
|
|
128
|
-
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
129
|
-
if (fs.existsSync(settingsPath)) {
|
|
130
|
-
try {
|
|
131
|
-
const existingSettings = await fs.readJSON(settingsPath);
|
|
132
|
-
// Merge hooks, preserving existing non-hook settings
|
|
133
|
-
settings.hooks = {
|
|
134
|
-
...existingSettings.hooks,
|
|
135
|
-
...settings.hooks,
|
|
136
|
-
};
|
|
137
|
-
// Preserve other settings
|
|
138
|
-
Object.keys(existingSettings).forEach((key) => {
|
|
139
|
-
if (key !== 'hooks' && !(key in settings)) {
|
|
140
|
-
settings[key] = existingSettings[key];
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
} catch (error) {
|
|
144
|
-
console.warn(chalk.yellow('Could not merge existing settings:'), error.message);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Write settings.json
|
|
149
|
-
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
150
|
-
|
|
151
|
-
// Copy README if it exists
|
|
152
|
-
const readmePath = path.join(claudeTemplateDir, 'README.md');
|
|
153
|
-
if (fs.existsSync(readmePath)) {
|
|
154
|
-
await fs.copy(readmePath, path.join(claudeDir, 'README.md'));
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Copy rules directory if it exists
|
|
158
|
-
const rulesTemplateDir = path.join(claudeTemplateDir, 'rules');
|
|
159
|
-
if (fs.existsSync(rulesTemplateDir)) {
|
|
160
|
-
const rulesDir = path.join(claudeDir, 'rules');
|
|
161
|
-
await fs.ensureDir(rulesDir);
|
|
162
|
-
await fs.copy(rulesTemplateDir, rulesDir, { overwrite: false });
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
console.log(chalk.green('Claude Code hooks configured'));
|
|
166
|
-
console.log(chalk.gray(` Enabled: ${levels.join(', ')}`));
|
|
167
|
-
console.log(
|
|
168
|
-
chalk.gray(` Scripts: ${Array.from(enabledHooks).length} hook scripts installed`)
|
|
169
|
-
);
|
|
170
|
-
console.log(chalk.blue('Hooks will activate on next Claude Code session'));
|
|
171
|
-
} catch (error) {
|
|
172
|
-
console.error(chalk.yellow('Failed to setup Claude Code hooks:'), error.message);
|
|
173
|
-
console.log(chalk.blue('You can manually copy .claude/ directory later'));
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Generate Claude Code settings with hooks configuration
|
|
179
|
-
* @param {string[]} levels - Enabled hook levels
|
|
180
|
-
* @param {Set<string>} enabledHooks - Set of enabled hook script names
|
|
181
|
-
* @returns {Object} Settings object for settings.json
|
|
182
|
-
*/
|
|
183
|
-
function generateClaudeSettings(levels, _enabledHooks) {
|
|
184
|
-
const settings = {
|
|
185
|
-
hooks: {},
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
// Build hooks configuration based on enabled levels
|
|
189
|
-
// Claude Code uses different event names and matcher patterns
|
|
190
|
-
|
|
191
|
-
if (levels.includes('safety')) {
|
|
192
|
-
// Block dangerous bash commands
|
|
193
|
-
settings.hooks.PreToolUse = settings.hooks.PreToolUse || [];
|
|
194
|
-
settings.hooks.PreToolUse.push({
|
|
195
|
-
matcher: 'Bash',
|
|
196
|
-
hooks: [
|
|
197
|
-
{
|
|
198
|
-
type: 'command',
|
|
199
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/block-dangerous.sh',
|
|
200
|
-
timeout: 10,
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
type: 'command',
|
|
204
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/worktree-guard.sh',
|
|
205
|
-
timeout: 10,
|
|
206
|
-
},
|
|
207
|
-
],
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
// Scan for secrets on file read
|
|
211
|
-
settings.hooks.PreToolUse.push({
|
|
212
|
-
matcher: 'Read',
|
|
213
|
-
hooks: [
|
|
214
|
-
{
|
|
215
|
-
type: 'command',
|
|
216
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/scan-secrets.sh',
|
|
217
|
-
timeout: 10,
|
|
218
|
-
},
|
|
219
|
-
],
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// Block Write/Edit on base branch while worktrees are active
|
|
223
|
-
settings.hooks.PreToolUse.push({
|
|
224
|
-
matcher: 'Write|Edit',
|
|
225
|
-
hooks: [
|
|
226
|
-
{
|
|
227
|
-
type: 'command',
|
|
228
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/worktree-write-guard.sh',
|
|
229
|
-
timeout: 10,
|
|
230
|
-
},
|
|
231
|
-
],
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// Worktree status warning on session start
|
|
235
|
-
settings.hooks.SessionStart = settings.hooks.SessionStart || [];
|
|
236
|
-
settings.hooks.SessionStart.push({
|
|
237
|
-
hooks: [
|
|
238
|
-
{
|
|
239
|
-
type: 'command',
|
|
240
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/session-caws-status.sh session-start',
|
|
241
|
-
timeout: 10,
|
|
242
|
-
},
|
|
243
|
-
],
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
// Worktree cleanup reminder on session end
|
|
247
|
-
settings.hooks.Stop = settings.hooks.Stop || [];
|
|
248
|
-
settings.hooks.Stop.push({
|
|
249
|
-
hooks: [
|
|
250
|
-
{
|
|
251
|
-
type: 'command',
|
|
252
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/stop-worktree-check.sh',
|
|
253
|
-
timeout: 10,
|
|
254
|
-
},
|
|
255
|
-
],
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (levels.includes('quality')) {
|
|
260
|
-
// Run quality checks after file edits
|
|
261
|
-
settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
|
|
262
|
-
settings.hooks.PostToolUse.push({
|
|
263
|
-
matcher: 'Write|Edit',
|
|
264
|
-
hooks: [
|
|
265
|
-
{
|
|
266
|
-
type: 'command',
|
|
267
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/quality-check.sh',
|
|
268
|
-
timeout: 30,
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
type: 'command',
|
|
272
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/validate-spec.sh',
|
|
273
|
-
timeout: 15,
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
type: 'command',
|
|
277
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/doc-frontmatter-check.sh',
|
|
278
|
-
timeout: 10,
|
|
279
|
-
},
|
|
280
|
-
],
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (levels.includes('scope')) {
|
|
285
|
-
// Scope guard before file writes
|
|
286
|
-
settings.hooks.PreToolUse = settings.hooks.PreToolUse || [];
|
|
287
|
-
settings.hooks.PreToolUse.push({
|
|
288
|
-
matcher: 'Write|Edit',
|
|
289
|
-
hooks: [
|
|
290
|
-
{
|
|
291
|
-
type: 'command',
|
|
292
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/scope-guard.sh',
|
|
293
|
-
timeout: 10,
|
|
294
|
-
},
|
|
295
|
-
],
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
// Naming check after edits
|
|
299
|
-
settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
|
|
300
|
-
settings.hooks.PostToolUse.push({
|
|
301
|
-
matcher: 'Write|Edit',
|
|
302
|
-
hooks: [
|
|
303
|
-
{
|
|
304
|
-
type: 'command',
|
|
305
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/naming-check.sh',
|
|
306
|
-
timeout: 10,
|
|
307
|
-
},
|
|
308
|
-
],
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (levels.includes('lite')) {
|
|
313
|
-
// Lite mode: sprawl check on Write, simplification guard on Edit
|
|
314
|
-
settings.hooks.PreToolUse = settings.hooks.PreToolUse || [];
|
|
315
|
-
settings.hooks.PreToolUse.push({
|
|
316
|
-
matcher: 'Write',
|
|
317
|
-
hooks: [
|
|
318
|
-
{
|
|
319
|
-
type: 'command',
|
|
320
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/lite-sprawl-check.sh',
|
|
321
|
-
timeout: 10,
|
|
322
|
-
},
|
|
323
|
-
],
|
|
324
|
-
});
|
|
325
|
-
settings.hooks.PreToolUse.push({
|
|
326
|
-
matcher: 'Edit',
|
|
327
|
-
hooks: [
|
|
328
|
-
{
|
|
329
|
-
type: 'command',
|
|
330
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/simplification-guard.sh',
|
|
331
|
-
timeout: 10,
|
|
332
|
-
},
|
|
333
|
-
],
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (levels.includes('audit')) {
|
|
338
|
-
// Session audit logging
|
|
339
|
-
settings.hooks.SessionStart = settings.hooks.SessionStart || [];
|
|
340
|
-
settings.hooks.SessionStart.push({
|
|
341
|
-
hooks: [
|
|
342
|
-
{
|
|
343
|
-
type: 'command',
|
|
344
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/audit.sh session-start',
|
|
345
|
-
timeout: 5,
|
|
346
|
-
},
|
|
347
|
-
{
|
|
348
|
-
type: 'command',
|
|
349
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/session-log.sh',
|
|
350
|
-
timeout: 10,
|
|
351
|
-
},
|
|
352
|
-
],
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
settings.hooks.Stop = settings.hooks.Stop || [];
|
|
356
|
-
settings.hooks.Stop.push({
|
|
357
|
-
hooks: [
|
|
358
|
-
{
|
|
359
|
-
type: 'command',
|
|
360
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/audit.sh stop',
|
|
361
|
-
timeout: 5,
|
|
362
|
-
},
|
|
363
|
-
{
|
|
364
|
-
type: 'command',
|
|
365
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/session-log.sh',
|
|
366
|
-
timeout: 15,
|
|
367
|
-
},
|
|
368
|
-
],
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
// Session transcript generation on context compaction
|
|
372
|
-
settings.hooks.PreCompact = settings.hooks.PreCompact || [];
|
|
373
|
-
settings.hooks.PreCompact.push({
|
|
374
|
-
hooks: [
|
|
375
|
-
{
|
|
376
|
-
type: 'command',
|
|
377
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/session-log.sh',
|
|
378
|
-
timeout: 15,
|
|
379
|
-
},
|
|
380
|
-
],
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
// Audit tool usage
|
|
384
|
-
settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
|
|
385
|
-
settings.hooks.PostToolUse.push({
|
|
386
|
-
matcher: 'Write|Edit|Bash',
|
|
387
|
-
hooks: [
|
|
388
|
-
{
|
|
389
|
-
type: 'command',
|
|
390
|
-
command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/audit.sh tool-use',
|
|
391
|
-
timeout: 5,
|
|
392
|
-
},
|
|
393
|
-
],
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
return settings;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Check if Claude Code hooks are already configured
|
|
402
|
-
* @param {string} projectDir - Project directory
|
|
403
|
-
* @returns {boolean} True if hooks are configured
|
|
404
|
-
*/
|
|
405
|
-
function hasClaudeHooks(projectDir) {
|
|
406
|
-
const settingsPath = path.join(projectDir, '.claude', 'settings.json');
|
|
407
|
-
if (!fs.existsSync(settingsPath)) {
|
|
408
|
-
return false;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
try {
|
|
412
|
-
const settings = fs.readJSONSync(settingsPath);
|
|
413
|
-
return settings.hooks && Object.keys(settings.hooks).length > 0;
|
|
414
|
-
} catch {
|
|
415
|
-
return false;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* List configured Claude Code hooks
|
|
421
|
-
* @param {string} projectDir - Project directory
|
|
422
|
-
* @returns {Object} Hook configuration or null
|
|
423
|
-
*/
|
|
424
|
-
function getClaudeHooksConfig(projectDir) {
|
|
425
|
-
const settingsPath = path.join(projectDir, '.claude', 'settings.json');
|
|
426
|
-
if (!fs.existsSync(settingsPath)) {
|
|
427
|
-
return null;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
try {
|
|
431
|
-
const settings = fs.readJSONSync(settingsPath);
|
|
432
|
-
return settings.hooks || null;
|
|
433
|
-
} catch {
|
|
434
|
-
return null;
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
module.exports = {
|
|
439
|
-
scaffoldClaudeHooks,
|
|
440
|
-
generateClaudeSettings,
|
|
441
|
-
hasClaudeHooks,
|
|
442
|
-
getClaudeHooksConfig,
|
|
443
|
-
};
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Cursor Hooks Scaffolding
|
|
3
|
-
* Functions for setting up Cursor IDE hooks for CAWS
|
|
4
|
-
* @author @darianrosebrook
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const fs = require('fs-extra');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const chalk = require('chalk');
|
|
10
|
-
|
|
11
|
-
// Import detection utilities
|
|
12
|
-
const { detectCAWSSetup, findPackageRoot } = require('../utils/detection');
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Scaffold Cursor hooks for a CAWS project
|
|
16
|
-
* @param {string} projectDir - Project directory path
|
|
17
|
-
* @param {string[]} levels - Hook levels to enable
|
|
18
|
-
*/
|
|
19
|
-
async function scaffoldCursorHooks(projectDir, levels = ['safety', 'quality', 'scope', 'audit']) {
|
|
20
|
-
try {
|
|
21
|
-
const cursorDir = path.join(projectDir, '.cursor');
|
|
22
|
-
const cursorHooksDir = path.join(cursorDir, 'hooks');
|
|
23
|
-
|
|
24
|
-
// Create .cursor directory structure
|
|
25
|
-
await fs.ensureDir(cursorDir);
|
|
26
|
-
await fs.ensureDir(cursorHooksDir);
|
|
27
|
-
await fs.ensureDir(path.join(cursorDir, 'logs'));
|
|
28
|
-
|
|
29
|
-
// Determine template directory - prefer bundled templates
|
|
30
|
-
const setup = detectCAWSSetup(projectDir);
|
|
31
|
-
|
|
32
|
-
// Find package root using shared utility
|
|
33
|
-
const packageRoot = findPackageRoot(__dirname);
|
|
34
|
-
|
|
35
|
-
// Try templates relative to package root first (works in both dev and global install)
|
|
36
|
-
const bundledTemplateDir = path.join(packageRoot, 'templates');
|
|
37
|
-
const fallbackTemplateDir = path.join(__dirname, '../../templates');
|
|
38
|
-
const templateDir = fs.existsSync(bundledTemplateDir)
|
|
39
|
-
? bundledTemplateDir
|
|
40
|
-
: fs.existsSync(fallbackTemplateDir)
|
|
41
|
-
? fallbackTemplateDir
|
|
42
|
-
: setup.templateDir || path.resolve(__dirname, '../templates');
|
|
43
|
-
|
|
44
|
-
const cursorTemplateDir = path.join(templateDir, '.cursor');
|
|
45
|
-
const cursorHooksTemplateDir = path.join(cursorTemplateDir, 'hooks');
|
|
46
|
-
|
|
47
|
-
if (!fs.existsSync(cursorTemplateDir)) {
|
|
48
|
-
console.warn(chalk.yellow('Cursor hooks templates not found'));
|
|
49
|
-
console.warn(chalk.blue('Skipping Cursor hooks setup'));
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Map levels to hook scripts
|
|
54
|
-
const hookMapping = {
|
|
55
|
-
safety: ['scan-secrets.sh', 'block-dangerous.sh'],
|
|
56
|
-
quality: ['format.sh', 'validate-spec.sh'],
|
|
57
|
-
scope: ['scope-guard.sh', 'naming-check.sh'],
|
|
58
|
-
audit: ['audit.sh'],
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
// Determine which hooks to enable
|
|
62
|
-
const enabledHooks = new Set();
|
|
63
|
-
levels.forEach((level) => {
|
|
64
|
-
const hooks = hookMapping[level] || [];
|
|
65
|
-
hooks.forEach((hook) => enabledHooks.add(hook));
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// Always enable audit.sh if any hooks are enabled
|
|
69
|
-
if (enabledHooks.size > 0) {
|
|
70
|
-
enabledHooks.add('audit.sh');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Copy enabled hook scripts
|
|
74
|
-
const allHookScripts = [
|
|
75
|
-
'audit.sh',
|
|
76
|
-
'validate-spec.sh',
|
|
77
|
-
'format.sh',
|
|
78
|
-
'scan-secrets.sh',
|
|
79
|
-
'block-dangerous.sh',
|
|
80
|
-
'scope-guard.sh',
|
|
81
|
-
'naming-check.sh',
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
for (const script of allHookScripts) {
|
|
85
|
-
if (enabledHooks.has(script)) {
|
|
86
|
-
const sourcePath = path.join(cursorHooksTemplateDir, script);
|
|
87
|
-
const destPath = path.join(cursorHooksDir, script);
|
|
88
|
-
|
|
89
|
-
if (fs.existsSync(sourcePath)) {
|
|
90
|
-
await fs.copy(sourcePath, destPath);
|
|
91
|
-
// Make executable
|
|
92
|
-
await fs.chmod(destPath, 0o755);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Generate hooks.json based on enabled hooks
|
|
98
|
-
const hooksConfig = {
|
|
99
|
-
version: 1,
|
|
100
|
-
hooks: {},
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// Build hooks configuration based on enabled levels
|
|
104
|
-
if (levels.includes('safety')) {
|
|
105
|
-
hooksConfig.hooks.beforeShellExecution = [
|
|
106
|
-
{ command: './.cursor/hooks/block-dangerous.sh' },
|
|
107
|
-
{ command: './.cursor/hooks/audit.sh' },
|
|
108
|
-
];
|
|
109
|
-
hooksConfig.hooks.beforeReadFile = [{ command: './.cursor/hooks/scan-secrets.sh' }];
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (levels.includes('quality')) {
|
|
113
|
-
hooksConfig.hooks.afterFileEdit = hooksConfig.hooks.afterFileEdit || [];
|
|
114
|
-
hooksConfig.hooks.afterFileEdit.push(
|
|
115
|
-
{ command: './.cursor/hooks/format.sh' },
|
|
116
|
-
{ command: './.cursor/hooks/validate-spec.sh' }
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (levels.includes('scope')) {
|
|
121
|
-
hooksConfig.hooks.afterFileEdit = hooksConfig.hooks.afterFileEdit || [];
|
|
122
|
-
hooksConfig.hooks.afterFileEdit.push({ command: './.cursor/hooks/naming-check.sh' });
|
|
123
|
-
hooksConfig.hooks.beforeSubmitPrompt = [
|
|
124
|
-
{ command: './.cursor/hooks/scope-guard.sh' },
|
|
125
|
-
{ command: './.cursor/hooks/audit.sh' },
|
|
126
|
-
];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (levels.includes('audit')) {
|
|
130
|
-
// Add audit to all events
|
|
131
|
-
if (!hooksConfig.hooks.afterFileEdit) {
|
|
132
|
-
hooksConfig.hooks.afterFileEdit = [];
|
|
133
|
-
}
|
|
134
|
-
hooksConfig.hooks.afterFileEdit.push({ command: './.cursor/hooks/audit.sh' });
|
|
135
|
-
|
|
136
|
-
hooksConfig.hooks.stop = [{ command: './.cursor/hooks/audit.sh' }];
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Write hooks.json
|
|
140
|
-
await fs.writeFile(path.join(cursorDir, 'hooks.json'), JSON.stringify(hooksConfig, null, 2));
|
|
141
|
-
|
|
142
|
-
// Copy README
|
|
143
|
-
const readmePath = path.join(cursorTemplateDir, 'README.md');
|
|
144
|
-
if (fs.existsSync(readmePath)) {
|
|
145
|
-
await fs.copy(readmePath, path.join(cursorDir, 'README.md'));
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Copy rules directory if it exists
|
|
149
|
-
const rulesTemplateDir = path.join(cursorTemplateDir, 'rules');
|
|
150
|
-
const rulesDestDir = path.join(cursorDir, 'rules');
|
|
151
|
-
if (fs.existsSync(rulesTemplateDir)) {
|
|
152
|
-
try {
|
|
153
|
-
await fs.ensureDir(rulesDestDir);
|
|
154
|
-
await fs.copy(rulesTemplateDir, rulesDestDir);
|
|
155
|
-
const ruleFiles = fs.readdirSync(rulesTemplateDir).filter((file) => file.endsWith('.mdc'));
|
|
156
|
-
console.log(chalk.green('Cursor rules configured'));
|
|
157
|
-
console.log(chalk.gray(` Rules: ${ruleFiles.length} rule files installed`));
|
|
158
|
-
} catch (error) {
|
|
159
|
-
console.warn(chalk.yellow('Failed to copy Cursor rules:'), error.message);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
console.log(chalk.green('Cursor hooks configured'));
|
|
164
|
-
console.log(chalk.gray(` Enabled: ${levels.join(', ')}`));
|
|
165
|
-
console.log(
|
|
166
|
-
chalk.gray(` Scripts: ${Array.from(enabledHooks).length} hook scripts installed`)
|
|
167
|
-
);
|
|
168
|
-
console.log(chalk.blue('Restart Cursor to activate hooks'));
|
|
169
|
-
} catch (error) {
|
|
170
|
-
console.error(chalk.yellow('Failed to setup Cursor hooks:'), error.message);
|
|
171
|
-
console.log(chalk.blue('You can manually copy .cursor/ directory later'));
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
module.exports = {
|
|
176
|
-
scaffoldCursorHooks,
|
|
177
|
-
};
|