@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,1143 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Provenance Command Handler
|
|
3
|
-
* Manages CAWS provenance tracking and audit trails
|
|
4
|
-
* @author @darianrosebrook
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/* global fetch */
|
|
8
|
-
|
|
9
|
-
const fs = require('fs-extra');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
const crypto = require('crypto');
|
|
12
|
-
const yaml = require('js-yaml');
|
|
13
|
-
const { execSync } = require('child_process');
|
|
14
|
-
const { commandWrapper } = require('../utils/command-wrapper');
|
|
15
|
-
const { resolveSpec } = require('../utils/spec-resolver');
|
|
16
|
-
|
|
17
|
-
async function resolveProvenanceSpec(options = {}) {
|
|
18
|
-
try {
|
|
19
|
-
return await resolveSpec({
|
|
20
|
-
specId: options.specId,
|
|
21
|
-
specFile: options.specFile,
|
|
22
|
-
warnLegacy: false,
|
|
23
|
-
});
|
|
24
|
-
} catch (error) {
|
|
25
|
-
const shouldFallbackToLegacy =
|
|
26
|
-
!options.specId &&
|
|
27
|
-
!options.specFile &&
|
|
28
|
-
error.message.includes('schema violations');
|
|
29
|
-
|
|
30
|
-
if (!shouldFallbackToLegacy) {
|
|
31
|
-
throw error;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const legacyPath = path.join(process.cwd(), '.caws', 'working-spec.yaml');
|
|
35
|
-
if (!(await fs.pathExists(legacyPath))) {
|
|
36
|
-
throw error;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const legacyContent = await fs.readFile(legacyPath, 'utf8');
|
|
40
|
-
const legacySpec = yaml.load(legacyContent);
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
path: legacyPath,
|
|
44
|
-
type: 'legacy',
|
|
45
|
-
spec: legacySpec,
|
|
46
|
-
degradedValidation: true,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Get quality gates status from saved report
|
|
53
|
-
* @returns {Object} Quality gates status
|
|
54
|
-
*/
|
|
55
|
-
function getQualityGatesStatus() {
|
|
56
|
-
const reportPath = path.join(process.cwd(), '.caws', 'quality-gates-report.json');
|
|
57
|
-
|
|
58
|
-
if (fs.existsSync(reportPath)) {
|
|
59
|
-
try {
|
|
60
|
-
const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
|
|
61
|
-
return {
|
|
62
|
-
status: report.passed ? 'passing' : 'failing',
|
|
63
|
-
last_validated: report.timestamp || new Date().toISOString(),
|
|
64
|
-
violations: report.violations || 0,
|
|
65
|
-
gates: report.gates || {}
|
|
66
|
-
};
|
|
67
|
-
} catch (error) {
|
|
68
|
-
// Fall through to default
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
status: 'not_validated',
|
|
74
|
-
last_validated: null,
|
|
75
|
-
violations: null
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Provenance command handler
|
|
81
|
-
* @param {string} subcommand - The subcommand to execute
|
|
82
|
-
* @param {Object} options - Command options
|
|
83
|
-
*/
|
|
84
|
-
async function provenanceCommand(subcommand, options) {
|
|
85
|
-
return commandWrapper(
|
|
86
|
-
async () => {
|
|
87
|
-
switch (subcommand) {
|
|
88
|
-
case 'update':
|
|
89
|
-
return await updateProvenance(options);
|
|
90
|
-
case 'show':
|
|
91
|
-
return await showProvenance(options);
|
|
92
|
-
case 'verify':
|
|
93
|
-
return await verifyProvenance(options);
|
|
94
|
-
case 'analyze-ai':
|
|
95
|
-
return await analyzeAIProvenance(options);
|
|
96
|
-
case 'init':
|
|
97
|
-
return await initProvenance(options);
|
|
98
|
-
case 'install-hooks':
|
|
99
|
-
return await installHooks(options);
|
|
100
|
-
default:
|
|
101
|
-
throw new Error(
|
|
102
|
-
`Unknown provenance subcommand: ${subcommand}.\n` +
|
|
103
|
-
'Available commands: update, show, verify, analyze-ai, init, install-hooks'
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
commandName: `provenance ${subcommand}`,
|
|
109
|
-
context: { subcommand, options },
|
|
110
|
-
}
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Update provenance with new commit information
|
|
116
|
-
* @param {Object} options - Command options
|
|
117
|
-
*/
|
|
118
|
-
async function updateProvenance(options) {
|
|
119
|
-
const { commit, message, author, quiet = false, output = '.caws/provenance' } = options;
|
|
120
|
-
|
|
121
|
-
if (!commit) {
|
|
122
|
-
throw new Error('Commit hash is required for provenance update');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Ensure output directory exists
|
|
126
|
-
await fs.ensureDir(output);
|
|
127
|
-
|
|
128
|
-
const resolved = await resolveProvenanceSpec(options);
|
|
129
|
-
const spec = resolved.spec;
|
|
130
|
-
|
|
131
|
-
// Load existing provenance chain
|
|
132
|
-
const provenanceChain = await loadProvenanceChain(output);
|
|
133
|
-
|
|
134
|
-
// Create new provenance entry
|
|
135
|
-
const newEntry = {
|
|
136
|
-
id: `prov-${Date.now()}`,
|
|
137
|
-
timestamp: new Date().toISOString(),
|
|
138
|
-
commit: {
|
|
139
|
-
hash: commit,
|
|
140
|
-
message: message || '',
|
|
141
|
-
author: author || 'Unknown',
|
|
142
|
-
},
|
|
143
|
-
working_spec: {
|
|
144
|
-
id: spec.id,
|
|
145
|
-
title: spec.title,
|
|
146
|
-
risk_tier: spec.risk_tier,
|
|
147
|
-
mode: spec.mode,
|
|
148
|
-
type: resolved.type,
|
|
149
|
-
path: resolved.path,
|
|
150
|
-
status: spec.status || null,
|
|
151
|
-
waiver_ids: spec.waiver_ids || [],
|
|
152
|
-
},
|
|
153
|
-
quality_gates: getQualityGatesStatus(),
|
|
154
|
-
agent: {
|
|
155
|
-
type: detectAgentType(),
|
|
156
|
-
confidence_level: null, // Would be populated by agent actions
|
|
157
|
-
},
|
|
158
|
-
cursor_tracking: await getCursorTrackingData(commit), // AI code tracking data
|
|
159
|
-
checkpoints: await getCursorCheckpoints(), // Composer checkpoint data
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
// Calculate hash including previous chain
|
|
163
|
-
const previousHash =
|
|
164
|
-
provenanceChain.length > 0 ? provenanceChain[provenanceChain.length - 1].hash : '';
|
|
165
|
-
newEntry.previous_hash = previousHash;
|
|
166
|
-
|
|
167
|
-
const hashContent = JSON.stringify(
|
|
168
|
-
{
|
|
169
|
-
...newEntry,
|
|
170
|
-
hash: undefined, // Exclude hash from hash calculation
|
|
171
|
-
},
|
|
172
|
-
Object.keys(newEntry).sort()
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
newEntry.hash = crypto.createHash('sha256').update(hashContent).digest('hex');
|
|
176
|
-
|
|
177
|
-
// Add to chain and save
|
|
178
|
-
provenanceChain.push(newEntry);
|
|
179
|
-
await saveProvenanceChain(provenanceChain, output);
|
|
180
|
-
|
|
181
|
-
if (!quiet) {
|
|
182
|
-
console.log(`Provenance updated for commit ${commit.substring(0, 8)}`);
|
|
183
|
-
console.log(` Spec: ${spec.id} (${resolved.type}) -> ${resolved.path}`);
|
|
184
|
-
if (resolved.degradedValidation) {
|
|
185
|
-
console.log(' Note: using legacy spec metadata despite schema validation issues');
|
|
186
|
-
}
|
|
187
|
-
console.log(` Chain length: ${provenanceChain.length} entries`);
|
|
188
|
-
console.log(` Hash: ${newEntry.hash.substring(0, 16)}...`);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Show current provenance information
|
|
194
|
-
* @param {Object} options - Command options
|
|
195
|
-
*/
|
|
196
|
-
async function showProvenance(options) {
|
|
197
|
-
const { output = '.caws/provenance', format = 'text' } = options;
|
|
198
|
-
|
|
199
|
-
const chain = await loadProvenanceChain(output);
|
|
200
|
-
|
|
201
|
-
if (chain.length === 0) {
|
|
202
|
-
if (format === 'dashboard') {
|
|
203
|
-
console.log('┌- CAWS Provenance Dashboard ----------------------┐');
|
|
204
|
-
console.log('│ No provenance data found │');
|
|
205
|
-
console.log('│ │');
|
|
206
|
-
console.log('│ Run "caws provenance init" to get started │');
|
|
207
|
-
console.log('└-------------------------------------------------┘');
|
|
208
|
-
} else {
|
|
209
|
-
console.log('No provenance data found');
|
|
210
|
-
console.log(`Run "caws provenance init" to get started`);
|
|
211
|
-
}
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (format === 'json') {
|
|
216
|
-
console.log(JSON.stringify(chain, null, 2));
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (format === 'dashboard') {
|
|
221
|
-
await showDashboardFormat(chain, output);
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
console.log('CAWS Provenance Chain');
|
|
226
|
-
console.log('==============================================');
|
|
227
|
-
console.log(`Total entries: ${chain.length}`);
|
|
228
|
-
console.log('');
|
|
229
|
-
|
|
230
|
-
// Show last 5 entries
|
|
231
|
-
const recent = chain.slice(-5);
|
|
232
|
-
recent.forEach((entry, index) => {
|
|
233
|
-
const commit = entry.commit.hash.substring(0, 8);
|
|
234
|
-
const time = new Date(entry.timestamp).toLocaleString();
|
|
235
|
-
const offset = chain.length - recent.length + index + 1;
|
|
236
|
-
|
|
237
|
-
console.log(`${offset}. ${commit} - ${time}`);
|
|
238
|
-
console.log(` ${entry.commit.message.split('\n')[0]}`);
|
|
239
|
-
console.log(` ${entry.commit.author}`);
|
|
240
|
-
if (entry.working_spec) {
|
|
241
|
-
console.log(` Spec: ${entry.working_spec.id} (${entry.working_spec.risk_tier})`);
|
|
242
|
-
}
|
|
243
|
-
if (entry.agent && entry.agent.type !== 'human') {
|
|
244
|
-
console.log(` Agent: ${entry.agent.type}`);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Display AI code tracking if available
|
|
248
|
-
if (entry.cursor_tracking && entry.cursor_tracking.available) {
|
|
249
|
-
const tracking = entry.cursor_tracking;
|
|
250
|
-
console.log(
|
|
251
|
-
` AI Code: ${tracking.ai_code_breakdown.composer_chat.percentage}% composer, ${tracking.ai_code_breakdown.tab_completions.percentage}% tab-complete, ${tracking.ai_code_breakdown.manual_human.percentage}% manual`
|
|
252
|
-
);
|
|
253
|
-
console.log(
|
|
254
|
-
` Quality: ${Math.round(tracking.quality_metrics.ai_code_quality_score * 100)}% AI score, ${Math.round(tracking.quality_metrics.acceptance_rate * 100)}% acceptance`
|
|
255
|
-
);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Display checkpoint info if available
|
|
259
|
-
if (entry.checkpoints && entry.checkpoints.available && entry.checkpoints.checkpoints) {
|
|
260
|
-
console.log(` Checkpoints: ${entry.checkpoints.checkpoints.length} created`);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
console.log('');
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
if (chain.length > 5) {
|
|
267
|
-
console.log(`... and ${chain.length - 5} earlier entries`);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Verify provenance chain integrity
|
|
273
|
-
* @param {Object} options - Command options
|
|
274
|
-
*/
|
|
275
|
-
async function verifyProvenance(options) {
|
|
276
|
-
const { output = '.caws/provenance' } = options;
|
|
277
|
-
|
|
278
|
-
const chain = await loadProvenanceChain(output);
|
|
279
|
-
|
|
280
|
-
if (chain.length === 0) {
|
|
281
|
-
console.log('No provenance data to verify');
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
console.log('Verifying provenance chain integrity...');
|
|
286
|
-
|
|
287
|
-
let valid = true;
|
|
288
|
-
for (let i = 0; i < chain.length; i++) {
|
|
289
|
-
const entry = chain[i];
|
|
290
|
-
|
|
291
|
-
// Verify hash integrity
|
|
292
|
-
const expectedPreviousHash = i === 0 ? '' : chain[i - 1].hash;
|
|
293
|
-
if (entry.previous_hash !== expectedPreviousHash) {
|
|
294
|
-
console.error(`Chain break at entry ${i + 1}: previous hash mismatch`);
|
|
295
|
-
valid = false;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Recalculate and verify current hash
|
|
299
|
-
const entryForHash = { ...entry };
|
|
300
|
-
delete entryForHash.hash; // Remove hash field before calculation
|
|
301
|
-
|
|
302
|
-
const hashContent = JSON.stringify(entryForHash, Object.keys(entryForHash).sort());
|
|
303
|
-
|
|
304
|
-
const calculatedHash = crypto.createHash('sha256').update(hashContent).digest('hex');
|
|
305
|
-
|
|
306
|
-
if (calculatedHash !== entry.hash) {
|
|
307
|
-
console.error(`Hash verification failed at entry ${i + 1}`);
|
|
308
|
-
console.error(` Expected: ${entry.hash}`);
|
|
309
|
-
console.error(` Calculated: ${calculatedHash}`);
|
|
310
|
-
valid = false;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
if (valid) {
|
|
315
|
-
console.log('Provenance chain integrity verified');
|
|
316
|
-
console.log(` ${chain.length} entries, all hashes valid`);
|
|
317
|
-
} else {
|
|
318
|
-
console.error('Provenance chain integrity compromised');
|
|
319
|
-
process.exit(1);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Load existing provenance chain from files
|
|
325
|
-
* @param {string} outputDir - Directory containing provenance files
|
|
326
|
-
* @returns {Array} Array of provenance entries
|
|
327
|
-
*/
|
|
328
|
-
async function loadProvenanceChain(outputDir) {
|
|
329
|
-
const chainFile = path.join(outputDir, 'chain.json');
|
|
330
|
-
|
|
331
|
-
if (!(await fs.pathExists(chainFile))) {
|
|
332
|
-
return [];
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
try {
|
|
336
|
-
const content = await fs.readFile(chainFile, 'utf8');
|
|
337
|
-
return JSON.parse(content);
|
|
338
|
-
} catch (error) {
|
|
339
|
-
console.warn(`Warning: Could not load provenance chain: ${error.message}`);
|
|
340
|
-
return [];
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Save provenance chain to file
|
|
346
|
-
* @param {Array} chain - Provenance entries array
|
|
347
|
-
* @param {string} outputDir - Directory to save to
|
|
348
|
-
*/
|
|
349
|
-
async function saveProvenanceChain(chain, outputDir) {
|
|
350
|
-
const chainFile = path.join(outputDir, 'chain.json');
|
|
351
|
-
await fs.writeFile(chainFile, JSON.stringify(chain, null, 2));
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Analyze AI patterns and effectiveness from provenance data
|
|
356
|
-
* @param {Object} options - Command options
|
|
357
|
-
*/
|
|
358
|
-
async function analyzeAIProvenance(options) {
|
|
359
|
-
const { output = '.caws/provenance' } = options;
|
|
360
|
-
|
|
361
|
-
const chain = await loadProvenanceChain(output);
|
|
362
|
-
|
|
363
|
-
if (chain.length === 0) {
|
|
364
|
-
console.log('No provenance data to analyze');
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
console.log('AI Code Effectiveness Analysis');
|
|
369
|
-
console.log('==============================================');
|
|
370
|
-
|
|
371
|
-
// Filter entries with AI tracking data
|
|
372
|
-
const aiEntries = chain.filter(
|
|
373
|
-
(entry) =>
|
|
374
|
-
entry.cursor_tracking &&
|
|
375
|
-
entry.cursor_tracking.available &&
|
|
376
|
-
entry.agent &&
|
|
377
|
-
entry.agent.type !== 'human'
|
|
378
|
-
);
|
|
379
|
-
|
|
380
|
-
if (aiEntries.length === 0) {
|
|
381
|
-
console.log('No AI tracking data found in provenance');
|
|
382
|
-
console.log('Configure CURSOR_TRACKING_API and CURSOR_CHECKPOINT_API environment variables');
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
console.log(`Analyzed ${aiEntries.length} AI-assisted commits`);
|
|
387
|
-
console.log('');
|
|
388
|
-
|
|
389
|
-
// Analyze AI code contribution patterns
|
|
390
|
-
const contributionPatterns = analyzeContributionPatterns(aiEntries);
|
|
391
|
-
const qualityMetrics = analyzeQualityMetrics(aiEntries);
|
|
392
|
-
const checkpointAnalysis = analyzeCheckpointUsage(aiEntries);
|
|
393
|
-
|
|
394
|
-
console.log('AI Contribution Patterns:');
|
|
395
|
-
console.log(` Average Composer/Chat contribution: ${contributionPatterns.avgComposerPercent}%`);
|
|
396
|
-
console.log(
|
|
397
|
-
` Average Tab completion contribution: ${contributionPatterns.avgTabCompletePercent}%`
|
|
398
|
-
);
|
|
399
|
-
console.log(` Average Manual override rate: ${contributionPatterns.avgManualPercent}%`);
|
|
400
|
-
console.log('');
|
|
401
|
-
|
|
402
|
-
console.log('Quality Metrics:');
|
|
403
|
-
console.log(
|
|
404
|
-
` Average AI code quality score: ${Math.round(qualityMetrics.avgQualityScore * 100)}%`
|
|
405
|
-
);
|
|
406
|
-
console.log(` Average acceptance rate: ${Math.round(qualityMetrics.avgAcceptanceRate * 100)}%`);
|
|
407
|
-
console.log(
|
|
408
|
-
` Average human override rate: ${Math.round(qualityMetrics.avgOverrideRate * 100)}%`
|
|
409
|
-
);
|
|
410
|
-
console.log('');
|
|
411
|
-
|
|
412
|
-
console.log('Checkpoint Analysis:');
|
|
413
|
-
console.log(
|
|
414
|
-
` Commits with checkpoints: ${checkpointAnalysis.entriesWithCheckpoints}/${aiEntries.length}`
|
|
415
|
-
);
|
|
416
|
-
console.log(` Average checkpoints per commit: ${checkpointAnalysis.avgCheckpointsPerEntry}`);
|
|
417
|
-
console.log(` Checkpoint revert rate: ${Math.round(checkpointAnalysis.revertRate * 100)}%`);
|
|
418
|
-
console.log('');
|
|
419
|
-
|
|
420
|
-
// Provide insights and recommendations
|
|
421
|
-
provideAIInsights(contributionPatterns, qualityMetrics, checkpointAnalysis);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
/**
|
|
425
|
-
* Analyze AI contribution patterns across entries
|
|
426
|
-
*/
|
|
427
|
-
function analyzeContributionPatterns(aiEntries) {
|
|
428
|
-
const contributions = aiEntries
|
|
429
|
-
.filter((entry) => entry.cursor_tracking?.ai_code_breakdown)
|
|
430
|
-
.map((entry) => entry.cursor_tracking.ai_code_breakdown);
|
|
431
|
-
|
|
432
|
-
if (contributions.length === 0) return {};
|
|
433
|
-
|
|
434
|
-
const avgComposer =
|
|
435
|
-
contributions.reduce((sum, c) => sum + c.composer_chat.percentage, 0) / contributions.length;
|
|
436
|
-
const avgTab =
|
|
437
|
-
contributions.reduce((sum, c) => sum + c.tab_completions.percentage, 0) / contributions.length;
|
|
438
|
-
const avgManual =
|
|
439
|
-
contributions.reduce((sum, c) => sum + c.manual_human.percentage, 0) / contributions.length;
|
|
440
|
-
|
|
441
|
-
return {
|
|
442
|
-
avgComposerPercent: Math.round(avgComposer),
|
|
443
|
-
avgTabCompletePercent: Math.round(avgTab),
|
|
444
|
-
avgManualPercent: Math.round(avgManual),
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
/**
|
|
449
|
-
* Analyze AI quality metrics across entries
|
|
450
|
-
*/
|
|
451
|
-
function analyzeQualityMetrics(aiEntries) {
|
|
452
|
-
const metrics = aiEntries
|
|
453
|
-
.filter((entry) => entry.cursor_tracking?.quality_metrics)
|
|
454
|
-
.map((entry) => entry.cursor_tracking.quality_metrics);
|
|
455
|
-
|
|
456
|
-
if (metrics.length === 0) return {};
|
|
457
|
-
|
|
458
|
-
const avgQuality = metrics.reduce((sum, m) => sum + m.ai_code_quality_score, 0) / metrics.length;
|
|
459
|
-
const avgAcceptance = metrics.reduce((sum, m) => sum + m.acceptance_rate, 0) / metrics.length;
|
|
460
|
-
const avgOverride = metrics.reduce((sum, m) => sum + m.human_override_rate, 0) / metrics.length;
|
|
461
|
-
|
|
462
|
-
return {
|
|
463
|
-
avgQualityScore: avgQuality,
|
|
464
|
-
avgAcceptanceRate: avgAcceptance,
|
|
465
|
-
avgOverrideRate: avgOverride,
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
/**
|
|
470
|
-
* Analyze checkpoint usage patterns
|
|
471
|
-
*/
|
|
472
|
-
/**
|
|
473
|
-
* Calculate actual revert rate from git history
|
|
474
|
-
* Analyzes commits for revert patterns and calculates the percentage
|
|
475
|
-
* @param {number} maxCommits - Maximum number of commits to analyze
|
|
476
|
-
* @returns {number} Revert rate as a decimal (0.0 - 1.0)
|
|
477
|
-
*/
|
|
478
|
-
function calculateRevertRate(maxCommits = 500) {
|
|
479
|
-
try {
|
|
480
|
-
// Get total commit count (limited)
|
|
481
|
-
const logOutput = execSync(`git log --oneline -n ${maxCommits} 2>/dev/null`, {
|
|
482
|
-
encoding: 'utf8',
|
|
483
|
-
cwd: process.cwd(),
|
|
484
|
-
}).trim();
|
|
485
|
-
|
|
486
|
-
if (!logOutput) {
|
|
487
|
-
return 0;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
const totalCommits = logOutput.split('\n').filter(Boolean).length;
|
|
491
|
-
|
|
492
|
-
// Count revert commits (commits with "revert" in the message)
|
|
493
|
-
const revertOutput = execSync(
|
|
494
|
-
`git log --oneline -n ${maxCommits} --grep="[Rr]evert" 2>/dev/null || true`,
|
|
495
|
-
{
|
|
496
|
-
encoding: 'utf8',
|
|
497
|
-
cwd: process.cwd(),
|
|
498
|
-
}
|
|
499
|
-
).trim();
|
|
500
|
-
|
|
501
|
-
const revertCommits = revertOutput ? revertOutput.split('\n').filter(Boolean).length : 0;
|
|
502
|
-
|
|
503
|
-
// Also check for reset/force-push patterns in reflog if available
|
|
504
|
-
let additionalReverts = 0;
|
|
505
|
-
try {
|
|
506
|
-
const reflogOutput = execSync(`git reflog --oneline -n ${maxCommits} 2>/dev/null || true`, {
|
|
507
|
-
encoding: 'utf8',
|
|
508
|
-
cwd: process.cwd(),
|
|
509
|
-
}).trim();
|
|
510
|
-
|
|
511
|
-
if (reflogOutput) {
|
|
512
|
-
const reflogLines = reflogOutput.split('\n').filter(Boolean);
|
|
513
|
-
additionalReverts = reflogLines.filter(
|
|
514
|
-
(line) => line.includes('reset:') || line.includes('checkout:')
|
|
515
|
-
).length;
|
|
516
|
-
// Weight reflog reverts less since they may not be actual code reverts
|
|
517
|
-
additionalReverts = Math.floor(additionalReverts * 0.1);
|
|
518
|
-
}
|
|
519
|
-
} catch {
|
|
520
|
-
// Reflog not available or failed
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
const totalReverts = revertCommits + additionalReverts;
|
|
524
|
-
const revertRate = totalCommits > 0 ? totalReverts / totalCommits : 0;
|
|
525
|
-
|
|
526
|
-
return Math.min(1.0, revertRate); // Cap at 100%
|
|
527
|
-
} catch {
|
|
528
|
-
// Git not available or not a repo
|
|
529
|
-
return 0;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
function analyzeCheckpointUsage(aiEntries) {
|
|
534
|
-
const entriesWithCheckpoints = aiEntries.filter(
|
|
535
|
-
(entry) => entry.checkpoints?.available && entry.checkpoints.checkpoints?.length > 0
|
|
536
|
-
).length;
|
|
537
|
-
|
|
538
|
-
const totalCheckpoints = aiEntries
|
|
539
|
-
.filter((entry) => entry.checkpoints?.available)
|
|
540
|
-
.reduce((sum, entry) => sum + (entry.checkpoints.checkpoints?.length || 0), 0);
|
|
541
|
-
|
|
542
|
-
// Calculate actual revert rate from git history
|
|
543
|
-
const revertRate = calculateRevertRate();
|
|
544
|
-
|
|
545
|
-
return {
|
|
546
|
-
entriesWithCheckpoints,
|
|
547
|
-
avgCheckpointsPerEntry:
|
|
548
|
-
entriesWithCheckpoints > 0 ? (totalCheckpoints / entriesWithCheckpoints).toFixed(1) : 0,
|
|
549
|
-
revertRate,
|
|
550
|
-
};
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* Install git hooks for automatic provenance updates
|
|
555
|
-
* @param {Object} options - Command options
|
|
556
|
-
*/
|
|
557
|
-
async function installHooks(options) {
|
|
558
|
-
const { output = '.caws/provenance', skipPreCommit = false, skipPostCommit = false } = options;
|
|
559
|
-
|
|
560
|
-
console.log('Installing CAWS Provenance Git Hooks');
|
|
561
|
-
console.log('==================================================');
|
|
562
|
-
|
|
563
|
-
// Check if we're in a git repository
|
|
564
|
-
if (!(await fs.pathExists('.git'))) {
|
|
565
|
-
console.log('Not in a git repository');
|
|
566
|
-
console.log('Initialize git first: git init');
|
|
567
|
-
process.exit(1);
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
// Check if provenance is initialized
|
|
571
|
-
if (!(await fs.pathExists(path.join(output, 'chain.json')))) {
|
|
572
|
-
console.log('Provenance not initialized');
|
|
573
|
-
console.log('Run "caws provenance init" first');
|
|
574
|
-
process.exit(1);
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
console.log('Found git repository and provenance setup');
|
|
578
|
-
|
|
579
|
-
// Ensure hooks directory exists
|
|
580
|
-
const hooksDir = '.git/hooks';
|
|
581
|
-
await fs.ensureDir(hooksDir);
|
|
582
|
-
console.log('Ensured hooks directory exists');
|
|
583
|
-
|
|
584
|
-
let hooksInstalled = 0;
|
|
585
|
-
|
|
586
|
-
// Install pre-commit hook for validation
|
|
587
|
-
if (!skipPreCommit) {
|
|
588
|
-
try {
|
|
589
|
-
const preCommitHook = await createPreCommitHook(output);
|
|
590
|
-
const preCommitPath = path.join(hooksDir, 'pre-commit');
|
|
591
|
-
|
|
592
|
-
await fs.writeFile(preCommitPath, preCommitHook);
|
|
593
|
-
await fs.chmod(preCommitPath, '755');
|
|
594
|
-
console.log('Installed pre-commit hook for provenance validation');
|
|
595
|
-
hooksInstalled++;
|
|
596
|
-
} catch (error) {
|
|
597
|
-
console.warn('Failed to install pre-commit hook:', error.message);
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// Install post-commit hook for provenance updates
|
|
602
|
-
if (!skipPostCommit) {
|
|
603
|
-
try {
|
|
604
|
-
const postCommitHook = await createPostCommitHook(output);
|
|
605
|
-
const postCommitPath = path.join(hooksDir, 'post-commit');
|
|
606
|
-
|
|
607
|
-
await fs.writeFile(postCommitPath, postCommitHook);
|
|
608
|
-
await fs.chmod(postCommitPath, '755');
|
|
609
|
-
console.log('Installed post-commit hook for provenance updates');
|
|
610
|
-
hooksInstalled++;
|
|
611
|
-
} catch (error) {
|
|
612
|
-
console.warn('Failed to install post-commit hook:', error.message);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
console.log('');
|
|
617
|
-
console.log('Git hooks installation complete!');
|
|
618
|
-
console.log('');
|
|
619
|
-
console.log(`Installed ${hooksInstalled} hook(s):`);
|
|
620
|
-
if (!skipPreCommit) {
|
|
621
|
-
console.log(' - pre-commit: Validates provenance before commits');
|
|
622
|
-
}
|
|
623
|
-
if (!skipPostCommit) {
|
|
624
|
-
console.log(' - post-commit: Updates provenance after commits');
|
|
625
|
-
}
|
|
626
|
-
console.log('');
|
|
627
|
-
console.log('Your commits will now automatically maintain provenance!');
|
|
628
|
-
console.log(' Run "caws provenance show" to view the updated chain');
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
/**
|
|
632
|
-
* Create pre-commit hook script for provenance validation
|
|
633
|
-
* @param {string} outputDir - Provenance output directory
|
|
634
|
-
* @returns {string} Hook script content
|
|
635
|
-
*/
|
|
636
|
-
async function createPreCommitHook(outputDir) {
|
|
637
|
-
const scriptPath = path.resolve('node_modules/.bin/caws');
|
|
638
|
-
const fallbackPath = path.resolve('packages/caws-cli/dist/index.js');
|
|
639
|
-
|
|
640
|
-
return `#!/bin/sh
|
|
641
|
-
# CAWS Provenance Pre-commit Hook
|
|
642
|
-
# Validates provenance integrity before allowing commits
|
|
643
|
-
|
|
644
|
-
echo "Validating CAWS provenance..."
|
|
645
|
-
|
|
646
|
-
# Find caws CLI
|
|
647
|
-
if command -v caws >/dev/null 2>&1; then
|
|
648
|
-
CAWS_CMD="caws"
|
|
649
|
-
elif [ -x "${scriptPath}" ]; then
|
|
650
|
-
CAWS_CMD="${scriptPath}"
|
|
651
|
-
elif [ -x "${fallbackPath}" ]; then
|
|
652
|
-
CAWS_CMD="node ${fallbackPath}"
|
|
653
|
-
else
|
|
654
|
-
echo "CAWS CLI not found, skipping provenance validation"
|
|
655
|
-
exit 0
|
|
656
|
-
fi
|
|
657
|
-
|
|
658
|
-
# Run provenance verification
|
|
659
|
-
if $CAWS_CMD provenance verify --output "${outputDir}" >/dev/null 2>&1; then
|
|
660
|
-
echo "Provenance validation passed"
|
|
661
|
-
exit 0
|
|
662
|
-
else
|
|
663
|
-
echo "Provenance validation failed"
|
|
664
|
-
echo "Run 'caws provenance show' to investigate"
|
|
665
|
-
exit 1
|
|
666
|
-
fi
|
|
667
|
-
`;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
/**
|
|
671
|
-
* Create post-commit hook script for provenance updates
|
|
672
|
-
* @param {string} outputDir - Provenance output directory
|
|
673
|
-
* @returns {string} Hook script content
|
|
674
|
-
*/
|
|
675
|
-
async function createPostCommitHook(outputDir) {
|
|
676
|
-
const scriptPath = path.resolve('node_modules/.bin/caws');
|
|
677
|
-
const fallbackPath = path.resolve('packages/caws-cli/dist/index.js');
|
|
678
|
-
|
|
679
|
-
return `#!/bin/sh
|
|
680
|
-
# CAWS Provenance Post-commit Hook
|
|
681
|
-
# Updates provenance chain after successful commits
|
|
682
|
-
|
|
683
|
-
echo "Updating CAWS provenance..."
|
|
684
|
-
|
|
685
|
-
# Get the current commit hash
|
|
686
|
-
COMMIT_HASH=$(git rev-parse HEAD)
|
|
687
|
-
COMMIT_MSG=$(git log -1 --pretty=%B | head -n 1)
|
|
688
|
-
AUTHOR=$(git log -1 --pretty=%an)
|
|
689
|
-
|
|
690
|
-
# Find caws CLI
|
|
691
|
-
if command -v caws >/dev/null 2>&1; then
|
|
692
|
-
CAWS_CMD="caws"
|
|
693
|
-
elif [ -x "${scriptPath}" ]; then
|
|
694
|
-
CAWS_CMD="${scriptPath}"
|
|
695
|
-
elif [ -x "${fallbackPath}" ]; then
|
|
696
|
-
CAWS_CMD="node ${fallbackPath}"
|
|
697
|
-
else
|
|
698
|
-
echo "CAWS CLI not found, skipping provenance update"
|
|
699
|
-
exit 0
|
|
700
|
-
fi
|
|
701
|
-
|
|
702
|
-
# Update provenance
|
|
703
|
-
if $CAWS_CMD provenance update --commit "$COMMIT_HASH" --message "$COMMIT_MSG" --author "$AUTHOR" --output "${outputDir}" --quiet; then
|
|
704
|
-
echo "Provenance updated for commit \${COMMIT_HASH:0:8}"
|
|
705
|
-
else
|
|
706
|
-
echo "Failed to update provenance (non-fatal)"
|
|
707
|
-
fi
|
|
708
|
-
|
|
709
|
-
exit 0
|
|
710
|
-
`;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
/**
|
|
714
|
-
* Show provenance data in dashboard format
|
|
715
|
-
* @param {Array} chain - Provenance chain entries
|
|
716
|
-
* @param {string} outputDir - Output directory path
|
|
717
|
-
*/
|
|
718
|
-
async function showDashboardFormat(chain, outputDir) {
|
|
719
|
-
// Calculate key metrics
|
|
720
|
-
const totalEntries = chain.length;
|
|
721
|
-
const aiEntries = chain.filter(
|
|
722
|
-
(entry) => entry.cursor_tracking?.available && entry.agent?.type !== 'human'
|
|
723
|
-
).length;
|
|
724
|
-
|
|
725
|
-
const avgQualityScore =
|
|
726
|
-
aiEntries > 0
|
|
727
|
-
? chain
|
|
728
|
-
.filter((entry) => entry.cursor_tracking?.quality_metrics?.ai_code_quality_score)
|
|
729
|
-
.reduce(
|
|
730
|
-
(sum, entry) => sum + entry.cursor_tracking.quality_metrics.ai_code_quality_score,
|
|
731
|
-
0
|
|
732
|
-
) /
|
|
733
|
-
chain.filter((entry) => entry.cursor_tracking?.quality_metrics?.ai_code_quality_score)
|
|
734
|
-
.length
|
|
735
|
-
: 0;
|
|
736
|
-
|
|
737
|
-
const avgAcceptanceRate =
|
|
738
|
-
aiEntries > 0
|
|
739
|
-
? chain
|
|
740
|
-
.filter((entry) => entry.cursor_tracking?.quality_metrics?.acceptance_rate)
|
|
741
|
-
.reduce((sum, entry) => sum + entry.cursor_tracking.quality_metrics.acceptance_rate, 0) /
|
|
742
|
-
chain.filter((entry) => entry.cursor_tracking?.quality_metrics?.acceptance_rate).length
|
|
743
|
-
: 0;
|
|
744
|
-
|
|
745
|
-
// Check config
|
|
746
|
-
let configStatus = 'Not configured';
|
|
747
|
-
try {
|
|
748
|
-
const configPath = path.join(outputDir, 'config.json');
|
|
749
|
-
if (await fs.pathExists(configPath)) {
|
|
750
|
-
const config = JSON.parse(await fs.readFile(configPath, 'utf8'));
|
|
751
|
-
const configured = [
|
|
752
|
-
config.cursor_tracking_api !== 'not_configured',
|
|
753
|
-
config.cursor_checkpoint_api !== 'not_configured',
|
|
754
|
-
config.cursor_project_id !== 'not_configured',
|
|
755
|
-
].filter(Boolean).length;
|
|
756
|
-
configStatus = configured === 3 ? 'Fully configured' : `${configured}/3 configured`;
|
|
757
|
-
}
|
|
758
|
-
} catch (error) {
|
|
759
|
-
// Ignore config read errors
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
// Display dashboard
|
|
763
|
-
console.log('┌- CAWS Provenance Dashboard ----------------------┐');
|
|
764
|
-
console.log(`│ Total Entries: ${totalEntries.toString().padEnd(33)} │`);
|
|
765
|
-
console.log(`│ AI-Assisted: ${aiEntries.toString().padEnd(35)} │`);
|
|
766
|
-
console.log(
|
|
767
|
-
`│ Avg Quality: ${(avgQualityScore * 100).toFixed(0).padEnd(2)}%${' '.repeat(33)} │`
|
|
768
|
-
);
|
|
769
|
-
console.log(
|
|
770
|
-
`│ Avg Acceptance: ${(avgAcceptanceRate * 100).toFixed(0).padEnd(2)}%${' '.repeat(30)} │`
|
|
771
|
-
);
|
|
772
|
-
console.log(`│ Config Status: ${configStatus.padEnd(31)} │`);
|
|
773
|
-
console.log('├-------------------------------------------------┤');
|
|
774
|
-
|
|
775
|
-
if (totalEntries > 0) {
|
|
776
|
-
console.log('│ Recent Activity: │');
|
|
777
|
-
const recent = chain.slice(-3);
|
|
778
|
-
recent.forEach((entry, index) => {
|
|
779
|
-
const commit = entry.commit.hash.substring(0, 8);
|
|
780
|
-
const time = new Date(entry.timestamp).toLocaleDateString();
|
|
781
|
-
const msg = entry.commit.message.split('\n')[0].substring(0, 30);
|
|
782
|
-
const line = `${index + 1}. ${commit} ${time} ${msg}`;
|
|
783
|
-
console.log(`│ ${line.padEnd(47)} │`);
|
|
784
|
-
});
|
|
785
|
-
|
|
786
|
-
if (aiEntries > 0) {
|
|
787
|
-
console.log('├-------------------------------------------------┤');
|
|
788
|
-
console.log('│ AI Contribution Breakdown: │');
|
|
789
|
-
|
|
790
|
-
const contributions = chain
|
|
791
|
-
.filter((entry) => entry.cursor_tracking?.ai_code_breakdown)
|
|
792
|
-
.map((entry) => entry.cursor_tracking.ai_code_breakdown);
|
|
793
|
-
|
|
794
|
-
if (contributions.length > 0) {
|
|
795
|
-
const avgComposer =
|
|
796
|
-
contributions.reduce((sum, c) => sum + c.composer_chat.percentage, 0) /
|
|
797
|
-
contributions.length;
|
|
798
|
-
const avgTab =
|
|
799
|
-
contributions.reduce((sum, c) => sum + c.tab_completions.percentage, 0) /
|
|
800
|
-
contributions.length;
|
|
801
|
-
const avgManual =
|
|
802
|
-
contributions.reduce((sum, c) => sum + c.manual_human.percentage, 0) /
|
|
803
|
-
contributions.length;
|
|
804
|
-
|
|
805
|
-
const composerBar = '█'.repeat(Math.round(avgComposer / 5));
|
|
806
|
-
const tabBar = '█'.repeat(Math.round(avgTab / 5));
|
|
807
|
-
const manualBar = '█'.repeat(Math.round(avgManual / 5));
|
|
808
|
-
|
|
809
|
-
console.log(
|
|
810
|
-
`│ Composer/Chat: ${composerBar.padEnd(10)} ${Math.round(avgComposer).toString().padStart(2)}%${' '.repeat(18)} │`
|
|
811
|
-
);
|
|
812
|
-
console.log(
|
|
813
|
-
`│ Tab Complete: ${tabBar.padEnd(10)} ${Math.round(avgTab).toString().padStart(2)}%${' '.repeat(18)} │`
|
|
814
|
-
);
|
|
815
|
-
console.log(
|
|
816
|
-
`│ Manual: ${manualBar.padEnd(10)} ${Math.round(avgManual).toString().padStart(2)}%${' '.repeat(18)} │`
|
|
817
|
-
);
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
console.log('└-------------------------------------------------┘');
|
|
823
|
-
|
|
824
|
-
// Add insights
|
|
825
|
-
if (aiEntries > 0) {
|
|
826
|
-
console.log('');
|
|
827
|
-
console.log('Insights:');
|
|
828
|
-
if (avgAcceptanceRate > 0.9) {
|
|
829
|
-
console.log(' High AI acceptance rate indicates effective collaboration');
|
|
830
|
-
} else if (avgAcceptanceRate < 0.7) {
|
|
831
|
-
console.log(' Lower acceptance rate may indicate AI refinement needed');
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
if (avgQualityScore > 0.8) {
|
|
835
|
-
console.log(' Excellent AI code quality - great results!');
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
/**
|
|
841
|
-
* Provide insights and recommendations based on AI analysis
|
|
842
|
-
*/
|
|
843
|
-
function provideAIInsights(contributionPatterns, qualityMetrics, checkpointAnalysis) {
|
|
844
|
-
console.log('AI Effectiveness Insights:');
|
|
845
|
-
|
|
846
|
-
if (contributionPatterns.avgComposerPercent > 60) {
|
|
847
|
-
console.log(' High Composer usage suggests complex feature development');
|
|
848
|
-
console.log(' → Consider breaking large features into smaller, focused sessions');
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
if (qualityMetrics.avgOverrideRate > 0.2) {
|
|
852
|
-
console.log(' High human override rate indicates AI suggestions need refinement');
|
|
853
|
-
console.log(' → Review AI confidence thresholds or provide clearer requirements');
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
if (checkpointAnalysis.avgCheckpointsPerEntry < 2) {
|
|
857
|
-
console.log(' Low checkpoint usage may limit ability to recover from bad AI directions');
|
|
858
|
-
console.log(' → Encourage more frequent checkpointing in Composer sessions');
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
if (qualityMetrics.avgAcceptanceRate > 0.9) {
|
|
862
|
-
console.log(' High acceptance rate indicates effective AI assistance');
|
|
863
|
-
console.log(' → Current AI integration is working well');
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
console.log('');
|
|
867
|
-
console.log('Recommendations:');
|
|
868
|
-
console.log(
|
|
869
|
-
` - Target Composer contribution: ${Math.max(40, contributionPatterns.avgComposerPercent - 10)}-${Math.min(80, contributionPatterns.avgComposerPercent + 10)}%`
|
|
870
|
-
);
|
|
871
|
-
console.log(
|
|
872
|
-
` - Acceptable override rate: <${Math.round((qualityMetrics.avgOverrideRate + 0.1) * 100)}%`
|
|
873
|
-
);
|
|
874
|
-
console.log(' - Checkpoint frequency: Every 10-15 minutes in active sessions');
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
/**
|
|
878
|
-
* Get Cursor AI code tracking data for a commit
|
|
879
|
-
* Uses Cursor's AI Code Tracking API (Enterprise feature)
|
|
880
|
-
* @see https://cursor.com/docs/account/teams/ai-code-tracking-api
|
|
881
|
-
* @param {string} commitHash - Git commit hash to analyze
|
|
882
|
-
* @returns {Promise<Object>} AI code tracking data
|
|
883
|
-
*/
|
|
884
|
-
async function getCursorTrackingData(commitHash) {
|
|
885
|
-
const apiUrl = process.env.CURSOR_TRACKING_API;
|
|
886
|
-
const apiKey = process.env.CURSOR_API_KEY;
|
|
887
|
-
|
|
888
|
-
if (!apiUrl || !apiKey) {
|
|
889
|
-
return {
|
|
890
|
-
available: false,
|
|
891
|
-
reason: 'Cursor API not configured. Set CURSOR_TRACKING_API and CURSOR_API_KEY environment variables.',
|
|
892
|
-
documentation: 'https://cursor.com/docs/account/teams/ai-code-tracking-api'
|
|
893
|
-
};
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
try {
|
|
897
|
-
// Basic auth: base64(apiKey:) - Cursor API uses API key with empty password
|
|
898
|
-
const auth = Buffer.from(`${apiKey}:`).toString('base64');
|
|
899
|
-
|
|
900
|
-
const response = await fetch(`${apiUrl}/analytics/ai-code/commits`, {
|
|
901
|
-
method: 'GET',
|
|
902
|
-
headers: {
|
|
903
|
-
'Authorization': `Basic ${auth}`,
|
|
904
|
-
'Content-Type': 'application/json',
|
|
905
|
-
}
|
|
906
|
-
});
|
|
907
|
-
|
|
908
|
-
if (!response.ok) {
|
|
909
|
-
return {
|
|
910
|
-
available: false,
|
|
911
|
-
reason: `Cursor API error: ${response.status} ${response.statusText}`
|
|
912
|
-
};
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
const data = await response.json();
|
|
916
|
-
|
|
917
|
-
// Find commit-specific data if available
|
|
918
|
-
const commitData = data.commits?.find(c => c.commit_hash === commitHash) || data;
|
|
919
|
-
|
|
920
|
-
// Transform API response to our internal format
|
|
921
|
-
return {
|
|
922
|
-
available: true,
|
|
923
|
-
commit_hash: commitHash,
|
|
924
|
-
ai_code_breakdown: commitData.ai_code_breakdown || {
|
|
925
|
-
tab_completions: { lines_added: 0, percentage: 0, files_affected: [] },
|
|
926
|
-
composer_chat: { lines_added: 0, percentage: 0, files_affected: [], checkpoints_created: 0 },
|
|
927
|
-
manual_human: { lines_added: 0, percentage: 0, files_affected: [] },
|
|
928
|
-
},
|
|
929
|
-
change_groups: commitData.change_groups || [],
|
|
930
|
-
quality_metrics: commitData.quality_metrics || {
|
|
931
|
-
ai_code_quality_score: 0,
|
|
932
|
-
human_override_rate: 0,
|
|
933
|
-
acceptance_rate: 0,
|
|
934
|
-
},
|
|
935
|
-
};
|
|
936
|
-
} catch (error) {
|
|
937
|
-
return {
|
|
938
|
-
available: false,
|
|
939
|
-
error: error.message,
|
|
940
|
-
reason: 'Failed to retrieve Cursor tracking data',
|
|
941
|
-
};
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
/**
|
|
946
|
-
* Initialize provenance tracking for the project
|
|
947
|
-
* @param {Object} options - Command options
|
|
948
|
-
*/
|
|
949
|
-
async function initProvenance(options) {
|
|
950
|
-
const { output = '.caws/provenance', cursorApi } = options;
|
|
951
|
-
|
|
952
|
-
console.log('Initializing CAWS Provenance Tracking');
|
|
953
|
-
console.log('===================================================');
|
|
954
|
-
|
|
955
|
-
// Check if already initialized
|
|
956
|
-
if (await fs.pathExists(path.join(output, 'chain.json'))) {
|
|
957
|
-
console.log('Provenance already initialized');
|
|
958
|
-
console.log(` Chain exists at: ${output}/chain.json`);
|
|
959
|
-
console.log('');
|
|
960
|
-
console.log('To reset, delete the provenance directory and run again');
|
|
961
|
-
return;
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
// Ensure output directory exists
|
|
965
|
-
await fs.ensureDir(output);
|
|
966
|
-
console.log(`Created provenance directory: ${output}`);
|
|
967
|
-
|
|
968
|
-
const resolved = await resolveProvenanceSpec(options);
|
|
969
|
-
console.log(`Found CAWS spec: ${resolved.spec.id} (${resolved.type})`);
|
|
970
|
-
if (resolved.degradedValidation) {
|
|
971
|
-
console.log(' Proceeding with legacy spec metadata despite schema validation issues');
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
// Initialize empty chain
|
|
975
|
-
const initialChain = [];
|
|
976
|
-
await saveProvenanceChain(initialChain, output);
|
|
977
|
-
console.log('Initialized empty provenance chain');
|
|
978
|
-
|
|
979
|
-
// Create environment configuration hints
|
|
980
|
-
const envConfig = {
|
|
981
|
-
spec: {
|
|
982
|
-
id: resolved.spec.id,
|
|
983
|
-
path: resolved.path,
|
|
984
|
-
type: resolved.type,
|
|
985
|
-
},
|
|
986
|
-
cursor_tracking_api: cursorApi || process.env.CURSOR_TRACKING_API || 'not_configured',
|
|
987
|
-
cursor_checkpoint_api: process.env.CURSOR_CHECKPOINT_API || 'not_configured',
|
|
988
|
-
cursor_project_id: process.env.CURSOR_PROJECT_ID || 'not_configured',
|
|
989
|
-
notes: [
|
|
990
|
-
'Configure CURSOR_TRACKING_API for AI code tracking',
|
|
991
|
-
'Configure CURSOR_CHECKPOINT_API for session recovery data',
|
|
992
|
-
'Configure CURSOR_PROJECT_ID to link with Cursor IDE',
|
|
993
|
-
],
|
|
994
|
-
};
|
|
995
|
-
|
|
996
|
-
await fs.writeFile(path.join(output, 'config.json'), JSON.stringify(envConfig, null, 2));
|
|
997
|
-
console.log('Created configuration template');
|
|
998
|
-
|
|
999
|
-
console.log('');
|
|
1000
|
-
console.log('Provenance tracking initialized!');
|
|
1001
|
-
console.log('');
|
|
1002
|
-
console.log('Next steps:');
|
|
1003
|
-
console.log('1. Install git hooks for automatic provenance (recommended):');
|
|
1004
|
-
console.log(' caws provenance install-hooks');
|
|
1005
|
-
console.log('');
|
|
1006
|
-
console.log('2. Configure environment variables (optional):');
|
|
1007
|
-
console.log(' export CURSOR_TRACKING_API="your-api-endpoint"');
|
|
1008
|
-
console.log(' export CURSOR_CHECKPOINT_API="your-checkpoint-endpoint"');
|
|
1009
|
-
console.log(' export CURSOR_PROJECT_ID="your-project-id"');
|
|
1010
|
-
console.log('');
|
|
1011
|
-
console.log('3. Manual provenance updates (if not using hooks):');
|
|
1012
|
-
console.log(' caws provenance update --commit <hash>');
|
|
1013
|
-
console.log('');
|
|
1014
|
-
console.log('4. View provenance history:');
|
|
1015
|
-
console.log(' caws provenance show');
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
/**
|
|
1019
|
-
* Get Cursor Composer/Chat checkpoint data
|
|
1020
|
-
* Reads from local .cursor/ directory since checkpoints are stored locally by Cursor Agent
|
|
1021
|
-
* @returns {Promise<Object>} Checkpoint data
|
|
1022
|
-
*/
|
|
1023
|
-
async function getCursorCheckpoints() {
|
|
1024
|
-
const cursorDir = path.join(process.cwd(), '.cursor');
|
|
1025
|
-
|
|
1026
|
-
if (!fs.existsSync(cursorDir)) {
|
|
1027
|
-
return {
|
|
1028
|
-
available: false,
|
|
1029
|
-
reason: 'No .cursor directory found. Checkpoints are only available when using Cursor IDE.'
|
|
1030
|
-
};
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
try {
|
|
1034
|
-
// Look for checkpoint metadata in .cursor directory
|
|
1035
|
-
// Cursor stores checkpoints locally during Composer/Agent sessions
|
|
1036
|
-
const checkpointPatterns = [
|
|
1037
|
-
'.cursor/**/checkpoint*.json',
|
|
1038
|
-
'.cursor/**/checkpoints.json',
|
|
1039
|
-
'.cursor/composer/checkpoints/*.json',
|
|
1040
|
-
'.cursor/agent/checkpoints/*.json',
|
|
1041
|
-
];
|
|
1042
|
-
|
|
1043
|
-
let checkpointFiles = [];
|
|
1044
|
-
for (const pattern of checkpointPatterns) {
|
|
1045
|
-
const glob = require('glob');
|
|
1046
|
-
const matches = glob.sync(pattern, { cwd: process.cwd(), absolute: true });
|
|
1047
|
-
checkpointFiles = checkpointFiles.concat(matches);
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
// Remove duplicates
|
|
1051
|
-
checkpointFiles = [...new Set(checkpointFiles)];
|
|
1052
|
-
|
|
1053
|
-
if (checkpointFiles.length === 0) {
|
|
1054
|
-
return {
|
|
1055
|
-
available: false,
|
|
1056
|
-
reason: 'No checkpoints found in current session. Checkpoints are created during Cursor Composer/Agent sessions.'
|
|
1057
|
-
};
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
// Parse checkpoint files and aggregate data
|
|
1061
|
-
const checkpoints = [];
|
|
1062
|
-
for (const file of checkpointFiles) {
|
|
1063
|
-
try {
|
|
1064
|
-
const content = await fs.readFile(file, 'utf8');
|
|
1065
|
-
const data = JSON.parse(content);
|
|
1066
|
-
|
|
1067
|
-
// Handle both single checkpoint and array of checkpoints
|
|
1068
|
-
if (Array.isArray(data)) {
|
|
1069
|
-
checkpoints.push(...data);
|
|
1070
|
-
} else if (data.checkpoints) {
|
|
1071
|
-
checkpoints.push(...data.checkpoints);
|
|
1072
|
-
} else if (data.id || data.timestamp) {
|
|
1073
|
-
checkpoints.push(data);
|
|
1074
|
-
}
|
|
1075
|
-
} catch (parseError) {
|
|
1076
|
-
// Skip invalid checkpoint files
|
|
1077
|
-
continue;
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
if (checkpoints.length === 0) {
|
|
1082
|
-
return {
|
|
1083
|
-
available: false,
|
|
1084
|
-
reason: 'No valid checkpoints found in checkpoint files.'
|
|
1085
|
-
};
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
// Sort by timestamp (newest first)
|
|
1089
|
-
checkpoints.sort((a, b) => {
|
|
1090
|
-
const timeA = new Date(a.timestamp || 0).getTime();
|
|
1091
|
-
const timeB = new Date(b.timestamp || 0).getTime();
|
|
1092
|
-
return timeB - timeA;
|
|
1093
|
-
});
|
|
1094
|
-
|
|
1095
|
-
// Mark latest checkpoint as non-revertible
|
|
1096
|
-
if (checkpoints.length > 0) {
|
|
1097
|
-
checkpoints[0].can_revert = false;
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
return { available: true, checkpoints };
|
|
1101
|
-
} catch (error) {
|
|
1102
|
-
return {
|
|
1103
|
-
available: false,
|
|
1104
|
-
error: error.message,
|
|
1105
|
-
reason: 'Failed to read Cursor checkpoint data',
|
|
1106
|
-
};
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
/**
|
|
1111
|
-
* Attempt to detect the type of agent/system making changes
|
|
1112
|
-
* @returns {string} Agent type identifier
|
|
1113
|
-
*/
|
|
1114
|
-
function detectAgentType() {
|
|
1115
|
-
// Check environment variables and context clues
|
|
1116
|
-
if (
|
|
1117
|
-
process.env.CURSOR_AGENT === 'true' ||
|
|
1118
|
-
process.env.CURSOR_TRACKING_API ||
|
|
1119
|
-
process.env.CURSOR_CHECKPOINT_API
|
|
1120
|
-
) {
|
|
1121
|
-
return 'cursor-ide';
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
if (process.env.GITHUB_ACTIONS === 'true') {
|
|
1125
|
-
return 'github-actions';
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
if (process.env.CI === 'true') {
|
|
1129
|
-
return 'ci-system';
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
// Default to human unless we can detect otherwise
|
|
1133
|
-
return 'human';
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
module.exports = {
|
|
1137
|
-
provenanceCommand,
|
|
1138
|
-
updateProvenance,
|
|
1139
|
-
showProvenance,
|
|
1140
|
-
verifyProvenance,
|
|
1141
|
-
initProvenance,
|
|
1142
|
-
installHooks,
|
|
1143
|
-
};
|