@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.
Files changed (51) hide show
  1. package/dist/budget-derivation.js +10 -10
  2. package/dist/commands/archive.js +22 -22
  3. package/dist/commands/burnup.js +7 -7
  4. package/dist/commands/diagnose.js +25 -25
  5. package/dist/commands/evaluate.js +20 -20
  6. package/dist/commands/init.js +71 -72
  7. package/dist/commands/iterate.js +21 -21
  8. package/dist/commands/mode.js +11 -11
  9. package/dist/commands/plan.js +5 -5
  10. package/dist/commands/provenance.js +86 -86
  11. package/dist/commands/quality-gates.js +4 -4
  12. package/dist/commands/quality-monitor.js +17 -17
  13. package/dist/commands/session.js +312 -0
  14. package/dist/commands/specs.js +44 -44
  15. package/dist/commands/status.js +43 -43
  16. package/dist/commands/templates.js +14 -14
  17. package/dist/commands/tool.js +1 -1
  18. package/dist/commands/troubleshoot.js +11 -11
  19. package/dist/commands/tutorial.js +119 -119
  20. package/dist/commands/validate.js +6 -6
  21. package/dist/commands/waivers.js +93 -60
  22. package/dist/commands/workflow.js +17 -17
  23. package/dist/commands/worktree.js +13 -13
  24. package/dist/config/index.js +5 -5
  25. package/dist/config/modes.js +7 -7
  26. package/dist/constants/spec-types.js +5 -5
  27. package/dist/error-handler.js +4 -4
  28. package/dist/generators/jest-config-generator.js +3 -3
  29. package/dist/generators/working-spec.js +4 -4
  30. package/dist/index.js +79 -27
  31. package/dist/minimal-cli.js +9 -9
  32. package/dist/policy/PolicyManager.js +1 -1
  33. package/dist/scaffold/claude-hooks.js +7 -7
  34. package/dist/scaffold/cursor-hooks.js +8 -8
  35. package/dist/scaffold/git-hooks.js +152 -152
  36. package/dist/scaffold/index.js +48 -48
  37. package/dist/session/session-manager.js +548 -0
  38. package/dist/test-analysis.js +20 -20
  39. package/dist/utils/command-wrapper.js +8 -8
  40. package/dist/utils/detection.js +7 -7
  41. package/dist/utils/finalization.js +21 -21
  42. package/dist/utils/git-lock.js +3 -3
  43. package/dist/utils/gitignore-updater.js +1 -1
  44. package/dist/utils/project-analysis.js +7 -7
  45. package/dist/utils/quality-gates-utils.js +35 -35
  46. package/dist/utils/spec-resolver.js +8 -8
  47. package/dist/utils/typescript-detector.js +5 -5
  48. package/dist/utils/yaml-validation.js +1 -1
  49. package/dist/validation/spec-validation.js +4 -4
  50. package/dist/worktree/worktree-manager.js +11 -5
  51. package/package.json +1 -1
@@ -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((field) => !options[field]);
101
+ const missing = required.filter((r) => !options[r.field]);
84
102
 
85
103
  if (missing.length > 0) {
86
- console.error(chalk.red(`\nโŒ Missing required fields: ${missing.join(', ')}`));
87
- console.log(chalk.yellow('\n๐Ÿ’ก Example:'));
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
- console.log(' --title="Emergency hotfix waiver" \\');
90
- console.log(' --reason=emergency_hotfix \\');
91
- console.log(' --description="Critical production bug requires immediate fix" \\');
92
- console.log(' --gates=coverage,mutation \\');
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(`\nโœ… Waiver created: ${waiverId}`));
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โš ๏ธ Remember: This waiver expires on ${waiver.expires_at}`));
145
- console.log(chalk.yellow(`โš ๏ธ Mitigation plan: ${waiver.mitigation_plan}\n`));
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('\nโ„น๏ธ No waivers found\n'));
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('\nโ„น๏ธ No waivers found\n'));
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('\n๐Ÿ”– CAWS Quality Gate Waivers\n'));
181
- console.log('โ”€'.repeat(60));
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('\nโœ… Active Waivers:\n'));
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(`๐Ÿ”– ${chalk.bold(waiver.id)}: ${waiver.title}`);
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('\nโš ๏ธ Expired Waivers:\n'));
234
+ console.log(chalk.yellow('\nExpired Waivers:\n'));
200
235
  expiredWaivers.forEach((waiver) => {
201
- console.log(`๐Ÿ”– ${chalk.bold(waiver.id)}: ${waiver.title}`);
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('\nโŒ Revoked Waivers:\n'));
243
+ console.log(chalk.red('\nRevoked Waivers:\n'));
209
244
  revokedWaivers.forEach((waiver) => {
210
- console.log(`๐Ÿ”– ${chalk.bold(waiver.id)}: ${waiver.title}`);
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('๐Ÿ“Š Summary:\n'));
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('\nโŒ Waiver ID required'));
229
- console.log(chalk.yellow('๐Ÿ’ก Usage: caws waivers show WV-1234\n'));
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(`\nโŒ Waiver not found: ${waiverId}\n`));
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 statusIcon = isActive ? 'โœ…' : isExpired ? 'โš ๏ธ' : 'โŒ';
280
+ const statusLabel = isActive ? chalk.green('Active') : isExpired ? chalk.yellow('Expired') : chalk.red(waiver.status);
246
281
 
247
- console.log(chalk.blue('\n๐Ÿ”– Waiver Details\n'));
248
- console.log('โ”€'.repeat(60));
249
- console.log(
250
- `\n${statusIcon} Status: ${chalk.bold(isActive ? 'Active' : isExpired ? 'Expired' : waiver.status)}`
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(`\n๐Ÿ“ Description:`);
289
+ console.log(`\nDescription:`);
257
290
  console.log(` ${waiver.description}`);
258
- console.log(`\n๐Ÿ”’ Waived Quality Gates:`);
291
+ console.log(`\nWaived Quality Gates:`);
259
292
  waiver.gates.forEach((gate) => {
260
- console.log(` โ€ข ${gate}`);
293
+ console.log(` - ${gate}`);
261
294
  });
262
- console.log(`\n๐Ÿ›ก๏ธ Mitigation Plan:`);
295
+ console.log(`\nMitigation Plan:`);
263
296
  console.log(` ${waiver.mitigation_plan}`);
264
- console.log(`\n๐Ÿ“… Timeline:`);
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(`\nโœ๏ธ Approved by: ${waiver.approved_by}\n`);
303
+ console.log(`\nApproved by: ${waiver.approved_by}\n`);
271
304
 
272
305
  if (isExpired && waiver.status === 'active') {
273
- console.log(chalk.yellow('โš ๏ธ This waiver has expired. Consider revoking it.\n'));
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('\nโŒ Waiver ID required'));
283
- console.log(chalk.yellow('๐Ÿ’ก Usage: caws waivers revoke WV-1234\n'));
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(`\nโŒ Waiver not found: ${waiverId}\n`));
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(`\nโ„น๏ธ Waiver ${waiverId} is already revoked\n`));
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(`\nโœ… Waiver revoked: ${waiverId}`));
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('โš ๏ธ Invalid context JSON, ignoring'));
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โŒ ${guidance.error}`));
168
+ console.error(chalk.red(`\n${guidance.error}`));
169
169
  if (guidance.available_types) {
170
- console.log(chalk.blue('\n๐Ÿ’ก Available workflow types:'));
170
+ console.log(chalk.blue('\nAvailable workflow types:'));
171
171
  guidance.available_types.forEach((type) => {
172
- console.log(chalk.blue(` โ€ข ${type}`));
172
+ console.log(chalk.blue(` - ${type}`));
173
173
  });
174
174
  }
175
175
  if (guidance.total_steps) {
176
- console.log(chalk.blue(`\n๐Ÿ’ก Valid steps: 1-${guidance.total_steps}`));
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('\n๐Ÿ”„ CAWS Workflow Guidance\n'));
183
- console.log('โ”€'.repeat(60));
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('\n๐Ÿ“‹ Guidance:\n'));
195
+ console.log(chalk.bold('\nGuidance:\n'));
196
196
  console.log(` ${guidance.guidance}`);
197
197
 
198
- console.log(chalk.bold('\nโœ… CAWS Recommendations:\n'));
198
+ console.log(chalk.bold('\nCAWS Recommendations:\n'));
199
199
  guidance.caws_recommendations.forEach((rec) => {
200
- console.log(chalk.blue(` โ€ข ${rec}`));
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('\nโญ๏ธ Next Step:\n'));
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('\n๐ŸŽ‰ Workflow Complete!\n'));
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 ๐Ÿ’ก Run: caws evaluate to check final quality'));
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('\n๐Ÿ“Š All Steps:\n'));
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 ? 'โ–ถ๏ธ ' : 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' + 'โ”€'.repeat(60) + '\n');
231
+ console.log('\n' + '-'.repeat(60) + '\n');
232
232
  } catch (error) {
233
- console.error(chalk.red(`\nโŒ Workflow guidance failed: ${error.message}`));
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(`โŒ ${error.message}`));
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('โŒ Worktree name is required'));
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(`๐ŸŒฟ Creating worktree: ${name}`));
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(`โœ… Worktree created`));
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(`\n๐Ÿ’ก cd ${entry.path} to start working in the isolated worktree`));
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('๐ŸŒฟ CAWS Worktrees'));
73
- console.log(chalk.cyan('โ”'.repeat(70)));
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('โ”€'.repeat(70)));
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('โŒ Worktree name is required'));
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(`๐Ÿ—‘๏ธ Destroying worktree: ${name}`));
112
+ console.log(chalk.cyan(`Destroying worktree: ${name}`));
113
113
  destroyWorktree(name, { deleteBranch, force });
114
- console.log(chalk.green(`โœ… Worktree '${name}' destroyed`));
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(`๐Ÿงน Pruning worktrees (max age: ${maxAge} days)`));
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(`โœ… Pruned ${pruned.length} worktree(s):`));
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
  }
@@ -28,7 +28,7 @@ function initializeGlobalSetup() {
28
28
  try {
29
29
  cawsSetup = detectCAWSSetup();
30
30
  } catch (error) {
31
- console.warn(chalk.yellow('โš ๏ธ Failed to detect CAWS setup:'), error.message);
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(`โœ… Loaded language support from: ${testPath}`);
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('โš ๏ธ Language support tools not available'));
131
- console.warn(chalk.blue('๐Ÿ’ก This may limit language-specific configuration features'));
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('๐Ÿ’ก For full functionality, ensure caws-template package is available')
133
+ chalk.blue('For full functionality, ensure caws-template package is available')
134
134
  );
135
135
  }
136
136
 
@@ -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('\n๐Ÿ“Š CAWS Complexity Tiers'));
225
- console.log(chalk.cyan('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n'));
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('โ”€'.repeat(90)));
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
  };
@@ -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โŒ ${error.message}`));
453
+ console.error(chalk.red(`\n${error.message}`));
454
454
 
455
455
  if (suggestions && suggestions.length > 0) {
456
- console.error(chalk.yellow('\n๐Ÿ’ก Suggestions:'));
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(`\n๐Ÿ” Troubleshooting Guide: ${guide.title}`));
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(`\n๐Ÿ“š Documentation: ${docLink}`));
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('โœ… Created jest.config.js'));
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('โœ… Created tests/setup.ts'));
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('โœ… Added test scripts to package.json'));
166
+ console.log(chalk.green('Added test scripts to package.json'));
167
167
  }
168
168
  }
169
169
  }