@paths.design/caws-cli 8.2.0 โ 8.2.3
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/dist/budget-derivation.js +10 -10
- package/dist/commands/archive.js +22 -22
- package/dist/commands/burnup.js +7 -7
- package/dist/commands/diagnose.js +25 -25
- package/dist/commands/evaluate.js +20 -20
- package/dist/commands/init.js +71 -72
- package/dist/commands/iterate.js +21 -21
- package/dist/commands/mode.js +11 -11
- package/dist/commands/plan.js +5 -5
- package/dist/commands/provenance.js +86 -86
- package/dist/commands/quality-gates.js +4 -4
- package/dist/commands/quality-monitor.js +17 -17
- package/dist/commands/session.js +312 -0
- package/dist/commands/specs.js +44 -44
- package/dist/commands/status.js +43 -43
- package/dist/commands/templates.js +14 -14
- package/dist/commands/tool.js +1 -1
- package/dist/commands/troubleshoot.js +11 -11
- package/dist/commands/tutorial.js +119 -119
- package/dist/commands/validate.js +6 -6
- package/dist/commands/waivers.js +93 -60
- package/dist/commands/workflow.js +17 -17
- package/dist/commands/worktree.js +13 -13
- package/dist/config/index.js +5 -5
- package/dist/config/modes.js +7 -7
- package/dist/constants/spec-types.js +5 -5
- package/dist/error-handler.js +4 -4
- package/dist/generators/jest-config-generator.js +3 -3
- package/dist/generators/working-spec.js +4 -4
- package/dist/index.js +79 -27
- package/dist/minimal-cli.js +9 -9
- package/dist/policy/PolicyManager.js +1 -1
- package/dist/scaffold/claude-hooks.js +7 -7
- package/dist/scaffold/cursor-hooks.js +8 -8
- package/dist/scaffold/git-hooks.js +152 -152
- package/dist/scaffold/index.js +48 -48
- package/dist/session/session-manager.js +548 -0
- package/dist/test-analysis.js +20 -20
- package/dist/utils/command-wrapper.js +8 -8
- package/dist/utils/detection.js +7 -7
- package/dist/utils/finalization.js +21 -21
- package/dist/utils/git-lock.js +3 -3
- package/dist/utils/gitignore-updater.js +1 -1
- package/dist/utils/project-analysis.js +7 -7
- package/dist/utils/quality-gates-utils.js +35 -35
- package/dist/utils/spec-resolver.js +8 -8
- package/dist/utils/typescript-detector.js +5 -5
- package/dist/utils/yaml-validation.js +1 -1
- package/dist/validation/spec-validation.js +4 -4
- package/dist/worktree/worktree-manager.js +11 -5
- package/package.json +1 -1
package/dist/commands/waivers.js
CHANGED
|
@@ -18,6 +18,24 @@ const { commandWrapper, Output } = require('../utils/command-wrapper');
|
|
|
18
18
|
|
|
19
19
|
const WAIVER_DIR = '.caws/waivers';
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Valid gate identifiers recognized by the quality-gates package.
|
|
23
|
+
* These must match the gate names used in processViolations() calls
|
|
24
|
+
* within the check-*.mjs files.
|
|
25
|
+
*/
|
|
26
|
+
const VALID_GATES = [
|
|
27
|
+
'naming',
|
|
28
|
+
'code_freeze',
|
|
29
|
+
'duplication',
|
|
30
|
+
'duplication_gate',
|
|
31
|
+
'god_objects',
|
|
32
|
+
'placeholders',
|
|
33
|
+
'simplification',
|
|
34
|
+
'hidden-todo',
|
|
35
|
+
'documentation',
|
|
36
|
+
'*',
|
|
37
|
+
];
|
|
38
|
+
|
|
21
39
|
/**
|
|
22
40
|
* Waivers command handler
|
|
23
41
|
*
|
|
@@ -69,44 +87,61 @@ async function waiversCommand(subcommand = 'list', options = {}) {
|
|
|
69
87
|
* Create a new waiver
|
|
70
88
|
*/
|
|
71
89
|
async function createWaiver(options) {
|
|
72
|
-
// Validate required fields
|
|
90
|
+
// Validate all required fields upfront (report all missing at once)
|
|
73
91
|
const required = [
|
|
74
|
-
'title',
|
|
75
|
-
'reason',
|
|
76
|
-
'description',
|
|
77
|
-
'gates',
|
|
78
|
-
'expiresAt',
|
|
79
|
-
'approvedBy',
|
|
80
|
-
'impactLevel',
|
|
81
|
-
'mitigationPlan',
|
|
92
|
+
{ field: 'title', flag: '--title', example: '"Emergency hotfix waiver"' },
|
|
93
|
+
{ field: 'reason', flag: '--reason', example: 'emergency_hotfix' },
|
|
94
|
+
{ field: 'description', flag: '--description', example: '"Critical production bug requires immediate fix"' },
|
|
95
|
+
{ field: 'gates', flag: '--gates', example: `placeholders,naming (valid: ${VALID_GATES.join(', ')})` },
|
|
96
|
+
{ field: 'expiresAt', flag: '--expires-at', example: '2025-12-31T23:59:59Z' },
|
|
97
|
+
{ field: 'approvedBy', flag: '--approved-by', example: '"@manager"' },
|
|
98
|
+
{ field: 'impactLevel', flag: '--impact-level', example: 'high' },
|
|
99
|
+
{ field: 'mitigationPlan', flag: '--mitigation-plan', example: '"Will add tests in follow-up PR within 48h"' },
|
|
82
100
|
];
|
|
83
|
-
const missing = required.filter((
|
|
101
|
+
const missing = required.filter((r) => !options[r.field]);
|
|
84
102
|
|
|
85
103
|
if (missing.length > 0) {
|
|
86
|
-
console.error(chalk.red(`\
|
|
87
|
-
|
|
104
|
+
console.error(chalk.red(`\nMissing ${missing.length} required option(s):\n`));
|
|
105
|
+
missing.forEach((r) => {
|
|
106
|
+
console.error(` ${chalk.yellow(r.flag)} e.g. ${r.example}`);
|
|
107
|
+
});
|
|
108
|
+
console.log(chalk.dim('\nFull example:'));
|
|
88
109
|
console.log(' caws waivers create \\');
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
console.log(' --expires-at=2025-12-31T23:59:59Z \\');
|
|
94
|
-
console.log(' --approved-by="@manager" \\');
|
|
95
|
-
console.log(' --impact-level=high \\');
|
|
96
|
-
console.log(' --mitigation-plan="Will add tests in follow-up PR within 48h"');
|
|
110
|
+
required.forEach((r, i) => {
|
|
111
|
+
const sep = i < required.length - 1 ? ' \\' : '';
|
|
112
|
+
console.log(` ${r.flag}=${r.example}${sep}`);
|
|
113
|
+
});
|
|
97
114
|
process.exit(1);
|
|
98
115
|
}
|
|
99
116
|
|
|
100
|
-
// Generate waiver ID
|
|
101
|
-
const waiverId = `WV-${Date.now().toString().slice(-4)}`;
|
|
102
|
-
const timestamp = new Date().toISOString();
|
|
103
|
-
|
|
104
117
|
// Parse gates
|
|
105
118
|
const gates =
|
|
106
119
|
typeof options.gates === 'string'
|
|
107
120
|
? options.gates.split(',').map((g) => g.trim())
|
|
108
121
|
: options.gates;
|
|
109
122
|
|
|
123
|
+
// Validate gate names against known identifiers
|
|
124
|
+
const invalidGates = gates.filter((g) => !VALID_GATES.includes(g));
|
|
125
|
+
if (invalidGates.length > 0) {
|
|
126
|
+
console.error(chalk.red(`\nUnrecognized gate name(s): ${invalidGates.join(', ')}`));
|
|
127
|
+
console.log(`\nValid gate names: ${VALID_GATES.join(', ')}`);
|
|
128
|
+
|
|
129
|
+
// Suggest close matches
|
|
130
|
+
invalidGates.forEach((bad) => {
|
|
131
|
+
const suggestion = VALID_GATES.find(
|
|
132
|
+
(v) => v !== '*' && (v.includes(bad) || bad.includes(v))
|
|
133
|
+
);
|
|
134
|
+
if (suggestion) {
|
|
135
|
+
console.log(chalk.yellow(` "${bad}" -> did you mean "${suggestion}"?`));
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Generate waiver ID
|
|
142
|
+
const waiverId = `WV-${Date.now().toString().slice(-4)}`;
|
|
143
|
+
const timestamp = new Date().toISOString();
|
|
144
|
+
|
|
110
145
|
// Create waiver object
|
|
111
146
|
const waiver = {
|
|
112
147
|
id: waiverId,
|
|
@@ -134,15 +169,15 @@ async function createWaiver(options) {
|
|
|
134
169
|
console.error(error.stack);
|
|
135
170
|
}
|
|
136
171
|
|
|
137
|
-
console.log(chalk.green(`\
|
|
172
|
+
console.log(chalk.green(`\nWaiver created: ${waiverId}`));
|
|
138
173
|
console.log(` Title: ${waiver.title}`);
|
|
139
174
|
console.log(` Reason: ${waiver.reason}`);
|
|
140
175
|
console.log(` Gates: ${waiver.gates.join(', ')}`);
|
|
141
176
|
console.log(` Expires: ${waiver.expires_at}`);
|
|
142
177
|
console.log(` Approved by: ${waiver.approved_by}`);
|
|
143
178
|
console.log(` Impact: ${waiver.impact_level}`);
|
|
144
|
-
console.log(chalk.yellow(`\n
|
|
145
|
-
console.log(chalk.yellow(
|
|
179
|
+
console.log(chalk.yellow(`\n Note: This waiver expires on ${waiver.expires_at}`));
|
|
180
|
+
console.log(chalk.yellow(` Mitigation plan: ${waiver.mitigation_plan}\n`));
|
|
146
181
|
}
|
|
147
182
|
|
|
148
183
|
/**
|
|
@@ -152,14 +187,14 @@ async function listWaivers(_options) {
|
|
|
152
187
|
const waiversDir = path.join(process.cwd(), WAIVER_DIR);
|
|
153
188
|
|
|
154
189
|
if (!fs.existsSync(waiversDir)) {
|
|
155
|
-
console.log(chalk.yellow('\
|
|
190
|
+
console.log(chalk.yellow('\nNo waivers found.\n'));
|
|
156
191
|
return;
|
|
157
192
|
}
|
|
158
193
|
|
|
159
194
|
const waiverFiles = fs.readdirSync(waiversDir).filter((f) => f.endsWith('.yaml'));
|
|
160
195
|
|
|
161
196
|
if (waiverFiles.length === 0) {
|
|
162
|
-
console.log(chalk.yellow('\
|
|
197
|
+
console.log(chalk.yellow('\nNo waivers found.\n'));
|
|
163
198
|
return;
|
|
164
199
|
}
|
|
165
200
|
|
|
@@ -177,16 +212,16 @@ async function listWaivers(_options) {
|
|
|
177
212
|
);
|
|
178
213
|
const revokedWaivers = waivers.filter((w) => w.status === 'revoked');
|
|
179
214
|
|
|
180
|
-
console.log(chalk.blue('\
|
|
181
|
-
console.log('
|
|
215
|
+
console.log(chalk.blue('\nCAWS Quality Gate Waivers\n'));
|
|
216
|
+
console.log('-'.repeat(60));
|
|
182
217
|
|
|
183
218
|
if (activeWaivers.length > 0) {
|
|
184
|
-
console.log(chalk.green('\
|
|
219
|
+
console.log(chalk.green('\nActive Waivers:\n'));
|
|
185
220
|
activeWaivers.forEach((waiver) => {
|
|
186
221
|
const daysLeft = Math.ceil(
|
|
187
222
|
(new Date(waiver.expires_at) - new Date()) / (1000 * 60 * 60 * 24)
|
|
188
223
|
);
|
|
189
|
-
console.log(
|
|
224
|
+
console.log(` ${chalk.bold(waiver.id)}: ${waiver.title}`);
|
|
190
225
|
console.log(` Reason: ${waiver.reason}`);
|
|
191
226
|
console.log(` Gates: ${waiver.gates.join(', ')}`);
|
|
192
227
|
console.log(` Expires: ${waiver.expires_at} (${daysLeft} days)`);
|
|
@@ -196,24 +231,24 @@ async function listWaivers(_options) {
|
|
|
196
231
|
}
|
|
197
232
|
|
|
198
233
|
if (expiredWaivers.length > 0) {
|
|
199
|
-
console.log(chalk.yellow('\
|
|
234
|
+
console.log(chalk.yellow('\nExpired Waivers:\n'));
|
|
200
235
|
expiredWaivers.forEach((waiver) => {
|
|
201
|
-
console.log(
|
|
236
|
+
console.log(` ${chalk.bold(waiver.id)}: ${waiver.title}`);
|
|
202
237
|
console.log(` Expired: ${waiver.expires_at}`);
|
|
203
238
|
console.log();
|
|
204
239
|
});
|
|
205
240
|
}
|
|
206
241
|
|
|
207
242
|
if (revokedWaivers.length > 0) {
|
|
208
|
-
console.log(chalk.red('\
|
|
243
|
+
console.log(chalk.red('\nRevoked Waivers:\n'));
|
|
209
244
|
revokedWaivers.forEach((waiver) => {
|
|
210
|
-
console.log(
|
|
245
|
+
console.log(` ${chalk.bold(waiver.id)}: ${waiver.title}`);
|
|
211
246
|
console.log(` Revoked: ${waiver.revoked_at}`);
|
|
212
247
|
console.log();
|
|
213
248
|
});
|
|
214
249
|
}
|
|
215
250
|
|
|
216
|
-
console.log(chalk.blue('
|
|
251
|
+
console.log(chalk.blue('Summary:\n'));
|
|
217
252
|
console.log(` Active: ${activeWaivers.length}`);
|
|
218
253
|
console.log(` Expired: ${expiredWaivers.length}`);
|
|
219
254
|
console.log(` Revoked: ${revokedWaivers.length}`);
|
|
@@ -225,15 +260,15 @@ async function listWaivers(_options) {
|
|
|
225
260
|
*/
|
|
226
261
|
async function showWaiver(waiverId, _options) {
|
|
227
262
|
if (!waiverId) {
|
|
228
|
-
console.error(chalk.red('\
|
|
229
|
-
console.log(chalk.yellow('
|
|
263
|
+
console.error(chalk.red('\nWaiver ID required'));
|
|
264
|
+
console.log(chalk.yellow('Usage: caws waivers show WV-1234\n'));
|
|
230
265
|
process.exit(1);
|
|
231
266
|
}
|
|
232
267
|
|
|
233
268
|
const waiverPath = path.join(process.cwd(), WAIVER_DIR, `${waiverId}.yaml`);
|
|
234
269
|
|
|
235
270
|
if (!fs.existsSync(waiverPath)) {
|
|
236
|
-
console.error(chalk.red(`\
|
|
271
|
+
console.error(chalk.red(`\nWaiver not found: ${waiverId}\n`));
|
|
237
272
|
process.exit(1);
|
|
238
273
|
}
|
|
239
274
|
|
|
@@ -242,35 +277,33 @@ async function showWaiver(waiverId, _options) {
|
|
|
242
277
|
|
|
243
278
|
const isExpired = new Date(waiver.expires_at) <= new Date();
|
|
244
279
|
const isActive = waiver.status === 'active' && !isExpired;
|
|
245
|
-
const
|
|
280
|
+
const statusLabel = isActive ? chalk.green('Active') : isExpired ? chalk.yellow('Expired') : chalk.red(waiver.status);
|
|
246
281
|
|
|
247
|
-
console.log(chalk.blue('\
|
|
248
|
-
console.log('
|
|
249
|
-
console.log(
|
|
250
|
-
|
|
251
|
-
);
|
|
252
|
-
console.log(`\n๐ ${chalk.bold(waiver.title)}`);
|
|
282
|
+
console.log(chalk.blue('\nWaiver Details\n'));
|
|
283
|
+
console.log('-'.repeat(60));
|
|
284
|
+
console.log(`\nStatus: ${statusLabel}`);
|
|
285
|
+
console.log(`\n${chalk.bold(waiver.title)}`);
|
|
253
286
|
console.log(` ID: ${waiver.id}`);
|
|
254
287
|
console.log(` Reason: ${waiver.reason}`);
|
|
255
288
|
console.log(` Impact Level: ${waiver.impact_level}`);
|
|
256
|
-
console.log(`\
|
|
289
|
+
console.log(`\nDescription:`);
|
|
257
290
|
console.log(` ${waiver.description}`);
|
|
258
|
-
console.log(`\
|
|
291
|
+
console.log(`\nWaived Quality Gates:`);
|
|
259
292
|
waiver.gates.forEach((gate) => {
|
|
260
|
-
console.log(`
|
|
293
|
+
console.log(` - ${gate}`);
|
|
261
294
|
});
|
|
262
|
-
console.log(`\
|
|
295
|
+
console.log(`\nMitigation Plan:`);
|
|
263
296
|
console.log(` ${waiver.mitigation_plan}`);
|
|
264
|
-
console.log(`\
|
|
297
|
+
console.log(`\nTimeline:`);
|
|
265
298
|
console.log(` Created: ${waiver.created_at}`);
|
|
266
299
|
console.log(` Expires: ${waiver.expires_at}`);
|
|
267
300
|
if (waiver.revoked_at) {
|
|
268
301
|
console.log(` Revoked: ${waiver.revoked_at}`);
|
|
269
302
|
}
|
|
270
|
-
console.log(`\
|
|
303
|
+
console.log(`\nApproved by: ${waiver.approved_by}\n`);
|
|
271
304
|
|
|
272
305
|
if (isExpired && waiver.status === 'active') {
|
|
273
|
-
console.log(chalk.yellow('
|
|
306
|
+
console.log(chalk.yellow('Warning: This waiver has expired. Consider revoking it.\n'));
|
|
274
307
|
}
|
|
275
308
|
}
|
|
276
309
|
|
|
@@ -279,15 +312,15 @@ async function showWaiver(waiverId, _options) {
|
|
|
279
312
|
*/
|
|
280
313
|
async function revokeWaiver(waiverId, options) {
|
|
281
314
|
if (!waiverId) {
|
|
282
|
-
console.error(chalk.red('\
|
|
283
|
-
console.log(chalk.yellow('
|
|
315
|
+
console.error(chalk.red('\nWaiver ID required'));
|
|
316
|
+
console.log(chalk.yellow('Usage: caws waivers revoke WV-1234\n'));
|
|
284
317
|
process.exit(1);
|
|
285
318
|
}
|
|
286
319
|
|
|
287
320
|
const waiverPath = path.join(process.cwd(), WAIVER_DIR, `${waiverId}.yaml`);
|
|
288
321
|
|
|
289
322
|
if (!fs.existsSync(waiverPath)) {
|
|
290
|
-
console.error(chalk.red(`\
|
|
323
|
+
console.error(chalk.red(`\nWaiver not found: ${waiverId}\n`));
|
|
291
324
|
process.exit(1);
|
|
292
325
|
}
|
|
293
326
|
|
|
@@ -295,7 +328,7 @@ async function revokeWaiver(waiverId, options) {
|
|
|
295
328
|
const waiver = yaml.load(content);
|
|
296
329
|
|
|
297
330
|
if (waiver.status === 'revoked') {
|
|
298
|
-
console.log(chalk.yellow(`\
|
|
331
|
+
console.log(chalk.yellow(`\nWaiver ${waiverId} is already revoked\n`));
|
|
299
332
|
return;
|
|
300
333
|
}
|
|
301
334
|
|
|
@@ -308,7 +341,7 @@ async function revokeWaiver(waiverId, options) {
|
|
|
308
341
|
// Save updated waiver
|
|
309
342
|
fs.writeFileSync(waiverPath, yaml.dump(waiver, { lineWidth: -1 }));
|
|
310
343
|
|
|
311
|
-
console.log(chalk.green(`\
|
|
344
|
+
console.log(chalk.green(`\nWaiver revoked: ${waiverId}`));
|
|
312
345
|
console.log(` Title: ${waiver.title}`);
|
|
313
346
|
console.log(` Revoked at: ${waiver.revoked_at}`);
|
|
314
347
|
console.log(` Revoked by: ${waiver.revoked_by}`);
|
|
@@ -156,7 +156,7 @@ async function workflowCommand(workflowType, options = {}) {
|
|
|
156
156
|
? JSON.parse(options.currentState)
|
|
157
157
|
: options.currentState;
|
|
158
158
|
} catch (e) {
|
|
159
|
-
console.warn(chalk.yellow('
|
|
159
|
+
console.warn(chalk.yellow('Invalid context JSON, ignoring'));
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
|
|
@@ -165,22 +165,22 @@ async function workflowCommand(workflowType, options = {}) {
|
|
|
165
165
|
|
|
166
166
|
// Handle errors
|
|
167
167
|
if (guidance.error) {
|
|
168
|
-
console.error(chalk.red(`\n
|
|
168
|
+
console.error(chalk.red(`\n${guidance.error}`));
|
|
169
169
|
if (guidance.available_types) {
|
|
170
|
-
console.log(chalk.blue('\
|
|
170
|
+
console.log(chalk.blue('\nAvailable workflow types:'));
|
|
171
171
|
guidance.available_types.forEach((type) => {
|
|
172
|
-
console.log(chalk.blue(`
|
|
172
|
+
console.log(chalk.blue(` - ${type}`));
|
|
173
173
|
});
|
|
174
174
|
}
|
|
175
175
|
if (guidance.total_steps) {
|
|
176
|
-
console.log(chalk.blue(`\
|
|
176
|
+
console.log(chalk.blue(`\nValid steps: 1-${guidance.total_steps}`));
|
|
177
177
|
}
|
|
178
178
|
process.exit(1);
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
// Display guidance
|
|
182
|
-
console.log(chalk.bold('\
|
|
183
|
-
console.log('
|
|
182
|
+
console.log(chalk.bold('\nCAWS Workflow Guidance\n'));
|
|
183
|
+
console.log('-'.repeat(60));
|
|
184
184
|
console.log(chalk.bold(`\nWorkflow: ${guidance.workflow_name} (${guidance.workflow_type})`));
|
|
185
185
|
console.log(
|
|
186
186
|
chalk.bold(
|
|
@@ -192,33 +192,33 @@ async function workflowCommand(workflowType, options = {}) {
|
|
|
192
192
|
console.log(chalk.gray(`\nContext: ${guidance.context}`));
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
console.log(chalk.bold('\
|
|
195
|
+
console.log(chalk.bold('\nGuidance:\n'));
|
|
196
196
|
console.log(` ${guidance.guidance}`);
|
|
197
197
|
|
|
198
|
-
console.log(chalk.bold('\
|
|
198
|
+
console.log(chalk.bold('\nCAWS Recommendations:\n'));
|
|
199
199
|
guidance.caws_recommendations.forEach((rec) => {
|
|
200
|
-
console.log(chalk.blue(`
|
|
200
|
+
console.log(chalk.blue(` - ${rec}`));
|
|
201
201
|
});
|
|
202
202
|
|
|
203
203
|
// Show next step if available
|
|
204
204
|
if (guidance.next_step) {
|
|
205
|
-
console.log(chalk.bold('\
|
|
205
|
+
console.log(chalk.bold('\nNext Step:\n'));
|
|
206
206
|
console.log(chalk.gray(` Step ${guidance.next_step}: ${guidance.next_step_description}`));
|
|
207
207
|
console.log(
|
|
208
208
|
chalk.gray(`\n Run: caws workflow ${workflowType} --step ${guidance.next_step}`)
|
|
209
209
|
);
|
|
210
210
|
} else {
|
|
211
|
-
console.log(chalk.bold('\
|
|
211
|
+
console.log(chalk.bold('\nWorkflow Complete!\n'));
|
|
212
212
|
console.log(chalk.green(' All steps in this workflow have been completed.'));
|
|
213
|
-
console.log(chalk.blue('\n
|
|
213
|
+
console.log(chalk.blue('\n Run: caws evaluate to check final quality'));
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
// Show all steps for reference
|
|
217
|
-
console.log(chalk.bold('\
|
|
217
|
+
console.log(chalk.bold('\nAll Steps:\n'));
|
|
218
218
|
guidance.all_steps.forEach((stepDesc, idx) => {
|
|
219
219
|
const stepNum = idx + 1;
|
|
220
220
|
const icon =
|
|
221
|
-
stepNum === guidance.current_step ? '
|
|
221
|
+
stepNum === guidance.current_step ? '' : stepNum < guidance.current_step ? '' : '';
|
|
222
222
|
const color =
|
|
223
223
|
stepNum === guidance.current_step
|
|
224
224
|
? chalk.bold
|
|
@@ -228,9 +228,9 @@ async function workflowCommand(workflowType, options = {}) {
|
|
|
228
228
|
console.log(color(` ${icon}${stepNum}. ${stepDesc}`));
|
|
229
229
|
});
|
|
230
230
|
|
|
231
|
-
console.log('\n' + '
|
|
231
|
+
console.log('\n' + '-'.repeat(60) + '\n');
|
|
232
232
|
} catch (error) {
|
|
233
|
-
console.error(chalk.red(`\
|
|
233
|
+
console.error(chalk.red(`\nWorkflow guidance failed: ${error.message}`));
|
|
234
234
|
console.error(chalk.gray(error.stack));
|
|
235
235
|
process.exit(1);
|
|
236
236
|
}
|
|
@@ -34,7 +34,7 @@ async function worktreeCommand(subcommand, options = {}) {
|
|
|
34
34
|
process.exit(1);
|
|
35
35
|
}
|
|
36
36
|
} catch (error) {
|
|
37
|
-
console.error(chalk.red(
|
|
37
|
+
console.error(chalk.red(`${error.message}`));
|
|
38
38
|
process.exit(1);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -43,21 +43,21 @@ function handleCreate(options) {
|
|
|
43
43
|
const { name, scope, baseBranch, specId } = options;
|
|
44
44
|
|
|
45
45
|
if (!name) {
|
|
46
|
-
console.error(chalk.red('
|
|
46
|
+
console.error(chalk.red('Worktree name is required'));
|
|
47
47
|
console.log(chalk.blue('Usage: caws worktree create <name> [--scope "src/auth/**"]'));
|
|
48
48
|
process.exit(1);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
console.log(chalk.cyan(
|
|
51
|
+
console.log(chalk.cyan(`Creating worktree: ${name}`));
|
|
52
52
|
|
|
53
53
|
const entry = createWorktree(name, { scope, baseBranch, specId });
|
|
54
54
|
|
|
55
|
-
console.log(chalk.green(
|
|
55
|
+
console.log(chalk.green(`Worktree created`));
|
|
56
56
|
console.log(chalk.gray(` Path: ${entry.path}`));
|
|
57
57
|
console.log(chalk.gray(` Branch: ${entry.branch}`));
|
|
58
58
|
if (entry.scope) console.log(chalk.gray(` Scope: ${entry.scope}`));
|
|
59
59
|
if (entry.specId) console.log(chalk.gray(` Spec: ${entry.specId}`));
|
|
60
|
-
console.log(chalk.blue(`\
|
|
60
|
+
console.log(chalk.blue(`\ncd ${entry.path} to start working in the isolated worktree`));
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
function handleList() {
|
|
@@ -69,8 +69,8 @@ function handleList() {
|
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
console.log(chalk.bold.cyan('
|
|
73
|
-
console.log(chalk.cyan('
|
|
72
|
+
console.log(chalk.bold.cyan('CAWS Worktrees'));
|
|
73
|
+
console.log(chalk.cyan('='.repeat(70)));
|
|
74
74
|
console.log(
|
|
75
75
|
chalk.bold(
|
|
76
76
|
'Name'.padEnd(20) +
|
|
@@ -79,7 +79,7 @@ function handleList() {
|
|
|
79
79
|
'Scope'
|
|
80
80
|
)
|
|
81
81
|
);
|
|
82
|
-
console.log(chalk.gray('
|
|
82
|
+
console.log(chalk.gray('-'.repeat(70)));
|
|
83
83
|
|
|
84
84
|
for (const entry of entries) {
|
|
85
85
|
const statusColor =
|
|
@@ -104,14 +104,14 @@ function handleDestroy(options) {
|
|
|
104
104
|
const { name, deleteBranch, force } = options;
|
|
105
105
|
|
|
106
106
|
if (!name) {
|
|
107
|
-
console.error(chalk.red('
|
|
107
|
+
console.error(chalk.red('Worktree name is required'));
|
|
108
108
|
console.log(chalk.blue('Usage: caws worktree destroy <name> [--delete-branch] [--force]'));
|
|
109
109
|
process.exit(1);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
console.log(chalk.cyan(
|
|
112
|
+
console.log(chalk.cyan(`Destroying worktree: ${name}`));
|
|
113
113
|
destroyWorktree(name, { deleteBranch, force });
|
|
114
|
-
console.log(chalk.green(
|
|
114
|
+
console.log(chalk.green(`Worktree '${name}' destroyed`));
|
|
115
115
|
if (deleteBranch) {
|
|
116
116
|
console.log(chalk.gray(' Branch also deleted'));
|
|
117
117
|
}
|
|
@@ -120,13 +120,13 @@ function handleDestroy(options) {
|
|
|
120
120
|
function handlePrune(options) {
|
|
121
121
|
const maxAge = options.maxAge !== undefined ? parseInt(options.maxAge, 10) : 30;
|
|
122
122
|
|
|
123
|
-
console.log(chalk.cyan(
|
|
123
|
+
console.log(chalk.cyan(`Pruning worktrees (max age: ${maxAge} days)`));
|
|
124
124
|
const pruned = pruneWorktrees({ maxAgeDays: maxAge });
|
|
125
125
|
|
|
126
126
|
if (pruned.length === 0) {
|
|
127
127
|
console.log(chalk.gray('Nothing to prune.'));
|
|
128
128
|
} else {
|
|
129
|
-
console.log(chalk.green(
|
|
129
|
+
console.log(chalk.green(`Pruned ${pruned.length} worktree(s):`));
|
|
130
130
|
for (const entry of pruned) {
|
|
131
131
|
console.log(chalk.gray(` - ${entry.name} (created ${entry.createdAt})`));
|
|
132
132
|
}
|
package/dist/config/index.js
CHANGED
|
@@ -28,7 +28,7 @@ function initializeGlobalSetup() {
|
|
|
28
28
|
try {
|
|
29
29
|
cawsSetup = detectCAWSSetup();
|
|
30
30
|
} catch (error) {
|
|
31
|
-
console.warn(chalk.yellow('
|
|
31
|
+
console.warn(chalk.yellow('Failed to detect CAWS setup:'), error.message);
|
|
32
32
|
cawsSetup = {
|
|
33
33
|
type: 'unknown',
|
|
34
34
|
hasCAWSDir: false,
|
|
@@ -119,7 +119,7 @@ function initializeLanguageSupport() {
|
|
|
119
119
|
languageSupport = require(testPath);
|
|
120
120
|
// Only log if not running version command
|
|
121
121
|
if (!process.argv.includes('--version') && !process.argv.includes('-V')) {
|
|
122
|
-
console.log(
|
|
122
|
+
console.log(`Loaded language support from: ${testPath}`);
|
|
123
123
|
}
|
|
124
124
|
break;
|
|
125
125
|
} catch (pathError) {
|
|
@@ -127,10 +127,10 @@ function initializeLanguageSupport() {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
} catch (error) {
|
|
130
|
-
console.warn(chalk.yellow('
|
|
131
|
-
console.warn(chalk.blue('
|
|
130
|
+
console.warn(chalk.yellow('Language support tools not available'));
|
|
131
|
+
console.warn(chalk.blue('This may limit language-specific configuration features'));
|
|
132
132
|
console.warn(
|
|
133
|
-
chalk.blue('
|
|
133
|
+
chalk.blue('For full functionality, ensure caws-template package is available')
|
|
134
134
|
);
|
|
135
135
|
}
|
|
136
136
|
|
package/dist/config/modes.js
CHANGED
|
@@ -14,7 +14,7 @@ const COMPLEXITY_TIERS = {
|
|
|
14
14
|
name: 'Lite',
|
|
15
15
|
description: 'Guardrails-only mode โ no YAML specs required',
|
|
16
16
|
color: chalk.magenta,
|
|
17
|
-
icon: '
|
|
17
|
+
icon: '',
|
|
18
18
|
features: {
|
|
19
19
|
workingSpec: false,
|
|
20
20
|
destructiveCommandBlocking: true,
|
|
@@ -40,7 +40,7 @@ const COMPLEXITY_TIERS = {
|
|
|
40
40
|
name: 'Simple',
|
|
41
41
|
description: 'Minimal CAWS for small projects and quick prototyping',
|
|
42
42
|
color: chalk.green,
|
|
43
|
-
icon: '
|
|
43
|
+
icon: '',
|
|
44
44
|
features: {
|
|
45
45
|
workingSpec: true,
|
|
46
46
|
basicValidation: true,
|
|
@@ -70,7 +70,7 @@ const COMPLEXITY_TIERS = {
|
|
|
70
70
|
name: 'Standard',
|
|
71
71
|
description: 'Balanced CAWS with change management and quality gates',
|
|
72
72
|
color: chalk.yellow,
|
|
73
|
-
icon: '
|
|
73
|
+
icon: '',
|
|
74
74
|
features: {
|
|
75
75
|
workingSpec: true,
|
|
76
76
|
fullValidation: true,
|
|
@@ -107,7 +107,7 @@ const COMPLEXITY_TIERS = {
|
|
|
107
107
|
name: 'Enterprise',
|
|
108
108
|
description: 'Full CAWS with comprehensive audit trails and compliance',
|
|
109
109
|
color: chalk.red,
|
|
110
|
-
icon: '
|
|
110
|
+
icon: '',
|
|
111
111
|
features: {
|
|
112
112
|
workingSpec: true,
|
|
113
113
|
fullValidation: true,
|
|
@@ -221,8 +221,8 @@ function isRiskTierSupported(riskTier, complexityTier = 'standard') {
|
|
|
221
221
|
* Display tier comparison
|
|
222
222
|
*/
|
|
223
223
|
function displayTierComparison() {
|
|
224
|
-
console.log(chalk.bold.cyan('\
|
|
225
|
-
console.log(chalk.cyan('
|
|
224
|
+
console.log(chalk.bold.cyan('\nCAWS Complexity Tiers'));
|
|
225
|
+
console.log(chalk.cyan('=========================================================\n'));
|
|
226
226
|
|
|
227
227
|
// Header
|
|
228
228
|
console.log(
|
|
@@ -234,7 +234,7 @@ function displayTierComparison() {
|
|
|
234
234
|
'Use Case'
|
|
235
235
|
)
|
|
236
236
|
);
|
|
237
|
-
console.log(chalk.gray('
|
|
237
|
+
console.log(chalk.gray('-'.repeat(90)));
|
|
238
238
|
|
|
239
239
|
Object.entries(COMPLEXITY_TIERS).forEach(([tierName, tier]) => {
|
|
240
240
|
const tierColor = tier.color;
|
|
@@ -12,27 +12,27 @@ const chalk = require('chalk');
|
|
|
12
12
|
const SPEC_TYPES = {
|
|
13
13
|
feature: {
|
|
14
14
|
color: chalk.green,
|
|
15
|
-
icon: '
|
|
15
|
+
icon: '',
|
|
16
16
|
description: 'New feature development',
|
|
17
17
|
},
|
|
18
18
|
fix: {
|
|
19
19
|
color: chalk.red,
|
|
20
|
-
icon: '
|
|
20
|
+
icon: '',
|
|
21
21
|
description: 'Bug fixes and patches',
|
|
22
22
|
},
|
|
23
23
|
refactor: {
|
|
24
24
|
color: chalk.blue,
|
|
25
|
-
icon: '
|
|
25
|
+
icon: '',
|
|
26
26
|
description: 'Code refactoring and improvements',
|
|
27
27
|
},
|
|
28
28
|
chore: {
|
|
29
29
|
color: chalk.gray,
|
|
30
|
-
icon: '
|
|
30
|
+
icon: '',
|
|
31
31
|
description: 'Maintenance and cleanup',
|
|
32
32
|
},
|
|
33
33
|
docs: {
|
|
34
34
|
color: chalk.cyan,
|
|
35
|
-
icon: '
|
|
35
|
+
icon: '',
|
|
36
36
|
description: 'Documentation updates',
|
|
37
37
|
},
|
|
38
38
|
};
|
package/dist/error-handler.js
CHANGED
|
@@ -450,10 +450,10 @@ function handleCliError(error, context = {}, exit = true) {
|
|
|
450
450
|
console.log(formatJsonOutput(jsonError));
|
|
451
451
|
} else {
|
|
452
452
|
// Human-readable output
|
|
453
|
-
console.error(chalk.red(`\n
|
|
453
|
+
console.error(chalk.red(`\n${error.message}`));
|
|
454
454
|
|
|
455
455
|
if (suggestions && suggestions.length > 0) {
|
|
456
|
-
console.error(chalk.yellow('\
|
|
456
|
+
console.error(chalk.yellow('\nSuggestions:'));
|
|
457
457
|
suggestions.forEach((suggestion) => {
|
|
458
458
|
console.error(chalk.yellow(` ${suggestion}`));
|
|
459
459
|
});
|
|
@@ -462,13 +462,13 @@ function handleCliError(error, context = {}, exit = true) {
|
|
|
462
462
|
// Add troubleshooting guide suggestion if available
|
|
463
463
|
if (troubleshootingGuide) {
|
|
464
464
|
const guide = getTroubleshootingGuide(troubleshootingGuide);
|
|
465
|
-
console.error(chalk.cyan(`\
|
|
465
|
+
console.error(chalk.cyan(`\nTroubleshooting Guide: ${guide.title}`));
|
|
466
466
|
console.error(
|
|
467
467
|
chalk.cyan(` Run: caws troubleshoot ${troubleshootingGuide} for detailed guide`)
|
|
468
468
|
);
|
|
469
469
|
}
|
|
470
470
|
|
|
471
|
-
console.error(chalk.blue(`\
|
|
471
|
+
console.error(chalk.blue(`\nDocumentation: ${docLink}`));
|
|
472
472
|
}
|
|
473
473
|
|
|
474
474
|
if (exit) {
|
|
@@ -134,7 +134,7 @@ async function configureJestForTypeScript(projectDir = process.cwd(), options =
|
|
|
134
134
|
await fs.writeFile(jestConfigPath, jestConfig);
|
|
135
135
|
|
|
136
136
|
if (!quiet) {
|
|
137
|
-
console.log(chalk.green('
|
|
137
|
+
console.log(chalk.green('Created jest.config.js'));
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
// Generate test setup file
|
|
@@ -143,7 +143,7 @@ async function configureJestForTypeScript(projectDir = process.cwd(), options =
|
|
|
143
143
|
await fs.writeFile(setupPath, generateTestSetup());
|
|
144
144
|
|
|
145
145
|
if (!quiet) {
|
|
146
|
-
console.log(chalk.green('
|
|
146
|
+
console.log(chalk.green('Created tests/setup.ts'));
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
// Update package.json with test script if needed
|
|
@@ -163,7 +163,7 @@ async function configureJestForTypeScript(projectDir = process.cwd(), options =
|
|
|
163
163
|
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
164
164
|
|
|
165
165
|
if (!quiet) {
|
|
166
|
-
console.log(chalk.green('
|
|
166
|
+
console.log(chalk.green('Added test scripts to package.json'));
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
}
|