@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
package/dist/commands/status.js
DELETED
|
@@ -1,1151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview CAWS Status Command
|
|
3
|
-
* Display project health overview
|
|
4
|
-
* @author @darianrosebrook
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const fs = require('fs-extra');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const yaml = require('js-yaml');
|
|
10
|
-
const chalk = require('chalk');
|
|
11
|
-
// child_process removed - execSync no longer used directly
|
|
12
|
-
const { safeAsync, outputResult } = require('../error-handler');
|
|
13
|
-
const { parallel } = require('../utils/async-utils');
|
|
14
|
-
const { resolveSpec } = require('../utils/spec-resolver');
|
|
15
|
-
// EVLOG-002 Phase 2 read flip: status reads working state from the event log
|
|
16
|
-
// via the pure renderer. loadStateFromEvents matches loadState's null contract
|
|
17
|
-
// exactly, so the `ws && ws.phase !== 'not-started'` guard and the
|
|
18
|
-
// `loadState(id) || null` coalesce below stay semantically correct.
|
|
19
|
-
const { loadStateFromEvents } = require('../utils/event-renderer');
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Load working specification (legacy single file approach)
|
|
23
|
-
* @param {string} specPath - Path to working spec
|
|
24
|
-
* @returns {Promise<Object|null>} Parsed spec or null
|
|
25
|
-
*/
|
|
26
|
-
async function loadWorkingSpec(specPath = '.caws/working-spec.yaml') {
|
|
27
|
-
try {
|
|
28
|
-
if (!(await fs.pathExists(specPath))) {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const content = await fs.readFile(specPath, 'utf8');
|
|
33
|
-
return yaml.load(content);
|
|
34
|
-
} catch (error) {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Resolve the primary spec for status display when explicitly targeted
|
|
41
|
-
* or when the resolver can identify a single canonical spec.
|
|
42
|
-
* Returns null when no spec can be auto-selected.
|
|
43
|
-
* @param {Object} options
|
|
44
|
-
* @returns {Promise<Object|null>}
|
|
45
|
-
*/
|
|
46
|
-
async function loadResolvedStatusSpec(options = {}) {
|
|
47
|
-
try {
|
|
48
|
-
const resolved = await resolveSpec({
|
|
49
|
-
specId: options.specId,
|
|
50
|
-
specFile: options.spec,
|
|
51
|
-
warnLegacy: false,
|
|
52
|
-
interactive: false,
|
|
53
|
-
quiet: Boolean(options.json),
|
|
54
|
-
});
|
|
55
|
-
return {
|
|
56
|
-
...resolved,
|
|
57
|
-
selected: true,
|
|
58
|
-
};
|
|
59
|
-
} catch (error) {
|
|
60
|
-
if (
|
|
61
|
-
error.message === 'Spec ID required when multiple specs exist' &&
|
|
62
|
-
!options.specId &&
|
|
63
|
-
!options.spec
|
|
64
|
-
) {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
if (error.message.includes('No CAWS spec found')) {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
throw error;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Load specs from the new multi-spec system
|
|
76
|
-
* @returns {Promise<Array>} Array of spec objects
|
|
77
|
-
*/
|
|
78
|
-
async function loadSpecsFromMultiSpec() {
|
|
79
|
-
const { listSpecFiles } = require('./specs');
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
return await listSpecFiles();
|
|
83
|
-
} catch (error) {
|
|
84
|
-
return [];
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Check Git hooks status
|
|
90
|
-
* @returns {Promise<Object>} Hooks status
|
|
91
|
-
*/
|
|
92
|
-
async function checkGitHooks() {
|
|
93
|
-
const hooksDir = '.git/hooks';
|
|
94
|
-
|
|
95
|
-
if (!(await fs.pathExists(hooksDir))) {
|
|
96
|
-
return {
|
|
97
|
-
installed: false,
|
|
98
|
-
count: 0,
|
|
99
|
-
active: [],
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const cawsHooks = ['pre-commit', 'post-commit', 'pre-push', 'commit-msg'];
|
|
104
|
-
const activeHooks = [];
|
|
105
|
-
|
|
106
|
-
for (const hook of cawsHooks) {
|
|
107
|
-
const hookPath = path.join(hooksDir, hook);
|
|
108
|
-
if (await fs.pathExists(hookPath)) {
|
|
109
|
-
const content = await fs.readFile(hookPath, 'utf8');
|
|
110
|
-
if (content.includes('CAWS')) {
|
|
111
|
-
activeHooks.push(hook);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
installed: activeHooks.length > 0,
|
|
118
|
-
count: activeHooks.length,
|
|
119
|
-
active: activeHooks,
|
|
120
|
-
total: cawsHooks.length,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Load provenance chain
|
|
126
|
-
* @returns {Promise<Object>} Provenance status
|
|
127
|
-
*/
|
|
128
|
-
async function loadProvenanceChain() {
|
|
129
|
-
const chainPath = '.caws/provenance/chain.json';
|
|
130
|
-
|
|
131
|
-
if (!(await fs.pathExists(chainPath))) {
|
|
132
|
-
return {
|
|
133
|
-
exists: false,
|
|
134
|
-
count: 0,
|
|
135
|
-
lastUpdate: null,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
const chain = JSON.parse(await fs.readFile(chainPath, 'utf8'));
|
|
141
|
-
const lastEntry = chain.length > 0 ? chain[chain.length - 1] : null;
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
exists: true,
|
|
145
|
-
count: chain.length,
|
|
146
|
-
lastUpdate: lastEntry?.timestamp || null,
|
|
147
|
-
lastCommit: lastEntry?.commit?.hash || null,
|
|
148
|
-
};
|
|
149
|
-
} catch (error) {
|
|
150
|
-
return {
|
|
151
|
-
exists: true,
|
|
152
|
-
count: 0,
|
|
153
|
-
lastUpdate: null,
|
|
154
|
-
error: error.message,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Load waiver status
|
|
161
|
-
* @returns {Promise<Object>} Waiver status
|
|
162
|
-
*/
|
|
163
|
-
async function loadWaiverStatus() {
|
|
164
|
-
const waiversDir = '.caws/waivers';
|
|
165
|
-
|
|
166
|
-
if (!(await fs.pathExists(waiversDir))) {
|
|
167
|
-
return {
|
|
168
|
-
exists: false,
|
|
169
|
-
active: 0,
|
|
170
|
-
expired: 0,
|
|
171
|
-
revoked: 0,
|
|
172
|
-
total: 0,
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
try {
|
|
177
|
-
const waiverFiles = await fs.readdir(waiversDir);
|
|
178
|
-
const yamlFiles = waiverFiles.filter((f) => f.endsWith('.yaml'));
|
|
179
|
-
|
|
180
|
-
let active = 0;
|
|
181
|
-
let expired = 0;
|
|
182
|
-
let revoked = 0;
|
|
183
|
-
|
|
184
|
-
for (const file of yamlFiles) {
|
|
185
|
-
const waiverPath = path.join(waiversDir, file);
|
|
186
|
-
const content = await fs.readFile(waiverPath, 'utf8');
|
|
187
|
-
const waiver = yaml.load(content);
|
|
188
|
-
|
|
189
|
-
if (waiver.status === 'revoked') {
|
|
190
|
-
revoked++;
|
|
191
|
-
} else if (waiver.status === 'active') {
|
|
192
|
-
const now = new Date();
|
|
193
|
-
const expiresAt = new Date(waiver.expires_at);
|
|
194
|
-
if (now > expiresAt) {
|
|
195
|
-
expired++;
|
|
196
|
-
} else {
|
|
197
|
-
active++;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return {
|
|
203
|
-
exists: true,
|
|
204
|
-
active,
|
|
205
|
-
expired,
|
|
206
|
-
revoked,
|
|
207
|
-
total: active + expired + revoked,
|
|
208
|
-
};
|
|
209
|
-
} catch (error) {
|
|
210
|
-
return {
|
|
211
|
-
exists: false,
|
|
212
|
-
active: 0,
|
|
213
|
-
expired: 0,
|
|
214
|
-
revoked: 0,
|
|
215
|
-
total: 0,
|
|
216
|
-
error: error.message,
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Check quality gates status (simplified)
|
|
223
|
-
* @returns {Promise<Object>} Quality gates status
|
|
224
|
-
*/
|
|
225
|
-
async function checkQualityGates() {
|
|
226
|
-
return {
|
|
227
|
-
checked: false,
|
|
228
|
-
message: 'Run: caws quality-gates for full gate status',
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Get test coverage from coverage reports
|
|
234
|
-
* Looks for common coverage report locations and formats
|
|
235
|
-
* @returns {Promise<Object>} Coverage data with percentage and details
|
|
236
|
-
*/
|
|
237
|
-
async function getTestCoverage() {
|
|
238
|
-
const coverageLocations = [
|
|
239
|
-
// Jest/Istanbul coverage
|
|
240
|
-
{ path: 'coverage/coverage-summary.json', type: 'istanbul' },
|
|
241
|
-
{ path: 'coverage/lcov-report/index.html', type: 'lcov-html' },
|
|
242
|
-
{ path: 'coverage/coverage-final.json', type: 'istanbul-final' },
|
|
243
|
-
// NYC coverage
|
|
244
|
-
{ path: '.nyc_output/coverage-summary.json', type: 'nyc' },
|
|
245
|
-
// C8 coverage
|
|
246
|
-
{ path: 'coverage/c8/coverage-summary.json', type: 'c8' },
|
|
247
|
-
];
|
|
248
|
-
|
|
249
|
-
try {
|
|
250
|
-
for (const loc of coverageLocations) {
|
|
251
|
-
const coveragePath = path.join(process.cwd(), loc.path);
|
|
252
|
-
if (await fs.pathExists(coveragePath)) {
|
|
253
|
-
if (loc.type === 'istanbul' || loc.type === 'nyc' || loc.type === 'c8') {
|
|
254
|
-
const content = await fs.readFile(coveragePath, 'utf8');
|
|
255
|
-
const data = JSON.parse(content);
|
|
256
|
-
|
|
257
|
-
// Istanbul/NYC format has a "total" key with coverage percentages
|
|
258
|
-
if (data.total) {
|
|
259
|
-
const lines = data.total.lines?.pct || 0;
|
|
260
|
-
const statements = data.total.statements?.pct || 0;
|
|
261
|
-
const branches = data.total.branches?.pct || 0;
|
|
262
|
-
const functions = data.total.functions?.pct || 0;
|
|
263
|
-
|
|
264
|
-
return {
|
|
265
|
-
available: true,
|
|
266
|
-
percentage: Math.round((lines + statements + branches + functions) / 4),
|
|
267
|
-
lines: Math.round(lines),
|
|
268
|
-
statements: Math.round(statements),
|
|
269
|
-
branches: Math.round(branches),
|
|
270
|
-
functions: Math.round(functions),
|
|
271
|
-
source: loc.path,
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
} else if (loc.type === 'istanbul-final') {
|
|
275
|
-
// coverage-final.json has per-file data, need to aggregate
|
|
276
|
-
const content = await fs.readFile(coveragePath, 'utf8');
|
|
277
|
-
const data = JSON.parse(content);
|
|
278
|
-
|
|
279
|
-
let totalStatements = 0;
|
|
280
|
-
let coveredStatements = 0;
|
|
281
|
-
|
|
282
|
-
for (const file of Object.values(data)) {
|
|
283
|
-
const s = file.s || {};
|
|
284
|
-
for (const count of Object.values(s)) {
|
|
285
|
-
totalStatements++;
|
|
286
|
-
if (count > 0) coveredStatements++;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (totalStatements > 0) {
|
|
291
|
-
const percentage = Math.round((coveredStatements / totalStatements) * 100);
|
|
292
|
-
return {
|
|
293
|
-
available: true,
|
|
294
|
-
percentage,
|
|
295
|
-
source: loc.path,
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// Try running test coverage command if no reports found
|
|
303
|
-
try {
|
|
304
|
-
// Check if package.json has a coverage script
|
|
305
|
-
const pkgPath = path.join(process.cwd(), 'package.json');
|
|
306
|
-
if (await fs.pathExists(pkgPath)) {
|
|
307
|
-
const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8'));
|
|
308
|
-
if (pkg.scripts && (pkg.scripts.coverage || pkg.scripts['test:coverage'])) {
|
|
309
|
-
return {
|
|
310
|
-
available: false,
|
|
311
|
-
percentage: null,
|
|
312
|
-
message: 'Run npm run coverage to generate coverage report',
|
|
313
|
-
};
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
} catch {
|
|
317
|
-
// Ignore package.json errors
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
return {
|
|
321
|
-
available: false,
|
|
322
|
-
percentage: null,
|
|
323
|
-
message: 'No coverage report found',
|
|
324
|
-
};
|
|
325
|
-
} catch (error) {
|
|
326
|
-
return {
|
|
327
|
-
available: false,
|
|
328
|
-
percentage: null,
|
|
329
|
-
message: `Error reading coverage: ${error.message}`,
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Get time since last update
|
|
336
|
-
* @param {string} timestamp - ISO timestamp
|
|
337
|
-
* @returns {string} Human-readable time
|
|
338
|
-
*/
|
|
339
|
-
function getTimeSince(timestamp) {
|
|
340
|
-
if (!timestamp) return 'never';
|
|
341
|
-
|
|
342
|
-
const now = new Date();
|
|
343
|
-
const then = new Date(timestamp);
|
|
344
|
-
const diffMs = now - then;
|
|
345
|
-
|
|
346
|
-
const diffMins = Math.floor(diffMs / 60000);
|
|
347
|
-
const diffHours = Math.floor(diffMs / 3600000);
|
|
348
|
-
const diffDays = Math.floor(diffMs / 86400000);
|
|
349
|
-
|
|
350
|
-
if (diffMins < 1) return 'just now';
|
|
351
|
-
if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? 's' : ''} ago`;
|
|
352
|
-
if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;
|
|
353
|
-
return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Display project status
|
|
358
|
-
* @param {Object} data - Status data
|
|
359
|
-
*/
|
|
360
|
-
function displayStatus(data) {
|
|
361
|
-
const { spec, specSelection, hooks, provenance, waivers, gates } = data;
|
|
362
|
-
|
|
363
|
-
console.log(chalk.bold.cyan('\nCAWS Project Status'));
|
|
364
|
-
console.log(chalk.cyan('==============================================\n'));
|
|
365
|
-
|
|
366
|
-
// Working Spec Status
|
|
367
|
-
if (spec) {
|
|
368
|
-
console.log(chalk.green('Working Spec'));
|
|
369
|
-
console.log(chalk.gray(` ID: ${spec.id} | Tier: ${spec.risk_tier} | Mode: ${spec.mode}`));
|
|
370
|
-
console.log(chalk.gray(` Title: ${spec.title}`));
|
|
371
|
-
if (specSelection?.specType) {
|
|
372
|
-
console.log(chalk.gray(` Source: ${specSelection.specType} (${specSelection.specPath})`));
|
|
373
|
-
}
|
|
374
|
-
} else {
|
|
375
|
-
console.log(chalk.red('Working Spec'));
|
|
376
|
-
console.log(chalk.gray(' No working spec found'));
|
|
377
|
-
console.log(chalk.yellow(' Run: caws init . to create one'));
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
console.log('');
|
|
381
|
-
|
|
382
|
-
// Working State (EVLOG-002: from event log)
|
|
383
|
-
if (spec && spec.id) {
|
|
384
|
-
let ws = null;
|
|
385
|
-
try { ws = loadStateFromEvents(spec.id); } catch { /* non-fatal */ }
|
|
386
|
-
if (ws && ws.phase !== 'not-started') {
|
|
387
|
-
const phaseLabels = {
|
|
388
|
-
'not-started': 'Not Started',
|
|
389
|
-
'spec-authoring': 'Spec Authoring',
|
|
390
|
-
'implementation': 'Implementation',
|
|
391
|
-
'verification': 'Verification',
|
|
392
|
-
'complete': 'Complete',
|
|
393
|
-
};
|
|
394
|
-
console.log(chalk.green('Working State'));
|
|
395
|
-
console.log(chalk.gray(` Phase: ${phaseLabels[ws.phase] || ws.phase}`));
|
|
396
|
-
if (ws.validation) {
|
|
397
|
-
const vIcon = ws.validation.passed ? chalk.green('pass') : chalk.red('fail');
|
|
398
|
-
console.log(chalk.gray(` Validation: ${vIcon}${ws.validation.grade ? ` (Grade ${ws.validation.grade})` : ''}`));
|
|
399
|
-
}
|
|
400
|
-
if (ws.evaluation) {
|
|
401
|
-
console.log(chalk.gray(` Evaluation: ${ws.evaluation.percentage}% (Grade ${ws.evaluation.grade})`));
|
|
402
|
-
}
|
|
403
|
-
if (ws.gates) {
|
|
404
|
-
const gIcon = ws.gates.passed ? chalk.green('pass') : chalk.red('blocked');
|
|
405
|
-
const s = ws.gates.summary;
|
|
406
|
-
console.log(chalk.gray(` Gates: ${gIcon} (${s.passed} pass, ${s.blocked} blocked, ${s.warned} warned)`));
|
|
407
|
-
}
|
|
408
|
-
if (ws.acceptance_criteria) {
|
|
409
|
-
const ac = ws.acceptance_criteria;
|
|
410
|
-
console.log(chalk.gray(` ACs: ${ac.pass}/${ac.total} pass, ${ac.fail} fail, ${ac.unchecked} unchecked`));
|
|
411
|
-
}
|
|
412
|
-
if (ws.files_touched && ws.files_touched.length > 0) {
|
|
413
|
-
console.log(chalk.gray(` Files touched: ${ws.files_touched.length}`));
|
|
414
|
-
}
|
|
415
|
-
if (ws.blockers && ws.blockers.length > 0) {
|
|
416
|
-
console.log(chalk.red(` Blockers: ${ws.blockers.length}`));
|
|
417
|
-
ws.blockers.forEach(b => console.log(chalk.red(` - ${b.message}`)));
|
|
418
|
-
}
|
|
419
|
-
console.log('');
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// Git Hooks Status
|
|
424
|
-
if (hooks.installed) {
|
|
425
|
-
console.log(chalk.green(`Git Hooks`));
|
|
426
|
-
console.log(chalk.gray(` ${hooks.count}/${hooks.total} active: ${hooks.active.join(', ')}`));
|
|
427
|
-
} else {
|
|
428
|
-
console.log(chalk.yellow('Git Hooks'));
|
|
429
|
-
console.log(chalk.gray(' No CAWS git hooks installed'));
|
|
430
|
-
console.log(chalk.yellow(' Run: caws hooks install'));
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
console.log('');
|
|
434
|
-
|
|
435
|
-
// Provenance Status
|
|
436
|
-
if (provenance.exists) {
|
|
437
|
-
console.log(chalk.green('Provenance'));
|
|
438
|
-
console.log(chalk.gray(` Chain: ${provenance.count} entries`));
|
|
439
|
-
if (provenance.lastUpdate) {
|
|
440
|
-
console.log(chalk.gray(` Last update: ${getTimeSince(provenance.lastUpdate)}`));
|
|
441
|
-
}
|
|
442
|
-
} else {
|
|
443
|
-
console.log(chalk.yellow('Provenance'));
|
|
444
|
-
console.log(chalk.gray(' Provenance tracking not initialized'));
|
|
445
|
-
console.log(chalk.yellow(' Run: caws provenance init'));
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
console.log('');
|
|
449
|
-
|
|
450
|
-
// Waivers Status
|
|
451
|
-
if (waivers.exists && waivers.total > 0) {
|
|
452
|
-
console.log(chalk.green('Quality Gate Waivers'));
|
|
453
|
-
console.log(
|
|
454
|
-
chalk.gray(
|
|
455
|
-
` ${waivers.active} active, ${waivers.expired} expired, ${waivers.revoked} revoked`
|
|
456
|
-
)
|
|
457
|
-
);
|
|
458
|
-
console.log(chalk.gray(` Total: ${waivers.total} waiver${waivers.total > 1 ? 's' : ''}`));
|
|
459
|
-
} else if (waivers.exists) {
|
|
460
|
-
console.log(chalk.blue('Quality Gate Waivers'));
|
|
461
|
-
console.log(chalk.gray(' No waivers configured'));
|
|
462
|
-
} else {
|
|
463
|
-
console.log(chalk.yellow('Quality Gate Waivers'));
|
|
464
|
-
console.log(chalk.gray(' Waiver system not initialized'));
|
|
465
|
-
console.log(chalk.yellow(' Run: caws waivers create (when needed)'));
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
console.log('');
|
|
469
|
-
|
|
470
|
-
// Quality Gates Status
|
|
471
|
-
console.log(chalk.blue('Quality Gates'));
|
|
472
|
-
console.log(chalk.gray(` ${gates.message}`));
|
|
473
|
-
|
|
474
|
-
// Suggestions
|
|
475
|
-
const suggestions = generateSuggestions(data);
|
|
476
|
-
if (suggestions.length > 0) {
|
|
477
|
-
console.log(chalk.bold.yellow('\nSuggestions:'));
|
|
478
|
-
suggestions.forEach((suggestion) => {
|
|
479
|
-
console.log(chalk.yellow(` ${suggestion}`));
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
// Quick Links
|
|
484
|
-
console.log(chalk.bold.blue('\nQuick Links:'));
|
|
485
|
-
if (spec) {
|
|
486
|
-
console.log(chalk.blue(' View spec: .caws/working-spec.yaml'));
|
|
487
|
-
}
|
|
488
|
-
if (hooks.installed) {
|
|
489
|
-
console.log(chalk.blue(' View hooks: .git/hooks/'));
|
|
490
|
-
}
|
|
491
|
-
if (provenance.exists) {
|
|
492
|
-
console.log(chalk.blue(' View provenance: caws provenance show --format=dashboard'));
|
|
493
|
-
}
|
|
494
|
-
if (waivers.exists && waivers.total > 0) {
|
|
495
|
-
console.log(chalk.blue(' View waivers: caws waivers list'));
|
|
496
|
-
}
|
|
497
|
-
console.log(chalk.blue(' Full documentation: docs/agents/full-guide.md'));
|
|
498
|
-
|
|
499
|
-
console.log('');
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
/**
|
|
503
|
-
* Generate actionable suggestions based on status and mode
|
|
504
|
-
* @param {Object} data - Status data
|
|
505
|
-
* @param {string} currentMode - Current CAWS mode
|
|
506
|
-
* @returns {string[]} Array of suggestions
|
|
507
|
-
*/
|
|
508
|
-
function generateSuggestions(data, currentMode) {
|
|
509
|
-
const { spec, specs, hooks, provenance, waivers } = data;
|
|
510
|
-
const modes = require('../config/modes');
|
|
511
|
-
const suggestions = [];
|
|
512
|
-
|
|
513
|
-
// Basic setup suggestions
|
|
514
|
-
if (!spec && (!specs || specs.length === 0)) {
|
|
515
|
-
suggestions.push('Create a spec: caws specs create <id>');
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
// Mode-specific suggestions
|
|
519
|
-
if (modes.isFeatureEnabled('gitHooks', currentMode) && !hooks.installed) {
|
|
520
|
-
suggestions.push('Install Git hooks: caws hooks install');
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
if (modes.isFeatureEnabled('provenance', currentMode) && !provenance.exists) {
|
|
524
|
-
suggestions.push('Initialize provenance tracking: caws provenance init');
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
if (modes.isFeatureEnabled('waivers', currentMode) && !waivers.exists) {
|
|
528
|
-
suggestions.push('Initialize waiver system: caws waivers create (when needed)');
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// Quality gate suggestions
|
|
532
|
-
if (modes.isFeatureEnabled('qualityGates', currentMode)) {
|
|
533
|
-
if (spec || (specs && specs.length > 0)) {
|
|
534
|
-
suggestions.push('Run quality gates: caws diagnose');
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// Mode switching suggestion
|
|
539
|
-
suggestions.push('Switch modes: caws mode set --interactive');
|
|
540
|
-
|
|
541
|
-
return suggestions;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
/**
|
|
545
|
-
* Create progress bar string
|
|
546
|
-
* @param {number} current - Current value
|
|
547
|
-
* @param {number} total - Total value
|
|
548
|
-
* @param {number} width - Bar width
|
|
549
|
-
* @returns {string} Progress bar string
|
|
550
|
-
*/
|
|
551
|
-
function createProgressBar(current, total, width = 20) {
|
|
552
|
-
if (total === 0) return '░'.repeat(width);
|
|
553
|
-
|
|
554
|
-
const percentage = Math.min(current / total, 1);
|
|
555
|
-
const filled = Math.round(percentage * width);
|
|
556
|
-
const empty = width - filled;
|
|
557
|
-
|
|
558
|
-
return '▓'.repeat(filled) + '░'.repeat(empty);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
/**
|
|
562
|
-
* Get color for progress percentage
|
|
563
|
-
* @param {number} percentage - Progress percentage
|
|
564
|
-
* @returns {string} Chalk color function
|
|
565
|
-
*/
|
|
566
|
-
function getProgressColor(percentage) {
|
|
567
|
-
if (percentage >= 80) return chalk.green;
|
|
568
|
-
if (percentage >= 50) return chalk.yellow;
|
|
569
|
-
return chalk.red;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
* Display enhanced visual status
|
|
574
|
-
* @param {Object} data - Status data
|
|
575
|
-
* @param {string} currentMode - Current CAWS mode
|
|
576
|
-
*/
|
|
577
|
-
async function displayVisualStatus(data, currentMode) {
|
|
578
|
-
const { spec, specs, hooks, provenance, waivers, gates } = data;
|
|
579
|
-
const modes = require('../config/modes');
|
|
580
|
-
const tierConfig = modes.getTier(currentMode);
|
|
581
|
-
|
|
582
|
-
console.log(
|
|
583
|
-
chalk.bold.cyan(
|
|
584
|
-
`\nCAWS Project Status (${tierConfig.icon} ${tierConfig.color(currentMode)})`
|
|
585
|
-
)
|
|
586
|
-
);
|
|
587
|
-
console.log(
|
|
588
|
-
chalk.cyan(
|
|
589
|
-
'=================================================================================\n'
|
|
590
|
-
)
|
|
591
|
-
);
|
|
592
|
-
|
|
593
|
-
// Multi-spec system status
|
|
594
|
-
if (specs && specs.length > 0) {
|
|
595
|
-
console.log(chalk.green(`Specs System (${specs.length} specs)`));
|
|
596
|
-
|
|
597
|
-
// Show active specs first
|
|
598
|
-
const activeSpecs = specs.filter((s) => s.status === 'active' || s.status === 'in_progress');
|
|
599
|
-
const draftSpecs = specs.filter((s) => s.status === 'draft');
|
|
600
|
-
const completedSpecs = specs.filter((s) => s.status === 'completed');
|
|
601
|
-
const closedSpecs = specs.filter((s) => s.status === 'closed' || s.status === 'archived');
|
|
602
|
-
|
|
603
|
-
if (activeSpecs.length > 0) {
|
|
604
|
-
console.log(
|
|
605
|
-
chalk.gray(` Active: ${activeSpecs.map((s) => `${s.id}(${s.type})`).join(', ')}`)
|
|
606
|
-
);
|
|
607
|
-
}
|
|
608
|
-
if (draftSpecs.length > 0) {
|
|
609
|
-
console.log(
|
|
610
|
-
chalk.gray(` Draft: ${draftSpecs.length} spec${draftSpecs.length > 1 ? 's' : ''}`)
|
|
611
|
-
);
|
|
612
|
-
// Show details for draft specs if not too many
|
|
613
|
-
if (draftSpecs.length <= 3) {
|
|
614
|
-
draftSpecs.forEach((s) => {
|
|
615
|
-
console.log(chalk.gray(` - ${s.id}: ${s.title}`));
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
if (completedSpecs.length > 0) {
|
|
620
|
-
console.log(
|
|
621
|
-
chalk.gray(
|
|
622
|
-
` Completed: ${completedSpecs.length} spec${completedSpecs.length > 1 ? 's' : ''}`
|
|
623
|
-
)
|
|
624
|
-
);
|
|
625
|
-
// Show details for completed specs if not too many
|
|
626
|
-
if (completedSpecs.length <= 3) {
|
|
627
|
-
completedSpecs.forEach((s) => {
|
|
628
|
-
console.log(chalk.gray(` - ${s.id}: ${s.title}`));
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
if (closedSpecs.length > 0) {
|
|
633
|
-
console.log(
|
|
634
|
-
chalk.gray(
|
|
635
|
-
` Closed: ${closedSpecs.length} spec${closedSpecs.length > 1 ? 's' : ''}`
|
|
636
|
-
)
|
|
637
|
-
);
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
// Overall specs progress (completed + closed both count as done)
|
|
641
|
-
const totalSpecs = specs.length;
|
|
642
|
-
const completedSpecsCount = specs.filter((s) =>
|
|
643
|
-
s.status === 'completed' || s.status === 'closed' || s.status === 'archived'
|
|
644
|
-
).length;
|
|
645
|
-
const activeSpecsCount = specs.filter((s) => s.status === 'active').length;
|
|
646
|
-
const progressPercentage =
|
|
647
|
-
totalSpecs > 0 ? Math.round((completedSpecsCount / totalSpecs) * 100) : 0;
|
|
648
|
-
const progressBar = createProgressBar(completedSpecsCount, totalSpecs);
|
|
649
|
-
const color = getProgressColor(progressPercentage);
|
|
650
|
-
|
|
651
|
-
console.log(
|
|
652
|
-
chalk.gray(
|
|
653
|
-
` Overall Progress: ${color(`${progressPercentage}%`)} ${progressBar} ${completedSpecsCount}/${totalSpecs} completed`
|
|
654
|
-
)
|
|
655
|
-
);
|
|
656
|
-
|
|
657
|
-
if (activeSpecsCount > 0) {
|
|
658
|
-
console.log(chalk.gray(` Active Features: ${activeSpecsCount} in progress`));
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
// Show risk tier breakdown
|
|
662
|
-
const riskBreakdown = {};
|
|
663
|
-
specs.forEach((s) => {
|
|
664
|
-
const tier = s.risk_tier || 'T3';
|
|
665
|
-
riskBreakdown[tier] = (riskBreakdown[tier] || 0) + 1;
|
|
666
|
-
});
|
|
667
|
-
|
|
668
|
-
if (Object.keys(riskBreakdown).length > 1) {
|
|
669
|
-
const tierDisplay = Object.entries(riskBreakdown)
|
|
670
|
-
.map(([tier, count]) => `${tier}:${count}`)
|
|
671
|
-
.join(', ');
|
|
672
|
-
console.log(chalk.gray(` Risk Distribution: ${tierDisplay}`));
|
|
673
|
-
}
|
|
674
|
-
} else if (spec) {
|
|
675
|
-
// Legacy single spec system
|
|
676
|
-
console.log(chalk.green('Working Spec'));
|
|
677
|
-
console.log(chalk.gray(` ID: ${spec.id} | Tier: ${spec.risk_tier} | Mode: ${spec.mode}`));
|
|
678
|
-
console.log(chalk.gray(` Title: ${spec.title}`));
|
|
679
|
-
|
|
680
|
-
// Acceptance Criteria Progress
|
|
681
|
-
if (spec.acceptance_criteria && spec.acceptance_criteria.length > 0) {
|
|
682
|
-
const total = spec.acceptance_criteria.length;
|
|
683
|
-
const completed = spec.acceptance_criteria.filter((c) => c.completed).length;
|
|
684
|
-
const percentage = Math.round((completed / total) * 100);
|
|
685
|
-
|
|
686
|
-
const color = getProgressColor(percentage);
|
|
687
|
-
const bar = createProgressBar(completed, total);
|
|
688
|
-
|
|
689
|
-
console.log(
|
|
690
|
-
chalk.gray(
|
|
691
|
-
` Acceptance Criteria: ${color(`${percentage}%`)} ${bar} ${completed}/${total}`
|
|
692
|
-
)
|
|
693
|
-
);
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
// Test Coverage
|
|
697
|
-
const coverage = await getTestCoverage();
|
|
698
|
-
if (coverage.available && coverage.percentage !== null) {
|
|
699
|
-
const coverageColor =
|
|
700
|
-
coverage.percentage >= 80
|
|
701
|
-
? chalk.green
|
|
702
|
-
: coverage.percentage >= 50
|
|
703
|
-
? chalk.yellow
|
|
704
|
-
: chalk.red;
|
|
705
|
-
const coverageBar = createProgressBar(coverage.percentage, 100);
|
|
706
|
-
console.log(
|
|
707
|
-
chalk.gray(
|
|
708
|
-
` Test Coverage: ${coverageColor(`${coverage.percentage}%`)} ${coverageBar}`
|
|
709
|
-
)
|
|
710
|
-
);
|
|
711
|
-
if (coverage.lines !== undefined) {
|
|
712
|
-
console.log(
|
|
713
|
-
chalk.gray(
|
|
714
|
-
` Lines: ${coverage.lines}% | Branches: ${coverage.branches}% | Functions: ${coverage.functions}%`
|
|
715
|
-
)
|
|
716
|
-
);
|
|
717
|
-
}
|
|
718
|
-
} else {
|
|
719
|
-
console.log(
|
|
720
|
-
chalk.gray(
|
|
721
|
-
` Test Coverage: ${chalk.yellow('N/A')} ${createProgressBar(0, 100)} ${chalk.gray(coverage.message || 'No report')}`
|
|
722
|
-
)
|
|
723
|
-
);
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
// Risk Tier Indicator
|
|
727
|
-
const riskColor =
|
|
728
|
-
spec.risk_tier === 'T1' ? chalk.red : spec.risk_tier === 'T2' ? chalk.yellow : chalk.green;
|
|
729
|
-
console.log(
|
|
730
|
-
chalk.gray(
|
|
731
|
-
` Risk Tier: ${riskColor(spec.risk_tier)} (Quality Gates: ${riskColor('Active')})`
|
|
732
|
-
)
|
|
733
|
-
);
|
|
734
|
-
} else {
|
|
735
|
-
console.log(chalk.red('No Specs Found'));
|
|
736
|
-
console.log(chalk.gray(' No working spec or specs directory found'));
|
|
737
|
-
console.log(chalk.yellow(' Run: caws specs create <id> to create specs'));
|
|
738
|
-
console.log(chalk.yellow(' Or run: caws init . for legacy single spec'));
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
console.log('');
|
|
742
|
-
|
|
743
|
-
// Git Hooks Status (only show in modes that support it)
|
|
744
|
-
if (modes.isFeatureEnabled('gitHooks', currentMode)) {
|
|
745
|
-
if (hooks.installed) {
|
|
746
|
-
const hookBar = createProgressBar(hooks.count, hooks.total);
|
|
747
|
-
console.log(chalk.green(`Git Hooks`));
|
|
748
|
-
console.log(
|
|
749
|
-
chalk.gray(` ${hookBar} ${hooks.count}/${hooks.total} active: ${hooks.active.join(', ')}`)
|
|
750
|
-
);
|
|
751
|
-
} else {
|
|
752
|
-
console.log(chalk.yellow('Git Hooks'));
|
|
753
|
-
console.log(chalk.gray(' No CAWS git hooks installed'));
|
|
754
|
-
console.log(chalk.yellow(' Run: caws hooks install'));
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
console.log('');
|
|
759
|
-
|
|
760
|
-
// Provenance Status (only show in modes that support it)
|
|
761
|
-
if (modes.isFeatureEnabled('provenance', currentMode)) {
|
|
762
|
-
if (provenance.exists) {
|
|
763
|
-
const provenanceBar = createProgressBar(provenance.count, Math.max(provenance.count, 10));
|
|
764
|
-
console.log(chalk.green('Provenance'));
|
|
765
|
-
console.log(chalk.gray(` ${provenanceBar} ${provenance.count} entries`));
|
|
766
|
-
if (provenance.lastUpdate) {
|
|
767
|
-
console.log(chalk.gray(` Last update: ${getTimeSince(provenance.lastUpdate)}`));
|
|
768
|
-
}
|
|
769
|
-
} else {
|
|
770
|
-
console.log(chalk.yellow('Provenance'));
|
|
771
|
-
console.log(chalk.gray(' Provenance tracking not initialized'));
|
|
772
|
-
console.log(chalk.yellow(' Run: caws provenance init'));
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
console.log('');
|
|
777
|
-
|
|
778
|
-
// Waivers Status (only show in modes that support it)
|
|
779
|
-
if (modes.isFeatureEnabled('waivers', currentMode)) {
|
|
780
|
-
if (waivers.exists && waivers.total > 0) {
|
|
781
|
-
const waiverBar = createProgressBar(waivers.active, waivers.total);
|
|
782
|
-
console.log(chalk.green('Quality Gate Waivers'));
|
|
783
|
-
console.log(
|
|
784
|
-
chalk.gray(
|
|
785
|
-
` ${waiverBar} ${waivers.active} active, ${waivers.expired} expired, ${waivers.revoked} revoked`
|
|
786
|
-
)
|
|
787
|
-
);
|
|
788
|
-
console.log(chalk.gray(` Total: ${waivers.total} waiver${waivers.total > 1 ? 's' : ''}`));
|
|
789
|
-
} else if (waivers.exists) {
|
|
790
|
-
console.log(chalk.blue('Quality Gate Waivers'));
|
|
791
|
-
console.log(chalk.gray(' No waivers configured'));
|
|
792
|
-
} else {
|
|
793
|
-
console.log(chalk.yellow('Quality Gate Waivers'));
|
|
794
|
-
console.log(chalk.gray(' Waiver system not initialized'));
|
|
795
|
-
console.log(chalk.yellow(' Run: caws waivers create (when needed)'));
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
console.log('');
|
|
800
|
-
|
|
801
|
-
// Quality Gates Status (only show in modes that support it)
|
|
802
|
-
if (modes.isFeatureEnabled('qualityGates', currentMode)) {
|
|
803
|
-
console.log(chalk.blue('Quality Gates'));
|
|
804
|
-
if (gates.checked) {
|
|
805
|
-
if (gates.passed) {
|
|
806
|
-
console.log(chalk.green(` ${createProgressBar(1, 1)} All gates passed`));
|
|
807
|
-
gates.results?.forEach((gate) => {
|
|
808
|
-
const gateStatus = gate.status === 'passed' ? chalk.green('[pass]') : chalk.red('[fail]');
|
|
809
|
-
console.log(chalk.gray(` ${gateStatus} ${gate.name}: ${gate.message || 'OK'}`));
|
|
810
|
-
});
|
|
811
|
-
} else {
|
|
812
|
-
console.log(
|
|
813
|
-
chalk.red(
|
|
814
|
-
` ${createProgressBar(0, gates.results?.length || 1)} ${gates.failed || 0} gates failed`
|
|
815
|
-
)
|
|
816
|
-
);
|
|
817
|
-
gates.results?.forEach((gate) => {
|
|
818
|
-
const gateStatus = gate.status === 'passed' ? chalk.green('[pass]') : chalk.red('[fail]');
|
|
819
|
-
console.log(chalk.gray(` ${gateStatus} ${gate.name}: ${gate.message || 'Failed'}`));
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
} else {
|
|
823
|
-
console.log(chalk.gray(` ${gates.message}`));
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
// Progress Summary
|
|
828
|
-
const overallProgress = calculateOverallProgress(data);
|
|
829
|
-
const progressColor = getProgressColor(overallProgress);
|
|
830
|
-
const progressBar = createProgressBar(overallProgress, 100);
|
|
831
|
-
|
|
832
|
-
console.log('');
|
|
833
|
-
console.log(chalk.bold.blue('Overall Progress'));
|
|
834
|
-
console.log(chalk.gray(` ${progressBar} ${progressColor(`${overallProgress}%`)} complete`));
|
|
835
|
-
|
|
836
|
-
// Suggestions (mode-aware)
|
|
837
|
-
const suggestions = generateSuggestions(data, currentMode);
|
|
838
|
-
if (suggestions.length > 0) {
|
|
839
|
-
console.log(chalk.bold.yellow('\nNext Steps:'));
|
|
840
|
-
suggestions.forEach((suggestion, index) => {
|
|
841
|
-
console.log(chalk.yellow(` ${index + 1}. ${suggestion}`));
|
|
842
|
-
});
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
// Quick Links (mode-aware)
|
|
846
|
-
console.log(chalk.bold.blue('\nQuick Actions:'));
|
|
847
|
-
if (spec || (specs && specs.length > 0)) {
|
|
848
|
-
if (modes.isFeatureEnabled('validate', currentMode)) {
|
|
849
|
-
console.log(chalk.blue(' View specs: caws specs list'));
|
|
850
|
-
}
|
|
851
|
-
if (modes.isFeatureEnabled('validate', currentMode)) {
|
|
852
|
-
console.log(chalk.blue(' Validate: caws validate'));
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
if (modes.isFeatureEnabled('gitHooks', currentMode) && hooks.installed) {
|
|
857
|
-
console.log(chalk.blue(' View hooks: caws hooks status'));
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
if (modes.isFeatureEnabled('provenance', currentMode) && provenance.exists) {
|
|
861
|
-
console.log(chalk.blue(' View provenance: caws provenance show'));
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
if (modes.isFeatureEnabled('waivers', currentMode) && waivers.exists && waivers.total > 0) {
|
|
865
|
-
console.log(chalk.blue(' View waivers: caws waivers list'));
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
console.log(chalk.blue(' Get help: caws help'));
|
|
869
|
-
console.log(chalk.blue(' Switch mode: caws mode set --interactive'));
|
|
870
|
-
|
|
871
|
-
console.log('');
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
/**
|
|
875
|
-
* Calculate overall project progress (mode-aware)
|
|
876
|
-
* @param {Object} data - Status data
|
|
877
|
-
* @returns {number} Overall progress percentage
|
|
878
|
-
*/
|
|
879
|
-
function calculateOverallProgress(data) {
|
|
880
|
-
const { spec, specs, hooks, provenance, waivers, currentMode } = data;
|
|
881
|
-
const modes = require('../config/modes');
|
|
882
|
-
|
|
883
|
-
let score = 0;
|
|
884
|
-
|
|
885
|
-
// Multi-spec system
|
|
886
|
-
if (specs && specs.length > 0) {
|
|
887
|
-
// Specs system (40%)
|
|
888
|
-
const completedSpecs = specs.filter((s) => s.status === 'completed').length;
|
|
889
|
-
if (specs.length > 0) {
|
|
890
|
-
const percentage = (completedSpecs / specs.length) * 40;
|
|
891
|
-
score += percentage;
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
// Git hooks (20%) - only if enabled in mode
|
|
895
|
-
if (modes.isFeatureEnabled('gitHooks', currentMode)) {
|
|
896
|
-
if (hooks.installed) score += 20;
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
// Provenance (20%) - only if enabled in mode
|
|
900
|
-
if (modes.isFeatureEnabled('provenance', currentMode)) {
|
|
901
|
-
if (provenance.exists) score += 20;
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
// Waivers (15%) - only if enabled in mode
|
|
905
|
-
if (modes.isFeatureEnabled('waivers', currentMode)) {
|
|
906
|
-
if (waivers.exists) score += 15;
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
// Quality gates (5%) - only if enabled in mode
|
|
910
|
-
if (modes.isFeatureEnabled('qualityGates', currentMode)) {
|
|
911
|
-
if (specs.length > 0) score += 5;
|
|
912
|
-
}
|
|
913
|
-
} else if (spec) {
|
|
914
|
-
// Legacy single spec system (30%)
|
|
915
|
-
if (spec) score += 30;
|
|
916
|
-
|
|
917
|
-
// Acceptance criteria progress (25%)
|
|
918
|
-
if (spec && spec.acceptance_criteria && spec.acceptance_criteria.length > 0) {
|
|
919
|
-
const completed = spec.acceptance_criteria.filter((c) => c.completed).length;
|
|
920
|
-
const percentage = (completed / spec.acceptance_criteria.length) * 25;
|
|
921
|
-
score += percentage;
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
// Git hooks (15%) - only if enabled in mode
|
|
925
|
-
if (modes.isFeatureEnabled('gitHooks', currentMode)) {
|
|
926
|
-
if (hooks.installed) score += 15;
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
// Provenance (15%) - only if enabled in mode
|
|
930
|
-
if (modes.isFeatureEnabled('provenance', currentMode)) {
|
|
931
|
-
if (provenance.exists) score += 15;
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
// Waivers (10%) - only if enabled in mode
|
|
935
|
-
if (modes.isFeatureEnabled('waivers', currentMode)) {
|
|
936
|
-
if (waivers.exists) score += 10;
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
// Quality gates (5%) - only if enabled in mode
|
|
940
|
-
if (modes.isFeatureEnabled('qualityGates', currentMode)) {
|
|
941
|
-
if (spec) score += 5;
|
|
942
|
-
}
|
|
943
|
-
} else {
|
|
944
|
-
// No specs system - check basic setup (mode-aware)
|
|
945
|
-
|
|
946
|
-
// Git hooks (30%) - only if enabled in mode
|
|
947
|
-
if (modes.isFeatureEnabled('gitHooks', currentMode)) {
|
|
948
|
-
if (hooks.installed) score += 30;
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
// Provenance (30%) - only if enabled in mode
|
|
952
|
-
if (modes.isFeatureEnabled('provenance', currentMode)) {
|
|
953
|
-
if (provenance.exists) score += 30;
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
// Waivers (20%) - only if enabled in mode
|
|
957
|
-
if (modes.isFeatureEnabled('waivers', currentMode)) {
|
|
958
|
-
if (waivers.exists) score += 20;
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
// Quality gates (20%) - only if enabled in mode
|
|
962
|
-
if (modes.isFeatureEnabled('qualityGates', currentMode)) {
|
|
963
|
-
if (hooks.installed || provenance.exists) score += 20;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
return Math.min(Math.round(score), 100);
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
/**
|
|
971
|
-
* Status command handler
|
|
972
|
-
* @param {Object} options - Command options
|
|
973
|
-
*/
|
|
974
|
-
async function statusCommand(options = {}) {
|
|
975
|
-
return safeAsync(
|
|
976
|
-
async () => {
|
|
977
|
-
// Check current mode and adjust behavior accordingly
|
|
978
|
-
const modes = require('../config/modes');
|
|
979
|
-
const currentMode = await modes.getCurrentMode();
|
|
980
|
-
|
|
981
|
-
// Load all status data in parallel for better performance
|
|
982
|
-
const [resolvedSpec, specs, hooks, provenance, waivers, gates] = await parallel([
|
|
983
|
-
loadResolvedStatusSpec(options),
|
|
984
|
-
loadSpecsFromMultiSpec(),
|
|
985
|
-
checkGitHooks(),
|
|
986
|
-
loadProvenanceChain(),
|
|
987
|
-
loadWaiverStatus(),
|
|
988
|
-
checkQualityGates(),
|
|
989
|
-
]);
|
|
990
|
-
const spec = resolvedSpec?.spec || null;
|
|
991
|
-
const specSelection = resolvedSpec
|
|
992
|
-
? {
|
|
993
|
-
specPath: resolvedSpec.path
|
|
994
|
-
? path.relative(process.cwd(), resolvedSpec.path)
|
|
995
|
-
: null,
|
|
996
|
-
specType: resolvedSpec.type,
|
|
997
|
-
}
|
|
998
|
-
: null;
|
|
999
|
-
|
|
1000
|
-
// Display status (visual mode if requested)
|
|
1001
|
-
if (options.visual || options.json) {
|
|
1002
|
-
if (options.json) {
|
|
1003
|
-
// JSON output for automation
|
|
1004
|
-
const result = {
|
|
1005
|
-
command: 'status',
|
|
1006
|
-
timestamp: new Date().toISOString(),
|
|
1007
|
-
system: specs.length > 0 ? 'multi-spec' : 'single-spec',
|
|
1008
|
-
specs:
|
|
1009
|
-
specs.length > 0
|
|
1010
|
-
? {
|
|
1011
|
-
count: specs.length,
|
|
1012
|
-
active: specs.filter((s) => s.status === 'active').length,
|
|
1013
|
-
draft: specs.filter((s) => s.status === 'draft').length,
|
|
1014
|
-
completed: specs.filter((s) => s.status === 'completed').length,
|
|
1015
|
-
list: specs.map((s) => ({
|
|
1016
|
-
id: s.id,
|
|
1017
|
-
type: s.type,
|
|
1018
|
-
status: s.status,
|
|
1019
|
-
title: s.title,
|
|
1020
|
-
})),
|
|
1021
|
-
}
|
|
1022
|
-
: null,
|
|
1023
|
-
legacySpec: spec
|
|
1024
|
-
? {
|
|
1025
|
-
id: spec.id,
|
|
1026
|
-
title: spec.title,
|
|
1027
|
-
riskTier: spec.risk_tier,
|
|
1028
|
-
mode: spec.mode,
|
|
1029
|
-
specType: specSelection?.specType || null,
|
|
1030
|
-
specPath: specSelection?.specPath || null,
|
|
1031
|
-
acceptanceCriteria: spec.acceptance_criteria?.length || 0,
|
|
1032
|
-
completedCriteria:
|
|
1033
|
-
spec.acceptance_criteria?.filter((c) => c.completed).length || 0,
|
|
1034
|
-
}
|
|
1035
|
-
: null,
|
|
1036
|
-
hooks: {
|
|
1037
|
-
installed: hooks.installed,
|
|
1038
|
-
count: hooks.count,
|
|
1039
|
-
total: hooks.total,
|
|
1040
|
-
active: hooks.active,
|
|
1041
|
-
},
|
|
1042
|
-
provenance: {
|
|
1043
|
-
exists: provenance.exists,
|
|
1044
|
-
count: provenance.count,
|
|
1045
|
-
lastUpdate: provenance.lastUpdate,
|
|
1046
|
-
},
|
|
1047
|
-
waivers: {
|
|
1048
|
-
exists: waivers.exists,
|
|
1049
|
-
active: waivers.active,
|
|
1050
|
-
expired: waivers.expired,
|
|
1051
|
-
revoked: waivers.revoked,
|
|
1052
|
-
total: waivers.total,
|
|
1053
|
-
},
|
|
1054
|
-
qualityGates: {
|
|
1055
|
-
checked: gates.checked,
|
|
1056
|
-
passed: gates.passed,
|
|
1057
|
-
message: gates.message,
|
|
1058
|
-
},
|
|
1059
|
-
workingState: spec && spec.id ? (loadStateFromEvents(spec.id) || null) : null,
|
|
1060
|
-
overallProgress: calculateOverallProgress({
|
|
1061
|
-
spec,
|
|
1062
|
-
specSelection,
|
|
1063
|
-
specs,
|
|
1064
|
-
hooks,
|
|
1065
|
-
provenance,
|
|
1066
|
-
waivers,
|
|
1067
|
-
gates,
|
|
1068
|
-
}),
|
|
1069
|
-
};
|
|
1070
|
-
|
|
1071
|
-
console.log(JSON.stringify(result, null, 2));
|
|
1072
|
-
return result;
|
|
1073
|
-
} else {
|
|
1074
|
-
// Visual output
|
|
1075
|
-
await displayVisualStatus(
|
|
1076
|
-
{
|
|
1077
|
-
spec,
|
|
1078
|
-
specs,
|
|
1079
|
-
hooks,
|
|
1080
|
-
provenance,
|
|
1081
|
-
waivers,
|
|
1082
|
-
gates,
|
|
1083
|
-
},
|
|
1084
|
-
currentMode
|
|
1085
|
-
);
|
|
1086
|
-
}
|
|
1087
|
-
} else {
|
|
1088
|
-
// Original text-based output
|
|
1089
|
-
displayStatus({
|
|
1090
|
-
spec,
|
|
1091
|
-
specSelection,
|
|
1092
|
-
hooks,
|
|
1093
|
-
provenance,
|
|
1094
|
-
waivers,
|
|
1095
|
-
gates,
|
|
1096
|
-
});
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
if (options.json) {
|
|
1100
|
-
return {
|
|
1101
|
-
command: 'status',
|
|
1102
|
-
mode: 'json',
|
|
1103
|
-
};
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
const result = outputResult({
|
|
1107
|
-
command: 'status',
|
|
1108
|
-
mode: options.visual ? 'visual' : options.json ? 'json' : 'text',
|
|
1109
|
-
system: specs.length > 0 ? 'multi-spec' : 'single-spec',
|
|
1110
|
-
currentMode: currentMode,
|
|
1111
|
-
specs: specs.length,
|
|
1112
|
-
legacySpec: spec ? 'loaded' : 'not found',
|
|
1113
|
-
hooks: modes.isFeatureEnabled('gitHooks', currentMode) ? hooks.installed : null,
|
|
1114
|
-
provenance: modes.isFeatureEnabled('provenance', currentMode)
|
|
1115
|
-
? provenance.count || 0
|
|
1116
|
-
: null,
|
|
1117
|
-
waivers: modes.isFeatureEnabled('waivers', currentMode) ? waivers.active || 0 : null,
|
|
1118
|
-
gates: modes.isFeatureEnabled('qualityGates', currentMode)
|
|
1119
|
-
? gates.passed
|
|
1120
|
-
? 'passed'
|
|
1121
|
-
: 'failed'
|
|
1122
|
-
: null,
|
|
1123
|
-
overallProgress: calculateOverallProgress({
|
|
1124
|
-
spec,
|
|
1125
|
-
specs,
|
|
1126
|
-
hooks,
|
|
1127
|
-
provenance,
|
|
1128
|
-
waivers,
|
|
1129
|
-
gates,
|
|
1130
|
-
currentMode,
|
|
1131
|
-
}),
|
|
1132
|
-
});
|
|
1133
|
-
|
|
1134
|
-
return result;
|
|
1135
|
-
},
|
|
1136
|
-
'status check',
|
|
1137
|
-
!options.json
|
|
1138
|
-
);
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
module.exports = {
|
|
1142
|
-
statusCommand,
|
|
1143
|
-
loadWorkingSpec,
|
|
1144
|
-
loadResolvedStatusSpec,
|
|
1145
|
-
checkGitHooks,
|
|
1146
|
-
loadProvenanceChain,
|
|
1147
|
-
loadWaiverStatus,
|
|
1148
|
-
checkQualityGates,
|
|
1149
|
-
displayStatus,
|
|
1150
|
-
generateSuggestions,
|
|
1151
|
-
};
|