@paths.design/caws-cli 10.1.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 -756
- 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/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 -1448
- package/dist/commands/status.js +0 -1151
- 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 -386
- 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 -93
- 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 -465
- 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 -112
- 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 -83
- 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 -174
- package/dist/templates/COMMIT_CONVENTIONS.md +0 -86
- package/dist/templates/OIDC_SETUP.md +0 -300
- package/dist/templates/agents.md +0 -145
- 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-session.js +0 -202
- 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 -921
- package/dist/waivers-manager.js +0 -732
- package/dist/worktree/worktree-manager.js +0 -1374
- package/templates/.caws/schemas/policy.schema.json +0 -112
- 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 -83
- 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 -174
- package/templates/COMMIT_CONVENTIONS.md +0 -86
- package/templates/OIDC_SETUP.md +0 -300
- package/templates/agents.md +0 -145
- 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,928 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Git Hooks Scaffolding for CAWS Provenance
|
|
3
|
-
* Functions for setting up git hooks that automatically update provenance
|
|
4
|
-
* @author @darianrosebrook
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const fs = require('fs-extra');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const { getTodoAnalyzerSuggestion } = require('../utils/project-analysis');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Scaffold git hooks for CAWS provenance tracking
|
|
13
|
-
* @param {string} projectDir - Project directory path
|
|
14
|
-
* @param {Object} options - Hook options
|
|
15
|
-
*/
|
|
16
|
-
async function scaffoldGitHooks(projectDir, options = {}) {
|
|
17
|
-
const { provenance = true, validation = true, qualityGates = true, force = false } = options;
|
|
18
|
-
|
|
19
|
-
console.log('Setting up Git hooks for CAWS provenance...');
|
|
20
|
-
|
|
21
|
-
const gitDir = path.join(projectDir, '.git');
|
|
22
|
-
const hooksDir = path.join(gitDir, 'hooks');
|
|
23
|
-
|
|
24
|
-
// Check if this is a git repository
|
|
25
|
-
if (!(await fs.pathExists(gitDir))) {
|
|
26
|
-
console.log('Not a git repository - skipping git hooks setup');
|
|
27
|
-
console.log('Initialize git first: git init');
|
|
28
|
-
return { added: 0, skipped: 0 };
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Ensure hooks directory exists
|
|
32
|
-
await fs.ensureDir(hooksDir);
|
|
33
|
-
|
|
34
|
-
let addedCount = 0;
|
|
35
|
-
let skippedCount = 0;
|
|
36
|
-
|
|
37
|
-
// Define hook configurations
|
|
38
|
-
const hooks = [
|
|
39
|
-
{
|
|
40
|
-
name: 'pre-commit',
|
|
41
|
-
description: 'Pre-commit validation and quality checks',
|
|
42
|
-
enabled: validation || qualityGates,
|
|
43
|
-
content: generatePreCommitHook({ validation, qualityGates, projectDir }),
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: 'post-commit',
|
|
47
|
-
description: 'Post-commit provenance tracking',
|
|
48
|
-
enabled: provenance,
|
|
49
|
-
content: generatePostCommitHook(),
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
name: 'pre-push',
|
|
53
|
-
description: 'Pre-push comprehensive validation',
|
|
54
|
-
enabled: qualityGates,
|
|
55
|
-
content: generatePrePushHook(),
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
name: 'commit-msg',
|
|
59
|
-
description: 'Commit message validation',
|
|
60
|
-
enabled: validation,
|
|
61
|
-
content: generateCommitMsgHook(),
|
|
62
|
-
},
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
for (const hook of hooks) {
|
|
66
|
-
if (!hook.enabled) continue;
|
|
67
|
-
|
|
68
|
-
const hookPath = path.join(hooksDir, hook.name);
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
// Check if hook already exists
|
|
72
|
-
const exists = await fs.pathExists(hookPath);
|
|
73
|
-
|
|
74
|
-
if (exists && !force) {
|
|
75
|
-
// Check if it's already a CAWS hook
|
|
76
|
-
const content = await fs.readFile(hookPath, 'utf8');
|
|
77
|
-
if (content.includes('# CAWS Hook')) {
|
|
78
|
-
console.log(`Skipped ${hook.description} (already configured)`);
|
|
79
|
-
skippedCount++;
|
|
80
|
-
continue;
|
|
81
|
-
} else {
|
|
82
|
-
console.log(`${hook.description} exists but not CAWS-managed`);
|
|
83
|
-
if (!options.backup) {
|
|
84
|
-
console.log(`Use --force to replace, or --backup to preserve original`);
|
|
85
|
-
skippedCount++;
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Backup existing hook if requested
|
|
92
|
-
if (exists && options.backup) {
|
|
93
|
-
const backupPath = `${hookPath}.backup.${Date.now()}`;
|
|
94
|
-
await fs.copy(hookPath, backupPath);
|
|
95
|
-
console.log(`Backed up existing ${hook.name} to ${path.basename(backupPath)}`);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Write the hook
|
|
99
|
-
await fs.writeFile(hookPath, hook.content);
|
|
100
|
-
await fs.chmod(hookPath, 0o755);
|
|
101
|
-
|
|
102
|
-
console.log(`Configured ${hook.description}`);
|
|
103
|
-
addedCount++;
|
|
104
|
-
} catch (error) {
|
|
105
|
-
console.log(`Failed to configure ${hook.description}: ${error.message}`);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (addedCount > 0) {
|
|
110
|
-
console.log(`\nGit hooks configured: ${addedCount} hooks active`);
|
|
111
|
-
console.log('Hooks will run automatically on git operations');
|
|
112
|
-
console.log('Use --no-verify to skip commit hooks: git commit --no-verify');
|
|
113
|
-
console.log('Note: --no-verify is BLOCKED on git push for safety');
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return { added: addedCount, skipped: skippedCount };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Generate pre-commit hook content with staged file quality gates
|
|
121
|
-
* Implements fallback chain: Node script → CLI → Python scripts → Skip gracefully
|
|
122
|
-
*/
|
|
123
|
-
function generatePreCommitHook(options) {
|
|
124
|
-
const { qualityGates = true, stagedOnly = true, projectDir = process.cwd() } = options;
|
|
125
|
-
|
|
126
|
-
// Get language-agnostic suggestions based on runtime availability
|
|
127
|
-
const todoSuggestion = getTodoAnalyzerSuggestion(projectDir);
|
|
128
|
-
|
|
129
|
-
return `#!/bin/bash
|
|
130
|
-
# CAWS Pre-commit Hook
|
|
131
|
-
# Runs validation and quality checks before commits
|
|
132
|
-
# Implements graceful fallback chain to avoid blocking commits
|
|
133
|
-
|
|
134
|
-
set -e
|
|
135
|
-
|
|
136
|
-
echo "Running CAWS Quality Gates${qualityGates ? ' (Crisis Response Mode)' : ''}..."
|
|
137
|
-
echo "Analyzing ${stagedOnly ? 'staged files only' : 'all files'}..."
|
|
138
|
-
|
|
139
|
-
# Check if CAWS is initialized
|
|
140
|
-
if [ ! -d ".caws" ]; then
|
|
141
|
-
echo "CAWS not initialized - skipping validation"
|
|
142
|
-
exit 0
|
|
143
|
-
fi
|
|
144
|
-
|
|
145
|
-
# Check for git locks before proceeding
|
|
146
|
-
if [ -f ".git/index.lock" ]; then
|
|
147
|
-
LOCK_AGE=$(($(date +%s) - $(stat -f %m .git/index.lock 2>/dev/null || stat -c %Y .git/index.lock 2>/dev/null || echo 0)))
|
|
148
|
-
LOCK_AGE_MINUTES=$((LOCK_AGE / 60))
|
|
149
|
-
|
|
150
|
-
if [ $LOCK_AGE_MINUTES -gt 5 ]; then
|
|
151
|
-
echo "Stale git lock detected (\${LOCK_AGE_MINUTES} minutes old)"
|
|
152
|
-
echo "This may indicate a crashed git process"
|
|
153
|
-
echo "Remove stale lock: rm .git/index.lock"
|
|
154
|
-
echo "Warning: Check for running git/editor processes before removing"
|
|
155
|
-
exit 1
|
|
156
|
-
else
|
|
157
|
-
echo "Git lock detected (\${LOCK_AGE_MINUTES} minutes old)"
|
|
158
|
-
echo "Another git process may be running"
|
|
159
|
-
echo "Wait for the other process to complete, or check for running processes"
|
|
160
|
-
exit 1
|
|
161
|
-
fi
|
|
162
|
-
fi
|
|
163
|
-
|
|
164
|
-
# Validate YAML syntax for all CAWS spec files
|
|
165
|
-
echo "Validating YAML syntax for CAWS spec files..."
|
|
166
|
-
YAML_VALIDATION_FAILED=false
|
|
167
|
-
|
|
168
|
-
# Find all staged .yaml/.yml files in .caws directory
|
|
169
|
-
STAGED_YAML_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\\.caws/.*\\.(yaml|yml)$' || true)
|
|
170
|
-
|
|
171
|
-
if [ -n "$STAGED_YAML_FILES" ]; then
|
|
172
|
-
# Use Node.js to validate YAML if available
|
|
173
|
-
if command -v node >/dev/null 2>&1; then
|
|
174
|
-
# Try to use CAWS CLI for validation
|
|
175
|
-
if command -v caws >/dev/null 2>&1; then
|
|
176
|
-
for file in $STAGED_YAML_FILES; do
|
|
177
|
-
if [ -f "$file" ]; then
|
|
178
|
-
# Use Node.js to validate YAML syntax
|
|
179
|
-
if ! node -e "
|
|
180
|
-
const yaml = require('js-yaml');
|
|
181
|
-
const fs = require('fs');
|
|
182
|
-
try {
|
|
183
|
-
const content = fs.readFileSync('$file', 'utf8');
|
|
184
|
-
yaml.load(content);
|
|
185
|
-
process.exit(0);
|
|
186
|
-
} catch (error) {
|
|
187
|
-
console.error('Invalid YAML in $file');
|
|
188
|
-
console.error(' Error:', error.message);
|
|
189
|
-
if (error.mark) {
|
|
190
|
-
console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
|
|
191
|
-
if (error.mark.snippet) console.error(' ' + error.mark.snippet);
|
|
192
|
-
}
|
|
193
|
-
process.exit(1);
|
|
194
|
-
}
|
|
195
|
-
" 2>&1; then
|
|
196
|
-
YAML_VALIDATION_FAILED=true
|
|
197
|
-
fi
|
|
198
|
-
fi
|
|
199
|
-
done
|
|
200
|
-
else
|
|
201
|
-
# Fallback: use node directly with js-yaml
|
|
202
|
-
for file in $STAGED_YAML_FILES; do
|
|
203
|
-
if [ -f "$file" ]; then
|
|
204
|
-
if ! node -e "
|
|
205
|
-
const yaml = require('js-yaml');
|
|
206
|
-
const fs = require('fs');
|
|
207
|
-
try {
|
|
208
|
-
const content = fs.readFileSync('$file', 'utf8');
|
|
209
|
-
yaml.load(content);
|
|
210
|
-
process.exit(0);
|
|
211
|
-
} catch (error) {
|
|
212
|
-
console.error('Invalid YAML in $file');
|
|
213
|
-
console.error(' Error:', error.message);
|
|
214
|
-
if (error.mark) {
|
|
215
|
-
console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
|
|
216
|
-
if (error.mark.snippet) console.error(' ' + error.mark.snippet);
|
|
217
|
-
}
|
|
218
|
-
process.exit(1);
|
|
219
|
-
}
|
|
220
|
-
" 2>&1; then
|
|
221
|
-
YAML_VALIDATION_FAILED=true
|
|
222
|
-
fi
|
|
223
|
-
fi
|
|
224
|
-
done
|
|
225
|
-
fi
|
|
226
|
-
else
|
|
227
|
-
echo "Node.js not available - skipping YAML validation"
|
|
228
|
-
echo "Install Node.js to enable YAML syntax validation"
|
|
229
|
-
fi
|
|
230
|
-
fi
|
|
231
|
-
|
|
232
|
-
if [ "$YAML_VALIDATION_FAILED" = true ]; then
|
|
233
|
-
echo "YAML syntax validation failed - commit blocked"
|
|
234
|
-
echo "Fix YAML syntax errors above before committing"
|
|
235
|
-
echo "Consider using 'caws specs create <id>' instead of manual creation"
|
|
236
|
-
exit 1
|
|
237
|
-
fi
|
|
238
|
-
|
|
239
|
-
# ===== CAWS Multi-Agent Safety Guard =====
|
|
240
|
-
# Prevents unsafe concurrent operations on shared branches
|
|
241
|
-
|
|
242
|
-
if [ -d ".caws" ]; then
|
|
243
|
-
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
|
244
|
-
|
|
245
|
-
# Guard 1a: Block commits on base branch when parallel worktrees are active (caws parallel)
|
|
246
|
-
if [ -f ".caws/parallel.json" ] && command -v node >/dev/null 2>&1; then
|
|
247
|
-
PARALLEL_BASE=$(node -e "
|
|
248
|
-
try {
|
|
249
|
-
var reg = JSON.parse(require('fs').readFileSync('.caws/parallel.json', 'utf8'));
|
|
250
|
-
console.log(reg.baseBranch || '');
|
|
251
|
-
} catch(e) { console.log(''); }
|
|
252
|
-
" 2>/dev/null)
|
|
253
|
-
|
|
254
|
-
if [ -n "$PARALLEL_BASE" ] && [ "$CURRENT_BRANCH" = "$PARALLEL_BASE" ]; then
|
|
255
|
-
AGENT_COUNT=$(node -e "
|
|
256
|
-
try {
|
|
257
|
-
var reg = JSON.parse(require('fs').readFileSync('.caws/parallel.json', 'utf8'));
|
|
258
|
-
console.log((reg.agents || []).length);
|
|
259
|
-
} catch(e) { console.log('0'); }
|
|
260
|
-
" 2>/dev/null)
|
|
261
|
-
|
|
262
|
-
if [ "$AGENT_COUNT" -gt 0 ] 2>/dev/null; then
|
|
263
|
-
echo "BLOCKED: Committing to '$CURRENT_BRANCH' while $AGENT_COUNT parallel agent worktree(s) are active."
|
|
264
|
-
echo " Active agents are working in isolated worktrees."
|
|
265
|
-
echo " Committing to the base branch risks interleaved history and merge conflicts."
|
|
266
|
-
echo ""
|
|
267
|
-
echo " To see parallel status: caws parallel status"
|
|
268
|
-
echo " To merge agent work: caws parallel merge"
|
|
269
|
-
echo " To override (unsafe): git commit --no-verify"
|
|
270
|
-
exit 1
|
|
271
|
-
fi
|
|
272
|
-
fi
|
|
273
|
-
fi
|
|
274
|
-
|
|
275
|
-
# Guard 1b: Block commits on base branch when ANY active worktrees exist (caws worktree create)
|
|
276
|
-
if [ -f ".caws/worktrees.json" ] && command -v node >/dev/null 2>&1; then
|
|
277
|
-
ACTIVE_WORKTREES=$(node -e "
|
|
278
|
-
try {
|
|
279
|
-
var reg = JSON.parse(require('fs').readFileSync('.caws/worktrees.json', 'utf8'));
|
|
280
|
-
var wts = Object.values(reg.worktrees || {});
|
|
281
|
-
var active = wts.filter(function(w) {
|
|
282
|
-
return (w.status === 'active' || w.status === 'fresh' || w.status === 'merged') && w.baseBranch === '$CURRENT_BRANCH';
|
|
283
|
-
});
|
|
284
|
-
console.log(active.length + ':' + active.map(function(w) { return w.name; }).join(','));
|
|
285
|
-
} catch(e) { console.log('0:'); }
|
|
286
|
-
" 2>/dev/null)
|
|
287
|
-
|
|
288
|
-
WT_COUNT=$(echo "$ACTIVE_WORKTREES" | cut -d: -f1)
|
|
289
|
-
WT_NAMES=$(echo "$ACTIVE_WORKTREES" | cut -d: -f2)
|
|
290
|
-
|
|
291
|
-
if [ "$WT_COUNT" -gt 0 ] 2>/dev/null; then
|
|
292
|
-
echo "BLOCKED: Committing to '$CURRENT_BRANCH' while $WT_COUNT active worktree(s) exist: $WT_NAMES"
|
|
293
|
-
echo " You should be working in your worktree, not on the base branch."
|
|
294
|
-
echo " Committing here risks interleaved history with agents in worktrees."
|
|
295
|
-
echo ""
|
|
296
|
-
echo " To work in your worktree: cd .caws/worktrees/<name>/"
|
|
297
|
-
echo " To see worktrees: caws worktree list"
|
|
298
|
-
echo " To override (unsafe): git commit --no-verify"
|
|
299
|
-
exit 1
|
|
300
|
-
fi
|
|
301
|
-
fi
|
|
302
|
-
|
|
303
|
-
# Guard 2: Warn if multiple active sessions exist on same branch
|
|
304
|
-
if [ -f ".caws/sessions.json" ] && command -v node >/dev/null 2>&1; then
|
|
305
|
-
ACTIVE_ON_BRANCH=$(node -e "
|
|
306
|
-
try {
|
|
307
|
-
var reg = JSON.parse(require('fs').readFileSync('.caws/sessions.json', 'utf8'));
|
|
308
|
-
var count = Object.values(reg.sessions || {}).filter(
|
|
309
|
-
function(s) { return s.status === 'active' && s.branch === '$CURRENT_BRANCH'; }
|
|
310
|
-
).length;
|
|
311
|
-
console.log(count);
|
|
312
|
-
} catch(e) { console.log('0'); }
|
|
313
|
-
" 2>/dev/null)
|
|
314
|
-
|
|
315
|
-
if [ "$ACTIVE_ON_BRANCH" -gt 1 ] 2>/dev/null; then
|
|
316
|
-
echo "WARNING: $ACTIVE_ON_BRANCH active sessions detected on branch '$CURRENT_BRANCH'."
|
|
317
|
-
echo " Multiple agents committing to the same branch risks interleaved history."
|
|
318
|
-
echo " Consider using worktrees: caws parallel setup <plan-file>"
|
|
319
|
-
echo ""
|
|
320
|
-
fi
|
|
321
|
-
fi
|
|
322
|
-
|
|
323
|
-
# Guard 3: Block --amend when HEAD commit may not belong to current session
|
|
324
|
-
# Detect --amend by inspecting the parent git process arguments
|
|
325
|
-
AMEND_FLAG=false
|
|
326
|
-
if command -v ps >/dev/null 2>&1; then
|
|
327
|
-
PARENT_ARGS=$(ps -o args= -p $PPID 2>/dev/null || echo "")
|
|
328
|
-
case "$PARENT_ARGS" in
|
|
329
|
-
*--amend*) AMEND_FLAG=true ;;
|
|
330
|
-
esac
|
|
331
|
-
fi
|
|
332
|
-
|
|
333
|
-
if [ "$AMEND_FLAG" = true ]; then
|
|
334
|
-
BLOCK_AMEND=false
|
|
335
|
-
if [ -f ".caws/parallel.json" ]; then
|
|
336
|
-
BLOCK_AMEND=true
|
|
337
|
-
elif [ -f ".caws/worktrees.json" ] && command -v node >/dev/null 2>&1; then
|
|
338
|
-
HAS_ACTIVE_WT=$(node -e "
|
|
339
|
-
try {
|
|
340
|
-
var reg = JSON.parse(require('fs').readFileSync('.caws/worktrees.json', 'utf8'));
|
|
341
|
-
var active = Object.values(reg.worktrees || {}).filter(function(w) { return w.status === 'active' || w.status === 'fresh' || w.status === 'merged'; });
|
|
342
|
-
console.log(active.length > 0 ? 'yes' : 'no');
|
|
343
|
-
} catch(e) { console.log('no'); }
|
|
344
|
-
" 2>/dev/null)
|
|
345
|
-
if [ "$HAS_ACTIVE_WT" = "yes" ]; then
|
|
346
|
-
BLOCK_AMEND=true
|
|
347
|
-
fi
|
|
348
|
-
fi
|
|
349
|
-
|
|
350
|
-
if [ "$BLOCK_AMEND" = true ]; then
|
|
351
|
-
echo "BLOCKED: --amend is not allowed while worktrees are active."
|
|
352
|
-
echo " Amending commits risks rewriting another agent's work."
|
|
353
|
-
echo " Create a new commit instead."
|
|
354
|
-
echo " To override (dangerous): git commit --amend --no-verify"
|
|
355
|
-
exit 1
|
|
356
|
-
fi
|
|
357
|
-
fi
|
|
358
|
-
fi
|
|
359
|
-
# ===== End Multi-Agent Safety Guard =====
|
|
360
|
-
|
|
361
|
-
# Run CAWS quality gates
|
|
362
|
-
QUALITY_GATES_RAN=false
|
|
363
|
-
QUALITY_GATES_WARNED=false
|
|
364
|
-
|
|
365
|
-
# Resolve spec ID from worktree context if available
|
|
366
|
-
SPEC_ID=""
|
|
367
|
-
WORKTREE_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
|
|
368
|
-
if [ -f ".caws/worktrees.json" ] && command -v node >/dev/null 2>&1; then
|
|
369
|
-
SPEC_ID=$(node -e "
|
|
370
|
-
try {
|
|
371
|
-
var reg = JSON.parse(require('fs').readFileSync('.caws/worktrees.json', 'utf8'));
|
|
372
|
-
var wt = Object.values(reg.worktrees || {}).find(function(w) {
|
|
373
|
-
return w.branch === '$WORKTREE_BRANCH';
|
|
374
|
-
});
|
|
375
|
-
if (wt && wt.specId) console.log(wt.specId);
|
|
376
|
-
} catch(e) {}
|
|
377
|
-
" 2>/dev/null || echo "")
|
|
378
|
-
fi
|
|
379
|
-
|
|
380
|
-
GATES_ARGS="--context=commit --quiet"
|
|
381
|
-
if [ -n "$SPEC_ID" ]; then
|
|
382
|
-
GATES_ARGS="$GATES_ARGS --spec-id $SPEC_ID"
|
|
383
|
-
fi
|
|
384
|
-
|
|
385
|
-
if command -v caws >/dev/null 2>&1; then
|
|
386
|
-
if caws gates run $GATES_ARGS; then
|
|
387
|
-
echo "Quality gates passed"
|
|
388
|
-
QUALITY_GATES_RAN=true
|
|
389
|
-
else
|
|
390
|
-
GATE_EXIT=$?
|
|
391
|
-
echo "Quality gates BLOCKED the commit (exit code $GATE_EXIT)"
|
|
392
|
-
exit 1
|
|
393
|
-
fi
|
|
394
|
-
else
|
|
395
|
-
echo "CAWS CLI not available — skipping quality gates"
|
|
396
|
-
echo "Install with: npm install -g @paths.design/caws-cli"
|
|
397
|
-
QUALITY_GATES_RAN=true
|
|
398
|
-
fi
|
|
399
|
-
|
|
400
|
-
# Run hidden TODO analysis on staged files only (if available)
|
|
401
|
-
if [ "$QUALITY_GATES_RAN" = true ]; then
|
|
402
|
-
echo "Checking for hidden TODOs in staged files..."
|
|
403
|
-
|
|
404
|
-
TODO_CHECK_RAN=false
|
|
405
|
-
|
|
406
|
-
# Option 1: Find TODO analyzer .mjs file (if installed locally)
|
|
407
|
-
if [ "$TODO_CHECK_RAN" = false ]; then
|
|
408
|
-
TODO_ANALYZER=""
|
|
409
|
-
|
|
410
|
-
# Try quality gates package TODO analyzer (published package)
|
|
411
|
-
if [ -f "node_modules/@paths.design/quality-gates/todo-analyzer.mjs" ]; then
|
|
412
|
-
TODO_ANALYZER="node_modules/@paths.design/quality-gates/todo-analyzer.mjs"
|
|
413
|
-
# Try quality gates package TODO analyzer (monorepo/local copy)
|
|
414
|
-
elif [ -f "node_modules/@caws/quality-gates/todo-analyzer.mjs" ]; then
|
|
415
|
-
TODO_ANALYZER="node_modules/@caws/quality-gates/todo-analyzer.mjs"
|
|
416
|
-
# Try monorepo structure (development)
|
|
417
|
-
elif [ -f "packages/quality-gates/todo-analyzer.mjs" ]; then
|
|
418
|
-
TODO_ANALYZER="packages/quality-gates/todo-analyzer.mjs"
|
|
419
|
-
# Try local copy in scripts directory (if scaffolded)
|
|
420
|
-
elif [ -f "scripts/todo-analyzer.mjs" ]; then
|
|
421
|
-
TODO_ANALYZER="scripts/todo-analyzer.mjs"
|
|
422
|
-
fi
|
|
423
|
-
|
|
424
|
-
# Run TODO analyzer if found
|
|
425
|
-
if [ -n "$TODO_ANALYZER" ] && command -v node >/dev/null 2>&1; then
|
|
426
|
-
if node "$TODO_ANALYZER" --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
|
|
427
|
-
echo "No critical hidden TODOs found in staged files"
|
|
428
|
-
TODO_CHECK_RAN=true
|
|
429
|
-
else
|
|
430
|
-
echo "Critical hidden TODOs detected in staged files - commit blocked"
|
|
431
|
-
echo "Fix stub implementations and placeholder code before committing"
|
|
432
|
-
echo "See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
|
|
433
|
-
echo ""
|
|
434
|
-
echo "Running detailed analysis on staged files..."
|
|
435
|
-
node "$TODO_ANALYZER" --staged-only --min-confidence 0.8
|
|
436
|
-
exit 1
|
|
437
|
-
fi
|
|
438
|
-
fi
|
|
439
|
-
fi
|
|
440
|
-
|
|
441
|
-
# Option 2: Fallback to legacy Python analyzer (deprecated - will be removed)
|
|
442
|
-
if [ "$TODO_CHECK_RAN" = false ] && command -v python3 >/dev/null 2>&1 && [ -f "scripts/v3/analysis/todo_analyzer.py" ]; then
|
|
443
|
-
echo "Using legacy Python TODO analyzer (deprecated)"
|
|
444
|
-
if python3 scripts/v3/analysis/todo_analyzer.py --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
|
|
445
|
-
echo "No critical hidden TODOs found in staged files"
|
|
446
|
-
TODO_CHECK_RAN=true
|
|
447
|
-
else
|
|
448
|
-
echo "Critical hidden TODOs detected in staged files - commit blocked"
|
|
449
|
-
echo "Fix stub implementations and placeholder code before committing"
|
|
450
|
-
echo "See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
|
|
451
|
-
echo ""
|
|
452
|
-
echo "Running detailed analysis on staged files..."
|
|
453
|
-
python3 scripts/v3/analysis/todo_analyzer.py --staged-only --min-confidence 0.8
|
|
454
|
-
exit 1
|
|
455
|
-
fi
|
|
456
|
-
fi
|
|
457
|
-
|
|
458
|
-
# Option 3: No analyzer available - show language-aware suggestions
|
|
459
|
-
if [ "$TODO_CHECK_RAN" = false ]; then
|
|
460
|
-
echo "TODO analyzer not available - skipping hidden TODO check"
|
|
461
|
-
echo "Available options for TODO analysis:"
|
|
462
|
-
${todoSuggestion
|
|
463
|
-
.split('\n')
|
|
464
|
-
.map((line) => ` echo "${line.replace(/"/g, '\\"')}"`)
|
|
465
|
-
.join('\n')}
|
|
466
|
-
fi
|
|
467
|
-
fi
|
|
468
|
-
|
|
469
|
-
if [ "$QUALITY_GATES_WARNED" = true ]; then
|
|
470
|
-
echo "Proceeding with commit (some quality checks had warnings)"
|
|
471
|
-
else
|
|
472
|
-
echo "All quality checks passed - proceeding with commit"
|
|
473
|
-
fi
|
|
474
|
-
exit 0
|
|
475
|
-
`;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* Generate post-commit hook content
|
|
480
|
-
*/
|
|
481
|
-
function generatePostCommitHook() {
|
|
482
|
-
return `#!/bin/bash
|
|
483
|
-
# CAWS Post-commit Hook
|
|
484
|
-
# Updates provenance tracking after successful commits
|
|
485
|
-
|
|
486
|
-
# Run in background to avoid blocking git operations
|
|
487
|
-
(
|
|
488
|
-
# Check if CAWS is initialized
|
|
489
|
-
if [ ! -d ".caws" ]; then
|
|
490
|
-
exit 0
|
|
491
|
-
fi
|
|
492
|
-
|
|
493
|
-
# Skip during merge operations — caws worktree merge triggers a merge
|
|
494
|
-
# commit, and writing to .caws/provenance/chain.json here would dirty
|
|
495
|
-
# the tree mid-merge, blocking subsequent operations.
|
|
496
|
-
if [ -f ".git/MERGE_HEAD" ] || [ -f "$(git rev-parse --git-dir 2>/dev/null)/MERGE_HEAD" ]; then
|
|
497
|
-
exit 0
|
|
498
|
-
fi
|
|
499
|
-
|
|
500
|
-
# Get the current commit hash
|
|
501
|
-
COMMIT_HASH=$(git rev-parse HEAD)
|
|
502
|
-
|
|
503
|
-
# Get commit details
|
|
504
|
-
COMMIT_MESSAGE=$(git log -1 --pretty=%B | head -1)
|
|
505
|
-
AUTHOR_NAME=$(git log -1 --pretty=%an)
|
|
506
|
-
AUTHOR_EMAIL=$(git log -1 --pretty=%ae)
|
|
507
|
-
|
|
508
|
-
# Update provenance if CAWS CLI is available
|
|
509
|
-
if command -v caws >/dev/null 2>&1; then
|
|
510
|
-
echo "Updating CAWS provenance for commit \${COMMIT_HASH:0:8}..."
|
|
511
|
-
|
|
512
|
-
# Run provenance update in background
|
|
513
|
-
(
|
|
514
|
-
caws provenance update \\
|
|
515
|
-
--commit "$COMMIT_HASH" \\
|
|
516
|
-
--message "$COMMIT_MESSAGE" \\
|
|
517
|
-
--author "$AUTHOR_NAME <$AUTHOR_EMAIL>" \\
|
|
518
|
-
--quiet
|
|
519
|
-
) &
|
|
520
|
-
fi
|
|
521
|
-
) >/dev/null 2>&1 &
|
|
522
|
-
`;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
/**
|
|
526
|
-
* Generate pre-push hook content
|
|
527
|
-
* Blocks --no-verify to enforce quality gates before pushing
|
|
528
|
-
*/
|
|
529
|
-
function generatePrePushHook() {
|
|
530
|
-
return `#!/bin/bash
|
|
531
|
-
# CAWS Pre-push Hook
|
|
532
|
-
# Runs comprehensive checks before pushing
|
|
533
|
-
# BLOCKS --no-verify for safety
|
|
534
|
-
|
|
535
|
-
set -e
|
|
536
|
-
|
|
537
|
-
# Block --no-verify on push operations
|
|
538
|
-
for arg in "$@"; do
|
|
539
|
-
if [[ "$arg" == "--no-verify" ]] || [[ "$arg" == "-n" ]]; then
|
|
540
|
-
echo "Error: --no-verify is BLOCKED on git push"
|
|
541
|
-
echo "==================================================="
|
|
542
|
-
echo "Push operations must pass all quality gates."
|
|
543
|
-
echo ""
|
|
544
|
-
echo "To fix issues locally:"
|
|
545
|
-
echo " 1. Run: caws validate"
|
|
546
|
-
echo " 2. Fix reported issues"
|
|
547
|
-
echo " 3. Commit fixes: git commit --no-verify \\(allowed\\)"
|
|
548
|
-
echo " 4. Push again: git push \\(no --no-verify\\)"
|
|
549
|
-
exit 1
|
|
550
|
-
fi
|
|
551
|
-
done
|
|
552
|
-
|
|
553
|
-
echo "CAWS Pre-push Validation"
|
|
554
|
-
echo "==================================================="
|
|
555
|
-
|
|
556
|
-
# Check if CAWS is initialized
|
|
557
|
-
if [ ! -d ".caws" ]; then
|
|
558
|
-
echo "CAWS not initialized - skipping validation"
|
|
559
|
-
exit 0
|
|
560
|
-
fi
|
|
561
|
-
|
|
562
|
-
# Run CAWS validation (supports multi-spec projects)
|
|
563
|
-
CAWS_VALIDATION_FAILED=false
|
|
564
|
-
if command -v caws >/dev/null 2>&1; then
|
|
565
|
-
echo "Running CAWS validation..."
|
|
566
|
-
|
|
567
|
-
# Multi-spec project: validate each open spec individually
|
|
568
|
-
if [ -d ".caws/specs" ] && command -v node >/dev/null 2>&1; then
|
|
569
|
-
OPEN_SPECS=$(node -e "
|
|
570
|
-
var fs = require('fs'), path = require('path'), dir = '.caws/specs';
|
|
571
|
-
try {
|
|
572
|
-
fs.readdirSync(dir).filter(function(f) { return f.endsWith('.yaml'); }).forEach(function(f) {
|
|
573
|
-
var content = fs.readFileSync(path.join(dir, f), 'utf8');
|
|
574
|
-
if (content.indexOf('status: closed') === -1) {
|
|
575
|
-
var match = content.match(/^id:\\s*(.+)$/m);
|
|
576
|
-
if (match) console.log(match[1].trim());
|
|
577
|
-
}
|
|
578
|
-
});
|
|
579
|
-
} catch(e) {}
|
|
580
|
-
" 2>/dev/null || echo "")
|
|
581
|
-
|
|
582
|
-
if [ -n "$OPEN_SPECS" ]; then
|
|
583
|
-
echo " Multi-spec project detected, validating open specs..."
|
|
584
|
-
while IFS= read -r spec_id; do
|
|
585
|
-
[ -z "$spec_id" ] && continue
|
|
586
|
-
echo " Validating spec: $spec_id"
|
|
587
|
-
if ! caws validate --spec-id "$spec_id" --quiet 2>&1; then
|
|
588
|
-
echo " Validation failed for spec: $spec_id"
|
|
589
|
-
CAWS_VALIDATION_FAILED=true
|
|
590
|
-
fi
|
|
591
|
-
done <<< "$OPEN_SPECS"
|
|
592
|
-
if [ "$CAWS_VALIDATION_FAILED" = false ]; then
|
|
593
|
-
echo "CAWS validation passed (all open specs)"
|
|
594
|
-
fi
|
|
595
|
-
else
|
|
596
|
-
echo " No open specs found, skipping CAWS validation"
|
|
597
|
-
fi
|
|
598
|
-
else
|
|
599
|
-
# Single-spec project: validate working-spec directly
|
|
600
|
-
VALIDATION_OUTPUT=$(caws validate --quiet 2>&1)
|
|
601
|
-
if [ $? -ne 0 ]; then
|
|
602
|
-
echo "$VALIDATION_OUTPUT"
|
|
603
|
-
CAWS_VALIDATION_FAILED=true
|
|
604
|
-
else
|
|
605
|
-
echo "CAWS validation passed"
|
|
606
|
-
fi
|
|
607
|
-
fi
|
|
608
|
-
|
|
609
|
-
if [ "$CAWS_VALIDATION_FAILED" = true ]; then
|
|
610
|
-
echo ""
|
|
611
|
-
echo "==================================================="
|
|
612
|
-
echo "CAWS validation failed"
|
|
613
|
-
echo "==================================================="
|
|
614
|
-
echo "Next Steps:"
|
|
615
|
-
echo " 1. Review errors above"
|
|
616
|
-
echo " 2. Fix issues in .caws/working-spec.yaml or .caws/specs/"
|
|
617
|
-
echo " 3. Run: caws validate (to verify fixes)"
|
|
618
|
-
echo " 4. Push again: git push"
|
|
619
|
-
echo "==================================================="
|
|
620
|
-
exit 1
|
|
621
|
-
fi
|
|
622
|
-
fi
|
|
623
|
-
|
|
624
|
-
# Run full pre-push checks (full test suite required before push)
|
|
625
|
-
# Note: Pre-commit uses filtered tests for speed, but push requires full suite
|
|
626
|
-
echo ""
|
|
627
|
-
echo "Running full pre-push checks (full test suite required)..."
|
|
628
|
-
echo "==================================================="
|
|
629
|
-
|
|
630
|
-
QUICK_CHECKS_FAILED=false
|
|
631
|
-
|
|
632
|
-
# 1. Linting (fast)
|
|
633
|
-
if [ -f "package.json" ]; then
|
|
634
|
-
if command -v npm >/dev/null 2>&1; then
|
|
635
|
-
if grep -q '"lint"' package.json; then
|
|
636
|
-
echo "Running linting..."
|
|
637
|
-
if npm run lint >/dev/null 2>&1; then
|
|
638
|
-
echo "Linting passed"
|
|
639
|
-
else
|
|
640
|
-
echo "Linting failed"
|
|
641
|
-
echo "Fix lint errors: npm run lint"
|
|
642
|
-
QUICK_CHECKS_FAILED=true
|
|
643
|
-
fi
|
|
644
|
-
fi
|
|
645
|
-
fi
|
|
646
|
-
fi
|
|
647
|
-
|
|
648
|
-
# 2. Type checking (fast for TypeScript/JavaScript)
|
|
649
|
-
if [ -f "package.json" ]; then
|
|
650
|
-
if command -v npm >/dev/null 2>&1; then
|
|
651
|
-
if grep -q '"typecheck"' package.json; then
|
|
652
|
-
echo "Running type checking..."
|
|
653
|
-
if npm run typecheck >/dev/null 2>&1; then
|
|
654
|
-
echo "Type checking passed"
|
|
655
|
-
else
|
|
656
|
-
echo "Type checking failed"
|
|
657
|
-
echo "Fix type errors: npm run typecheck"
|
|
658
|
-
QUICK_CHECKS_FAILED=true
|
|
659
|
-
fi
|
|
660
|
-
fi
|
|
661
|
-
fi
|
|
662
|
-
fi
|
|
663
|
-
|
|
664
|
-
# 3. Run FULL test suite (required for push) - no filtering
|
|
665
|
-
# Pre-commit uses filtered tests for speed, but push requires full suite
|
|
666
|
-
if [ -f "package.json" ]; then
|
|
667
|
-
if command -v npm >/dev/null 2>&1 && grep -q '"test"' package.json; then
|
|
668
|
-
echo "Running FULL test suite (required for push)..."
|
|
669
|
-
echo "==================================================="
|
|
670
|
-
if npm test 2>&1 | tee /tmp/pre-push-test-full.log; then
|
|
671
|
-
echo "Full test suite passed"
|
|
672
|
-
rm -f /tmp/pre-push-test-full.log
|
|
673
|
-
else
|
|
674
|
-
FULL_TEST_EXIT_CODE=\${PIPESTATUS[0]}
|
|
675
|
-
echo "Full test suite failed (exit code: \${FULL_TEST_EXIT_CODE})"
|
|
676
|
-
echo "==================================================="
|
|
677
|
-
echo "Test output (last 100 lines):"
|
|
678
|
-
tail -100 /tmp/pre-push-test-full.log 2>/dev/null || echo "No test output captured"
|
|
679
|
-
echo "==================================================="
|
|
680
|
-
echo "Fix test failures before pushing: npm test"
|
|
681
|
-
rm -f /tmp/pre-push-test-full.log
|
|
682
|
-
QUICK_CHECKS_FAILED=true
|
|
683
|
-
fi
|
|
684
|
-
fi
|
|
685
|
-
fi
|
|
686
|
-
|
|
687
|
-
# 4. Security checks (non-blocking warnings)
|
|
688
|
-
echo ""
|
|
689
|
-
echo "Running security checks..."
|
|
690
|
-
if [ -f "package.json" ]; then
|
|
691
|
-
if command -v npm >/dev/null 2>&1; then
|
|
692
|
-
echo "Checking for vulnerabilities..."
|
|
693
|
-
if npm audit --audit-level moderate >/dev/null 2>&1; then
|
|
694
|
-
echo "Security audit passed"
|
|
695
|
-
else
|
|
696
|
-
echo "Security vulnerabilities found (non-blocking)"
|
|
697
|
-
echo "Review with: npm audit"
|
|
698
|
-
fi
|
|
699
|
-
fi
|
|
700
|
-
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
|
701
|
-
if command -v pip-audit >/dev/null 2>&1; then
|
|
702
|
-
echo "Checking Python vulnerabilities..."
|
|
703
|
-
pip-audit --desc 2>/dev/null || echo "Install pip-audit: pip install pip-audit"
|
|
704
|
-
fi
|
|
705
|
-
elif [ -f "Cargo.toml" ]; then
|
|
706
|
-
if command -v cargo-audit >/dev/null 2>&1; then
|
|
707
|
-
echo "Checking Rust vulnerabilities..."
|
|
708
|
-
cargo audit 2>/dev/null || echo "Install cargo-audit: cargo install cargo-audit"
|
|
709
|
-
fi
|
|
710
|
-
fi
|
|
711
|
-
|
|
712
|
-
# Fail if any checks failed
|
|
713
|
-
if [ "$QUICK_CHECKS_FAILED" = true ]; then
|
|
714
|
-
echo ""
|
|
715
|
-
echo "==================================================="
|
|
716
|
-
echo "Pre-push checks failed"
|
|
717
|
-
echo "==================================================="
|
|
718
|
-
echo "All checks (linting/type checking/full test suite) must pass before push."
|
|
719
|
-
echo ""
|
|
720
|
-
echo "Fix failures before pushing:"
|
|
721
|
-
echo " - Linting: npm run lint"
|
|
722
|
-
echo " - Type checking: npm run typecheck"
|
|
723
|
-
echo " - Tests: npm test"
|
|
724
|
-
echo "==================================================="
|
|
725
|
-
exit 1
|
|
726
|
-
fi
|
|
727
|
-
|
|
728
|
-
echo ""
|
|
729
|
-
echo "Pre-push checks completed!"
|
|
730
|
-
echo "All quality gates passed - ready to push"
|
|
731
|
-
`;
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
/**
|
|
735
|
-
* Generate commit-msg hook content
|
|
736
|
-
*/
|
|
737
|
-
function generateCommitMsgHook() {
|
|
738
|
-
return `#!/bin/bash
|
|
739
|
-
# CAWS Commit Message Hook
|
|
740
|
-
# Validates commit message format and enforces merge(worktree): convention
|
|
741
|
-
|
|
742
|
-
COMMIT_MSG_FILE=$1
|
|
743
|
-
|
|
744
|
-
# Read the commit message
|
|
745
|
-
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
|
|
746
|
-
|
|
747
|
-
# Resolve CAWS root (works from worktrees too)
|
|
748
|
-
CAWS_ROOT="."
|
|
749
|
-
if command -v git >/dev/null 2>&1; then
|
|
750
|
-
_GIT_COMMON=$(git rev-parse --git-common-dir 2>/dev/null || echo ".git")
|
|
751
|
-
if [ "$_GIT_COMMON" != ".git" ]; then
|
|
752
|
-
_CANDIDATE=$(cd "$_GIT_COMMON/.." 2>/dev/null && pwd || echo "")
|
|
753
|
-
if [ -n "$_CANDIDATE" ] && [ -d "$_CANDIDATE/.caws" ]; then
|
|
754
|
-
CAWS_ROOT="$_CANDIDATE"
|
|
755
|
-
fi
|
|
756
|
-
fi
|
|
757
|
-
fi
|
|
758
|
-
|
|
759
|
-
# Check if CAWS is initialized
|
|
760
|
-
if [ ! -d "$CAWS_ROOT/.caws" ]; then
|
|
761
|
-
exit 0
|
|
762
|
-
fi
|
|
763
|
-
|
|
764
|
-
# ===== Worktree merge message guard =====
|
|
765
|
-
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
|
766
|
-
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null || echo ".git")
|
|
767
|
-
HAS_ACTIVE_WORKTREES=false
|
|
768
|
-
|
|
769
|
-
if [ -f "$CAWS_ROOT/.caws/worktrees.json" ] && command -v node >/dev/null 2>&1; then
|
|
770
|
-
WT_COUNT=$(node -e "
|
|
771
|
-
try {
|
|
772
|
-
var reg = JSON.parse(require('fs').readFileSync('$CAWS_ROOT/.caws/worktrees.json', 'utf8'));
|
|
773
|
-
var active = Object.values(reg.worktrees || {}).filter(function(w) {
|
|
774
|
-
return (w.status === 'active' || w.status === 'fresh' || w.status === 'merged') && w.baseBranch === '$CURRENT_BRANCH';
|
|
775
|
-
});
|
|
776
|
-
console.log(active.length);
|
|
777
|
-
} catch(e) { console.log('0'); }
|
|
778
|
-
" 2>/dev/null)
|
|
779
|
-
if [ "$WT_COUNT" -gt 0 ] 2>/dev/null; then
|
|
780
|
-
HAS_ACTIVE_WORKTREES=true
|
|
781
|
-
fi
|
|
782
|
-
fi
|
|
783
|
-
|
|
784
|
-
if [ "$HAS_ACTIVE_WORKTREES" = true ]; then
|
|
785
|
-
IS_GIT_MERGE=false
|
|
786
|
-
if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
|
|
787
|
-
IS_GIT_MERGE=true
|
|
788
|
-
fi
|
|
789
|
-
|
|
790
|
-
if [[ "$COMMIT_MSG" =~ ^merge\\(worktree\\): ]] || [ "$IS_GIT_MERGE" = true ]; then
|
|
791
|
-
echo "Merge commit to base branch allowed (worktrees active)"
|
|
792
|
-
elif [[ "$COMMIT_MSG" =~ ^wip\\(checkpoint\\): ]]; then
|
|
793
|
-
echo "Checkpoint commit allowed (prior-session cleanup)"
|
|
794
|
-
else
|
|
795
|
-
echo "BLOCKED: Direct commit to '$CURRENT_BRANCH' while worktrees are active."
|
|
796
|
-
echo " Only these commit types are allowed on the base branch during parallel work:"
|
|
797
|
-
echo ""
|
|
798
|
-
echo " merge(worktree): <description> — merge a completed worktree branch"
|
|
799
|
-
echo " wip(checkpoint): <description> — commit prior-session dirty files"
|
|
800
|
-
echo " git merge --no-ff <branch> — git merge commit"
|
|
801
|
-
echo ""
|
|
802
|
-
echo " To override (unsafe): git commit --no-verify"
|
|
803
|
-
exit 1
|
|
804
|
-
fi
|
|
805
|
-
fi
|
|
806
|
-
# ===== End worktree merge message guard =====
|
|
807
|
-
|
|
808
|
-
# Basic commit message validation
|
|
809
|
-
if [ \${#COMMIT_MSG} -lt 10 ]; then
|
|
810
|
-
echo "Commit message too short (minimum 10 characters)"
|
|
811
|
-
echo " Write descriptive commit messages"
|
|
812
|
-
exit 1
|
|
813
|
-
fi
|
|
814
|
-
|
|
815
|
-
# Check for conventional commit format (optional but encouraged)
|
|
816
|
-
if [[ $COMMIT_MSG =~ ^(feat|fix|docs|style|refactor|test|chore|merge|perf|wip)(\\(.*\\))?: ]]; then
|
|
817
|
-
: # valid format
|
|
818
|
-
else
|
|
819
|
-
if [[ ! $COMMIT_MSG =~ ^Merge\\ (branch|remote) ]]; then
|
|
820
|
-
echo "Consider using conventional commit format:"
|
|
821
|
-
echo " feat: / fix: / docs: / refactor: / chore: / merge(worktree):"
|
|
822
|
-
fi
|
|
823
|
-
fi
|
|
824
|
-
|
|
825
|
-
echo "Commit message validation passed"
|
|
826
|
-
`;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
/**
|
|
830
|
-
* Remove CAWS git hooks
|
|
831
|
-
* @param {string} projectDir - Project directory path
|
|
832
|
-
*/
|
|
833
|
-
async function removeGitHooks(projectDir) {
|
|
834
|
-
console.log('Removing CAWS Git hooks...');
|
|
835
|
-
|
|
836
|
-
const hooksDir = path.join(projectDir, '.git', 'hooks');
|
|
837
|
-
const cawsHooks = ['pre-commit', 'post-commit', 'pre-push', 'commit-msg'];
|
|
838
|
-
|
|
839
|
-
let removedCount = 0;
|
|
840
|
-
|
|
841
|
-
for (const hookName of cawsHooks) {
|
|
842
|
-
const hookPath = path.join(hooksDir, hookName);
|
|
843
|
-
|
|
844
|
-
try {
|
|
845
|
-
if (await fs.pathExists(hookPath)) {
|
|
846
|
-
const content = await fs.readFile(hookPath, 'utf8');
|
|
847
|
-
if (content.includes('# CAWS Hook') || content.includes('# CAWS Pre-commit Hook')) {
|
|
848
|
-
await fs.remove(hookPath);
|
|
849
|
-
console.log(`Removed ${hookName} hook`);
|
|
850
|
-
removedCount++;
|
|
851
|
-
} else {
|
|
852
|
-
console.log(`Skipped ${hookName} (not CAWS-managed)`);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
} catch (error) {
|
|
856
|
-
console.log(`Failed to remove ${hookName}: ${error.message}`);
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
if (removedCount > 0) {
|
|
861
|
-
console.log(`Removed ${removedCount} CAWS git hooks`);
|
|
862
|
-
} else {
|
|
863
|
-
console.log('No CAWS git hooks found');
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
/**
|
|
868
|
-
* Check git hooks status
|
|
869
|
-
* @param {string} projectDir - Project directory path
|
|
870
|
-
*/
|
|
871
|
-
async function checkGitHooksStatus(projectDir) {
|
|
872
|
-
const hooksDir = path.join(projectDir, '.git', 'hooks');
|
|
873
|
-
const cawsHooks = ['pre-commit', 'post-commit', 'pre-push', 'commit-msg'];
|
|
874
|
-
|
|
875
|
-
console.log('Git Hooks Status:');
|
|
876
|
-
console.log('===================================================');
|
|
877
|
-
|
|
878
|
-
let activeCount = 0;
|
|
879
|
-
let totalCount = 0;
|
|
880
|
-
|
|
881
|
-
for (const hookName of cawsHooks) {
|
|
882
|
-
totalCount++;
|
|
883
|
-
const hookPath = path.join(hooksDir, hookName);
|
|
884
|
-
|
|
885
|
-
try {
|
|
886
|
-
if (await fs.pathExists(hookPath)) {
|
|
887
|
-
const content = await fs.readFile(hookPath, 'utf8');
|
|
888
|
-
const isExecutable = (await fs.stat(hookPath)).mode & 0o111;
|
|
889
|
-
|
|
890
|
-
if (content.includes('# CAWS') && isExecutable) {
|
|
891
|
-
console.log(`${hookName}: Active`);
|
|
892
|
-
activeCount++;
|
|
893
|
-
} else if (content.includes('# CAWS')) {
|
|
894
|
-
console.log(`${hookName}: Configured but not executable`);
|
|
895
|
-
} else {
|
|
896
|
-
console.log(`${hookName}: Not CAWS-managed`);
|
|
897
|
-
}
|
|
898
|
-
} else {
|
|
899
|
-
console.log(`${hookName}: Not installed`);
|
|
900
|
-
}
|
|
901
|
-
} catch (error) {
|
|
902
|
-
console.log(`${hookName}: Error checking status`);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
console.log('');
|
|
907
|
-
console.log(`Status: ${activeCount}/${totalCount} CAWS hooks active`);
|
|
908
|
-
|
|
909
|
-
if (activeCount < totalCount) {
|
|
910
|
-
console.log('');
|
|
911
|
-
console.log('To install missing hooks:');
|
|
912
|
-
console.log(' caws scaffold');
|
|
913
|
-
console.log('');
|
|
914
|
-
console.log('To check detailed status:');
|
|
915
|
-
console.log(' ls -la .git/hooks/');
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
module.exports = {
|
|
920
|
-
scaffoldGitHooks,
|
|
921
|
-
removeGitHooks,
|
|
922
|
-
checkGitHooksStatus,
|
|
923
|
-
// Export generator functions for testing
|
|
924
|
-
generatePrePushHook,
|
|
925
|
-
generatePreCommitHook,
|
|
926
|
-
generatePostCommitHook,
|
|
927
|
-
generateCommitMsgHook,
|
|
928
|
-
};
|