@paths.design/caws-cli 9.3.2 → 10.0.1
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 +58 -27
- package/dist/commands/archive.js +67 -28
- package/dist/commands/burnup.js +20 -11
- package/dist/commands/diagnose.js +34 -22
- package/dist/commands/evaluate.js +27 -15
- package/dist/commands/gates.js +122 -0
- package/dist/commands/init.js +143 -15
- package/dist/commands/iterate.js +77 -4
- package/dist/commands/parallel.js +4 -0
- package/dist/commands/plan.js +9 -19
- package/dist/commands/provenance.js +53 -17
- package/dist/commands/quality-monitor.js +64 -45
- package/dist/commands/sidecar.js +71 -0
- package/dist/commands/specs.js +233 -44
- package/dist/commands/status.js +113 -9
- package/dist/commands/tutorial.js +10 -9
- package/dist/commands/validate.js +49 -6
- package/dist/commands/verify-acs.js +35 -78
- package/dist/commands/waivers.js +69 -12
- package/dist/commands/worktree.js +50 -25
- package/dist/error-handler.js +2 -13
- package/dist/gates/budget-limit.js +116 -0
- package/dist/gates/feedback.js +260 -0
- package/dist/gates/format.js +179 -0
- package/dist/gates/god-object.js +117 -0
- package/dist/gates/pipeline.js +167 -0
- package/dist/gates/scope-boundary.js +93 -0
- package/dist/gates/spec-completeness.js +102 -0
- package/dist/gates/todo-detection.js +205 -0
- package/dist/index.js +130 -151
- package/dist/parallel/parallel-manager.js +3 -3
- package/dist/policy/PolicyManager.js +42 -10
- package/dist/scaffold/claude-hooks.js +24 -1
- package/dist/scaffold/git-hooks.js +45 -102
- package/dist/scaffold/index.js +4 -3
- package/dist/session/session-manager.js +71 -14
- package/dist/sidecars/index.js +33 -0
- package/dist/sidecars/listeners.js +40 -0
- package/dist/sidecars/provenance-summary.js +238 -0
- package/dist/sidecars/quality-gaps.js +258 -0
- package/dist/sidecars/schema.js +149 -0
- package/dist/sidecars/spec-drift.js +151 -0
- package/dist/sidecars/waiver-draft.js +176 -0
- package/dist/templates/.caws/schemas/policy.schema.json +50 -0
- package/dist/templates/.caws/schemas/waivers.schema.json +30 -24
- package/dist/templates/.caws/schemas/working-spec.schema.json +51 -8
- package/dist/templates/.caws/schemas/worktrees.schema.json +3 -1
- package/dist/templates/.caws/templates/working-spec.template.yml +7 -3
- package/dist/templates/.claude/hooks/audit.sh +0 -0
- package/dist/templates/.claude/hooks/block-dangerous.sh +52 -11
- package/dist/templates/.claude/hooks/classify_command.py +592 -0
- package/dist/templates/.claude/hooks/doc-frontmatter-check.sh +173 -0
- package/dist/templates/.claude/hooks/quality-check.sh +23 -10
- package/dist/templates/.claude/hooks/scope-guard.sh +34 -32
- package/dist/templates/.claude/hooks/session-caws-status.sh +2 -2
- package/dist/templates/.claude/hooks/session-log.sh +76 -3
- package/dist/templates/.claude/hooks/stop-worktree-check.sh +1 -1
- package/dist/templates/.claude/hooks/test_classify_command.py +370 -0
- package/dist/templates/.claude/hooks/test_wrapper_smoke.sh +96 -0
- package/dist/templates/.claude/hooks/worktree-guard.sh +2 -2
- package/dist/templates/.claude/hooks/worktree-write-guard.sh +1 -1
- package/dist/templates/.claude/settings.json +26 -0
- package/dist/templates/.cursor/hooks/caws-quality-check.sh +4 -4
- package/dist/templates/.cursor/hooks/caws-scope-guard.sh +1 -1
- package/dist/templates/.cursor/hooks/session-log.sh +924 -0
- package/dist/templates/.cursor/hooks.json +25 -0
- package/dist/templates/.cursor/rules/02-quality-gates.mdc +3 -5
- package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +6 -11
- package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +14 -18
- package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +4 -4
- package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +3 -13
- package/dist/templates/.github/copilot-instructions.md +5 -5
- package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +1 -1
- package/dist/templates/.junie/guidelines.md +2 -2
- package/dist/templates/.vscode/settings.json +3 -1
- package/dist/templates/.windsurf/rules/caws-quality-standards.md +2 -2
- package/dist/templates/.windsurf/workflows/caws-guided-development.md +3 -3
- package/dist/templates/CLAUDE.md +43 -8
- package/dist/templates/agents.md +29 -9
- package/dist/templates/docs/README.md +8 -7
- package/dist/templates/scripts/new_feature.sh +80 -0
- package/dist/test-analysis.js +43 -30
- package/dist/tool-loader.js +1 -1
- package/dist/utils/agent-session.js +202 -0
- package/dist/utils/detection.js +8 -2
- package/dist/utils/finalization.js +7 -6
- package/dist/utils/gitignore-updater.js +3 -0
- package/dist/utils/lifecycle-events.js +94 -0
- package/dist/utils/quality-gates-utils.js +29 -44
- package/dist/utils/schema-validator.js +42 -0
- package/dist/utils/spec-resolver.js +93 -21
- package/dist/utils/working-state.js +505 -0
- package/dist/validation/spec-validation.js +92 -22
- package/dist/waivers-manager.js +60 -6
- package/dist/worktree/worktree-manager.js +390 -93
- package/package.json +6 -6
- package/templates/.caws/schemas/policy.schema.json +50 -0
- package/templates/.caws/schemas/waivers.schema.json +30 -24
- package/templates/.caws/schemas/working-spec.schema.json +51 -8
- package/templates/.caws/schemas/worktrees.schema.json +3 -1
- package/templates/.caws/templates/working-spec.template.yml +7 -3
- package/templates/.claude/hooks/block-dangerous.sh +52 -11
- package/templates/.claude/hooks/classify_command.py +592 -0
- package/templates/.claude/hooks/doc-frontmatter-check.sh +173 -0
- package/templates/.claude/hooks/quality-check.sh +23 -10
- package/templates/.claude/hooks/scope-guard.sh +34 -32
- package/templates/.claude/hooks/session-caws-status.sh +2 -2
- package/templates/.claude/hooks/session-log.sh +76 -3
- package/templates/.claude/hooks/stop-worktree-check.sh +1 -1
- package/templates/.claude/hooks/test_classify_command.py +370 -0
- package/templates/.claude/hooks/test_wrapper_smoke.sh +96 -0
- package/templates/.claude/hooks/worktree-guard.sh +2 -2
- package/templates/.claude/hooks/worktree-write-guard.sh +1 -1
- package/templates/.claude/settings.json +26 -0
- package/templates/.cursor/hooks/caws-quality-check.sh +4 -4
- package/templates/.cursor/hooks/caws-scope-guard.sh +1 -1
- package/templates/.cursor/hooks/session-log.sh +924 -0
- package/templates/.cursor/hooks.json +25 -0
- package/templates/.cursor/rules/02-quality-gates.mdc +3 -5
- package/templates/.cursor/rules/10-documentation-quality-standards.mdc +6 -11
- package/templates/.cursor/rules/11-scope-management-waivers.mdc +14 -18
- package/templates/.cursor/rules/12-implementation-completeness.mdc +4 -4
- package/templates/.cursor/rules/13-language-agnostic-standards.mdc +3 -13
- package/templates/.github/copilot-instructions.md +5 -5
- package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +1 -1
- package/templates/.junie/guidelines.md +2 -2
- package/templates/.vscode/settings.json +3 -1
- package/templates/.windsurf/rules/caws-quality-standards.md +2 -2
- package/templates/.windsurf/workflows/caws-guided-development.md +3 -3
- package/templates/CLAUDE.md +43 -8
- package/templates/{AGENTS.md → agents.md} +29 -9
- package/templates/docs/README.md +8 -7
- package/templates/scripts/new_feature.sh +80 -0
- package/dist/budget-derivation.d.ts +0 -74
- package/dist/budget-derivation.d.ts.map +0 -1
- package/dist/cicd-optimizer.d.ts +0 -142
- package/dist/cicd-optimizer.d.ts.map +0 -1
- package/dist/commands/archive.d.ts +0 -51
- package/dist/commands/archive.d.ts.map +0 -1
- package/dist/commands/burnup.d.ts +0 -6
- package/dist/commands/burnup.d.ts.map +0 -1
- package/dist/commands/diagnose.d.ts +0 -52
- package/dist/commands/diagnose.d.ts.map +0 -1
- package/dist/commands/evaluate.d.ts +0 -8
- package/dist/commands/evaluate.d.ts.map +0 -1
- package/dist/commands/init.d.ts +0 -5
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/iterate.d.ts +0 -8
- package/dist/commands/iterate.d.ts.map +0 -1
- package/dist/commands/mode.d.ts +0 -25
- package/dist/commands/mode.d.ts.map +0 -1
- package/dist/commands/parallel.d.ts +0 -7
- package/dist/commands/parallel.d.ts.map +0 -1
- package/dist/commands/plan.d.ts +0 -49
- package/dist/commands/plan.d.ts.map +0 -1
- package/dist/commands/provenance.d.ts +0 -32
- package/dist/commands/provenance.d.ts.map +0 -1
- package/dist/commands/quality-gates.d.ts +0 -6
- package/dist/commands/quality-gates.d.ts.map +0 -1
- package/dist/commands/quality-gates.js +0 -444
- package/dist/commands/quality-monitor.d.ts +0 -17
- package/dist/commands/quality-monitor.d.ts.map +0 -1
- package/dist/commands/session.d.ts +0 -7
- package/dist/commands/session.d.ts.map +0 -1
- package/dist/commands/specs.d.ts +0 -77
- package/dist/commands/specs.d.ts.map +0 -1
- package/dist/commands/status.d.ts +0 -44
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/templates.d.ts +0 -74
- package/dist/commands/templates.d.ts.map +0 -1
- package/dist/commands/tool.d.ts +0 -13
- package/dist/commands/tool.d.ts.map +0 -1
- package/dist/commands/troubleshoot.d.ts +0 -8
- package/dist/commands/troubleshoot.d.ts.map +0 -1
- package/dist/commands/troubleshoot.js +0 -104
- package/dist/commands/tutorial.d.ts +0 -55
- package/dist/commands/tutorial.d.ts.map +0 -1
- package/dist/commands/validate.d.ts +0 -15
- package/dist/commands/validate.d.ts.map +0 -1
- package/dist/commands/waivers.d.ts +0 -8
- package/dist/commands/waivers.d.ts.map +0 -1
- package/dist/commands/workflow.d.ts +0 -85
- package/dist/commands/workflow.d.ts.map +0 -1
- package/dist/commands/worktree.d.ts +0 -7
- package/dist/commands/worktree.d.ts.map +0 -1
- package/dist/config/index.d.ts +0 -29
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/lite-scope.d.ts +0 -33
- package/dist/config/lite-scope.d.ts.map +0 -1
- package/dist/config/modes.d.ts +0 -264
- package/dist/config/modes.d.ts.map +0 -1
- package/dist/constants/spec-types.d.ts +0 -93
- package/dist/constants/spec-types.d.ts.map +0 -1
- package/dist/error-handler.d.ts +0 -151
- package/dist/error-handler.d.ts.map +0 -1
- package/dist/generators/jest-config-generator.d.ts +0 -32
- package/dist/generators/jest-config-generator.d.ts.map +0 -1
- package/dist/generators/jest-config.d.ts +0 -32
- package/dist/generators/jest-config.d.ts.map +0 -1
- package/dist/generators/jest-config.js +0 -242
- package/dist/generators/working-spec.d.ts +0 -13
- package/dist/generators/working-spec.d.ts.map +0 -1
- package/dist/index-new.d.ts +0 -5
- package/dist/index-new.d.ts.map +0 -1
- package/dist/index-new.js +0 -317
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.backup +0 -4711
- package/dist/minimal-cli.d.ts +0 -3
- package/dist/minimal-cli.d.ts.map +0 -1
- package/dist/parallel/parallel-manager.d.ts +0 -67
- package/dist/parallel/parallel-manager.d.ts.map +0 -1
- package/dist/policy/PolicyManager.d.ts +0 -104
- package/dist/policy/PolicyManager.d.ts.map +0 -1
- package/dist/scaffold/claude-hooks.d.ts +0 -28
- package/dist/scaffold/claude-hooks.d.ts.map +0 -1
- package/dist/scaffold/cursor-hooks.d.ts +0 -7
- package/dist/scaffold/cursor-hooks.d.ts.map +0 -1
- package/dist/scaffold/git-hooks.d.ts +0 -38
- package/dist/scaffold/git-hooks.d.ts.map +0 -1
- package/dist/scaffold/index.d.ts +0 -17
- package/dist/scaffold/index.d.ts.map +0 -1
- package/dist/session/session-manager.d.ts +0 -94
- package/dist/session/session-manager.d.ts.map +0 -1
- package/dist/spec/SpecFileManager.d.ts +0 -146
- package/dist/spec/SpecFileManager.d.ts.map +0 -1
- package/dist/templates/.cursor/hooks/caws-tool-validation.sh +0 -121
- package/dist/templates/.github/copilot/instructions.md +0 -311
- package/dist/test-analysis.d.ts +0 -231
- package/dist/test-analysis.d.ts.map +0 -1
- package/dist/tool-interface.d.ts +0 -236
- package/dist/tool-interface.d.ts.map +0 -1
- package/dist/tool-loader.d.ts +0 -77
- package/dist/tool-loader.d.ts.map +0 -1
- package/dist/tool-validator.d.ts +0 -72
- package/dist/tool-validator.d.ts.map +0 -1
- package/dist/utils/async-utils.d.ts +0 -73
- package/dist/utils/async-utils.d.ts.map +0 -1
- package/dist/utils/command-wrapper.d.ts +0 -66
- package/dist/utils/command-wrapper.d.ts.map +0 -1
- package/dist/utils/detection.d.ts +0 -14
- package/dist/utils/detection.d.ts.map +0 -1
- package/dist/utils/error-categories.d.ts +0 -52
- package/dist/utils/error-categories.d.ts.map +0 -1
- package/dist/utils/finalization.d.ts +0 -17
- package/dist/utils/finalization.d.ts.map +0 -1
- package/dist/utils/git-lock.d.ts +0 -13
- package/dist/utils/git-lock.d.ts.map +0 -1
- package/dist/utils/gitignore-updater.d.ts +0 -39
- package/dist/utils/gitignore-updater.d.ts.map +0 -1
- package/dist/utils/ide-detection.d.ts +0 -89
- package/dist/utils/ide-detection.d.ts.map +0 -1
- package/dist/utils/project-analysis.d.ts +0 -34
- package/dist/utils/project-analysis.d.ts.map +0 -1
- package/dist/utils/promise-utils.d.ts +0 -30
- package/dist/utils/promise-utils.d.ts.map +0 -1
- package/dist/utils/quality-gates-utils.d.ts +0 -49
- package/dist/utils/quality-gates-utils.d.ts.map +0 -1
- package/dist/utils/quality-gates.d.ts +0 -49
- package/dist/utils/quality-gates.d.ts.map +0 -1
- package/dist/utils/quality-gates.js +0 -402
- package/dist/utils/spec-resolver.d.ts +0 -80
- package/dist/utils/spec-resolver.d.ts.map +0 -1
- package/dist/utils/typescript-detector.d.ts +0 -66
- package/dist/utils/typescript-detector.d.ts.map +0 -1
- package/dist/utils/yaml-validation.d.ts +0 -32
- package/dist/utils/yaml-validation.d.ts.map +0 -1
- package/dist/validation/spec-validation.d.ts +0 -43
- package/dist/validation/spec-validation.d.ts.map +0 -1
- package/dist/waivers-manager.d.ts +0 -167
- package/dist/waivers-manager.d.ts.map +0 -1
- package/dist/worktree/worktree-manager.d.ts +0 -54
- package/dist/worktree/worktree-manager.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -12,8 +12,8 @@ The CAWS CLI serves as the central control point for:
|
|
|
12
12
|
- **Quality Validation**: Run comprehensive validation against working specifications
|
|
13
13
|
- **Agent Integration**: Programmatic APIs for AI agents to evaluate and guide development
|
|
14
14
|
- **Waiver Management**: Fast-lane escape hatches with full audit trails
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
15
|
+
- **Quality Gates**: v2 pipeline with configurable gate modules
|
|
16
|
+
- **Session Management**: Track and manage agent work sessions
|
|
17
17
|
|
|
18
18
|
## Installation
|
|
19
19
|
|
|
@@ -86,40 +86,69 @@ caws waivers list
|
|
|
86
86
|
caws waivers revoke WV-0001
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
###
|
|
89
|
+
### Quality Gates
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
|
-
#
|
|
93
|
-
caws
|
|
92
|
+
# Run quality gates v2 pipeline
|
|
93
|
+
caws gates run
|
|
94
94
|
|
|
95
|
-
#
|
|
96
|
-
caws
|
|
95
|
+
# Run legacy quality gates
|
|
96
|
+
caws quality-gates
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Worktree Management
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Create an isolated worktree for parallel agent work
|
|
103
|
+
caws worktree create <name>
|
|
104
|
+
|
|
105
|
+
# List active worktrees
|
|
106
|
+
caws worktree list
|
|
97
107
|
|
|
98
|
-
#
|
|
99
|
-
caws
|
|
108
|
+
# Merge a completed worktree back to base
|
|
109
|
+
caws worktree merge <name>
|
|
110
|
+
|
|
111
|
+
# Destroy a worktree
|
|
112
|
+
caws worktree destroy <name>
|
|
100
113
|
```
|
|
101
114
|
|
|
102
|
-
###
|
|
115
|
+
### Session Management
|
|
103
116
|
|
|
104
117
|
```bash
|
|
105
|
-
#
|
|
106
|
-
caws
|
|
118
|
+
# Start a tracked session
|
|
119
|
+
caws session start
|
|
120
|
+
|
|
121
|
+
# Create a session checkpoint
|
|
122
|
+
caws session checkpoint
|
|
107
123
|
|
|
108
|
-
#
|
|
109
|
-
caws
|
|
124
|
+
# End a session
|
|
125
|
+
caws session end
|
|
126
|
+
|
|
127
|
+
# List past sessions
|
|
128
|
+
caws session list
|
|
110
129
|
```
|
|
111
130
|
|
|
112
|
-
###
|
|
131
|
+
### Spec Management
|
|
113
132
|
|
|
114
133
|
```bash
|
|
115
|
-
# List
|
|
116
|
-
caws
|
|
134
|
+
# List all specs (project + feature)
|
|
135
|
+
caws specs list
|
|
136
|
+
|
|
137
|
+
# Create a feature spec
|
|
138
|
+
caws specs create FEAT-001 --type feature --title "description"
|
|
139
|
+
|
|
140
|
+
# Show a spec
|
|
141
|
+
caws specs show FEAT-001
|
|
142
|
+
|
|
143
|
+
# Check for scope conflicts between specs
|
|
144
|
+
caws specs conflicts
|
|
145
|
+
```
|
|
117
146
|
|
|
118
|
-
|
|
119
|
-
caws tools run validate
|
|
147
|
+
### Tool Management
|
|
120
148
|
|
|
121
|
-
|
|
122
|
-
|
|
149
|
+
```bash
|
|
150
|
+
# Run the CAWS tool interface
|
|
151
|
+
caws tool
|
|
123
152
|
```
|
|
124
153
|
|
|
125
154
|
## Architecture
|
|
@@ -131,7 +160,7 @@ caws-cli/
|
|
|
131
160
|
├── src/
|
|
132
161
|
│ ├── index.js # Main CLI entry point
|
|
133
162
|
│ ├── waivers-manager.js # Waiver system implementation
|
|
134
|
-
│ ├──
|
|
163
|
+
│ ├── quality-gates/ # v2 gate modules
|
|
135
164
|
│ └── tool-loader.js # Dynamic tool loading system
|
|
136
165
|
├── templates/ # Project templates
|
|
137
166
|
└── dist/ # Compiled output
|
|
@@ -142,7 +171,7 @@ caws-cli/
|
|
|
142
171
|
- **Command Parser**: Commander.js-based CLI with subcommands
|
|
143
172
|
- **Tool System**: Dynamic loading of quality gate tools
|
|
144
173
|
- **Waiver Manager**: Fast-lane escape hatch management
|
|
145
|
-
- **
|
|
174
|
+
- **Quality Gates v2**: Modular gate pipeline with configurable modules
|
|
146
175
|
- **Agent Interface**: JSON APIs for programmatic agent integration
|
|
147
176
|
|
|
148
177
|
## Integration with CAWS Ecosystem
|
|
@@ -168,14 +197,16 @@ caws-cli/
|
|
|
168
197
|
|
|
169
198
|
### Quality Gates Integration
|
|
170
199
|
|
|
171
|
-
The
|
|
200
|
+
The v2 quality gates pipeline (`caws gates run`) executes modular gate checks:
|
|
172
201
|
|
|
173
|
-
1. **Spec Validation**: Validates working specifications against schema
|
|
202
|
+
1. **Spec Validation**: Validates working specifications against schema (mode, blast_radius, rollback SLO)
|
|
174
203
|
2. **Security Scanning**: Runs security checks and secret detection
|
|
175
|
-
3. **
|
|
176
|
-
4. **Test
|
|
204
|
+
3. **Scope Enforcement**: Verifies changes stay within spec-defined boundaries
|
|
205
|
+
4. **Test & Coverage**: Runs tests and validates coverage thresholds per risk tier
|
|
177
206
|
5. **Performance Checks**: Validates performance budgets and metrics
|
|
178
207
|
|
|
208
|
+
Gates can be configured per-spec with `mode` (block/warn/skip) and custom `thresholds` in policy.yaml.
|
|
209
|
+
|
|
179
210
|
### Agent Workflow Integration
|
|
180
211
|
|
|
181
212
|
The CLI provides structured APIs for agents:
|
package/dist/commands/archive.js
CHANGED
|
@@ -10,6 +10,7 @@ const yaml = require('js-yaml');
|
|
|
10
10
|
const chalk = require('chalk');
|
|
11
11
|
const { execSync } = require('child_process');
|
|
12
12
|
const { safeAsync, outputResult } = require('../error-handler');
|
|
13
|
+
const { findProjectRoot } = require('../utils/detection');
|
|
13
14
|
|
|
14
15
|
// Import spec resolution system
|
|
15
16
|
const { resolveSpec } = require('../utils/spec-resolver');
|
|
@@ -20,7 +21,8 @@ const { resolveSpec } = require('../utils/spec-resolver');
|
|
|
20
21
|
* @returns {Promise<Object|null>} Change data or null
|
|
21
22
|
*/
|
|
22
23
|
async function loadChange(changeId) {
|
|
23
|
-
const
|
|
24
|
+
const projectRoot = findProjectRoot();
|
|
25
|
+
const changesDir = path.join(projectRoot, '.caws/changes');
|
|
24
26
|
const changePath = path.join(changesDir, changeId);
|
|
25
27
|
|
|
26
28
|
if (!(await fs.pathExists(changePath))) {
|
|
@@ -44,10 +46,11 @@ async function loadChange(changeId) {
|
|
|
44
46
|
path: changePath,
|
|
45
47
|
metadata,
|
|
46
48
|
workingSpec,
|
|
49
|
+
workingSpecPath: (await fs.pathExists(workingSpecPath)) ? workingSpecPath : null,
|
|
47
50
|
exists: true,
|
|
48
51
|
};
|
|
49
52
|
} catch (error) {
|
|
50
|
-
|
|
53
|
+
throw new Error(`Failed to load change '${changeId}': ${error.message}`);
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
|
|
@@ -57,18 +60,24 @@ async function loadChange(changeId) {
|
|
|
57
60
|
* @returns {Promise<Object>} Validation result
|
|
58
61
|
*/
|
|
59
62
|
async function validateAcceptanceCriteria(workingSpec) {
|
|
60
|
-
|
|
63
|
+
const criteria = Array.isArray(workingSpec?.acceptance_criteria)
|
|
64
|
+
? workingSpec.acceptance_criteria
|
|
65
|
+
: Array.isArray(workingSpec?.acceptance)
|
|
66
|
+
? workingSpec.acceptance
|
|
67
|
+
: [];
|
|
68
|
+
|
|
69
|
+
if (!workingSpec || criteria.length === 0) {
|
|
61
70
|
return {
|
|
62
71
|
valid: false,
|
|
63
72
|
message: 'No acceptance criteria found in working spec',
|
|
64
73
|
};
|
|
65
74
|
}
|
|
66
75
|
|
|
67
|
-
const
|
|
76
|
+
const hasCompletionTracking = criteria.some((criterion) => criterion.completed !== undefined);
|
|
68
77
|
const incomplete = [];
|
|
69
78
|
|
|
70
79
|
for (const criterion of criteria) {
|
|
71
|
-
if (
|
|
80
|
+
if (criterion.completed === false) {
|
|
72
81
|
incomplete.push(criterion.id || 'unknown');
|
|
73
82
|
}
|
|
74
83
|
}
|
|
@@ -80,6 +89,13 @@ async function validateAcceptanceCriteria(workingSpec) {
|
|
|
80
89
|
};
|
|
81
90
|
}
|
|
82
91
|
|
|
92
|
+
if (!hasCompletionTracking) {
|
|
93
|
+
return {
|
|
94
|
+
valid: true,
|
|
95
|
+
message: `Acceptance criteria present (${criteria.length}); no explicit completion flags found`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
83
99
|
return {
|
|
84
100
|
valid: true,
|
|
85
101
|
message: `All ${criteria.length} acceptance criteria completed`,
|
|
@@ -212,8 +228,8 @@ async function validateQualityGates(_changeId) {
|
|
|
212
228
|
* @param {Object} change - Change data
|
|
213
229
|
* @returns {Promise<string>} Summary text
|
|
214
230
|
*/
|
|
215
|
-
async function generateChangeSummary(change) {
|
|
216
|
-
const {
|
|
231
|
+
async function generateChangeSummary(change, workingSpec) {
|
|
232
|
+
const { metadata } = change;
|
|
217
233
|
|
|
218
234
|
let summary = `# Change Summary: ${change.id}\n\n`;
|
|
219
235
|
|
|
@@ -267,7 +283,7 @@ async function archiveChange(change) {
|
|
|
267
283
|
* @param {Object} change - Change data
|
|
268
284
|
* @returns {Promise<void>}
|
|
269
285
|
*/
|
|
270
|
-
async function updateProvenance(change) {
|
|
286
|
+
async function updateProvenance(change, specSelection) {
|
|
271
287
|
const provenanceDir = '.caws/provenance';
|
|
272
288
|
const chainPath = path.join(provenanceDir, 'chain.json');
|
|
273
289
|
|
|
@@ -284,8 +300,11 @@ async function updateProvenance(change) {
|
|
|
284
300
|
action: 'change_completed',
|
|
285
301
|
change_id: change.id,
|
|
286
302
|
metadata: {
|
|
287
|
-
title: change.workingSpec?.title,
|
|
288
|
-
risk_tier: change.workingSpec?.risk_tier,
|
|
303
|
+
title: specSelection?.spec?.title || change.workingSpec?.title,
|
|
304
|
+
risk_tier: specSelection?.spec?.risk_tier || change.workingSpec?.risk_tier,
|
|
305
|
+
spec_id: specSelection?.spec?.id || change.workingSpec?.id || null,
|
|
306
|
+
spec_path: specSelection?.path || change.workingSpecPath || null,
|
|
307
|
+
spec_type: specSelection?.type || (change.workingSpecPath ? 'change-snapshot' : null),
|
|
289
308
|
files_changed: change.metadata?.files_changed || 0,
|
|
290
309
|
lines_added: change.metadata?.lines_added || 0,
|
|
291
310
|
lines_removed: change.metadata?.lines_removed || 0,
|
|
@@ -309,10 +328,20 @@ async function updateProvenance(change) {
|
|
|
309
328
|
* @param {Object} validation - Validation result
|
|
310
329
|
* @param {Object} qualityGates - Quality gates result
|
|
311
330
|
*/
|
|
312
|
-
function displayArchiveResults(change, validation, qualityGates) {
|
|
331
|
+
function displayArchiveResults(change, validation, qualityGates, specSelection) {
|
|
313
332
|
console.log(chalk.bold.cyan(`\nArchiving Change: ${change.id}`));
|
|
314
333
|
console.log(chalk.cyan('==============================================\n'));
|
|
315
334
|
|
|
335
|
+
if (specSelection?.spec) {
|
|
336
|
+
console.log(chalk.blue('Spec Context:'));
|
|
337
|
+
console.log(
|
|
338
|
+
chalk.gray(
|
|
339
|
+
` ${specSelection.spec.id || 'unknown'} (${specSelection.type}) -> ${specSelection.path}`
|
|
340
|
+
)
|
|
341
|
+
);
|
|
342
|
+
console.log('');
|
|
343
|
+
}
|
|
344
|
+
|
|
316
345
|
// Validation status
|
|
317
346
|
if (validation.valid) {
|
|
318
347
|
console.log(chalk.green('Acceptance Criteria'));
|
|
@@ -363,22 +392,27 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
363
392
|
}
|
|
364
393
|
|
|
365
394
|
// Resolve spec using priority system
|
|
366
|
-
let
|
|
367
|
-
if (
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
395
|
+
let specSelection = null;
|
|
396
|
+
if (options.specId || options.specFile) {
|
|
397
|
+
specSelection = await resolveSpec({
|
|
398
|
+
specId: options.specId,
|
|
399
|
+
specFile: options.specFile,
|
|
400
|
+
warnLegacy: false,
|
|
401
|
+
});
|
|
402
|
+
} else if (change.workingSpec) {
|
|
403
|
+
specSelection = {
|
|
404
|
+
path: change.workingSpecPath || path.join(change.path, 'working-spec.yaml'),
|
|
405
|
+
type: 'change-snapshot',
|
|
406
|
+
spec: change.workingSpec,
|
|
407
|
+
};
|
|
408
|
+
} else {
|
|
409
|
+
specSelection = await resolveSpec({
|
|
410
|
+
warnLegacy: false,
|
|
411
|
+
});
|
|
380
412
|
}
|
|
381
413
|
|
|
414
|
+
const workingSpec = specSelection.spec;
|
|
415
|
+
|
|
382
416
|
// Validate acceptance criteria
|
|
383
417
|
const validation = await validateAcceptanceCriteria(workingSpec);
|
|
384
418
|
|
|
@@ -386,7 +420,7 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
386
420
|
const qualityGates = await validateQualityGates(changeId);
|
|
387
421
|
|
|
388
422
|
// Display results
|
|
389
|
-
displayArchiveResults(change, validation, qualityGates);
|
|
423
|
+
displayArchiveResults(change, validation, qualityGates, specSelection);
|
|
390
424
|
|
|
391
425
|
// Check if we should proceed with archival
|
|
392
426
|
if (!validation.valid) {
|
|
@@ -423,7 +457,7 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
423
457
|
change.metadata.archived = true;
|
|
424
458
|
|
|
425
459
|
// Generate and save summary
|
|
426
|
-
const summary = await generateChangeSummary(change);
|
|
460
|
+
const summary = await generateChangeSummary(change, workingSpec);
|
|
427
461
|
const summaryPath = path.join(change.path, 'archive-summary.md');
|
|
428
462
|
await fs.writeFile(summaryPath, summary);
|
|
429
463
|
|
|
@@ -431,7 +465,7 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
431
465
|
await archiveChange(change);
|
|
432
466
|
|
|
433
467
|
// Update provenance
|
|
434
|
-
await updateProvenance(change);
|
|
468
|
+
await updateProvenance(change, specSelection);
|
|
435
469
|
|
|
436
470
|
console.log(chalk.green(`\nSuccessfully archived change: ${changeId}`));
|
|
437
471
|
|
|
@@ -439,6 +473,11 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
439
473
|
command: 'archive',
|
|
440
474
|
change: changeId,
|
|
441
475
|
archived: true,
|
|
476
|
+
specSelection: {
|
|
477
|
+
id: workingSpec?.id || null,
|
|
478
|
+
path: specSelection?.path || null,
|
|
479
|
+
type: specSelection?.type || null,
|
|
480
|
+
},
|
|
442
481
|
validation: validation.valid,
|
|
443
482
|
qualityGates: qualityGates.valid,
|
|
444
483
|
summary: summary,
|
package/dist/commands/burnup.js
CHANGED
|
@@ -11,6 +11,7 @@ const chalk = require('chalk');
|
|
|
11
11
|
const { execSync } = require('child_process');
|
|
12
12
|
|
|
13
13
|
const { deriveBudget, generateBurnupReport } = require('../budget-derivation');
|
|
14
|
+
const { resolveSpec } = require('../utils/spec-resolver');
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Get actual git change statistics from the repository
|
|
@@ -86,24 +87,32 @@ function getGitChangeStats(specDir) {
|
|
|
86
87
|
|
|
87
88
|
/**
|
|
88
89
|
* Burn-up command handler
|
|
89
|
-
* @param {string} specFile - Path to spec file
|
|
90
|
+
* @param {string} specFile - Path to spec file (positional, optional)
|
|
91
|
+
* @param {object} options - Command options including --spec-id
|
|
90
92
|
*/
|
|
91
|
-
async function burnupCommand(specFile) {
|
|
93
|
+
async function burnupCommand(specFile, options = {}) {
|
|
92
94
|
try {
|
|
93
|
-
let specPath
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
let specPath;
|
|
96
|
+
let spec;
|
|
97
|
+
|
|
98
|
+
// Resolve spec: explicit file > --spec-id > resolver default
|
|
99
|
+
if (specFile) {
|
|
100
|
+
specPath = specFile;
|
|
101
|
+
if (!fs.existsSync(specPath)) {
|
|
102
|
+
console.error(chalk.red(`Spec file not found: ${specPath}`));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
spec = yaml.load(fs.readFileSync(specPath, 'utf8'));
|
|
106
|
+
} else {
|
|
107
|
+
const resolved = await resolveSpec({ specId: options.specId });
|
|
108
|
+
specPath = resolved.path;
|
|
109
|
+
spec = resolved.spec;
|
|
98
110
|
}
|
|
99
111
|
|
|
100
|
-
const specContent = fs.readFileSync(specPath, 'utf8');
|
|
101
|
-
const spec = yaml.load(specContent);
|
|
102
|
-
|
|
103
112
|
console.log(chalk.cyan('Generating CAWS budget burn-up report...'));
|
|
104
113
|
|
|
105
114
|
// Derive budget
|
|
106
|
-
const derivedBudget = deriveBudget(spec, path.dirname(specPath));
|
|
115
|
+
const derivedBudget = await deriveBudget(spec, path.dirname(specPath));
|
|
107
116
|
|
|
108
117
|
// Get actual git change statistics
|
|
109
118
|
const gitStats = getGitChangeStats(path.dirname(specPath));
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
const fs = require('fs-extra');
|
|
8
8
|
const path = require('path');
|
|
9
|
-
const yaml = require('js-yaml');
|
|
10
9
|
const chalk = require('chalk');
|
|
10
|
+
const { resolveSpec } = require('../utils/spec-resolver');
|
|
11
11
|
|
|
12
12
|
// Import utilities
|
|
13
13
|
const { checkTypeScriptTestConfig } = require('../utils/typescript-detector');
|
|
@@ -17,29 +17,23 @@ const { configureJestForTypeScript } = require('../generators/jest-config-genera
|
|
|
17
17
|
* Health check: Working spec validity
|
|
18
18
|
* @returns {Promise<Object>} Check result
|
|
19
19
|
*/
|
|
20
|
-
async function checkWorkingSpec() {
|
|
21
|
-
const specPath = '.caws/working-spec.yaml';
|
|
22
|
-
|
|
23
|
-
if (!(await fs.pathExists(specPath))) {
|
|
24
|
-
return {
|
|
25
|
-
passed: false,
|
|
26
|
-
severity: 'high',
|
|
27
|
-
message: 'Working spec not found',
|
|
28
|
-
fix: 'Initialize CAWS: caws init .',
|
|
29
|
-
autoFixable: false,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
20
|
+
async function checkWorkingSpec(options = {}) {
|
|
33
21
|
try {
|
|
34
|
-
const
|
|
35
|
-
|
|
22
|
+
const resolved = await resolveSpec({
|
|
23
|
+
specId: options.specId,
|
|
24
|
+
specFile: options.spec,
|
|
25
|
+
warnLegacy: false,
|
|
26
|
+
interactive: false,
|
|
27
|
+
});
|
|
28
|
+
const spec = resolved.spec;
|
|
29
|
+
const specPath = path.relative(process.cwd(), resolved.path);
|
|
36
30
|
|
|
37
31
|
// Basic validation
|
|
38
32
|
if (!spec.id || !spec.title || !spec.risk_tier) {
|
|
39
33
|
return {
|
|
40
34
|
passed: false,
|
|
41
35
|
severity: 'high',
|
|
42
|
-
message:
|
|
36
|
+
message: `Spec missing required fields (${specPath})`,
|
|
43
37
|
fix: 'Run: caws validate for details',
|
|
44
38
|
autoFixable: false,
|
|
45
39
|
};
|
|
@@ -47,13 +41,31 @@ async function checkWorkingSpec() {
|
|
|
47
41
|
|
|
48
42
|
return {
|
|
49
43
|
passed: true,
|
|
50
|
-
message:
|
|
44
|
+
message: `Spec is valid (${specPath})`,
|
|
51
45
|
};
|
|
52
46
|
} catch (error) {
|
|
47
|
+
if (error.message === 'Spec ID required when multiple specs exist' && !options.specId) {
|
|
48
|
+
return {
|
|
49
|
+
passed: false,
|
|
50
|
+
severity: 'high',
|
|
51
|
+
message: 'Multiple specs detected, but no --spec-id was provided',
|
|
52
|
+
fix: 'Run: caws diagnose --spec-id <id>',
|
|
53
|
+
autoFixable: false,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (error.message.includes('No CAWS spec found')) {
|
|
57
|
+
return {
|
|
58
|
+
passed: false,
|
|
59
|
+
severity: 'high',
|
|
60
|
+
message: 'No CAWS spec found',
|
|
61
|
+
fix: 'Initialize CAWS: caws init . or create a feature spec with caws specs create <id>',
|
|
62
|
+
autoFixable: false,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
53
65
|
return {
|
|
54
66
|
passed: false,
|
|
55
67
|
severity: 'high',
|
|
56
|
-
message: `
|
|
68
|
+
message: `Spec has errors: ${error.message}`,
|
|
57
69
|
fix: 'Run: caws validate for details',
|
|
58
70
|
autoFixable: false,
|
|
59
71
|
};
|
|
@@ -285,9 +297,9 @@ async function checkCAWSTools() {
|
|
|
285
297
|
* Run all health checks
|
|
286
298
|
* @returns {Promise<Object>} Diagnosis results
|
|
287
299
|
*/
|
|
288
|
-
async function runDiagnosis() {
|
|
300
|
+
async function runDiagnosis(options = {}) {
|
|
289
301
|
const checks = [
|
|
290
|
-
{ name: 'Working spec validity', fn: checkWorkingSpec },
|
|
302
|
+
{ name: 'Working spec validity', fn: () => checkWorkingSpec(options) },
|
|
291
303
|
{ name: 'Git repository', fn: checkGitSetup },
|
|
292
304
|
{ name: 'Git hooks', fn: checkGitHooks },
|
|
293
305
|
{ name: 'TypeScript configuration', fn: checkTypeScriptConfig },
|
|
@@ -447,7 +459,7 @@ async function applyAutoFixes(results) {
|
|
|
447
459
|
async function diagnoseCommand(options = {}) {
|
|
448
460
|
try {
|
|
449
461
|
// Run all health checks
|
|
450
|
-
const results = await runDiagnosis();
|
|
462
|
+
const results = await runDiagnosis(options);
|
|
451
463
|
|
|
452
464
|
// Display results
|
|
453
465
|
displayResults(results);
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* @author @darianrosebrook
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
const fs = require('fs');
|
|
11
10
|
const path = require('path');
|
|
12
|
-
const yaml = require('js-yaml');
|
|
13
11
|
const chalk = require('chalk');
|
|
14
12
|
const { initializeGlobalSetup } = require('../config');
|
|
13
|
+
const { resolveSpec } = require('../utils/spec-resolver');
|
|
14
|
+
const { recordEvaluation } = require('../utils/working-state');
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Evaluate command handler
|
|
@@ -19,30 +19,29 @@ const { initializeGlobalSetup } = require('../config');
|
|
|
19
19
|
* @param {string} specFile - Path to working spec file
|
|
20
20
|
* @param {object} options - Command options
|
|
21
21
|
*/
|
|
22
|
-
async function evaluateCommand(specFile
|
|
22
|
+
async function evaluateCommand(specFile, options = {}) {
|
|
23
23
|
try {
|
|
24
24
|
console.log('Detecting CAWS setup...');
|
|
25
25
|
const setup = initializeGlobalSetup();
|
|
26
26
|
|
|
27
27
|
if (setup.hasWorkingSpec) {
|
|
28
|
-
console.log(`Detected ${setup.
|
|
28
|
+
console.log(`Detected ${setup.type} CAWS setup`);
|
|
29
29
|
console.log(` Capabilities: ${setup.capabilities.join(', ')}`);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const specContent = fs.readFileSync(specPath, 'utf8');
|
|
42
|
-
const spec = yaml.load(specContent);
|
|
32
|
+
const resolved = await resolveSpec({
|
|
33
|
+
specId: options.specId,
|
|
34
|
+
specFile: specFile || undefined,
|
|
35
|
+
warnLegacy: false,
|
|
36
|
+
interactive: false,
|
|
37
|
+
});
|
|
38
|
+
const specPath = resolved.path;
|
|
39
|
+
const spec = resolved.spec;
|
|
43
40
|
|
|
44
41
|
console.log(chalk.blue('\nEvaluating CAWS Quality Standards\n'));
|
|
45
42
|
console.log('-'.repeat(60));
|
|
43
|
+
console.log(chalk.gray(`Spec: ${path.relative(process.cwd(), specPath)}`));
|
|
44
|
+
console.log(chalk.gray(`Type: ${resolved.type}`));
|
|
46
45
|
|
|
47
46
|
// Evaluation results
|
|
48
47
|
const results = {
|
|
@@ -203,6 +202,19 @@ async function evaluateCommand(specFile = '.caws/working-spec.yaml', options = {
|
|
|
203
202
|
? 'D'
|
|
204
203
|
: 'F';
|
|
205
204
|
|
|
205
|
+
// Record to working state
|
|
206
|
+
try {
|
|
207
|
+
const checksPassed = results.checks.filter(c => c.status === 'pass').length;
|
|
208
|
+
recordEvaluation(spec.id, {
|
|
209
|
+
score: results.score,
|
|
210
|
+
max_score: results.maxScore,
|
|
211
|
+
percentage,
|
|
212
|
+
grade,
|
|
213
|
+
checks_passed: checksPassed,
|
|
214
|
+
checks_total: results.checks.length,
|
|
215
|
+
});
|
|
216
|
+
} catch { /* non-fatal */ }
|
|
217
|
+
|
|
206
218
|
console.log('\n' + '-'.repeat(60));
|
|
207
219
|
console.log(
|
|
208
220
|
chalk.bold(
|