@howlil/ez-agents 3.0.0 → 3.4.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.
Files changed (61) hide show
  1. package/README.md +295 -714
  2. package/bin/install.js +446 -78
  3. package/commands/ez/auth.md +87 -0
  4. package/commands/ez/join-discord.md +1 -1
  5. package/ez-agents/bin/ez-tools.cjs +120 -2
  6. package/ez-agents/bin/lib/assistant-adapter.cjs +62 -3
  7. package/ez-agents/bin/lib/audit-exec.cjs +20 -8
  8. package/ez-agents/bin/lib/auth.cjs +2 -1
  9. package/ez-agents/bin/lib/circuit-breaker.cjs +1 -1
  10. package/ez-agents/bin/lib/commands.cjs +42 -23
  11. package/ez-agents/bin/lib/config.cjs +18 -11
  12. package/ez-agents/bin/lib/core.cjs +42 -25
  13. package/ez-agents/bin/lib/file-lock.cjs +3 -3
  14. package/ez-agents/bin/lib/fs-utils.cjs +1 -1
  15. package/ez-agents/bin/lib/git-utils.cjs +1 -1
  16. package/ez-agents/bin/lib/health-check.cjs +2 -3
  17. package/ez-agents/bin/lib/index.cjs +1 -1
  18. package/ez-agents/bin/lib/init.cjs +70 -23
  19. package/ez-agents/bin/lib/logger.cjs +11 -4
  20. package/ez-agents/bin/lib/model-provider.cjs +124 -29
  21. package/ez-agents/bin/lib/phase.cjs +39 -22
  22. package/ez-agents/bin/lib/planning-write.cjs +107 -0
  23. package/ez-agents/bin/lib/retry.cjs +1 -1
  24. package/ez-agents/bin/lib/roadmap.cjs +3 -2
  25. package/ez-agents/bin/lib/safe-exec.cjs +1 -1
  26. package/ez-agents/bin/lib/safe-path.cjs +1 -1
  27. package/ez-agents/bin/lib/state.cjs +24 -9
  28. package/ez-agents/bin/lib/temp-file.cjs +1 -1
  29. package/ez-agents/bin/lib/template.cjs +2 -1
  30. package/ez-agents/bin/lib/test-file-lock.cjs +1 -1
  31. package/ez-agents/bin/lib/test-graceful.cjs +2 -2
  32. package/ez-agents/bin/lib/test-logger.cjs +2 -2
  33. package/ez-agents/bin/lib/test-temp-file.cjs +1 -1
  34. package/ez-agents/bin/lib/timeout-exec.cjs +4 -3
  35. package/ez-agents/bin/lib/verify.cjs +54 -25
  36. package/ez-agents/references/continuation-format.md +1 -1
  37. package/ez-agents/workflows/add-tests.md +2 -2
  38. package/ez-agents/workflows/add-todo.md +1 -1
  39. package/ez-agents/workflows/autonomous.md +15 -15
  40. package/ez-agents/workflows/diagnose-issues.md +1 -1
  41. package/ez-agents/workflows/discuss-phase.md +3 -3
  42. package/ez-agents/workflows/execute-phase.md +2 -2
  43. package/ez-agents/workflows/health.md +1 -1
  44. package/ez-agents/workflows/help.md +2 -2
  45. package/ez-agents/workflows/map-codebase.md +1 -1
  46. package/ez-agents/workflows/new-milestone.md +5 -5
  47. package/ez-agents/workflows/new-project.md +12 -10
  48. package/ez-agents/workflows/plan-phase.md +8 -8
  49. package/ez-agents/workflows/progress.md +1 -1
  50. package/ez-agents/workflows/set-profile.md +1 -1
  51. package/ez-agents/workflows/settings.md +9 -9
  52. package/ez-agents/workflows/stats.md +1 -1
  53. package/ez-agents/workflows/ui-phase.md +3 -3
  54. package/ez-agents/workflows/ui-review.md +2 -2
  55. package/ez-agents/workflows/update.md +1 -1
  56. package/ez-agents/workflows/validate-phase.md +3 -3
  57. package/ez-agents/workflows/verify-work.md +3 -3
  58. package/package.json +1 -1
  59. package/scripts/build-hooks.js +1 -1
  60. package/scripts/fix-qwen-installation.js +144 -0
  61. package/README.zh-CN.md +0 -702
@@ -6,6 +6,7 @@ const fs = require('fs');
6
6
  const path = require('path');
7
7
  const { normalizePhaseName, findPhaseInternal, generateSlugInternal, toPosixPath, output, error } = require('./core.cjs');
8
8
  const { reconstructFrontmatter } = require('./frontmatter.cjs');
9
+ const { safePlanningWriteSync } = require('./planning-write.cjs');
9
10
 
10
11
  function cmdTemplateSelect(cwd, planPath, raw) {
11
12
  if (!planPath) {
@@ -214,7 +215,7 @@ function cmdTemplateFill(cwd, templateType, options, raw) {
214
215
  return;
215
216
  }
216
217
 
217
- fs.writeFileSync(outPath, fullContent, 'utf-8');
218
+ safePlanningWriteSync(outPath, fullContent);
218
219
  const relPath = toPosixPath(path.relative(cwd, outPath));
219
220
  output({ created: true, path: relPath, template: templateType }, raw, relPath);
220
221
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Test script for GSD File Lock
4
+ * Test script for EZ File Lock
5
5
  * Run: node ez-agents/bin/lib/test-file-lock.cjs
6
6
  */
7
7
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Test script for GSD Health Check and Timeout Exec
4
+ * Test script for EZ Health Check and Timeout Exec
5
5
  * Run: node ez-agents/bin/lib/test-graceful.cjs
6
6
  */
7
7
 
@@ -9,7 +9,7 @@ const HealthCheck = require('./health-check.cjs');
9
9
  const { execWithTimeout } = require('./timeout-exec.cjs');
10
10
 
11
11
  console.log('='.repeat(50));
12
- console.log('Testing GSD Graceful Degradation...');
12
+ console.log('Testing EZ Graceful Degradation...');
13
13
  console.log('='.repeat(50));
14
14
 
15
15
  // Test 1: Health Check
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Test script for GSD Logger
4
+ * Test script for EZ Logger
5
5
  * Run: node ez-agents/bin/lib/test-logger.cjs
6
6
  */
7
7
 
@@ -9,7 +9,7 @@ const Logger = require('./logger.cjs');
9
9
  const path = require('path');
10
10
 
11
11
  console.log('='.repeat(50));
12
- console.log('Testing GSD Logger...');
12
+ console.log('Testing EZ Logger...');
13
13
  console.log('='.repeat(50));
14
14
 
15
15
  const logger = new Logger();
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Test script for GSD Temp File Handler
4
+ * Test script for EZ Temp File Handler
5
5
  * Run: node ez-agents/bin/lib/test-temp-file.cjs
6
6
  */
7
7
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * GSD Timeout Exec — Command execution with timeout and fallback
4
+ * EZ Timeout Exec — Command execution with timeout and fallback
5
5
  *
6
6
  * Provides safe command execution with configurable timeout
7
7
  * Logs errors and supports fallback values
@@ -30,11 +30,12 @@ const DEFAULT_TIMEOUT = 5000; // 5 seconds
30
30
  */
31
31
  async function execWithTimeout(cmd, args, options = {}) {
32
32
  const { timeout = DEFAULT_TIMEOUT, fallback = null } = options;
33
+ const hasFallback = Object.prototype.hasOwnProperty.call(options, 'fallback');
33
34
 
34
35
  return new Promise(async (resolve, reject) => {
35
36
  const timeoutId = setTimeout(() => {
36
37
  logger.error(`Command timed out: ${cmd} ${args.join(' ')}`, { timeout });
37
- if (fallback) {
38
+ if (hasFallback) {
38
39
  logger.info('Using fallback value', { fallback });
39
40
  resolve(fallback);
40
41
  } else {
@@ -49,7 +50,7 @@ async function execWithTimeout(cmd, args, options = {}) {
49
50
  } catch (err) {
50
51
  clearTimeout(timeoutId);
51
52
  logger.error(`Command failed: ${cmd}`, { error: err.message, args });
52
- if (fallback) {
53
+ if (hasFallback) {
53
54
  logger.info('Using fallback value', { fallback });
54
55
  resolve(fallback);
55
56
  } else {
@@ -7,8 +7,9 @@ const path = require('path');
7
7
  const { safeReadFile, normalizePhaseName, execGit, findPhaseInternal, getMilestoneInfo, output, error } = require('./core.cjs');
8
8
  const { extractFrontmatter, parseMustHavesBlock } = require('./frontmatter.cjs');
9
9
  const { writeStateMd } = require('./state.cjs');
10
+ const { defaultLogger: logger } = require('./logger.cjs');
10
11
 
11
- function cmdVerifySummary(cwd, summaryPath, checkFileCount, raw) {
12
+ async function cmdVerifySummary(cwd, summaryPath, checkFileCount, raw) {
12
13
  if (!summaryPath) {
13
14
  error('summary-path required');
14
15
  }
@@ -66,7 +67,7 @@ function cmdVerifySummary(cwd, summaryPath, checkFileCount, raw) {
66
67
  let commitsExist = false;
67
68
  if (hashes.length > 0) {
68
69
  for (const hash of hashes.slice(0, 3)) {
69
- const result = execGit(cwd, ['cat-file', '-t', hash]);
70
+ const result = await execGit(cwd, ['cat-file', '-t', hash]);
70
71
  if (result.exitCode === 0 && result.stdout === 'commit') {
71
72
  commitsExist = true;
72
73
  break;
@@ -179,7 +180,13 @@ function cmdVerifyPhaseCompleteness(cwd, phase, raw) {
179
180
 
180
181
  // List plans and summaries
181
182
  let files;
182
- try { files = fs.readdirSync(phaseDir); } catch { output({ error: 'Cannot read phase directory' }, raw); return; }
183
+ try {
184
+ files = fs.readdirSync(phaseDir);
185
+ } catch (err) {
186
+ logger.warn('Failed to read phase directory in cmdVerifyPhaseCompleteness', { phaseDir, error: err.message });
187
+ output({ error: 'Cannot read phase directory' }, raw);
188
+ return;
189
+ }
183
190
 
184
191
  const plans = files.filter(f => f.match(/-PLAN\.md$/i));
185
192
  const summaries = files.filter(f => f.match(/-SUMMARY\.md$/i));
@@ -257,13 +264,13 @@ function cmdVerifyReferences(cwd, filePath, raw) {
257
264
  }, raw, missing.length === 0 ? 'valid' : 'invalid');
258
265
  }
259
266
 
260
- function cmdVerifyCommits(cwd, hashes, raw) {
267
+ async function cmdVerifyCommits(cwd, hashes, raw) {
261
268
  if (!hashes || hashes.length === 0) { error('At least one commit hash required'); }
262
269
 
263
270
  const valid = [];
264
271
  const invalid = [];
265
272
  for (const hash of hashes) {
266
- const result = execGit(cwd, ['cat-file', '-t', hash]);
273
+ const result = await execGit(cwd, ['cat-file', '-t', hash]);
267
274
  if (result.exitCode === 0 && result.stdout.trim() === 'commit') {
268
275
  valid.push(hash);
269
276
  } else {
@@ -369,7 +376,8 @@ function cmdVerifyKeyLinks(cwd, planFilePath, raw) {
369
376
  check.detail = `Pattern "${link.pattern}" not found in source or target`;
370
377
  }
371
378
  }
372
- } catch {
379
+ } catch (err) {
380
+ logger.warn('Invalid regex while verifying key links', { pattern: link.pattern, error: err.message });
373
381
  check.detail = `Invalid regex pattern: ${link.pattern}`;
374
382
  }
375
383
  } else {
@@ -426,7 +434,9 @@ function cmdValidateConsistency(cwd, raw) {
426
434
  const dm = dir.match(/^(\d+[A-Z]?(?:\.\d+)*)/i);
427
435
  if (dm) diskPhases.add(dm[1]);
428
436
  }
429
- } catch {}
437
+ } catch (err) {
438
+ logger.warn('Failed to enumerate phase directories while validating consistency', { phasesDir, error: err.message });
439
+ }
430
440
 
431
441
  // Check: phases in ROADMAP but not on disk
432
442
  for (const p of roadmapPhases) {
@@ -488,7 +498,9 @@ function cmdValidateConsistency(cwd, raw) {
488
498
  }
489
499
  }
490
500
  }
491
- } catch {}
501
+ } catch (err) {
502
+ logger.warn('Failed to validate plan numbering while validating consistency', { phasesDir, error: err.message });
503
+ }
492
504
 
493
505
  // Check: frontmatter in plans has required fields
494
506
  try {
@@ -508,7 +520,9 @@ function cmdValidateConsistency(cwd, raw) {
508
520
  }
509
521
  }
510
522
  }
511
- } catch {}
523
+ } catch (err) {
524
+ logger.warn('Failed to validate plan frontmatter while validating consistency', { phasesDir, error: err.message });
525
+ }
512
526
 
513
527
  const passed = errors.length === 0;
514
528
  output({ passed, errors, warnings, warning_count: warnings.length }, raw, passed ? 'passed' : 'failed');
@@ -537,7 +551,7 @@ function cmdValidateHealth(cwd, options, raw) {
537
551
 
538
552
  // ─── Check 1: .planning/ exists ───────────────────────────────────────────
539
553
  if (!fs.existsSync(planningDir)) {
540
- addIssue('error', 'E001', '.planning/ directory not found', 'Run /gsd:new-project to initialize');
554
+ addIssue('error', 'E001', '.planning/ directory not found', 'Run /ez:new-project to initialize');
541
555
  output({
542
556
  status: 'broken',
543
557
  errors,
@@ -550,7 +564,7 @@ function cmdValidateHealth(cwd, options, raw) {
550
564
 
551
565
  // ─── Check 2: PROJECT.md exists and has required sections ─────────────────
552
566
  if (!fs.existsSync(projectPath)) {
553
- addIssue('error', 'E002', 'PROJECT.md not found', 'Run /gsd:new-project to create');
567
+ addIssue('error', 'E002', 'PROJECT.md not found', 'Run /ez:new-project to create');
554
568
  } else {
555
569
  const content = fs.readFileSync(projectPath, 'utf-8');
556
570
  const requiredSections = ['## What This Is', '## Core Value', '## Requirements'];
@@ -563,12 +577,12 @@ function cmdValidateHealth(cwd, options, raw) {
563
577
 
564
578
  // ─── Check 3: ROADMAP.md exists ───────────────────────────────────────────
565
579
  if (!fs.existsSync(roadmapPath)) {
566
- addIssue('error', 'E003', 'ROADMAP.md not found', 'Run /gsd:new-milestone to create roadmap');
580
+ addIssue('error', 'E003', 'ROADMAP.md not found', 'Run /ez:new-milestone to create roadmap');
567
581
  }
568
582
 
569
583
  // ─── Check 4: STATE.md exists and references valid phases ─────────────────
570
584
  if (!fs.existsSync(statePath)) {
571
- addIssue('error', 'E004', 'STATE.md not found', 'Run /gsd:health --repair to regenerate', true);
585
+ addIssue('error', 'E004', 'STATE.md not found', 'Run /ez:health --repair to regenerate', true);
572
586
  repairs.push('regenerateState');
573
587
  } else {
574
588
  const stateContent = fs.readFileSync(statePath, 'utf-8');
@@ -584,14 +598,16 @@ function cmdValidateHealth(cwd, options, raw) {
584
598
  if (m) diskPhases.add(m[1]);
585
599
  }
586
600
  }
587
- } catch {}
601
+ } catch (err) {
602
+ logger.warn('Failed to read phase directories while validating STATE references', { phasesDir, error: err.message });
603
+ }
588
604
  // Check for invalid references
589
605
  for (const ref of phaseRefs) {
590
606
  const normalizedRef = String(parseInt(ref, 10)).padStart(2, '0');
591
607
  if (!diskPhases.has(ref) && !diskPhases.has(normalizedRef) && !diskPhases.has(String(parseInt(ref, 10)))) {
592
608
  // Only warn if phases dir has any content (not just an empty project)
593
609
  if (diskPhases.size > 0) {
594
- addIssue('warning', 'W002', `STATE.md references phase ${ref}, but only phases ${[...diskPhases].sort().join(', ')} exist`, 'Run /gsd:health --repair to regenerate STATE.md', true);
610
+ addIssue('warning', 'W002', `STATE.md references phase ${ref}, but only phases ${[...diskPhases].sort().join(', ')} exist`, 'Run /ez:health --repair to regenerate STATE.md', true);
595
611
  if (!repairs.includes('regenerateState')) repairs.push('regenerateState');
596
612
  }
597
613
  }
@@ -600,7 +616,7 @@ function cmdValidateHealth(cwd, options, raw) {
600
616
 
601
617
  // ─── Check 5: config.json valid JSON + valid schema ───────────────────────
602
618
  if (!fs.existsSync(configPath)) {
603
- addIssue('warning', 'W003', 'config.json not found', 'Run /gsd:health --repair to create with defaults', true);
619
+ addIssue('warning', 'W003', 'config.json not found', 'Run /ez:health --repair to create with defaults', true);
604
620
  repairs.push('createConfig');
605
621
  } else {
606
622
  try {
@@ -612,7 +628,8 @@ function cmdValidateHealth(cwd, options, raw) {
612
628
  addIssue('warning', 'W004', `config.json: invalid model_profile "${parsed.model_profile}"`, `Valid values: ${validProfiles.join(', ')}`);
613
629
  }
614
630
  } catch (err) {
615
- addIssue('error', 'E005', `config.json: JSON parse error - ${err.message}`, 'Run /gsd:health --repair to reset to defaults', true);
631
+ logger.warn('Failed to parse config.json in cmdValidateHealth', { configPath, error: err.message });
632
+ addIssue('error', 'E005', `config.json: JSON parse error - ${err.message}`, 'Run /ez:health --repair to reset to defaults', true);
616
633
  repairs.push('resetConfig');
617
634
  }
618
635
  }
@@ -623,10 +640,12 @@ function cmdValidateHealth(cwd, options, raw) {
623
640
  const configRaw = fs.readFileSync(configPath, 'utf-8');
624
641
  const configParsed = JSON.parse(configRaw);
625
642
  if (configParsed.workflow && configParsed.workflow.nyquist_validation === undefined) {
626
- addIssue('warning', 'W008', 'config.json: workflow.nyquist_validation absent (defaults to enabled but agents may skip)', 'Run /gsd:health --repair to add key', true);
643
+ addIssue('warning', 'W008', 'config.json: workflow.nyquist_validation absent (defaults to enabled but agents may skip)', 'Run /ez:health --repair to add key', true);
627
644
  if (!repairs.includes('addNyquistKey')) repairs.push('addNyquistKey');
628
645
  }
629
- } catch {}
646
+ } catch (err) {
647
+ logger.warn('Failed to parse config for nyquist key check', { configPath, error: err.message });
648
+ }
630
649
  }
631
650
 
632
651
  // ─── Check 6: Phase directory naming (NN-name format) ─────────────────────
@@ -637,7 +656,9 @@ function cmdValidateHealth(cwd, options, raw) {
637
656
  addIssue('warning', 'W005', `Phase directory "${e.name}" doesn't follow NN-name format`, 'Rename to match pattern (e.g., 01-setup)');
638
657
  }
639
658
  }
640
- } catch {}
659
+ } catch (err) {
660
+ logger.warn('Failed to inspect phase directory naming in health validation', { phasesDir, error: err.message });
661
+ }
641
662
 
642
663
  // ─── Check 7: Orphaned plans (PLAN without SUMMARY) ───────────────────────
643
664
  try {
@@ -656,7 +677,9 @@ function cmdValidateHealth(cwd, options, raw) {
656
677
  }
657
678
  }
658
679
  }
659
- } catch {}
680
+ } catch (err) {
681
+ logger.warn('Failed to inspect orphaned plans in health validation', { phasesDir, error: err.message });
682
+ }
660
683
 
661
684
  // ─── Check 7b: Nyquist VALIDATION.md consistency ────────────────────────
662
685
  try {
@@ -670,11 +693,13 @@ function cmdValidateHealth(cwd, options, raw) {
670
693
  const researchFile = phaseFiles.find(f => f.endsWith('-RESEARCH.md'));
671
694
  const researchContent = fs.readFileSync(path.join(phasesDir, e.name, researchFile), 'utf-8');
672
695
  if (researchContent.includes('## Validation Architecture')) {
673
- addIssue('warning', 'W009', `Phase ${e.name}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`, 'Re-run /gsd:plan-phase with --research to regenerate');
696
+ addIssue('warning', 'W009', `Phase ${e.name}: has Validation Architecture in RESEARCH.md but no VALIDATION.md`, 'Re-run /ez-plan-phase with --research to regenerate');
674
697
  }
675
698
  }
676
699
  }
677
- } catch {}
700
+ } catch (err) {
701
+ logger.warn('Failed to inspect validation architecture consistency in health validation', { phasesDir, error: err.message });
702
+ }
678
703
 
679
704
  // ─── Check 8: Run existing consistency checks ─────────────────────────────
680
705
  // Inline subset of cmdValidateConsistency
@@ -696,7 +721,9 @@ function cmdValidateHealth(cwd, options, raw) {
696
721
  if (dm) diskPhases.add(dm[1]);
697
722
  }
698
723
  }
699
- } catch {}
724
+ } catch (err) {
725
+ logger.warn('Failed to run roadmap/disk consistency checks in health validation', { roadmapPath, phasesDir, error: err.message });
726
+ }
700
727
 
701
728
  // Phases in ROADMAP but not on disk
702
729
  for (const p of roadmapPhases) {
@@ -755,7 +782,7 @@ function cmdValidateHealth(cwd, options, raw) {
755
782
  stateContent += `**Current phase:** (determining...)\n`;
756
783
  stateContent += `**Status:** Resuming\n\n`;
757
784
  stateContent += `## Session Log\n\n`;
758
- stateContent += `- ${new Date().toISOString().split('T')[0]}: STATE.md regenerated by /gsd:health --repair\n`;
785
+ stateContent += `- ${new Date().toISOString().split('T')[0]}: STATE.md regenerated by /ez:health --repair\n`;
759
786
  writeStateMd(statePath, stateContent, cwd);
760
787
  repairActions.push({ action: repair, success: true, path: 'STATE.md' });
761
788
  break;
@@ -772,6 +799,7 @@ function cmdValidateHealth(cwd, options, raw) {
772
799
  }
773
800
  repairActions.push({ action: repair, success: true, path: 'config.json' });
774
801
  } catch (err) {
802
+ logger.error('Failed to repair nyquist key', { error: err.message });
775
803
  repairActions.push({ action: repair, success: false, error: err.message });
776
804
  }
777
805
  }
@@ -779,6 +807,7 @@ function cmdValidateHealth(cwd, options, raw) {
779
807
  }
780
808
  }
781
809
  } catch (err) {
810
+ logger.error('Failed to perform repair action', { action: repair, error: err.message });
782
811
  repairActions.push({ action: repair, success: false, error: err.message });
783
812
  }
784
813
  }
@@ -242,7 +242,7 @@ Sounds like an afterthought. Use "Also available:" instead.
242
242
 
243
243
  ```
244
244
  ```
245
- /gsd:plan-phase 3
245
+ /ez:plan-phase 3
246
246
  ```
247
247
  ```
248
248
 
@@ -61,7 +61,7 @@ Exit.
61
61
  Present banner:
62
62
  ```
63
63
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
64
- GSD ► ADD TESTS — Phase ${phase_number}: ${phase_name}
64
+ EZ ► ADD TESTS — Phase ${phase_number}: ${phase_name}
65
65
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
66
66
  ```
67
67
  </step>
@@ -275,7 +275,7 @@ Create a test coverage report and present to user:
275
275
 
276
276
  ```
277
277
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
278
- GSD ► TEST GENERATION COMPLETE
278
+ EZ ► TEST GENERATION COMPLETE
279
279
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
280
280
 
281
281
  ## Results
@@ -1,5 +1,5 @@
1
1
  <purpose>
2
- Capture an idea, task, or issue that surfaces during a GSD session as a structured todo for later work. Enables "thought → capture → continue" flow without losing context.
2
+ Capture an idea, task, or issue that surfaces during an EZ session as a structured todo for later work. Enables "thought → capture → continue" flow without losing context.
3
3
  </purpose>
4
4
 
5
5
  <required_reading>
@@ -40,7 +40,7 @@ Display startup banner:
40
40
 
41
41
  ```
42
42
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
43
- GSD ► AUTONOMOUS
43
+ EZ ► AUTONOMOUS
44
44
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
45
45
 
46
46
  Milestone: {milestone_version} — {milestone_name}
@@ -73,7 +73,7 @@ Parse the JSON `phases` array.
73
73
 
74
74
  ```
75
75
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
76
- GSD ► AUTONOMOUS ▸ COMPLETE 🎉
76
+ EZ ► AUTONOMOUS ▸ COMPLETE 🎉
77
77
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
78
78
 
79
79
  All phases complete! Nothing left to do.
@@ -112,7 +112,7 @@ For the current phase, display the progress banner:
112
112
 
113
113
  ```
114
114
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
115
- GSD ► AUTONOMOUS ▸ Phase {N}/{T}: {Name} [████░░░░] {P}%
115
+ EZ ► AUTONOMOUS ▸ Phase {N}/{T}: {Name} [████░░░░] {P}%
116
116
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
117
117
  ```
118
118
 
@@ -149,7 +149,7 @@ Check `has_context`. If false → go to handle_blocker: "Smart discuss for phase
149
149
  **3b. Plan**
150
150
 
151
151
  ```
152
- Skill(skill="gsd:plan-phase", args="${PHASE_NUM}")
152
+ Skill(skill="ez:plan-phase", args="${PHASE_NUM}")
153
153
  ```
154
154
 
155
155
  Verify plan produced output — re-run `init phase-op` and check `has_plans`. If false → go to handle_blocker: "Plan phase ${PHASE_NUM} did not produce any plans."
@@ -157,7 +157,7 @@ Verify plan produced output — re-run `init phase-op` and check `has_plans`. If
157
157
  **3c. Execute**
158
158
 
159
159
  ```
160
- Skill(skill="gsd:execute-phase", args="${PHASE_NUM} --no-transition")
160
+ Skill(skill="ez:execute-phase", args="${PHASE_NUM} --no-transition")
161
161
  ```
162
162
 
163
163
  **3d. Post-Execution Routing**
@@ -222,14 +222,14 @@ Ask user via AskUserQuestion:
222
222
  On **"Run gap closure"**: Execute gap closure cycle (limit: 1 attempt):
223
223
 
224
224
  ```
225
- Skill(skill="gsd:plan-phase", args="${PHASE_NUM} --gaps")
225
+ Skill(skill="ez:plan-phase", args="${PHASE_NUM} --gaps")
226
226
  ```
227
227
 
228
228
  Verify gap plans were created — re-run `init phase-op ${PHASE_NUM}` and check `has_plans`. If no new gap plans → go to handle_blocker: "Gap closure planning for phase ${PHASE_NUM} did not produce plans."
229
229
 
230
230
  Re-execute:
231
231
  ```
232
- Skill(skill="gsd:execute-phase", args="${PHASE_NUM} --no-transition")
232
+ Skill(skill="ez:execute-phase", args="${PHASE_NUM} --no-transition")
233
233
  ```
234
234
 
235
235
  Re-read verification status:
@@ -260,7 +260,7 @@ On **"Stop autonomous mode"**: Go to handle_blocker with "User stopped — gaps
260
260
 
261
261
  Run smart discuss for the current phase. Proposes grey area answers in batch tables — the user accepts or overrides per area. Produces identical CONTEXT.md output to regular discuss-phase.
262
262
 
263
- > **Note:** Smart discuss is an autonomous-optimized variant of the `gsd:discuss-phase` skill. It produces identical CONTEXT.md output but uses batch table proposals instead of sequential questioning. The original `discuss-phase` skill remains unchanged (per CTRL-03). Future milestones may extract this to a separate skill file.
263
+ > **Note:** Smart discuss is an autonomous-optimized variant of the `ez:discuss-phase` skill. It produces identical CONTEXT.md output but uses batch table proposals instead of sequential questioning. The original `discuss-phase` skill remains unchanged (per CTRL-03). Future milestones may extract this to a separate skill file.
264
264
 
265
265
  **Inputs:** `PHASE_NUM` from execute_phase. Run init to get phase paths:
266
266
 
@@ -577,7 +577,7 @@ Display lifecycle transition banner:
577
577
 
578
578
  ```
579
579
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
580
- GSD ► AUTONOMOUS ▸ LIFECYCLE
580
+ EZ ► AUTONOMOUS ▸ LIFECYCLE
581
581
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
582
582
 
583
583
  All phases complete → Starting lifecycle: audit → complete → cleanup
@@ -587,7 +587,7 @@ Display lifecycle transition banner:
587
587
  **5a. Audit**
588
588
 
589
589
  ```
590
- Skill(skill="gsd:audit-milestone")
590
+ Skill(skill="ez:audit-milestone")
591
591
  ```
592
592
 
593
593
  After audit completes, detect the result:
@@ -643,7 +643,7 @@ On **"Stop"**: Go to handle_blocker with "User stopped — tech debt to address.
643
643
  **5b. Complete Milestone**
644
644
 
645
645
  ```
646
- Skill(skill="gsd:complete-milestone", args="${milestone_version}")
646
+ Skill(skill="ez:complete-milestone", args="${milestone_version}")
647
647
  ```
648
648
 
649
649
  After complete-milestone returns, verify it produced output:
@@ -657,7 +657,7 @@ If the archive file does not exist, go to handle_blocker: "Complete milestone di
657
657
  **5c. Cleanup**
658
658
 
659
659
  ```
660
- Skill(skill="gsd:cleanup")
660
+ Skill(skill="ez:cleanup")
661
661
  ```
662
662
 
663
663
  Cleanup shows its own dry-run and asks user for approval internally — this is an acceptable pause per CTRL-01 since it's an explicit decision about file deletion.
@@ -668,7 +668,7 @@ Display final completion banner:
668
668
 
669
669
  ```
670
670
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
671
- GSD ► AUTONOMOUS ▸ COMPLETE 🎉
671
+ EZ ► AUTONOMOUS ▸ COMPLETE 🎉
672
672
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
673
673
 
674
674
  Milestone: {milestone_version} — {milestone_name}
@@ -701,7 +701,7 @@ When any phase operation fails or a blocker is detected, present 3 options via A
701
701
 
702
702
  ```
703
703
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
704
- GSD ► AUTONOMOUS ▸ STOPPED
704
+ EZ ► AUTONOMOUS ▸ STOPPED
705
705
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
706
706
 
707
707
  Completed: {list of completed phases}
@@ -732,7 +732,7 @@ When any phase operation fails or a blocker is detected, present 3 options via A
732
732
  - [ ] Final completion or stop summary displayed
733
733
  - [ ] After all phases complete, lifecycle step is invoked (not manual suggestion)
734
734
  - [ ] Lifecycle transition banner displayed before audit
735
- - [ ] Audit invoked via Skill(skill="gsd:audit-milestone")
735
+ - [ ] Audit invoked via Skill(skill="ez:audit-milestone")
736
736
  - [ ] Audit result routing: passed → auto-continue, gaps_found → user decides, tech_debt → user decides
737
737
  - [ ] Audit technical failure (no file/no status) routes to handle_blocker
738
738
  - [ ] Complete-milestone invoked via Skill() with ${milestone_version} arg
@@ -168,7 +168,7 @@ node "$HOME/.claude/ez-agents/bin/ez-tools.cjs" commit "docs({phase_num}): add r
168
168
  Display:
169
169
  ```
170
170
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
171
- GSD ► DIAGNOSIS COMPLETE
171
+ EZ ► DIAGNOSIS COMPLETE
172
172
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
173
173
 
174
174
  | Gap (Truth) | Root Cause | Files |
@@ -697,7 +697,7 @@ node "$HOME/.claude/ez-agents/bin/ez-tools.cjs" config-set workflow._auto_chain_
697
697
  Display banner:
698
698
  ```
699
699
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
700
- GSD ► AUTO-ADVANCING TO PLAN
700
+ EZ ► AUTO-ADVANCING TO PLAN
701
701
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
702
702
 
703
703
  Context captured. Launching plan-phase...
@@ -705,7 +705,7 @@ Context captured. Launching plan-phase...
705
705
 
706
706
  Launch plan-phase using the Skill tool to avoid nested Task sessions (which cause runtime freezes due to deep agent nesting — see #686):
707
707
  ```
708
- Skill(skill="gsd:plan-phase", args="${PHASE} --auto")
708
+ Skill(skill="ez:plan-phase", args="${PHASE} --auto")
709
709
  ```
710
710
 
711
711
  This keeps the auto-advance chain flat — discuss, plan, and execute all run at the same nesting level rather than spawning increasingly deep Task agents.
@@ -714,7 +714,7 @@ This keeps the auto-advance chain flat — discuss, plan, and execute all run at
714
714
  - **PHASE COMPLETE** → Full chain succeeded. Display:
715
715
  ```
716
716
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
717
- GSD ► PHASE ${PHASE} COMPLETE
717
+ EZ ► PHASE ${PHASE} COMPLETE
718
718
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
719
719
 
720
720
  Auto-advance pipeline finished: discuss → plan → execute
@@ -174,7 +174,7 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true`
174
174
 
175
175
  5. **Handle failures:**
176
176
 
177
- **Known Claude Code bug (classifyHandoffIfNeeded):** If an agent reports "failed" with error containing `classifyHandoffIfNeeded is not defined`, this is a Claude Code runtime bug — not a GSD or agent issue. The error fires in the completion handler AFTER all tool calls finish. In this case: run the same spot-checks as step 4 (SUMMARY.md exists, git commits present, no Self-Check: FAILED). If spot-checks PASS → treat as **successful**. If spot-checks FAIL → treat as real failure below.
177
+ **Known Claude Code bug (classifyHandoffIfNeeded):** If an agent reports "failed" with error containing `classifyHandoffIfNeeded is not defined`, this is a Claude Code runtime bug — not an EZ or agent issue. The error fires in the completion handler AFTER all tool calls finish. In this case: run the same spot-checks as step 4 (SUMMARY.md exists, git commits present, no Self-Check: FAILED). If spot-checks PASS → treat as **successful**. If spot-checks FAIL → treat as real failure below.
178
178
 
179
179
  For real failures: report which plan failed → ask "Continue?" or "Stop?" → if continue, dependent plans may also fail. If stop, partial completion report.
180
180
 
@@ -454,7 +454,7 @@ Orchestrator: ~10-15% context. Subagents: fresh 200k each. No polling (Task bloc
454
454
  </context_efficiency>
455
455
 
456
456
  <failure_handling>
457
- - **classifyHandoffIfNeeded false failure:** Agent reports "failed" but error is `classifyHandoffIfNeeded is not defined` → Claude Code bug, not GSD. Spot-check (SUMMARY exists, commits present) → if pass, treat as success
457
+ - **classifyHandoffIfNeeded false failure:** Agent reports "failed" but error is `classifyHandoffIfNeeded is not defined` → Claude Code bug, not EZ. Spot-check (SUMMARY exists, commits present) → if pass, treat as success
458
458
  - **Agent fails mid-plan:** Missing SUMMARY.md → report, ask user how to proceed
459
459
  - **Dependency chain breaks:** Wave 1 fails → Wave 2 dependents likely fail → user chooses attempt or skip
460
460
  - **All agents in wave fail:** Systemic issue → stop, report for investigation
@@ -42,7 +42,7 @@ Parse JSON output:
42
42
 
43
43
  ```
44
44
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
45
- GSD Health Check
45
+ EZ Health Check
46
46
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
47
47
 
48
48
  Status: HEALTHY | DEGRADED | BROKEN
@@ -119,7 +119,7 @@ Usage: `/ez:execute-phase 5`
119
119
  ### Quick Mode
120
120
 
121
121
  **`/ez:quick`**
122
- Execute small, ad-hoc tasks with GSD guarantees but skip optional agents.
122
+ Execute small, ad-hoc tasks with EZ guarantees but skip optional agents.
123
123
 
124
124
  Quick mode uses the same system with a shorter path:
125
125
  - Spawns planner + executor (skips researcher, checker, verifier)
@@ -307,7 +307,7 @@ Configure workflow toggles and model profile interactively.
307
307
  Usage: `/ez:settings`
308
308
 
309
309
  **`/ez:set-profile <profile>`**
310
- Quick switch model profile for GSD agents.
310
+ Quick switch model profile for EZ agents.
311
311
 
312
312
  - `quality` — Opus everywhere except verification
313
313
  - `balanced` — Opus for planning, Sonnet for execution (default)
@@ -312,5 +312,5 @@ End workflow.
312
312
  - Read agent output files to collect confirmations
313
313
  - All 7 codebase documents exist
314
314
  - Clear completion summary with line counts
315
- - User offered clear next steps in GSD style
315
+ - User offered clear next steps in EZ style
316
316
  </success_criteria>