@paths.design/caws-cli 10.0.1 → 10.1.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.
Files changed (54) hide show
  1. package/README.md +13 -5
  2. package/dist/budget-derivation.js +221 -74
  3. package/dist/commands/evaluate.js +26 -12
  4. package/dist/commands/gates.js +31 -4
  5. package/dist/commands/init.js +7 -4
  6. package/dist/commands/iterate.js +7 -3
  7. package/dist/commands/scope.js +264 -0
  8. package/dist/commands/sidecar.js +6 -3
  9. package/dist/commands/specs.js +148 -1
  10. package/dist/commands/status.js +8 -4
  11. package/dist/commands/templates.js +0 -8
  12. package/dist/commands/validate.js +34 -13
  13. package/dist/commands/verify-acs.js +25 -10
  14. package/dist/commands/waivers.js +147 -5
  15. package/dist/commands/worktree.js +81 -1
  16. package/dist/gates/budget-limit.js +6 -1
  17. package/dist/gates/spec-completeness.js +8 -1
  18. package/dist/index.js +27 -0
  19. package/dist/policy/PolicyManager.js +9 -7
  20. package/dist/session/session-manager.js +34 -0
  21. package/dist/templates/.caws/schemas/policy.schema.json +96 -34
  22. package/dist/templates/.caws/schemas/scope.schema.json +3 -3
  23. package/dist/templates/.caws/schemas/waivers.schema.json +91 -21
  24. package/dist/templates/.caws/schemas/working-spec.schema.json +253 -89
  25. package/dist/templates/.caws/templates/working-spec.template.yml +3 -1
  26. package/dist/templates/.caws/tools/scope-guard.js +66 -15
  27. package/dist/templates/.claude/README.md +1 -1
  28. package/dist/templates/.claude/hooks/protected-paths.sh +39 -0
  29. package/dist/templates/.claude/hooks/scope-guard.sh +106 -27
  30. package/dist/templates/.claude/hooks/worktree-write-guard.sh +96 -3
  31. package/dist/templates/.claude/settings.json +5 -0
  32. package/dist/templates/CLAUDE.md +34 -0
  33. package/dist/templates/agents.md +21 -0
  34. package/dist/utils/event-log.js +584 -0
  35. package/dist/utils/event-renderer.js +521 -0
  36. package/dist/utils/schema-validator.js +10 -2
  37. package/dist/utils/working-state.js +25 -0
  38. package/dist/validation/spec-validation.js +99 -9
  39. package/dist/waivers-manager.js +84 -0
  40. package/dist/worktree/worktree-manager.js +214 -8
  41. package/package.json +5 -4
  42. package/templates/.caws/schemas/policy.schema.json +96 -34
  43. package/templates/.caws/schemas/scope.schema.json +3 -3
  44. package/templates/.caws/schemas/waivers.schema.json +91 -21
  45. package/templates/.caws/schemas/working-spec.schema.json +253 -89
  46. package/templates/.caws/templates/working-spec.template.yml +3 -1
  47. package/templates/.caws/tools/scope-guard.js +66 -15
  48. package/templates/.claude/README.md +1 -1
  49. package/templates/.claude/hooks/protected-paths.sh +39 -0
  50. package/templates/.claude/hooks/scope-guard.sh +106 -27
  51. package/templates/.claude/hooks/worktree-write-guard.sh +96 -3
  52. package/templates/.claude/settings.json +5 -0
  53. package/templates/CLAUDE.md +34 -0
  54. package/templates/agents.md +21 -0
@@ -1,36 +1,106 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "title": "CAWS Waiver",
4
4
  "description": "Individual waiver file created by caws waivers create",
5
5
  "type": "object",
6
- "required": ["id", "title", "reason", "gates", "created_at", "expires_at", "approved_by", "status"],
6
+ "required": ["id", "applies_to", "gates", "delta", "reason_code", "expires_at", "risk_owner", "approvers", "status"],
7
7
  "properties": {
8
- "id": { "type": "string", "pattern": "^WV-\\d{4}$" },
9
- "title": { "type": "string", "minLength": 1 },
10
- "reason": { "type": "string", "minLength": 10 },
11
- "description": { "type": "string" },
8
+ "id": {
9
+ "type": "string",
10
+ "pattern": "^WV-\\d{4}$",
11
+ "description": "Waiver ID in format WV-XXXX"
12
+ },
13
+ "applies_to": {
14
+ "type": "string",
15
+ "description": "Spec ID or PR number this waiver applies to"
16
+ },
12
17
  "gates": {
13
18
  "type": "array",
14
- "items": { "type": "string" },
19
+ "items": {
20
+ "type": "string",
21
+ "enum": ["budget_limit", "spec_completeness", "contract_compliance", "coverage_threshold", "mutation_threshold", "security_scan", "accessibility_check", "performance_budget", "scope_boundary"]
22
+ },
23
+ "minItems": 1,
24
+ "description": "Quality gates to waive"
25
+ },
26
+ "delta": {
27
+ "type": "object",
28
+ "description": "Additive budget deltas (only positive values allowed)",
29
+ "properties": {
30
+ "max_files": {
31
+ "type": "integer",
32
+ "minimum": 0,
33
+ "description": "Additional files allowed"
34
+ },
35
+ "max_loc": {
36
+ "type": "integer",
37
+ "minimum": 0,
38
+ "description": "Additional lines of code allowed"
39
+ }
40
+ },
41
+ "additionalProperties": false
42
+ },
43
+ "reason_code": {
44
+ "type": "string",
45
+ "enum": ["emergency_hotfix", "legacy_integration", "experimental_feature", "third_party_constraint", "performance_critical", "security_patch", "infrastructure_limitation", "architectural_refactor", "other"],
46
+ "description": "Controlled vocabulary for waiver reasons"
47
+ },
48
+ "description": {
49
+ "type": "string",
50
+ "minLength": 50,
51
+ "maxLength": 1000,
52
+ "description": "Detailed explanation of why waiver is needed"
53
+ },
54
+ "mitigation": {
55
+ "type": "string",
56
+ "minLength": 50,
57
+ "description": "Plan to address the underlying issue"
58
+ },
59
+ "expires_at": {
60
+ "type": "string",
61
+ "format": "date-time",
62
+ "description": "ISO 8601 datetime when waiver expires"
63
+ },
64
+ "risk_owner": {
65
+ "type": "string",
66
+ "description": "Person/entity responsible for managing this risk"
67
+ },
68
+ "approvers": {
69
+ "type": "array",
70
+ "items": {
71
+ "type": "object",
72
+ "required": ["handle"],
73
+ "properties": {
74
+ "handle": {
75
+ "type": "string",
76
+ "description": "GitHub handle or email of approver"
77
+ },
78
+ "approved_at": {
79
+ "type": "string",
80
+ "format": "date-time",
81
+ "description": "When this approval was given"
82
+ }
83
+ },
84
+ "additionalProperties": false
85
+ },
15
86
  "minItems": 1,
16
- "description": "Gate names this waiver applies to"
87
+ "description": "List of people who approved this waiver"
17
88
  },
18
- "created_at": { "type": "string" },
19
- "expires_at": { "type": "string" },
20
- "approved_by": { "type": "string" },
21
- "impact_level": { "type": "string" },
22
- "mitigation_plan": { "type": "string" },
23
89
  "status": {
24
90
  "type": "string",
25
- "enum": ["active", "expired", "revoked"],
26
- "default": "active"
91
+ "enum": ["proposed", "active", "expired", "revoked"],
92
+ "description": "Current status of the waiver"
27
93
  },
28
- "created_by_session": { "type": ["string", "null"] },
29
- "compensating_control": { "type": "string" },
30
- "ticket_url": { "type": "string", "format": "uri" },
31
- "revoked_at": { "type": "string" },
32
- "revoked_by": { "type": "string" },
33
- "revocation_reason": { "type": "string" }
94
+ "metadata": {
95
+ "type": "object",
96
+ "properties": {
97
+ "related_pr": { "type": "string" },
98
+ "related_issue": { "type": "string" },
99
+ "environment": { "type": "string", "enum": ["development", "staging", "production"] },
100
+ "urgency": { "type": "string", "enum": ["low", "normal", "high", "critical"] }
101
+ },
102
+ "additionalProperties": false
103
+ }
34
104
  },
35
105
  "additionalProperties": false
36
106
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "title": "CAWS Working Spec",
4
4
  "type": "object",
5
5
  "required": [
@@ -15,79 +15,178 @@
15
15
  "non_functional",
16
16
  "contracts"
17
17
  ],
18
+ "not": {
19
+ "required": [
20
+ "change_budget"
21
+ ]
22
+ },
18
23
  "properties": {
19
- "id": { "type": "string", "pattern": "^[A-Z]{2,6}-\\d{3,4}$" },
20
- "title": { "type": "string", "minLength": 10, "maxLength": 200 },
21
- "type": { "type": "string", "enum": ["feature", "fix", "refactor", "chore", "docs"] },
24
+ "id": {
25
+ "type": "string",
26
+ "pattern": "^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*-\\d+$",
27
+ "description": "Unique identifier for the change. Format: uppercase/digit PREFIX segments separated by dashes, final segment is one+ digits (e.g. CAWSFIX-16, P03-TRUTH-001, ALG-001A-HARDEN-01). Matches SPEC_ID_PATTERN in spec-validation.js (CAWSFIX-21 alignment)."
28
+ },
29
+ "title": {
30
+ "type": "string",
31
+ "minLength": 10,
32
+ "maxLength": 200,
33
+ "description": "Clear, descriptive title"
34
+ },
35
+ "type": {
36
+ "type": "string",
37
+ "enum": [
38
+ "feature",
39
+ "fix",
40
+ "refactor",
41
+ "chore",
42
+ "doc",
43
+ "docs"
44
+ ],
45
+ "description": "Type of work (informational; `mode` is the enforced gate input)"
46
+ },
22
47
  "status": {
23
48
  "type": "string",
24
- "enum": ["draft", "active", "in_progress", "completed", "closed", "archived"]
49
+ "enum": [
50
+ "draft",
51
+ "active",
52
+ "in_progress",
53
+ "completed",
54
+ "closed",
55
+ "archived"
56
+ ]
57
+ },
58
+ "created_at": {
59
+ "type": "string"
60
+ },
61
+ "updated_at": {
62
+ "type": "string"
63
+ },
64
+ "worktree": {
65
+ "type": "string",
66
+ "description": "CAWS worktree name assigned to this spec"
67
+ },
68
+ "risk_tier": {
69
+ "type": [
70
+ "integer",
71
+ "string"
72
+ ],
73
+ "enum": [
74
+ 1,
75
+ 2,
76
+ 3,
77
+ "1",
78
+ "2",
79
+ "3"
80
+ ],
81
+ "description": "Risk level (1=high, 2=medium, 3=low)"
82
+ },
83
+ "mode": {
84
+ "type": "string",
85
+ "enum": [
86
+ "feature",
87
+ "refactor",
88
+ "fix",
89
+ "doc",
90
+ "docs",
91
+ "chore",
92
+ "development"
93
+ ],
94
+ "description": "Mode of change. `development` is the default used by `caws specs create`; feature/refactor/fix/doc/chore are the classic modes the legacy validator accepted."
25
95
  },
26
- "created_at": { "type": "string" },
27
- "updated_at": { "type": "string" },
28
- "risk_tier": { "type": ["integer", "string"], "enum": [1, 2, 3, "1", "2", "3"] },
29
- "mode": { "type": "string", "enum": ["feature", "refactor", "fix", "doc", "docs", "chore", "development"] },
30
96
  "waiver_ids": {
31
97
  "type": "array",
32
- "items": { "type": "string", "pattern": "^WV-\\d{4}$" },
98
+ "items": {
99
+ "type": "string",
100
+ "pattern": "^WV-\\d{4}$"
101
+ },
33
102
  "description": "IDs of active waivers applying to this spec"
34
103
  },
35
104
  "blast_radius": {
36
105
  "type": "object",
37
- "required": ["modules"],
106
+ "required": [
107
+ "modules",
108
+ "data_migration"
109
+ ],
38
110
  "properties": {
39
- "modules": { "type": "array", "items": { "type": "string" } },
40
- "data_migration": { "type": "boolean" }
41
- }
111
+ "modules": {
112
+ "type": "array",
113
+ "items": {
114
+ "type": "string"
115
+ },
116
+ "description": "List of modules/paths the change touches"
117
+ },
118
+ "data_migration": {
119
+ "type": "boolean",
120
+ "description": "Whether the change requires a data migration"
121
+ }
122
+ },
123
+ "additionalProperties": true
124
+ },
125
+ "operational_rollback_slo": {
126
+ "type": "string",
127
+ "minLength": 1,
128
+ "description": "Time target for operational rollback (e.g. '5m', '30m', '1h')"
42
129
  },
43
- "operational_rollback_slo": { "type": "string" },
44
130
  "scope": {
45
131
  "type": "object",
46
- "required": ["in", "out"],
132
+ "required": [
133
+ "in"
134
+ ],
47
135
  "properties": {
48
- "in": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
49
- "out": { "type": "array", "items": { "type": "string" } }
50
- }
136
+ "in": {
137
+ "type": "array",
138
+ "items": {
139
+ "type": "string"
140
+ },
141
+ "minItems": 1,
142
+ "description": "Files/paths allowed to be edited (non-empty)"
143
+ },
144
+ "out": {
145
+ "type": "array",
146
+ "items": {
147
+ "type": "string"
148
+ },
149
+ "description": "Files/paths explicitly excluded from edits"
150
+ }
151
+ },
152
+ "additionalProperties": true
51
153
  },
52
- "invariants": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
53
- "acceptance": {
154
+ "invariants": {
54
155
  "type": "array",
55
- "minItems": 0,
56
156
  "items": {
57
- "type": "object",
58
- "required": ["id", "given", "when", "then"],
59
- "properties": {
60
- "id": { "type": "string", "pattern": "^A\\d+$" },
61
- "given": { "type": "string" },
62
- "when": { "type": "string" },
63
- "then": { "type": "string" }
64
- }
65
- }
157
+ "type": "string"
158
+ },
159
+ "minItems": 1,
160
+ "description": "Properties that must hold across the change (non-empty)"
66
161
  },
67
- "acceptance_criteria": {
162
+ "acceptance": {
68
163
  "type": "array",
69
- "minItems": 0,
164
+ "minItems": 1,
165
+ "description": "Given/When/Then acceptance criteria (non-empty)",
70
166
  "items": {
71
167
  "type": "object",
72
- "required": ["id"],
168
+ "required": [
169
+ "id",
170
+ "given",
171
+ "when",
172
+ "then"
173
+ ],
73
174
  "properties": {
74
- "id": { "type": "string" },
75
- "description": { "type": "string" },
76
- "completed": { "type": "boolean" },
77
- "test": { "type": "string" },
78
- "test_command": { "type": "string" },
79
- "test_nodeids": {
80
- "type": "array",
81
- "items": { "type": "string" }
175
+ "id": {
176
+ "type": "string",
177
+ "minLength": 1
82
178
  },
83
- "evidence": {
84
- "oneOf": [
85
- { "type": "string" },
86
- {
87
- "type": "array",
88
- "items": { "type": "string" }
89
- }
90
- ]
179
+ "given": {
180
+ "type": "string",
181
+ "minLength": 1
182
+ },
183
+ "when": {
184
+ "type": "string",
185
+ "minLength": 1
186
+ },
187
+ "then": {
188
+ "type": "string",
189
+ "minLength": 1
91
190
  }
92
191
  },
93
192
  "additionalProperties": true
@@ -95,82 +194,147 @@
95
194
  },
96
195
  "non_functional": {
97
196
  "type": "object",
197
+ "required": [
198
+ "a11y",
199
+ "perf",
200
+ "security"
201
+ ],
98
202
  "properties": {
99
- "a11y": { "type": "array", "items": { "type": "string" } },
203
+ "a11y": {
204
+ "type": "array",
205
+ "items": {
206
+ "type": "string"
207
+ },
208
+ "description": "Accessibility requirements (may be empty array if not applicable)"
209
+ },
100
210
  "perf": {
101
211
  "type": "object",
102
- "properties": {
103
- "api_p95_ms": { "type": "integer", "minimum": 1 },
104
- "lcp_ms": { "type": "integer", "minimum": 1 }
105
- },
106
- "additionalProperties": false
212
+ "description": "Performance requirements (e.g. api_p95_ms, lcp_ms)"
107
213
  },
108
- "security": { "type": "array", "items": { "type": "string" } }
214
+ "security": {
215
+ "type": "array",
216
+ "items": {
217
+ "type": "string"
218
+ },
219
+ "description": "Security requirements (may be empty array if not applicable)"
220
+ }
109
221
  },
110
- "additionalProperties": false
222
+ "additionalProperties": true
111
223
  },
112
224
  "contracts": {
113
225
  "type": "array",
226
+ "description": "API contracts. Empty array is permitted; CAWSFIX-06 will warn (not fail) when mode=feature with empty contracts.",
114
227
  "items": {
115
228
  "type": "object",
116
- "required": ["type", "path"],
229
+ "required": [
230
+ "type",
231
+ "path"
232
+ ],
117
233
  "properties": {
118
- "type": { "type": "string", "enum": ["openapi", "graphql", "proto", "pact", "project_setup"] },
119
- "path": { "type": "string" },
120
- "description": { "type": "string" },
121
- "version": { "type": "string" }
122
- }
234
+ "type": {
235
+ "type": "string",
236
+ "enum": [
237
+ "openapi",
238
+ "graphql",
239
+ "proto",
240
+ "pact",
241
+ "project_setup"
242
+ ]
243
+ },
244
+ "path": {
245
+ "type": "string"
246
+ },
247
+ "description": {
248
+ "type": "string"
249
+ },
250
+ "version": {
251
+ "type": "string"
252
+ }
253
+ },
254
+ "additionalProperties": true
123
255
  }
124
256
  },
125
257
  "observability": {
126
- "type": "object",
127
- "properties": {
128
- "logs": { "type": "array", "items": { "type": "string" } },
129
- "metrics": { "type": "array", "items": { "type": "string" } },
130
- "traces": { "type": "array", "items": { "type": "string" } }
258
+ "type": "object"
259
+ },
260
+ "migrations": {
261
+ "type": "array",
262
+ "items": {
263
+ "type": "string"
264
+ }
265
+ },
266
+ "rollback": {
267
+ "type": "array",
268
+ "items": {
269
+ "type": "string"
131
270
  }
132
271
  },
133
- "migrations": { "type": "array", "items": { "type": "string" } },
134
- "rollback": { "type": "array", "items": { "type": "string" } },
135
272
  "experimental_mode": {
136
273
  "type": "object",
137
- "description": "Enables experimental mode with reduced requirements",
138
- "required": ["enabled", "rationale", "expires_at"],
274
+ "required": [
275
+ "enabled",
276
+ "rationale",
277
+ "expires_at"
278
+ ],
139
279
  "properties": {
140
- "enabled": { "type": "boolean" },
141
- "rationale": { "type": "string" },
142
- "expires_at": { "type": "string" }
280
+ "enabled": {
281
+ "type": "boolean"
282
+ },
283
+ "rationale": {
284
+ "type": "string"
285
+ },
286
+ "expires_at": {
287
+ "type": "string"
288
+ }
143
289
  }
144
290
  },
145
291
  "timeboxed_hours": {
146
292
  "type": "integer",
147
- "minimum": 1,
148
- "description": "Time limit for experimental features in hours"
293
+ "minimum": 1
149
294
  },
150
295
  "human_override": {
151
296
  "type": "object",
297
+ "required": [
298
+ "approved_by",
299
+ "reason"
300
+ ],
152
301
  "properties": {
153
- "approved_by": { "type": "string" },
154
- "reason": { "type": "string" },
302
+ "approved_by": {
303
+ "type": "string"
304
+ },
305
+ "reason": {
306
+ "type": "string"
307
+ },
155
308
  "waived_requirements": {
156
309
  "type": "array",
157
310
  "items": {
158
- "type": "string",
159
- "enum": ["mutation_testing", "contract_tests", "coverage", "manual_review"]
311
+ "type": "string"
160
312
  }
161
313
  },
162
- "expiry_date": { "type": "string", "format": "date-time" }
163
- },
164
- "required": ["approved_by", "reason"]
314
+ "expiry_date": {
315
+ "type": "string"
316
+ }
317
+ }
165
318
  },
166
319
  "ai_assessment": {
167
320
  "type": "object",
168
321
  "properties": {
169
- "confidence_level": { "type": "integer", "minimum": 1, "maximum": 10 },
170
- "uncertainty_areas": { "type": "array", "items": { "type": "string" } },
171
- "recommended_pairing": { "type": "boolean" }
322
+ "confidence_level": {
323
+ "type": "integer",
324
+ "minimum": 1,
325
+ "maximum": 10
326
+ },
327
+ "uncertainty_areas": {
328
+ "type": "array",
329
+ "items": {
330
+ "type": "string"
331
+ }
332
+ },
333
+ "recommended_pairing": {
334
+ "type": "boolean"
335
+ }
172
336
  }
173
337
  }
174
338
  },
175
- "additionalProperties": false
339
+ "additionalProperties": true
176
340
  }
@@ -1,9 +1,12 @@
1
1
  id: '{{FEATURE_ID}}'
2
2
  title: '{{FEATURE_TITLE}}'
3
+ # Recommended when the spec belongs to a CAWS worktree:
4
+ # worktree: '{{WORKTREE_NAME}}'
3
5
  risk_tier: {{TIER}}
4
6
  mode: feature
5
7
  blast_radius:
6
8
  modules: []
9
+ data_migration: false
7
10
  operational_rollback_slo: "30m"
8
11
  scope:
9
12
  in:
@@ -75,4 +78,3 @@ rollback:
75
78
  # reason: "Urgent production fix - bypassing mutation tests for immediate deployment"
76
79
  # waived_requirements: ["mutation_testing", "manual_review"]
77
80
  # expiry_date: "2025-10-01T00:00:00Z"
78
-