lean-spec 0.2.5-dev.20251124044002 → 0.2.5-dev.20251124050427

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 (35) hide show
  1. package/dist/{chunk-IGNO4GX2.js → chunk-YKBICZNR.js} +760 -550
  2. package/dist/chunk-YKBICZNR.js.map +1 -0
  3. package/dist/cli.js +6 -1
  4. package/dist/cli.js.map +1 -1
  5. package/dist/mcp-server.js +1 -1
  6. package/package.json +1 -1
  7. package/templates/examples/api-refactor/README.md +81 -0
  8. package/templates/examples/api-refactor/package.json +16 -0
  9. package/templates/examples/api-refactor/src/app.js +40 -0
  10. package/templates/examples/api-refactor/src/services/currencyService.js +43 -0
  11. package/templates/examples/api-refactor/src/services/timezoneService.js +41 -0
  12. package/templates/examples/api-refactor/src/services/weatherService.js +42 -0
  13. package/templates/examples/dashboard-widgets/README.md +70 -0
  14. package/templates/examples/dashboard-widgets/index.html +12 -0
  15. package/templates/examples/dashboard-widgets/package.json +22 -0
  16. package/templates/examples/dashboard-widgets/src/App.css +20 -0
  17. package/templates/examples/dashboard-widgets/src/App.jsx +16 -0
  18. package/templates/examples/dashboard-widgets/src/components/Dashboard.css +17 -0
  19. package/templates/examples/dashboard-widgets/src/components/Dashboard.jsx +15 -0
  20. package/templates/examples/dashboard-widgets/src/components/WidgetWrapper.css +23 -0
  21. package/templates/examples/dashboard-widgets/src/components/WidgetWrapper.jsx +16 -0
  22. package/templates/examples/dashboard-widgets/src/components/widgets/ChartWidget.css +33 -0
  23. package/templates/examples/dashboard-widgets/src/components/widgets/ChartWidget.jsx +28 -0
  24. package/templates/examples/dashboard-widgets/src/components/widgets/StatsWidget.css +24 -0
  25. package/templates/examples/dashboard-widgets/src/components/widgets/StatsWidget.jsx +22 -0
  26. package/templates/examples/dashboard-widgets/src/index.css +13 -0
  27. package/templates/examples/dashboard-widgets/src/main.jsx +10 -0
  28. package/templates/examples/dashboard-widgets/src/utils/mockData.js +30 -0
  29. package/templates/examples/dashboard-widgets/vite.config.js +6 -0
  30. package/templates/examples/email-notifications/README.md +55 -0
  31. package/templates/examples/email-notifications/package.json +16 -0
  32. package/templates/examples/email-notifications/src/server.js +57 -0
  33. package/templates/examples/email-notifications/src/storage.js +40 -0
  34. package/templates/examples/email-notifications/src/users.js +38 -0
  35. package/dist/chunk-IGNO4GX2.js.map +0 -1
@@ -3,12 +3,12 @@ import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mc
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { readFileSync, existsSync } from 'fs';
5
5
  import { fileURLToPath } from 'url';
6
- import * as path4 from 'path';
6
+ import * as path15 from 'path';
7
7
  import { dirname, join, resolve } from 'path';
8
8
  import { z } from 'zod';
9
9
  import * as fs9 from 'fs/promises';
10
10
  import { readFile, writeFile } from 'fs/promises';
11
- import chalk18 from 'chalk';
11
+ import chalk19 from 'chalk';
12
12
  import matter2 from 'gray-matter';
13
13
  import yaml2 from 'js-yaml';
14
14
  import { Command } from 'commander';
@@ -41,7 +41,7 @@ var DEFAULT_CONFIG = {
41
41
  }
42
42
  };
43
43
  async function loadConfig(cwd = process.cwd()) {
44
- const configPath = path4.join(cwd, ".lean-spec", "config.json");
44
+ const configPath = path15.join(cwd, ".lean-spec", "config.json");
45
45
  try {
46
46
  const content = await fs9.readFile(configPath, "utf-8");
47
47
  const userConfig = JSON.parse(content);
@@ -53,8 +53,8 @@ async function loadConfig(cwd = process.cwd()) {
53
53
  }
54
54
  }
55
55
  async function saveConfig(config, cwd = process.cwd()) {
56
- const configDir = path4.join(cwd, ".lean-spec");
57
- const configPath = path4.join(configDir, "config.json");
56
+ const configDir = path15.join(cwd, ".lean-spec");
57
+ const configPath = path15.join(configDir, "config.json");
58
58
  await fs9.mkdir(configDir, { recursive: true });
59
59
  await fs9.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
60
60
  }
@@ -153,7 +153,7 @@ async function getGlobalNextSeq(specsDir, digits) {
153
153
  }
154
154
  }
155
155
  if (entry.name === "archived") continue;
156
- const subDir = path4.join(dir, entry.name);
156
+ const subDir = path15.join(dir, entry.name);
157
157
  await scanDirectory(subDir);
158
158
  }
159
159
  } catch {
@@ -170,7 +170,7 @@ async function getGlobalNextSeq(specsDir, digits) {
170
170
  }
171
171
  }
172
172
  async function resolveSpecPath(specPath, cwd, specsDir) {
173
- if (path4.isAbsolute(specPath)) {
173
+ if (path15.isAbsolute(specPath)) {
174
174
  try {
175
175
  await fs9.access(specPath);
176
176
  return specPath;
@@ -178,13 +178,13 @@ async function resolveSpecPath(specPath, cwd, specsDir) {
178
178
  return null;
179
179
  }
180
180
  }
181
- const cwdPath = path4.resolve(cwd, specPath);
181
+ const cwdPath = path15.resolve(cwd, specPath);
182
182
  try {
183
183
  await fs9.access(cwdPath);
184
184
  return cwdPath;
185
185
  } catch {
186
186
  }
187
- const specsPath = path4.join(specsDir, specPath);
187
+ const specsPath = path15.join(specsDir, specPath);
188
188
  try {
189
189
  await fs9.access(specsPath);
190
190
  return specsPath;
@@ -211,10 +211,10 @@ async function searchBySequence(specsDir, seqNum) {
211
211
  if (match) {
212
212
  const entrySeq = parseInt(match[1], 10);
213
213
  if (entrySeq === seqNum) {
214
- return path4.join(dir, entry.name);
214
+ return path15.join(dir, entry.name);
215
215
  }
216
216
  }
217
- const subDir = path4.join(dir, entry.name);
217
+ const subDir = path15.join(dir, entry.name);
218
218
  const result = await scanDirectory(subDir);
219
219
  if (result) return result;
220
220
  }
@@ -231,9 +231,9 @@ async function searchInAllDirectories(specsDir, specName) {
231
231
  for (const entry of entries) {
232
232
  if (!entry.isDirectory()) continue;
233
233
  if (entry.name === specName) {
234
- return path4.join(dir, entry.name);
234
+ return path15.join(dir, entry.name);
235
235
  }
236
- const subDir = path4.join(dir, entry.name);
236
+ const subDir = path15.join(dir, entry.name);
237
237
  const result = await scanDirectory(subDir);
238
238
  if (result) return result;
239
239
  }
@@ -264,7 +264,7 @@ async function getGitInfo() {
264
264
  }
265
265
  async function getProjectName(cwd = process.cwd()) {
266
266
  try {
267
- const packageJsonPath = path4.join(cwd, "package.json");
267
+ const packageJsonPath = path15.join(cwd, "package.json");
268
268
  const content = await fs9.readFile(packageJsonPath, "utf-8");
269
269
  const packageJson2 = JSON.parse(content);
270
270
  return packageJson2.name || null;
@@ -353,9 +353,9 @@ async function loadSubFiles(specDir, options = {}) {
353
353
  for (const entry of entries) {
354
354
  if (entry.name === "README.md") continue;
355
355
  if (entry.isDirectory()) continue;
356
- const filePath = path4.join(specDir, entry.name);
356
+ const filePath = path15.join(specDir, entry.name);
357
357
  const stat6 = await fs9.stat(filePath);
358
- const ext = path4.extname(entry.name).toLowerCase();
358
+ const ext = path15.extname(entry.name).toLowerCase();
359
359
  const isDocument = ext === ".md";
360
360
  const subFile = {
361
361
  name: entry.name,
@@ -381,7 +381,7 @@ async function loadSubFiles(specDir, options = {}) {
381
381
  async function loadAllSpecs(options = {}) {
382
382
  const config = await loadConfig();
383
383
  const cwd = process.cwd();
384
- const specsDir = path4.join(cwd, config.specsDir);
384
+ const specsDir = path15.join(cwd, config.specsDir);
385
385
  const specs = [];
386
386
  try {
387
387
  await fs9.access(specsDir);
@@ -395,7 +395,7 @@ async function loadAllSpecs(options = {}) {
395
395
  for (const entry of entries) {
396
396
  if (!entry.isDirectory()) continue;
397
397
  if (entry.name === "archived" && relativePath === "") continue;
398
- const entryPath = path4.join(dir, entry.name);
398
+ const entryPath = path15.join(dir, entry.name);
399
399
  const entryRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
400
400
  if (specPattern.test(entry.name)) {
401
401
  const specFile = await getSpecFile(entryPath, config.structure.defaultFile);
@@ -444,7 +444,7 @@ async function loadAllSpecs(options = {}) {
444
444
  }
445
445
  await loadSpecsFromDir(specsDir);
446
446
  if (options.includeArchived) {
447
- const archivedPath = path4.join(specsDir, "archived");
447
+ const archivedPath = path15.join(specsDir, "archived");
448
448
  await loadSpecsFromDir(archivedPath, "archived");
449
449
  }
450
450
  const sortBy = options.sortBy || "id";
@@ -492,12 +492,12 @@ async function loadAllSpecs(options = {}) {
492
492
  async function getSpec(specPath) {
493
493
  const config = await loadConfig();
494
494
  const cwd = process.cwd();
495
- const specsDir = path4.join(cwd, config.specsDir);
495
+ const specsDir = path15.join(cwd, config.specsDir);
496
496
  let fullPath;
497
- if (path4.isAbsolute(specPath)) {
497
+ if (path15.isAbsolute(specPath)) {
498
498
  fullPath = specPath;
499
499
  } else {
500
- fullPath = path4.join(specsDir, specPath);
500
+ fullPath = path15.join(specsDir, specPath);
501
501
  }
502
502
  try {
503
503
  await fs9.access(fullPath);
@@ -509,8 +509,8 @@ async function getSpec(specPath) {
509
509
  const frontmatter = await parseFrontmatter(specFile, config);
510
510
  if (!frontmatter) return null;
511
511
  const content = await fs9.readFile(specFile, "utf-8");
512
- const relativePath = path4.relative(specsDir, fullPath);
513
- const parts = relativePath.split(path4.sep);
512
+ const relativePath = path15.relative(specsDir, fullPath);
513
+ const parts = relativePath.split(path15.sep);
514
514
  const date = parts[0] === "archived" ? parts[1] : parts[0];
515
515
  const name = parts[parts.length - 1];
516
516
  return {
@@ -558,12 +558,12 @@ function checkCommand() {
558
558
  async function checkSpecs(options = {}) {
559
559
  const config = await loadConfig();
560
560
  const cwd = process.cwd();
561
- path4.join(cwd, config.specsDir);
561
+ path15.join(cwd, config.specsDir);
562
562
  const specs = await loadAllSpecs();
563
563
  const sequenceMap = /* @__PURE__ */ new Map();
564
564
  const specPattern = createSpecDirPattern();
565
565
  for (const spec of specs) {
566
- const specName = path4.basename(spec.path);
566
+ const specName = path15.basename(spec.path);
567
567
  const match = specName.match(specPattern);
568
568
  if (match) {
569
569
  const seq = parseInt(match[1], 10);
@@ -578,30 +578,30 @@ async function checkSpecs(options = {}) {
578
578
  const conflicts = Array.from(sequenceMap.entries()).filter(([_, paths]) => paths.length > 1).sort(([a], [b]) => a - b);
579
579
  if (conflicts.length === 0) {
580
580
  if (!options.quiet && !options.silent) {
581
- console.log(chalk18.green("\u2713 No sequence conflicts detected"));
581
+ console.log(chalk19.green("\u2713 No sequence conflicts detected"));
582
582
  }
583
583
  return true;
584
584
  }
585
585
  if (!options.silent) {
586
586
  if (!options.quiet) {
587
587
  console.log("");
588
- console.log(chalk18.yellow("\u26A0\uFE0F Sequence conflicts detected:\n"));
588
+ console.log(chalk19.yellow("\u26A0\uFE0F Sequence conflicts detected:\n"));
589
589
  for (const [seq, paths] of conflicts) {
590
- console.log(chalk18.red(` Sequence ${String(seq).padStart(config.structure.sequenceDigits, "0")}:`));
590
+ console.log(chalk19.red(` Sequence ${String(seq).padStart(config.structure.sequenceDigits, "0")}:`));
591
591
  for (const p of paths) {
592
- console.log(chalk18.gray(` - ${sanitizeUserInput(p)}`));
592
+ console.log(chalk19.gray(` - ${sanitizeUserInput(p)}`));
593
593
  }
594
594
  console.log("");
595
595
  }
596
- console.log(chalk18.cyan("Tip: Use date prefix to prevent conflicts:"));
597
- console.log(chalk18.gray(' Edit .lean-spec/config.json \u2192 structure.prefix: "{YYYYMMDD}-"'));
596
+ console.log(chalk19.cyan("Tip: Use date prefix to prevent conflicts:"));
597
+ console.log(chalk19.gray(' Edit .lean-spec/config.json \u2192 structure.prefix: "{YYYYMMDD}-"'));
598
598
  console.log("");
599
- console.log(chalk18.cyan("Or rename folders manually to resolve."));
599
+ console.log(chalk19.cyan("Or rename folders manually to resolve."));
600
600
  console.log("");
601
601
  } else {
602
602
  console.log("");
603
- console.log(chalk18.yellow(`\u26A0\uFE0F Conflict warning: ${conflicts.length} sequence conflict(s) detected`));
604
- console.log(chalk18.gray("Run: lean-spec check"));
603
+ console.log(chalk19.yellow(`\u26A0\uFE0F Conflict warning: ${conflicts.length} sequence conflict(s) detected`));
604
+ console.log(chalk19.gray("Run: lean-spec check"));
605
605
  console.log("");
606
606
  }
607
607
  }
@@ -654,7 +654,7 @@ function createCommand() {
654
654
  async function createSpec(name, options = {}) {
655
655
  const config = await loadConfig();
656
656
  const cwd = process.cwd();
657
- const specsDir = path4.join(cwd, config.specsDir);
657
+ const specsDir = path15.join(cwd, config.specsDir);
658
658
  await fs9.mkdir(specsDir, { recursive: true });
659
659
  const seq = await getGlobalNextSeq(specsDir, config.structure.sequenceDigits);
660
660
  let specRelativePath;
@@ -675,8 +675,8 @@ async function createSpec(name, options = {}) {
675
675
  } else {
676
676
  throw new Error(`Unknown pattern: ${config.structure.pattern}`);
677
677
  }
678
- const specDir = path4.join(specsDir, specRelativePath);
679
- const specFile = path4.join(specDir, config.structure.defaultFile);
678
+ const specDir = path15.join(specsDir, specRelativePath);
679
+ const specFile = path15.join(specDir, config.structure.defaultFile);
680
680
  try {
681
681
  await fs9.access(specDir);
682
682
  throw new Error(`Spec already exists: ${sanitizeUserInput(specDir)}`);
@@ -686,7 +686,7 @@ async function createSpec(name, options = {}) {
686
686
  }
687
687
  }
688
688
  await fs9.mkdir(specDir, { recursive: true });
689
- const templatesDir = path4.join(cwd, ".lean-spec", "templates");
689
+ const templatesDir = path15.join(cwd, ".lean-spec", "templates");
690
690
  let templateName;
691
691
  if (options.template) {
692
692
  if (config.templates?.[options.template]) {
@@ -698,7 +698,7 @@ async function createSpec(name, options = {}) {
698
698
  } else {
699
699
  templateName = config.template || "spec-template.md";
700
700
  }
701
- const templatePath = path4.join(templatesDir, templateName);
701
+ const templatePath = path15.join(templatesDir, templateName);
702
702
  let content;
703
703
  try {
704
704
  const template = await fs9.readFile(templatePath, "utf-8");
@@ -746,8 +746,8 @@ ${options.description}`
746
746
  throw new Error(`Template not found: ${templatePath}. Run: lean-spec init`);
747
747
  }
748
748
  await fs9.writeFile(specFile, content, "utf-8");
749
- console.log(chalk18.green(`\u2713 Created: ${sanitizeUserInput(specDir)}/`));
750
- console.log(chalk18.gray(` Edit: ${sanitizeUserInput(specFile)}`));
749
+ console.log(chalk19.green(`\u2713 Created: ${sanitizeUserInput(specDir)}/`));
750
+ console.log(chalk19.gray(` Edit: ${sanitizeUserInput(specFile)}`));
751
751
  await autoCheckIfEnabled();
752
752
  }
753
753
  function archiveCommand() {
@@ -759,7 +759,7 @@ async function archiveSpec(specPath) {
759
759
  await autoCheckIfEnabled();
760
760
  const config = await loadConfig();
761
761
  const cwd = process.cwd();
762
- const specsDir = path4.join(cwd, config.specsDir);
762
+ const specsDir = path15.join(cwd, config.specsDir);
763
763
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
764
764
  if (!resolvedPath) {
765
765
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);
@@ -768,12 +768,12 @@ async function archiveSpec(specPath) {
768
768
  if (specFile) {
769
769
  await updateFrontmatter(specFile, { status: "archived" });
770
770
  }
771
- const archiveDir = path4.join(specsDir, "archived");
771
+ const archiveDir = path15.join(specsDir, "archived");
772
772
  await fs9.mkdir(archiveDir, { recursive: true });
773
- const specName = path4.basename(resolvedPath);
774
- const archivePath = path4.join(archiveDir, specName);
773
+ const specName = path15.basename(resolvedPath);
774
+ const archivePath = path15.join(archiveDir, specName);
775
775
  await fs9.rename(resolvedPath, archivePath);
776
- console.log(chalk18.green(`\u2713 Archived: ${sanitizeUserInput(archivePath)}`));
776
+ console.log(chalk19.green(`\u2713 Archived: ${sanitizeUserInput(archivePath)}`));
777
777
  }
778
778
 
779
779
  // src/utils/pattern-detection.ts
@@ -803,59 +803,59 @@ var STATUS_CONFIG = {
803
803
  planned: {
804
804
  emoji: "\u{1F4C5}",
805
805
  label: "Planned",
806
- colorFn: chalk18.blue,
807
- badge: (s = "planned") => chalk18.blue(`[${s}]`)
806
+ colorFn: chalk19.blue,
807
+ badge: (s = "planned") => chalk19.blue(`[${s}]`)
808
808
  },
809
809
  "in-progress": {
810
810
  emoji: "\u23F3",
811
811
  label: "In Progress",
812
- colorFn: chalk18.yellow,
813
- badge: (s = "in-progress") => chalk18.yellow(`[${s}]`)
812
+ colorFn: chalk19.yellow,
813
+ badge: (s = "in-progress") => chalk19.yellow(`[${s}]`)
814
814
  },
815
815
  complete: {
816
816
  emoji: "\u2705",
817
817
  label: "Complete",
818
- colorFn: chalk18.green,
819
- badge: (s = "complete") => chalk18.green(`[${s}]`)
818
+ colorFn: chalk19.green,
819
+ badge: (s = "complete") => chalk19.green(`[${s}]`)
820
820
  },
821
821
  archived: {
822
822
  emoji: "\u{1F4E6}",
823
823
  label: "Archived",
824
- colorFn: chalk18.gray,
825
- badge: (s = "archived") => chalk18.gray(`[${s}]`)
824
+ colorFn: chalk19.gray,
825
+ badge: (s = "archived") => chalk19.gray(`[${s}]`)
826
826
  }
827
827
  };
828
828
  var PRIORITY_CONFIG = {
829
829
  critical: {
830
830
  emoji: "\u{1F534}",
831
- colorFn: chalk18.red.bold,
832
- badge: (s = "critical") => chalk18.red.bold(`[${s}]`)
831
+ colorFn: chalk19.red.bold,
832
+ badge: (s = "critical") => chalk19.red.bold(`[${s}]`)
833
833
  },
834
834
  high: {
835
835
  emoji: "\u{1F7E0}",
836
- colorFn: chalk18.hex("#FFA500"),
837
- badge: (s = "high") => chalk18.hex("#FFA500")(`[${s}]`)
836
+ colorFn: chalk19.hex("#FFA500"),
837
+ badge: (s = "high") => chalk19.hex("#FFA500")(`[${s}]`)
838
838
  },
839
839
  medium: {
840
840
  emoji: "\u{1F7E1}",
841
- colorFn: chalk18.yellow,
842
- badge: (s = "medium") => chalk18.yellow(`[${s}]`)
841
+ colorFn: chalk19.yellow,
842
+ badge: (s = "medium") => chalk19.yellow(`[${s}]`)
843
843
  },
844
844
  low: {
845
845
  emoji: "\u{1F7E2}",
846
- colorFn: chalk18.gray,
847
- badge: (s = "low") => chalk18.gray(`[${s}]`)
846
+ colorFn: chalk19.gray,
847
+ badge: (s = "low") => chalk19.gray(`[${s}]`)
848
848
  }
849
849
  };
850
850
  function formatStatusBadge(status) {
851
- return STATUS_CONFIG[status]?.badge() || chalk18.white(`[${status}]`);
851
+ return STATUS_CONFIG[status]?.badge() || chalk19.white(`[${status}]`);
852
852
  }
853
853
  function formatPriorityBadge(priority) {
854
- return PRIORITY_CONFIG[priority]?.badge() || chalk18.white(`[${priority}]`);
854
+ return PRIORITY_CONFIG[priority]?.badge() || chalk19.white(`[${priority}]`);
855
855
  }
856
856
  function getStatusIndicator(status) {
857
857
  const config = STATUS_CONFIG[status];
858
- if (!config) return chalk18.gray("[unknown]");
858
+ if (!config) return chalk19.gray("[unknown]");
859
859
  return config.colorFn(`[${status}]`);
860
860
  }
861
861
  function getStatusEmoji(status) {
@@ -886,7 +886,7 @@ async function listSpecs(options = {}) {
886
886
  await autoCheckIfEnabled();
887
887
  const config = await loadConfig();
888
888
  const cwd = process.cwd();
889
- const specsDir = path4.join(cwd, config.specsDir);
889
+ const specsDir = path15.join(cwd, config.specsDir);
890
890
  try {
891
891
  await fs9.access(specsDir);
892
892
  } catch {
@@ -913,10 +913,10 @@ async function listSpecs(options = {}) {
913
913
  })
914
914
  );
915
915
  if (specs.length === 0) {
916
- console.log(chalk18.dim("No specs found."));
916
+ console.log(chalk19.dim("No specs found."));
917
917
  return;
918
918
  }
919
- console.log(chalk18.bold.cyan("\u{1F4C4} Spec List"));
919
+ console.log(chalk19.bold.cyan("\u{1F4C4} Spec List"));
920
920
  const filterParts = [];
921
921
  if (options.status) {
922
922
  const statusStr = Array.isArray(options.status) ? options.status.join(",") : options.status;
@@ -929,7 +929,7 @@ async function listSpecs(options = {}) {
929
929
  }
930
930
  if (options.assignee) filterParts.push(`assignee=${options.assignee}`);
931
931
  if (filterParts.length > 0) {
932
- console.log(chalk18.dim(`Filtered by: ${filterParts.join(", ")}`));
932
+ console.log(chalk19.dim(`Filtered by: ${filterParts.join(", ")}`));
933
933
  }
934
934
  console.log("");
935
935
  const patternInfo = detectPatternType(config);
@@ -939,7 +939,7 @@ async function listSpecs(options = {}) {
939
939
  renderFlatList(specs);
940
940
  }
941
941
  console.log("");
942
- console.log(chalk18.bold(`Total: ${chalk18.green(specs.length)} spec${specs.length !== 1 ? "s" : ""}`));
942
+ console.log(chalk19.bold(`Total: ${chalk19.green(specs.length)} spec${specs.length !== 1 ? "s" : ""}`));
943
943
  }
944
944
  function renderFlatList(specs) {
945
945
  for (const spec of specs) {
@@ -947,25 +947,25 @@ function renderFlatList(specs) {
947
947
  const priorityEmoji = getPriorityEmoji(spec.frontmatter.priority);
948
948
  let assigneeStr = "";
949
949
  if (spec.frontmatter.assignee) {
950
- assigneeStr = " " + chalk18.cyan(`@${sanitizeUserInput(spec.frontmatter.assignee)}`);
950
+ assigneeStr = " " + chalk19.cyan(`@${sanitizeUserInput(spec.frontmatter.assignee)}`);
951
951
  }
952
952
  let tagsStr = "";
953
953
  if (spec.frontmatter.tags?.length) {
954
954
  const tags = Array.isArray(spec.frontmatter.tags) ? spec.frontmatter.tags : [];
955
955
  if (tags.length > 0) {
956
956
  const tagStr = tags.map((tag) => `#${sanitizeUserInput(tag)}`).join(" ");
957
- tagsStr = " " + chalk18.dim(chalk18.magenta(tagStr));
957
+ tagsStr = " " + chalk19.dim(chalk19.magenta(tagStr));
958
958
  }
959
959
  }
960
960
  let subSpecStr = "";
961
961
  if (spec.subFiles) {
962
962
  const docCount = spec.subFiles.filter((f) => f.type === "document").length;
963
963
  if (docCount > 0) {
964
- subSpecStr = " " + chalk18.dim(chalk18.yellow(`(+${docCount} sub-spec${docCount > 1 ? "s" : ""})`));
964
+ subSpecStr = " " + chalk19.dim(chalk19.yellow(`(+${docCount} sub-spec${docCount > 1 ? "s" : ""})`));
965
965
  }
966
966
  }
967
967
  const priorityPrefix = priorityEmoji ? `${priorityEmoji} ` : "";
968
- console.log(`${priorityPrefix}${statusEmoji} ${chalk18.cyan(sanitizeUserInput(spec.path))}${assigneeStr}${tagsStr}${subSpecStr}`);
968
+ console.log(`${priorityPrefix}${statusEmoji} ${chalk19.cyan(sanitizeUserInput(spec.path))}${assigneeStr}${tagsStr}${subSpecStr}`);
969
969
  }
970
970
  }
971
971
  function renderGroupedList(specs, groupExtractor) {
@@ -994,7 +994,7 @@ function renderGroupedList(specs, groupExtractor) {
994
994
  const groupName = sortedGroups[i];
995
995
  const groupSpecs = groups.get(groupName);
996
996
  const groupEmoji = /^\d{8}$/.test(groupName) ? "\u{1F4C5}" : groupName.startsWith("milestone") ? "\u{1F3AF}" : "\u{1F4C1}";
997
- console.log(`${chalk18.bold.cyan(`${groupEmoji} ${groupName}/`)} ${chalk18.dim(`(${groupSpecs.length})`)}`);
997
+ console.log(`${chalk19.bold.cyan(`${groupEmoji} ${groupName}/`)} ${chalk19.dim(`(${groupSpecs.length})`)}`);
998
998
  console.log("");
999
999
  for (const spec of groupSpecs) {
1000
1000
  const statusEmoji = getStatusEmoji(spec.frontmatter.status);
@@ -1002,25 +1002,25 @@ function renderGroupedList(specs, groupExtractor) {
1002
1002
  const displayPath = spec.path.includes("/") ? spec.path.split("/").slice(1).join("/") : spec.path;
1003
1003
  let assigneeStr = "";
1004
1004
  if (spec.frontmatter.assignee) {
1005
- assigneeStr = " " + chalk18.cyan(`@${sanitizeUserInput(spec.frontmatter.assignee)}`);
1005
+ assigneeStr = " " + chalk19.cyan(`@${sanitizeUserInput(spec.frontmatter.assignee)}`);
1006
1006
  }
1007
1007
  let tagsStr = "";
1008
1008
  if (spec.frontmatter.tags?.length) {
1009
1009
  const tags = Array.isArray(spec.frontmatter.tags) ? spec.frontmatter.tags : [];
1010
1010
  if (tags.length > 0) {
1011
1011
  const tagStr = tags.map((tag) => `#${sanitizeUserInput(tag)}`).join(" ");
1012
- tagsStr = " " + chalk18.dim(chalk18.magenta(tagStr));
1012
+ tagsStr = " " + chalk19.dim(chalk19.magenta(tagStr));
1013
1013
  }
1014
1014
  }
1015
1015
  let subSpecStr = "";
1016
1016
  if (spec.subFiles) {
1017
1017
  const docCount = spec.subFiles.filter((f) => f.type === "document").length;
1018
1018
  if (docCount > 0) {
1019
- subSpecStr = " " + chalk18.dim(chalk18.yellow(`(+${docCount} sub-spec${docCount > 1 ? "s" : ""})`));
1019
+ subSpecStr = " " + chalk19.dim(chalk19.yellow(`(+${docCount} sub-spec${docCount > 1 ? "s" : ""})`));
1020
1020
  }
1021
1021
  }
1022
1022
  const priorityPrefix = priorityEmoji ? `${priorityEmoji} ` : "";
1023
- console.log(` ${priorityPrefix}${statusEmoji} ${chalk18.cyan(sanitizeUserInput(displayPath))}${assigneeStr}${tagsStr}${subSpecStr}`);
1023
+ console.log(` ${priorityPrefix}${statusEmoji} ${chalk19.cyan(sanitizeUserInput(displayPath))}${assigneeStr}${tagsStr}${subSpecStr}`);
1024
1024
  }
1025
1025
  if (i < sortedGroups.length - 1) {
1026
1026
  console.log("");
@@ -1053,7 +1053,7 @@ async function updateSpec(specPath, updates, options = {}) {
1053
1053
  await autoCheckIfEnabled();
1054
1054
  const cwd = options.cwd ?? process.cwd();
1055
1055
  const config = await loadConfig(cwd);
1056
- const specsDir = path4.join(cwd, config.specsDir);
1056
+ const specsDir = path15.join(cwd, config.specsDir);
1057
1057
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
1058
1058
  if (!resolvedPath) {
1059
1059
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}. Tried: ${sanitizeUserInput(specPath)}, specs/${sanitizeUserInput(specPath)}, and searching in date directories`);
@@ -1075,12 +1075,12 @@ async function updateSpec(specPath, updates, options = {}) {
1075
1075
  });
1076
1076
  }
1077
1077
  await updateFrontmatter(specFile, allUpdates);
1078
- console.log(chalk18.green(`\u2713 Updated: ${sanitizeUserInput(path4.relative(cwd, resolvedPath))}`));
1078
+ console.log(chalk19.green(`\u2713 Updated: ${sanitizeUserInput(path15.relative(cwd, resolvedPath))}`));
1079
1079
  const updatedFields = Object.keys(updates).filter((k) => k !== "customFields");
1080
1080
  if (updates.customFields) {
1081
1081
  updatedFields.push(...Object.keys(updates.customFields));
1082
1082
  }
1083
- console.log(chalk18.gray(` Fields: ${updatedFields.join(", ")}`));
1083
+ console.log(chalk19.gray(` Fields: ${updatedFields.join(", ")}`));
1084
1084
  }
1085
1085
  function linkCommand() {
1086
1086
  return new Command("link").description("Add relationships between specs (depends_on, related)").argument("<spec>", "Spec to update").option("--depends-on <specs>", "Add dependencies (comma-separated spec numbers or names)").option("--related <specs>", "Add related specs (comma-separated spec numbers or names)").action(async (specPath, options) => {
@@ -1095,7 +1095,7 @@ async function linkSpec(specPath, options) {
1095
1095
  await autoCheckIfEnabled();
1096
1096
  const config = await loadConfig();
1097
1097
  const cwd = process.cwd();
1098
- const specsDir = path4.join(cwd, config.specsDir);
1098
+ const specsDir = path15.join(cwd, config.specsDir);
1099
1099
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
1100
1100
  if (!resolvedPath) {
1101
1101
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);
@@ -1108,7 +1108,7 @@ async function linkSpec(specPath, options) {
1108
1108
  const specMap = new Map(allSpecs.map((s) => [s.path, s]));
1109
1109
  const dependsOnSpecs = options.dependsOn ? options.dependsOn.split(",").map((s) => s.trim()) : [];
1110
1110
  const relatedSpecs = options.related ? options.related.split(",").map((s) => s.trim()) : [];
1111
- const targetSpecName = path4.basename(resolvedPath);
1111
+ const targetSpecName = path15.basename(resolvedPath);
1112
1112
  const allRelationshipSpecs = [...dependsOnSpecs, ...relatedSpecs];
1113
1113
  const resolvedRelationships = /* @__PURE__ */ new Map();
1114
1114
  for (const relSpec of allRelationshipSpecs) {
@@ -1122,7 +1122,7 @@ async function linkSpec(specPath, options) {
1122
1122
  if (relResolvedPath === resolvedPath) {
1123
1123
  throw new Error(`Cannot link spec to itself: ${sanitizeUserInput(relSpec)}`);
1124
1124
  }
1125
- const relSpecName = path4.basename(relResolvedPath);
1125
+ const relSpecName = path15.basename(relResolvedPath);
1126
1126
  resolvedRelationships.set(relSpec, relSpecName);
1127
1127
  }
1128
1128
  const { parseFrontmatter: parseFrontmatter2 } = await import('./frontmatter-R2DANL5X.js');
@@ -1142,7 +1142,7 @@ async function linkSpec(specPath, options) {
1142
1142
  }
1143
1143
  updates.depends_on = newDependsOn;
1144
1144
  if (added === 0) {
1145
- console.log(chalk18.gray(`\u2139 Dependencies already exist, no changes made`));
1145
+ console.log(chalk19.gray(`\u2139 Dependencies already exist, no changes made`));
1146
1146
  }
1147
1147
  }
1148
1148
  if (relatedSpecs.length > 0) {
@@ -1169,19 +1169,19 @@ async function linkSpec(specPath, options) {
1169
1169
  await updateFrontmatter(relSpecFile, {
1170
1170
  related: [...relCurrentRelated, targetSpecName]
1171
1171
  });
1172
- console.log(chalk18.gray(` Updated: ${sanitizeUserInput(relSpecName)} (bidirectional)`));
1172
+ console.log(chalk19.gray(` Updated: ${sanitizeUserInput(relSpecName)} (bidirectional)`));
1173
1173
  }
1174
1174
  }
1175
1175
  }
1176
1176
  }
1177
1177
  if (added === 0) {
1178
- console.log(chalk18.gray(`\u2139 Related specs already exist, no changes made`));
1178
+ console.log(chalk19.gray(`\u2139 Related specs already exist, no changes made`));
1179
1179
  }
1180
1180
  }
1181
1181
  if (updates.depends_on && updates.depends_on.length > 0) {
1182
1182
  const cycles = detectCycles(targetSpecName, updates.depends_on, specMap);
1183
1183
  if (cycles.length > 0) {
1184
- console.log(chalk18.yellow(`\u26A0\uFE0F Dependency cycle detected: ${cycles.join(" \u2192 ")}`));
1184
+ console.log(chalk19.yellow(`\u26A0\uFE0F Dependency cycle detected: ${cycles.join(" \u2192 ")}`));
1185
1185
  }
1186
1186
  }
1187
1187
  await updateFrontmatter(specFile, updates);
@@ -1192,8 +1192,8 @@ async function linkSpec(specPath, options) {
1192
1192
  if (relatedSpecs.length > 0) {
1193
1193
  updatedFields.push(`related: ${relatedSpecs.join(", ")}`);
1194
1194
  }
1195
- console.log(chalk18.green(`\u2713 Added relationships: ${updatedFields.join(", ")}`));
1196
- console.log(chalk18.gray(` Updated: ${sanitizeUserInput(path4.relative(cwd, resolvedPath))}`));
1195
+ console.log(chalk19.green(`\u2713 Added relationships: ${updatedFields.join(", ")}`));
1196
+ console.log(chalk19.gray(` Updated: ${sanitizeUserInput(path15.relative(cwd, resolvedPath))}`));
1197
1197
  }
1198
1198
  function detectCycles(startSpec, dependsOn, specMap, visited = /* @__PURE__ */ new Set(), path31 = []) {
1199
1199
  if (visited.has(startSpec)) {
@@ -1229,7 +1229,7 @@ async function unlinkSpec(specPath, options) {
1229
1229
  await autoCheckIfEnabled();
1230
1230
  const config = await loadConfig();
1231
1231
  const cwd = process.cwd();
1232
- const specsDir = path4.join(cwd, config.specsDir);
1232
+ const specsDir = path15.join(cwd, config.specsDir);
1233
1233
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
1234
1234
  if (!resolvedPath) {
1235
1235
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);
@@ -1238,7 +1238,7 @@ async function unlinkSpec(specPath, options) {
1238
1238
  if (!specFile) {
1239
1239
  throw new Error(`No spec file found in: ${sanitizeUserInput(specPath)}`);
1240
1240
  }
1241
- const targetSpecName = path4.basename(resolvedPath);
1241
+ const targetSpecName = path15.basename(resolvedPath);
1242
1242
  const { parseFrontmatter: parseFrontmatter2 } = await import('./frontmatter-R2DANL5X.js');
1243
1243
  const currentFrontmatter = await parseFrontmatter2(specFile);
1244
1244
  const currentDependsOn = currentFrontmatter?.depends_on || [];
@@ -1255,7 +1255,7 @@ async function unlinkSpec(specPath, options) {
1255
1255
  for (const spec of toRemove) {
1256
1256
  const resolvedSpecPath = await resolveSpecPath(spec, cwd, specsDir);
1257
1257
  if (resolvedSpecPath) {
1258
- resolvedToRemove.add(path4.basename(resolvedSpecPath));
1258
+ resolvedToRemove.add(path15.basename(resolvedSpecPath));
1259
1259
  } else {
1260
1260
  resolvedToRemove.add(spec);
1261
1261
  }
@@ -1279,7 +1279,7 @@ async function unlinkSpec(specPath, options) {
1279
1279
  await updateFrontmatter(relSpecFile, {
1280
1280
  related: relNewRelated
1281
1281
  });
1282
- console.log(chalk18.gray(` Updated: ${sanitizeUserInput(relSpec)} (bidirectional)`));
1282
+ console.log(chalk19.gray(` Updated: ${sanitizeUserInput(relSpec)} (bidirectional)`));
1283
1283
  }
1284
1284
  }
1285
1285
  }
@@ -1292,7 +1292,7 @@ async function unlinkSpec(specPath, options) {
1292
1292
  for (const spec of toRemove) {
1293
1293
  const resolvedSpecPath = await resolveSpecPath(spec, cwd, specsDir);
1294
1294
  if (resolvedSpecPath) {
1295
- const specName = path4.basename(resolvedSpecPath);
1295
+ const specName = path15.basename(resolvedSpecPath);
1296
1296
  resolvedToRemove.add(specName);
1297
1297
  const relSpecFile = await getSpecFile(resolvedSpecPath, config.structure.defaultFile);
1298
1298
  if (relSpecFile) {
@@ -1303,7 +1303,7 @@ async function unlinkSpec(specPath, options) {
1303
1303
  await updateFrontmatter(relSpecFile, {
1304
1304
  related: relNewRelated
1305
1305
  });
1306
- console.log(chalk18.gray(` Updated: ${sanitizeUserInput(specName)} (bidirectional)`));
1306
+ console.log(chalk19.gray(` Updated: ${sanitizeUserInput(specName)} (bidirectional)`));
1307
1307
  }
1308
1308
  }
1309
1309
  } else {
@@ -1317,7 +1317,7 @@ async function unlinkSpec(specPath, options) {
1317
1317
  }
1318
1318
  await updateFrontmatter(specFile, updates);
1319
1319
  if (removedCount === 0) {
1320
- console.log(chalk18.gray(`\u2139 No matching relationships found to remove`));
1320
+ console.log(chalk19.gray(`\u2139 No matching relationships found to remove`));
1321
1321
  } else {
1322
1322
  const updatedFields = [];
1323
1323
  if (options.dependsOn !== void 0) {
@@ -1326,8 +1326,8 @@ async function unlinkSpec(specPath, options) {
1326
1326
  if (options.related !== void 0) {
1327
1327
  updatedFields.push(`related`);
1328
1328
  }
1329
- console.log(chalk18.green(`\u2713 Removed relationships: ${updatedFields.join(", ")} (${removedCount} total)`));
1330
- console.log(chalk18.gray(` Updated: ${sanitizeUserInput(path4.relative(cwd, resolvedPath))}`));
1329
+ console.log(chalk19.green(`\u2713 Removed relationships: ${updatedFields.join(", ")} (${removedCount} total)`));
1330
+ console.log(chalk19.gray(` Updated: ${sanitizeUserInput(path15.relative(cwd, resolvedPath))}`));
1331
1331
  }
1332
1332
  }
1333
1333
  function isGitRepository() {
@@ -1480,7 +1480,7 @@ async function backfillTimestamps(options = {}) {
1480
1480
  specs = [];
1481
1481
  const config = await loadConfig();
1482
1482
  const cwd = process.cwd();
1483
- const specsDir = path4.join(cwd, config.specsDir);
1483
+ const specsDir = path15.join(cwd, config.specsDir);
1484
1484
  for (const specPath of options.specs) {
1485
1485
  const resolved = await resolveSpecPath(specPath, cwd, specsDir);
1486
1486
  if (!resolved) {
@@ -1676,79 +1676,79 @@ function templatesCommand() {
1676
1676
  }
1677
1677
  async function listTemplates(cwd = process.cwd()) {
1678
1678
  const config = await loadConfig(cwd);
1679
- const templatesDir = path4.join(cwd, ".lean-spec", "templates");
1679
+ const templatesDir = path15.join(cwd, ".lean-spec", "templates");
1680
1680
  console.log("");
1681
- console.log(chalk18.green("=== Project Templates ==="));
1681
+ console.log(chalk19.green("=== Project Templates ==="));
1682
1682
  console.log("");
1683
1683
  try {
1684
1684
  await fs9.access(templatesDir);
1685
1685
  } catch {
1686
- console.log(chalk18.yellow("No templates directory found."));
1687
- console.log(chalk18.gray("Run: lean-spec init"));
1686
+ console.log(chalk19.yellow("No templates directory found."));
1687
+ console.log(chalk19.gray("Run: lean-spec init"));
1688
1688
  console.log("");
1689
1689
  return;
1690
1690
  }
1691
1691
  const files = await fs9.readdir(templatesDir);
1692
1692
  const templateFiles = files.filter((f) => f.endsWith(".md"));
1693
1693
  if (templateFiles.length === 0) {
1694
- console.log(chalk18.yellow("No templates found."));
1694
+ console.log(chalk19.yellow("No templates found."));
1695
1695
  console.log("");
1696
1696
  return;
1697
1697
  }
1698
1698
  if (config.templates && Object.keys(config.templates).length > 0) {
1699
- console.log(chalk18.cyan("Registered:"));
1699
+ console.log(chalk19.cyan("Registered:"));
1700
1700
  for (const [name, file] of Object.entries(config.templates)) {
1701
1701
  const isDefault = config.template === file;
1702
- const marker = isDefault ? chalk18.green("\u2713 (default)") : "";
1703
- console.log(` ${chalk18.bold(name)}: ${file} ${marker}`);
1702
+ const marker = isDefault ? chalk19.green("\u2713 (default)") : "";
1703
+ console.log(` ${chalk19.bold(name)}: ${file} ${marker}`);
1704
1704
  }
1705
1705
  console.log("");
1706
1706
  }
1707
- console.log(chalk18.cyan("Available files:"));
1707
+ console.log(chalk19.cyan("Available files:"));
1708
1708
  for (const file of templateFiles) {
1709
- const filePath = path4.join(templatesDir, file);
1709
+ const filePath = path15.join(templatesDir, file);
1710
1710
  const stat6 = await fs9.stat(filePath);
1711
1711
  const sizeKB = (stat6.size / 1024).toFixed(1);
1712
1712
  console.log(` ${file} (${sizeKB} KB)`);
1713
1713
  }
1714
1714
  console.log("");
1715
- console.log(chalk18.gray("Use templates with: lean-spec create <name> --template=<template-name>"));
1715
+ console.log(chalk19.gray("Use templates with: lean-spec create <name> --template=<template-name>"));
1716
1716
  console.log("");
1717
1717
  }
1718
1718
  async function showTemplate(templateName, cwd = process.cwd()) {
1719
1719
  const config = await loadConfig(cwd);
1720
1720
  if (!config.templates?.[templateName]) {
1721
- console.error(chalk18.red(`Template not found: ${templateName}`));
1722
- console.error(chalk18.gray(`Available: ${Object.keys(config.templates || {}).join(", ")}`));
1721
+ console.error(chalk19.red(`Template not found: ${templateName}`));
1722
+ console.error(chalk19.gray(`Available: ${Object.keys(config.templates || {}).join(", ")}`));
1723
1723
  process.exit(1);
1724
1724
  }
1725
- const templatesDir = path4.join(cwd, ".lean-spec", "templates");
1725
+ const templatesDir = path15.join(cwd, ".lean-spec", "templates");
1726
1726
  const templateFile = config.templates[templateName];
1727
- const templatePath = path4.join(templatesDir, templateFile);
1727
+ const templatePath = path15.join(templatesDir, templateFile);
1728
1728
  try {
1729
1729
  const content = await fs9.readFile(templatePath, "utf-8");
1730
1730
  console.log("");
1731
- console.log(chalk18.cyan(`=== Template: ${templateName} (${templateFile}) ===`));
1731
+ console.log(chalk19.cyan(`=== Template: ${templateName} (${templateFile}) ===`));
1732
1732
  console.log("");
1733
1733
  console.log(content);
1734
1734
  console.log("");
1735
1735
  } catch (error) {
1736
- console.error(chalk18.red(`Error reading template: ${templateFile}`));
1736
+ console.error(chalk19.red(`Error reading template: ${templateFile}`));
1737
1737
  console.error(error);
1738
1738
  process.exit(1);
1739
1739
  }
1740
1740
  }
1741
1741
  async function addTemplate(name, file, cwd = process.cwd()) {
1742
1742
  const config = await loadConfig(cwd);
1743
- const templatesDir = path4.join(cwd, ".lean-spec", "templates");
1744
- const templatePath = path4.join(templatesDir, file);
1743
+ const templatesDir = path15.join(cwd, ".lean-spec", "templates");
1744
+ const templatePath = path15.join(templatesDir, file);
1745
1745
  try {
1746
1746
  await fs9.access(templatePath);
1747
1747
  } catch {
1748
- console.error(chalk18.red(`Template file not found: ${file}`));
1749
- console.error(chalk18.gray(`Expected at: ${templatePath}`));
1748
+ console.error(chalk19.red(`Template file not found: ${file}`));
1749
+ console.error(chalk19.gray(`Expected at: ${templatePath}`));
1750
1750
  console.error(
1751
- chalk18.yellow("Create the file first or use: lean-spec templates copy <source> <target>")
1751
+ chalk19.yellow("Create the file first or use: lean-spec templates copy <source> <target>")
1752
1752
  );
1753
1753
  process.exit(1);
1754
1754
  }
@@ -1756,60 +1756,60 @@ async function addTemplate(name, file, cwd = process.cwd()) {
1756
1756
  config.templates = {};
1757
1757
  }
1758
1758
  if (config.templates[name]) {
1759
- console.log(chalk18.yellow(`Warning: Template '${name}' already exists, updating...`));
1759
+ console.log(chalk19.yellow(`Warning: Template '${name}' already exists, updating...`));
1760
1760
  }
1761
1761
  config.templates[name] = file;
1762
1762
  await saveConfig(config, cwd);
1763
- console.log(chalk18.green(`\u2713 Added template: ${name} \u2192 ${file}`));
1764
- console.log(chalk18.gray(` Use with: lean-spec create <spec-name> --template=${name}`));
1763
+ console.log(chalk19.green(`\u2713 Added template: ${name} \u2192 ${file}`));
1764
+ console.log(chalk19.gray(` Use with: lean-spec create <spec-name> --template=${name}`));
1765
1765
  }
1766
1766
  async function removeTemplate(name, cwd = process.cwd()) {
1767
1767
  const config = await loadConfig(cwd);
1768
1768
  if (!config.templates?.[name]) {
1769
- console.error(chalk18.red(`Template not found: ${name}`));
1770
- console.error(chalk18.gray(`Available: ${Object.keys(config.templates || {}).join(", ")}`));
1769
+ console.error(chalk19.red(`Template not found: ${name}`));
1770
+ console.error(chalk19.gray(`Available: ${Object.keys(config.templates || {}).join(", ")}`));
1771
1771
  process.exit(1);
1772
1772
  }
1773
1773
  if (name === "default") {
1774
- console.error(chalk18.red("Cannot remove default template"));
1774
+ console.error(chalk19.red("Cannot remove default template"));
1775
1775
  process.exit(1);
1776
1776
  }
1777
1777
  const file = config.templates[name];
1778
1778
  delete config.templates[name];
1779
1779
  await saveConfig(config, cwd);
1780
- console.log(chalk18.green(`\u2713 Removed template: ${name}`));
1781
- console.log(chalk18.gray(` Note: Template file ${file} still exists in .lean-spec/templates/`));
1780
+ console.log(chalk19.green(`\u2713 Removed template: ${name}`));
1781
+ console.log(chalk19.gray(` Note: Template file ${file} still exists in .lean-spec/templates/`));
1782
1782
  }
1783
1783
  async function copyTemplate(source, target, cwd = process.cwd()) {
1784
1784
  const config = await loadConfig(cwd);
1785
- const templatesDir = path4.join(cwd, ".lean-spec", "templates");
1785
+ const templatesDir = path15.join(cwd, ".lean-spec", "templates");
1786
1786
  let sourceFile;
1787
1787
  if (config.templates?.[source]) {
1788
1788
  sourceFile = config.templates[source];
1789
1789
  } else {
1790
1790
  sourceFile = source;
1791
1791
  }
1792
- const sourcePath = path4.join(templatesDir, sourceFile);
1792
+ const sourcePath = path15.join(templatesDir, sourceFile);
1793
1793
  try {
1794
1794
  await fs9.access(sourcePath);
1795
1795
  } catch {
1796
- console.error(chalk18.red(`Source template not found: ${source}`));
1797
- console.error(chalk18.gray(`Expected at: ${sourcePath}`));
1796
+ console.error(chalk19.red(`Source template not found: ${source}`));
1797
+ console.error(chalk19.gray(`Expected at: ${sourcePath}`));
1798
1798
  process.exit(1);
1799
1799
  }
1800
1800
  const targetFile = target.endsWith(".md") ? target : `${target}.md`;
1801
- const targetPath = path4.join(templatesDir, targetFile);
1801
+ const targetPath = path15.join(templatesDir, targetFile);
1802
1802
  await fs9.copyFile(sourcePath, targetPath);
1803
- console.log(chalk18.green(`\u2713 Copied: ${sourceFile} \u2192 ${targetFile}`));
1803
+ console.log(chalk19.green(`\u2713 Copied: ${sourceFile} \u2192 ${targetFile}`));
1804
1804
  if (!config.templates) {
1805
1805
  config.templates = {};
1806
1806
  }
1807
1807
  const templateName = target.replace(/\.md$/, "");
1808
1808
  config.templates[templateName] = targetFile;
1809
1809
  await saveConfig(config, cwd);
1810
- console.log(chalk18.green(`\u2713 Registered template: ${templateName}`));
1811
- console.log(chalk18.gray(` Edit: ${targetPath}`));
1812
- console.log(chalk18.gray(` Use with: lean-spec create <spec-name> --template=${templateName}`));
1810
+ console.log(chalk19.green(`\u2713 Registered template: ${templateName}`));
1811
+ console.log(chalk19.gray(` Edit: ${targetPath}`));
1812
+ console.log(chalk19.gray(` Use with: lean-spec create <spec-name> --template=${templateName}`));
1813
1813
  }
1814
1814
  async function detectExistingSystemPrompts(cwd) {
1815
1815
  const commonFiles = [
@@ -1820,7 +1820,7 @@ async function detectExistingSystemPrompts(cwd) {
1820
1820
  const found = [];
1821
1821
  for (const file of commonFiles) {
1822
1822
  try {
1823
- await fs9.access(path4.join(cwd, file));
1823
+ await fs9.access(path15.join(cwd, file));
1824
1824
  found.push(file);
1825
1825
  } catch {
1826
1826
  }
@@ -1829,8 +1829,8 @@ async function detectExistingSystemPrompts(cwd) {
1829
1829
  }
1830
1830
  async function handleExistingFiles(action, existingFiles, templateDir, cwd, variables = {}) {
1831
1831
  for (const file of existingFiles) {
1832
- const filePath = path4.join(cwd, file);
1833
- const templateFilePath = path4.join(templateDir, "files", file);
1832
+ const filePath = path15.join(cwd, file);
1833
+ const templateFilePath = path15.join(templateDir, "files", file);
1834
1834
  try {
1835
1835
  await fs9.access(templateFilePath);
1836
1836
  } catch {
@@ -1842,7 +1842,7 @@ async function handleExistingFiles(action, existingFiles, templateDir, cwd, vari
1842
1842
  for (const [key, value] of Object.entries(variables)) {
1843
1843
  template = template.replace(new RegExp(`\\{${key}\\}`, "g"), value);
1844
1844
  }
1845
- const promptPath = path4.join(cwd, ".lean-spec", "MERGE-AGENTS-PROMPT.md");
1845
+ const promptPath = path15.join(cwd, ".lean-spec", "MERGE-AGENTS-PROMPT.md");
1846
1846
  const aiPrompt = `# AI Prompt: Consolidate AGENTS.md
1847
1847
 
1848
1848
  ## Task
@@ -1874,16 +1874,16 @@ Create a single consolidated AGENTS.md that:
1874
1874
  - Maintains clear structure and readability
1875
1875
  - Removes any duplicate or conflicting guidance
1876
1876
  `;
1877
- await fs9.mkdir(path4.dirname(promptPath), { recursive: true });
1877
+ await fs9.mkdir(path15.dirname(promptPath), { recursive: true });
1878
1878
  await fs9.writeFile(promptPath, aiPrompt, "utf-8");
1879
- console.log(chalk18.green(`\u2713 Created AI consolidation prompt`));
1880
- console.log(chalk18.cyan(` \u2192 ${promptPath}`));
1879
+ console.log(chalk19.green(`\u2713 Created AI consolidation prompt`));
1880
+ console.log(chalk19.cyan(` \u2192 ${promptPath}`));
1881
1881
  console.log("");
1882
- console.log(chalk18.yellow("\u{1F4DD} Next steps:"));
1883
- console.log(chalk18.gray(" 1. Open .lean-spec/MERGE-AGENTS-PROMPT.md"));
1884
- console.log(chalk18.gray(" 2. Send it to your AI coding assistant (GitHub Copilot, Cursor, etc.)"));
1885
- console.log(chalk18.gray(" 3. Let AI create the consolidated AGENTS.md"));
1886
- console.log(chalk18.gray(" 4. Review and commit the result"));
1882
+ console.log(chalk19.yellow("\u{1F4DD} Next steps:"));
1883
+ console.log(chalk19.gray(" 1. Open .lean-spec/MERGE-AGENTS-PROMPT.md"));
1884
+ console.log(chalk19.gray(" 2. Send it to your AI coding assistant (GitHub Copilot, Cursor, etc.)"));
1885
+ console.log(chalk19.gray(" 3. Let AI create the consolidated AGENTS.md"));
1886
+ console.log(chalk19.gray(" 4. Review and commit the result"));
1887
1887
  console.log("");
1888
1888
  } else if (action === "merge-append" && file === "AGENTS.md") {
1889
1889
  const existing = await fs9.readFile(filePath, "utf-8");
@@ -1899,19 +1899,19 @@ Create a single consolidated AGENTS.md that:
1899
1899
 
1900
1900
  ${template.split("\n").slice(1).join("\n")}`;
1901
1901
  await fs9.writeFile(filePath, merged, "utf-8");
1902
- console.log(chalk18.green(`\u2713 Appended LeanSpec section to ${file}`));
1903
- console.log(chalk18.yellow(" \u26A0 Note: May be verbose. Consider consolidating later."));
1902
+ console.log(chalk19.green(`\u2713 Appended LeanSpec section to ${file}`));
1903
+ console.log(chalk19.yellow(" \u26A0 Note: May be verbose. Consider consolidating later."));
1904
1904
  } else if (action === "overwrite") {
1905
1905
  const backupPath = `${filePath}.backup`;
1906
1906
  await fs9.rename(filePath, backupPath);
1907
- console.log(chalk18.yellow(`\u2713 Backed up ${file} \u2192 ${file}.backup`));
1907
+ console.log(chalk19.yellow(`\u2713 Backed up ${file} \u2192 ${file}.backup`));
1908
1908
  let content = await fs9.readFile(templateFilePath, "utf-8");
1909
1909
  for (const [key, value] of Object.entries(variables)) {
1910
1910
  content = content.replace(new RegExp(`\\{${key}\\}`, "g"), value);
1911
1911
  }
1912
1912
  await fs9.writeFile(filePath, content, "utf-8");
1913
- console.log(chalk18.green(`\u2713 Created new ${file}`));
1914
- console.log(chalk18.gray(` \u{1F4A1} Your original content is preserved in ${file}.backup`));
1913
+ console.log(chalk19.green(`\u2713 Created new ${file}`));
1914
+ console.log(chalk19.gray(` \u{1F4A1} Your original content is preserved in ${file}.backup`));
1915
1915
  }
1916
1916
  }
1917
1917
  }
@@ -1919,8 +1919,8 @@ async function copyDirectory(src, dest, skipFiles = [], variables = {}) {
1919
1919
  await fs9.mkdir(dest, { recursive: true });
1920
1920
  const entries = await fs9.readdir(src, { withFileTypes: true });
1921
1921
  for (const entry of entries) {
1922
- const srcPath = path4.join(src, entry.name);
1923
- const destPath = path4.join(dest, entry.name);
1922
+ const srcPath = path15.join(src, entry.name);
1923
+ const destPath = path15.join(dest, entry.name);
1924
1924
  if (skipFiles.includes(entry.name)) {
1925
1925
  continue;
1926
1926
  }
@@ -1941,7 +1941,7 @@ async function copyDirectory(src, dest, skipFiles = [], variables = {}) {
1941
1941
  }
1942
1942
  async function getProjectName2(cwd) {
1943
1943
  try {
1944
- const packageJsonPath = path4.join(cwd, "package.json");
1944
+ const packageJsonPath = path15.join(cwd, "package.json");
1945
1945
  const content = await fs9.readFile(packageJsonPath, "utf-8");
1946
1946
  const pkg = JSON.parse(content);
1947
1947
  if (pkg.name) {
@@ -1949,33 +1949,88 @@ async function getProjectName2(cwd) {
1949
1949
  }
1950
1950
  } catch {
1951
1951
  }
1952
- return path4.basename(cwd);
1952
+ return path15.basename(cwd);
1953
+ }
1954
+
1955
+ // src/utils/examples.ts
1956
+ var EXAMPLES = {
1957
+ "email-notifications": {
1958
+ name: "email-notifications",
1959
+ title: "Email Notifications API",
1960
+ description: "Add email notifications to a user registration API",
1961
+ difficulty: "beginner",
1962
+ tutorial: "Your First Feature with AI",
1963
+ tutorialUrl: "https://leanspec.dev/docs/tutorials/first-feature",
1964
+ tech: ["Express.js", "Node.js"],
1965
+ files: 6,
1966
+ lines: 200
1967
+ },
1968
+ "dashboard-widgets": {
1969
+ name: "dashboard-widgets",
1970
+ title: "Dashboard Widgets",
1971
+ description: "Add three new widgets to an analytics dashboard",
1972
+ difficulty: "intermediate",
1973
+ tutorial: "Managing Multiple Features",
1974
+ tutorialUrl: "https://leanspec.dev/docs/tutorials/multiple-features",
1975
+ tech: ["React", "Vite"],
1976
+ files: 17,
1977
+ lines: 300
1978
+ },
1979
+ "api-refactor": {
1980
+ name: "api-refactor",
1981
+ title: "API Client Refactor",
1982
+ description: "Extract reusable API client from monolithic code",
1983
+ difficulty: "intermediate",
1984
+ tutorial: "Refactoring with Specs",
1985
+ tutorialUrl: "https://leanspec.dev/docs/tutorials/refactoring-specs",
1986
+ tech: ["Node.js"],
1987
+ files: 7,
1988
+ lines: 250
1989
+ }
1990
+ };
1991
+ function getExamplesList() {
1992
+ return Object.values(EXAMPLES);
1993
+ }
1994
+ function getExample(name) {
1995
+ return EXAMPLES[name];
1996
+ }
1997
+ function exampleExists(name) {
1998
+ return name in EXAMPLES;
1953
1999
  }
1954
2000
 
1955
2001
  // src/commands/init.ts
1956
- var __dirname = path4.dirname(fileURLToPath(import.meta.url));
1957
- var TEMPLATES_DIR = path4.join(__dirname, "..", "templates");
2002
+ var __dirname = path15.dirname(fileURLToPath(import.meta.url));
2003
+ var TEMPLATES_DIR = path15.join(__dirname, "..", "templates");
2004
+ var EXAMPLES_DIR = path15.join(TEMPLATES_DIR, "examples");
1958
2005
  function initCommand() {
1959
- return new Command("init").description("Initialize LeanSpec in current directory").option("-y, --yes", "Skip prompts and use defaults (quick start with standard template)").action(async (options) => {
2006
+ return new Command("init").description("Initialize LeanSpec in current directory").option("-y, --yes", "Skip prompts and use defaults (quick start with standard template)").option("--example <name>", "Scaffold an example project for tutorials").option("--name <dirname>", "Custom directory name for example project").option("--list", "List available example projects").action(async (options) => {
2007
+ if (options.list) {
2008
+ await listExamples();
2009
+ return;
2010
+ }
2011
+ if (options.example !== void 0) {
2012
+ await scaffoldExample(options.example, options.name);
2013
+ return;
2014
+ }
1960
2015
  await initProject(options.yes);
1961
2016
  });
1962
2017
  }
1963
2018
  async function initProject(skipPrompts = false) {
1964
2019
  const cwd = process.cwd();
1965
2020
  try {
1966
- await fs9.access(path4.join(cwd, ".lean-spec", "config.json"));
1967
- console.log(chalk18.yellow("\u26A0 LeanSpec already initialized in this directory."));
1968
- console.log(chalk18.gray("To reinitialize, delete .lean-spec/ directory first."));
2021
+ await fs9.access(path15.join(cwd, ".lean-spec", "config.json"));
2022
+ console.log(chalk19.yellow("\u26A0 LeanSpec already initialized in this directory."));
2023
+ console.log(chalk19.gray("To reinitialize, delete .lean-spec/ directory first."));
1969
2024
  return;
1970
2025
  } catch {
1971
2026
  }
1972
2027
  console.log("");
1973
- console.log(chalk18.green("Welcome to LeanSpec!"));
2028
+ console.log(chalk19.green("Welcome to LeanSpec!"));
1974
2029
  console.log("");
1975
2030
  let setupMode = "quick";
1976
2031
  let templateName = "standard";
1977
2032
  if (skipPrompts) {
1978
- console.log(chalk18.gray("Using defaults: quick start with standard template"));
2033
+ console.log(chalk19.gray("Using defaults: quick start with standard template"));
1979
2034
  console.log("");
1980
2035
  } else {
1981
2036
  setupMode = await select({
@@ -2014,14 +2069,14 @@ async function initProject(skipPrompts = false) {
2014
2069
  });
2015
2070
  }
2016
2071
  }
2017
- const templateDir = path4.join(TEMPLATES_DIR, templateName);
2018
- const templateConfigPath = path4.join(templateDir, "config.json");
2072
+ const templateDir = path15.join(TEMPLATES_DIR, templateName);
2073
+ const templateConfigPath = path15.join(templateDir, "config.json");
2019
2074
  let templateConfig;
2020
2075
  try {
2021
2076
  const content = await fs9.readFile(templateConfigPath, "utf-8");
2022
2077
  templateConfig = JSON.parse(content).config;
2023
2078
  } catch {
2024
- console.error(chalk18.red(`Error: Template not found: ${templateName}`));
2079
+ console.error(chalk19.red(`Error: Template not found: ${templateName}`));
2025
2080
  process.exit(1);
2026
2081
  }
2027
2082
  let patternChoice = "simple";
@@ -2064,27 +2119,27 @@ async function initProject(skipPrompts = false) {
2064
2119
  templateConfig.structure.prefix = "{YYYYMMDD}-";
2065
2120
  } else if (patternChoice === "custom") {
2066
2121
  console.log("");
2067
- console.log(chalk18.yellow("\u26A0 Custom pattern input is not yet implemented."));
2068
- console.log(chalk18.gray(" You can manually edit .lean-spec/config.json after initialization."));
2069
- console.log(chalk18.gray(" Using simple pattern for now."));
2122
+ console.log(chalk19.yellow("\u26A0 Custom pattern input is not yet implemented."));
2123
+ console.log(chalk19.gray(" You can manually edit .lean-spec/config.json after initialization."));
2124
+ console.log(chalk19.gray(" Using simple pattern for now."));
2070
2125
  console.log("");
2071
2126
  templateConfig.structure.pattern = "flat";
2072
2127
  templateConfig.structure.prefix = "";
2073
2128
  }
2074
- const templatesDir = path4.join(cwd, ".lean-spec", "templates");
2129
+ const templatesDir = path15.join(cwd, ".lean-spec", "templates");
2075
2130
  try {
2076
2131
  await fs9.mkdir(templatesDir, { recursive: true });
2077
2132
  } catch (error) {
2078
- console.error(chalk18.red("Error creating templates directory:"), error);
2133
+ console.error(chalk19.red("Error creating templates directory:"), error);
2079
2134
  process.exit(1);
2080
2135
  }
2081
- const templateSpecPath = path4.join(templateDir, "spec-template.md");
2082
- const targetSpecPath = path4.join(templatesDir, "spec-template.md");
2136
+ const templateSpecPath = path15.join(templateDir, "spec-template.md");
2137
+ const targetSpecPath = path15.join(templatesDir, "spec-template.md");
2083
2138
  try {
2084
2139
  await fs9.copyFile(templateSpecPath, targetSpecPath);
2085
- console.log(chalk18.green("\u2713 Created .lean-spec/templates/spec-template.md"));
2140
+ console.log(chalk19.green("\u2713 Created .lean-spec/templates/spec-template.md"));
2086
2141
  } catch (error) {
2087
- console.error(chalk18.red("Error copying template:"), error);
2142
+ console.error(chalk19.red("Error copying template:"), error);
2088
2143
  process.exit(1);
2089
2144
  }
2090
2145
  templateConfig.template = "spec-template.md";
@@ -2092,14 +2147,14 @@ async function initProject(skipPrompts = false) {
2092
2147
  default: "spec-template.md"
2093
2148
  };
2094
2149
  await saveConfig(templateConfig, cwd);
2095
- console.log(chalk18.green("\u2713 Created .lean-spec/config.json"));
2150
+ console.log(chalk19.green("\u2713 Created .lean-spec/config.json"));
2096
2151
  const existingFiles = await detectExistingSystemPrompts(cwd);
2097
2152
  let skipFiles = [];
2098
2153
  if (existingFiles.length > 0) {
2099
2154
  console.log("");
2100
- console.log(chalk18.yellow(`Found existing: ${existingFiles.join(", ")}`));
2155
+ console.log(chalk19.yellow(`Found existing: ${existingFiles.join(", ")}`));
2101
2156
  if (skipPrompts) {
2102
- console.log(chalk18.gray("Using AI-Assisted Merge for existing AGENTS.md"));
2157
+ console.log(chalk19.gray("Using AI-Assisted Merge for existing AGENTS.md"));
2103
2158
  const projectName2 = await getProjectName2(cwd);
2104
2159
  await handleExistingFiles("merge-ai", existingFiles, templateDir, cwd, { project_name: projectName2 });
2105
2160
  } else {
@@ -2136,31 +2191,151 @@ async function initProject(skipPrompts = false) {
2136
2191
  }
2137
2192
  }
2138
2193
  const projectName = await getProjectName2(cwd);
2139
- const filesDir = path4.join(templateDir, "files");
2194
+ const filesDir = path15.join(templateDir, "files");
2140
2195
  try {
2141
2196
  await copyDirectory(filesDir, cwd, skipFiles, { project_name: projectName });
2142
- console.log(chalk18.green("\u2713 Initialized project structure"));
2197
+ console.log(chalk19.green("\u2713 Initialized project structure"));
2143
2198
  } catch (error) {
2144
- console.error(chalk18.red("Error copying template files:"), error);
2199
+ console.error(chalk19.red("Error copying template files:"), error);
2145
2200
  process.exit(1);
2146
2201
  }
2147
- const specsDir = path4.join(cwd, "specs");
2202
+ const specsDir = path15.join(cwd, "specs");
2148
2203
  try {
2149
2204
  await fs9.mkdir(specsDir, { recursive: true });
2150
- console.log(chalk18.green("\u2713 Created specs/ directory"));
2205
+ console.log(chalk19.green("\u2713 Created specs/ directory"));
2151
2206
  } catch (error) {
2152
- console.error(chalk18.red("Error creating specs directory:"), error);
2207
+ console.error(chalk19.red("Error creating specs directory:"), error);
2208
+ process.exit(1);
2209
+ }
2210
+ console.log("");
2211
+ console.log(chalk19.green("\u2713 LeanSpec initialized!"));
2212
+ console.log("");
2213
+ console.log("Next steps:");
2214
+ console.log(chalk19.gray(" - Review and customize AGENTS.md"));
2215
+ console.log(chalk19.gray(" - Check out example spec in specs/"));
2216
+ console.log(chalk19.gray(" - Create your first spec: lean-spec create my-feature"));
2217
+ console.log("");
2218
+ }
2219
+ async function listExamples() {
2220
+ const examples = getExamplesList();
2221
+ console.log("");
2222
+ console.log(chalk19.bold("Available Examples:"));
2223
+ console.log("");
2224
+ for (const example of examples) {
2225
+ const difficultyColor = example.difficulty === "beginner" ? chalk19.green : example.difficulty === "intermediate" ? chalk19.yellow : chalk19.red;
2226
+ console.log(chalk19.cyan(` ${example.name}`));
2227
+ console.log(` ${example.description}`);
2228
+ console.log(` ${difficultyColor(example.difficulty)} \u2022 ${example.tech.join(", ")} \u2022 ~${example.lines} lines`);
2229
+ console.log(` Tutorial: ${chalk19.gray(example.tutorialUrl)}`);
2230
+ console.log("");
2231
+ }
2232
+ console.log("Usage:");
2233
+ console.log(chalk19.gray(" lean-spec init --example <name>"));
2234
+ console.log(chalk19.gray(" lean-spec init --example email-notifications"));
2235
+ console.log("");
2236
+ }
2237
+ async function scaffoldExample(exampleName, customName) {
2238
+ if (!exampleName) {
2239
+ exampleName = await selectExample();
2240
+ }
2241
+ if (!exampleExists(exampleName)) {
2242
+ console.error(chalk19.red(`Error: Example "${exampleName}" not found.`));
2243
+ console.log("");
2244
+ console.log("Available examples:");
2245
+ getExamplesList().forEach((ex) => {
2246
+ console.log(` - ${ex.name}`);
2247
+ });
2248
+ console.log("");
2249
+ console.log("Use: lean-spec init --list");
2153
2250
  process.exit(1);
2154
2251
  }
2252
+ const example = getExample(exampleName);
2253
+ const targetDirName = customName || exampleName;
2254
+ const targetPath = path15.join(process.cwd(), targetDirName);
2255
+ try {
2256
+ const files = await fs9.readdir(targetPath);
2257
+ const nonGitFiles = files.filter((f) => f !== ".git");
2258
+ if (nonGitFiles.length > 0) {
2259
+ console.error(chalk19.red(`Error: Directory "${targetDirName}" already exists and is not empty.`));
2260
+ console.log(chalk19.gray("Choose a different name with --name option."));
2261
+ process.exit(1);
2262
+ }
2263
+ } catch {
2264
+ }
2265
+ console.log("");
2266
+ console.log(chalk19.green(`Setting up example: ${example.title}`));
2267
+ console.log(chalk19.gray(example.description));
2268
+ console.log("");
2269
+ await fs9.mkdir(targetPath, { recursive: true });
2270
+ console.log(chalk19.green(`\u2713 Created directory: ${targetDirName}/`));
2271
+ const examplePath = path15.join(EXAMPLES_DIR, exampleName);
2272
+ await copyDirectoryRecursive(examplePath, targetPath);
2273
+ console.log(chalk19.green("\u2713 Copied example project"));
2274
+ const packageManager = await detectPackageManager();
2275
+ console.log(chalk19.gray(`Installing dependencies with ${packageManager}...`));
2276
+ try {
2277
+ const { execSync: execSync3 } = await import('child_process');
2278
+ execSync3(`${packageManager} install`, {
2279
+ cwd: targetPath,
2280
+ stdio: "inherit"
2281
+ });
2282
+ console.log(chalk19.green("\u2713 Installed dependencies"));
2283
+ } catch (error) {
2284
+ console.log(chalk19.yellow("\u26A0 Failed to install dependencies automatically"));
2285
+ console.log(chalk19.gray(` Run: cd ${targetDirName} && ${packageManager} install`));
2286
+ }
2155
2287
  console.log("");
2156
- console.log(chalk18.green("\u2713 LeanSpec initialized!"));
2288
+ console.log(chalk19.green("\u2713 Example project ready!"));
2157
2289
  console.log("");
2158
2290
  console.log("Next steps:");
2159
- console.log(chalk18.gray(" - Review and customize AGENTS.md"));
2160
- console.log(chalk18.gray(" - Check out example spec in specs/"));
2161
- console.log(chalk18.gray(" - Create your first spec: lean-spec create my-feature"));
2291
+ console.log(chalk19.cyan(` 1. cd ${targetDirName}`));
2292
+ console.log(chalk19.cyan(" 2. Open this project in your editor"));
2293
+ console.log(chalk19.cyan(` 3. Follow the tutorial: ${example.tutorialUrl}`));
2294
+ console.log(chalk19.cyan(` 4. Ask your AI: "Help me with this tutorial using LeanSpec"`));
2162
2295
  console.log("");
2163
2296
  }
2297
+ async function selectExample() {
2298
+ const examples = getExamplesList();
2299
+ const choice = await select({
2300
+ message: "Select an example project:",
2301
+ choices: examples.map((ex) => {
2302
+ const difficultyLabel = ex.difficulty === "beginner" ? "\u2605\u2606\u2606" : ex.difficulty === "intermediate" ? "\u2605\u2605\u2606" : "\u2605\u2605\u2605";
2303
+ return {
2304
+ name: `${ex.title} (${difficultyLabel})`,
2305
+ value: ex.name,
2306
+ description: `${ex.description} \u2022 ${ex.tech.join(", ")}`
2307
+ };
2308
+ })
2309
+ });
2310
+ return choice;
2311
+ }
2312
+ async function copyDirectoryRecursive(src, dest) {
2313
+ const entries = await fs9.readdir(src, { withFileTypes: true });
2314
+ for (const entry of entries) {
2315
+ const srcPath = path15.join(src, entry.name);
2316
+ const destPath = path15.join(dest, entry.name);
2317
+ if (entry.isDirectory()) {
2318
+ await fs9.mkdir(destPath, { recursive: true });
2319
+ await copyDirectoryRecursive(srcPath, destPath);
2320
+ } else {
2321
+ await fs9.copyFile(srcPath, destPath);
2322
+ }
2323
+ }
2324
+ }
2325
+ async function detectPackageManager() {
2326
+ const cwd = process.cwd();
2327
+ try {
2328
+ await fs9.access(path15.join(cwd, "..", "pnpm-lock.yaml"));
2329
+ return "pnpm";
2330
+ } catch {
2331
+ }
2332
+ try {
2333
+ await fs9.access(path15.join(cwd, "..", "yarn.lock"));
2334
+ return "yarn";
2335
+ } catch {
2336
+ }
2337
+ return "npm";
2338
+ }
2164
2339
  function normalizeDateFields2(data) {
2165
2340
  const dateFields = ["created", "completed", "updated", "due"];
2166
2341
  for (const field of dateFields) {
@@ -2552,7 +2727,7 @@ var TokenCounter = class {
2552
2727
  };
2553
2728
  }
2554
2729
  for (const file of filesToCount) {
2555
- const filePath = path4.join(specPath, file);
2730
+ const filePath = path15.join(specPath, file);
2556
2731
  const content = await fs9.readFile(filePath, "utf-8");
2557
2732
  const tokens = await this.countString(content);
2558
2733
  const lines = content.split("\n").length;
@@ -2888,7 +3063,7 @@ var ComplexityValidator = class {
2888
3063
  let hasSubSpecs = false;
2889
3064
  let subSpecCount = 0;
2890
3065
  try {
2891
- const specDir = path4.dirname(spec.filePath);
3066
+ const specDir = path15.dirname(spec.filePath);
2892
3067
  const files = await fs9.readdir(specDir);
2893
3068
  const mdFiles = files.filter(
2894
3069
  (f) => f.endsWith(".md") && f !== "README.md"
@@ -3465,7 +3640,7 @@ async function showFiles(specPath, options = {}) {
3465
3640
  await autoCheckIfEnabled();
3466
3641
  const config = await loadConfig();
3467
3642
  const cwd = process.cwd();
3468
- const specsDir = path4.join(cwd, config.specsDir);
3643
+ const specsDir = path15.join(cwd, config.specsDir);
3469
3644
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
3470
3645
  if (!resolvedPath) {
3471
3646
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}. Try using the full path or spec name (e.g., 001-my-spec)`);
@@ -3476,14 +3651,14 @@ async function showFiles(specPath, options = {}) {
3476
3651
  }
3477
3652
  const subFiles = await loadSubFiles(spec.fullPath);
3478
3653
  console.log("");
3479
- console.log(chalk18.cyan(`\u{1F4C4} Files in ${sanitizeUserInput(spec.name)}`));
3654
+ console.log(chalk19.cyan(`\u{1F4C4} Files in ${sanitizeUserInput(spec.name)}`));
3480
3655
  console.log("");
3481
- console.log(chalk18.green("Required:"));
3656
+ console.log(chalk19.green("Required:"));
3482
3657
  const readmeStat = await fs9.stat(spec.filePath);
3483
3658
  const readmeSize = formatSize(readmeStat.size);
3484
3659
  const readmeContent = await fs9.readFile(spec.filePath, "utf-8");
3485
3660
  const readmeTokens = await countTokens({ content: readmeContent });
3486
- console.log(chalk18.green(` \u2713 README.md (${readmeSize}, ~${readmeTokens.total.toLocaleString()} tokens) Main spec`));
3661
+ console.log(chalk19.green(` \u2713 README.md (${readmeSize}, ~${readmeTokens.total.toLocaleString()} tokens) Main spec`));
3487
3662
  console.log("");
3488
3663
  let filteredFiles = subFiles;
3489
3664
  if (options.type === "docs") {
@@ -3492,27 +3667,27 @@ async function showFiles(specPath, options = {}) {
3492
3667
  filteredFiles = subFiles.filter((f) => f.type === "asset");
3493
3668
  }
3494
3669
  if (filteredFiles.length === 0) {
3495
- console.log(chalk18.gray("No additional files"));
3670
+ console.log(chalk19.gray("No additional files"));
3496
3671
  console.log("");
3497
3672
  return;
3498
3673
  }
3499
3674
  const documents = filteredFiles.filter((f) => f.type === "document");
3500
3675
  const assets = filteredFiles.filter((f) => f.type === "asset");
3501
3676
  if (documents.length > 0 && (!options.type || options.type === "docs")) {
3502
- console.log(chalk18.cyan("Documents:"));
3677
+ console.log(chalk19.cyan("Documents:"));
3503
3678
  for (const file of documents) {
3504
3679
  const size = formatSize(file.size);
3505
3680
  const content = await fs9.readFile(file.path, "utf-8");
3506
3681
  const tokenCount = await countTokens({ content });
3507
- console.log(chalk18.cyan(` \u2713 ${sanitizeUserInput(file.name).padEnd(20)} (${size}, ~${tokenCount.total.toLocaleString()} tokens)`));
3682
+ console.log(chalk19.cyan(` \u2713 ${sanitizeUserInput(file.name).padEnd(20)} (${size}, ~${tokenCount.total.toLocaleString()} tokens)`));
3508
3683
  }
3509
3684
  console.log("");
3510
3685
  }
3511
3686
  if (assets.length > 0 && (!options.type || options.type === "assets")) {
3512
- console.log(chalk18.yellow("Assets:"));
3687
+ console.log(chalk19.yellow("Assets:"));
3513
3688
  for (const file of assets) {
3514
3689
  const size = formatSize(file.size);
3515
- console.log(chalk18.yellow(` \u2713 ${sanitizeUserInput(file.name).padEnd(20)} (${size})`));
3690
+ console.log(chalk19.yellow(` \u2713 ${sanitizeUserInput(file.name).padEnd(20)} (${size})`));
3516
3691
  }
3517
3692
  console.log("");
3518
3693
  }
@@ -3520,7 +3695,7 @@ async function showFiles(specPath, options = {}) {
3520
3695
  const totalSize = formatSize(
3521
3696
  readmeStat.size + filteredFiles.reduce((sum, f) => sum + f.size, 0)
3522
3697
  );
3523
- console.log(chalk18.gray(`Total: ${totalFiles} files, ${totalSize}`));
3698
+ console.log(chalk19.gray(`Total: ${totalFiles} files, ${totalSize}`));
3524
3699
  console.log("");
3525
3700
  }
3526
3701
  function formatSize(bytes) {
@@ -3532,6 +3707,41 @@ function formatSize(bytes) {
3532
3707
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
3533
3708
  }
3534
3709
  }
3710
+ function examplesCommand() {
3711
+ return new Command("examples").description("List available example projects for tutorials").action(async () => {
3712
+ await listExamples2();
3713
+ });
3714
+ }
3715
+ async function listExamples2() {
3716
+ const examples = getExamplesList();
3717
+ console.log("");
3718
+ console.log(chalk19.bold("LeanSpec Example Projects"));
3719
+ console.log("");
3720
+ console.log("Scaffold complete example projects to follow tutorials:");
3721
+ console.log("");
3722
+ for (const example of examples) {
3723
+ const difficultyColor = example.difficulty === "beginner" ? chalk19.green : example.difficulty === "intermediate" ? chalk19.yellow : chalk19.red;
3724
+ const difficultyStars = example.difficulty === "beginner" ? "\u2605\u2606\u2606" : example.difficulty === "intermediate" ? "\u2605\u2605\u2606" : "\u2605\u2605\u2605";
3725
+ console.log(chalk19.cyan.bold(` ${example.title}`));
3726
+ console.log(` ${chalk19.gray(example.name)}`);
3727
+ console.log(` ${example.description}`);
3728
+ console.log(` ${difficultyColor(difficultyStars + " " + example.difficulty)} \u2022 ${example.tech.join(", ")} \u2022 ~${example.lines} lines`);
3729
+ console.log(` ${chalk19.gray("Tutorial:")} ${example.tutorial}`);
3730
+ console.log(` ${chalk19.gray(example.tutorialUrl)}`);
3731
+ console.log("");
3732
+ }
3733
+ console.log(chalk19.bold("Usage:"));
3734
+ console.log("");
3735
+ console.log(" # Scaffold an example");
3736
+ console.log(chalk19.cyan(" lean-spec init --example <name>"));
3737
+ console.log("");
3738
+ console.log(" # Interactive selection");
3739
+ console.log(chalk19.cyan(" lean-spec init --example"));
3740
+ console.log("");
3741
+ console.log(" # Custom directory name");
3742
+ console.log(chalk19.cyan(" lean-spec init --example email-notifications --name my-demo"));
3743
+ console.log("");
3744
+ }
3535
3745
  var FrontmatterValidator = class {
3536
3746
  name = "frontmatter";
3537
3747
  description = "Validate spec frontmatter for required fields and valid values";
@@ -4019,7 +4229,7 @@ var SubSpecValidator = class {
4019
4229
  */
4020
4230
  validateNamingConventions(subSpecs, warnings) {
4021
4231
  for (const subSpec of subSpecs) {
4022
- const baseName = path4.basename(subSpec.name, ".md");
4232
+ const baseName = path15.basename(subSpec.name, ".md");
4023
4233
  if (baseName !== baseName.toUpperCase()) {
4024
4234
  warnings.push({
4025
4235
  message: `Sub-spec filename should be uppercase: ${subSpec.name}`,
@@ -4183,17 +4393,17 @@ function formatFileIssues(fileResult, specsDir) {
4183
4393
  const priority = fileResult.spec.frontmatter.priority || "medium";
4184
4394
  const statusBadge = formatStatusBadge(status);
4185
4395
  const priorityBadge = formatPriorityBadge(priority);
4186
- lines.push(chalk18.bold.cyan(`${specName} ${statusBadge} ${priorityBadge}`));
4396
+ lines.push(chalk19.bold.cyan(`${specName} ${statusBadge} ${priorityBadge}`));
4187
4397
  } else {
4188
- lines.push(chalk18.cyan.underline(relativePath));
4398
+ lines.push(chalk19.cyan.underline(relativePath));
4189
4399
  }
4190
4400
  for (const issue of fileResult.issues) {
4191
- const severityColor = issue.severity === "error" ? chalk18.red : chalk18.yellow;
4401
+ const severityColor = issue.severity === "error" ? chalk19.red : chalk19.yellow;
4192
4402
  const severityText = severityColor(issue.severity.padEnd(9));
4193
- const ruleText = chalk18.gray(issue.ruleName);
4403
+ const ruleText = chalk19.gray(issue.ruleName);
4194
4404
  lines.push(` ${severityText}${issue.message.padEnd(60)} ${ruleText}`);
4195
4405
  if (issue.suggestion) {
4196
- lines.push(chalk18.gray(` \u2192 ${issue.suggestion}`));
4406
+ lines.push(chalk19.gray(` \u2192 ${issue.suggestion}`));
4197
4407
  }
4198
4408
  }
4199
4409
  lines.push("");
@@ -4203,25 +4413,25 @@ function formatSummary(totalSpecs, errorCount, warningCount, cleanCount) {
4203
4413
  if (errorCount > 0) {
4204
4414
  const errorText = errorCount === 1 ? "error" : "errors";
4205
4415
  const warningText = warningCount === 1 ? "warning" : "warnings";
4206
- return chalk18.red.bold(
4416
+ return chalk19.red.bold(
4207
4417
  `\u2716 ${errorCount} ${errorText}, ${warningCount} ${warningText} (${totalSpecs} specs checked, ${cleanCount} clean)`
4208
4418
  );
4209
4419
  } else if (warningCount > 0) {
4210
4420
  const warningText = warningCount === 1 ? "warning" : "warnings";
4211
- return chalk18.yellow.bold(
4421
+ return chalk19.yellow.bold(
4212
4422
  `\u26A0 ${warningCount} ${warningText} (${totalSpecs} specs checked, ${cleanCount} clean)`
4213
4423
  );
4214
4424
  } else {
4215
- return chalk18.green.bold(`\u2713 All ${totalSpecs} specs passed`);
4425
+ return chalk19.green.bold(`\u2713 All ${totalSpecs} specs passed`);
4216
4426
  }
4217
4427
  }
4218
4428
  function formatPassingSpecs(specs, specsDir) {
4219
4429
  const lines = [];
4220
- lines.push(chalk18.green.bold(`
4430
+ lines.push(chalk19.green.bold(`
4221
4431
  \u2713 ${specs.length} specs passed:`));
4222
4432
  for (const spec of specs) {
4223
4433
  const relativePath = normalizeFilePath(spec.filePath);
4224
- lines.push(chalk18.gray(` ${relativePath}`));
4434
+ lines.push(chalk19.gray(` ${relativePath}`));
4225
4435
  }
4226
4436
  return lines.join("\n");
4227
4437
  }
@@ -4267,13 +4477,13 @@ function formatValidationResults(results, specs, specsDir, options = {}) {
4267
4477
  return formatJson(displayResults, specs.length, errorCount2, warningCount2);
4268
4478
  }
4269
4479
  const lines = [];
4270
- lines.push(chalk18.bold(`
4480
+ lines.push(chalk19.bold(`
4271
4481
  Validating ${specs.length} specs...
4272
4482
  `));
4273
4483
  let previousSpecName;
4274
4484
  for (const fileResult of displayResults) {
4275
4485
  if (fileResult.spec && previousSpecName && fileResult.spec.name !== previousSpecName) {
4276
- lines.push(chalk18.gray("\u2500".repeat(80)));
4486
+ lines.push(chalk19.gray("\u2500".repeat(80)));
4277
4487
  lines.push("");
4278
4488
  }
4279
4489
  lines.push(formatFileIssues(fileResult));
@@ -4297,7 +4507,7 @@ Validating ${specs.length} specs...
4297
4507
  lines.push(formatPassingSpecs(passingSpecs));
4298
4508
  }
4299
4509
  if (!options.verbose && cleanCount > 0 && displayResults.length > 0) {
4300
- lines.push(chalk18.gray("\nRun with --verbose to see passing specs."));
4510
+ lines.push(chalk19.gray("\nRun with --verbose to see passing specs."));
4301
4511
  }
4302
4512
  return lines.join("\n");
4303
4513
  }
@@ -4325,12 +4535,12 @@ async function validateSpecs(options = {}) {
4325
4535
  specs = [];
4326
4536
  for (const specPath of options.specs) {
4327
4537
  const spec = allSpecs.find(
4328
- (s) => s.path.includes(specPath) || path4.basename(s.path).includes(specPath)
4538
+ (s) => s.path.includes(specPath) || path15.basename(s.path).includes(specPath)
4329
4539
  );
4330
4540
  if (spec) {
4331
4541
  specs.push(spec);
4332
4542
  } else {
4333
- console.error(chalk18.red(`Error: Spec not found: ${specPath}`));
4543
+ console.error(chalk19.red(`Error: Spec not found: ${specPath}`));
4334
4544
  return false;
4335
4545
  }
4336
4546
  }
@@ -4358,7 +4568,7 @@ async function validateSpecs(options = {}) {
4358
4568
  try {
4359
4569
  content = await fs9.readFile(spec.filePath, "utf-8");
4360
4570
  } catch (error) {
4361
- console.error(chalk18.red(`Error reading ${spec.filePath}:`), error);
4571
+ console.error(chalk19.red(`Error reading ${spec.filePath}:`), error);
4362
4572
  continue;
4363
4573
  }
4364
4574
  for (const validator of validators) {
@@ -4371,7 +4581,7 @@ async function validateSpecs(options = {}) {
4371
4581
  content
4372
4582
  });
4373
4583
  } catch (error) {
4374
- console.error(chalk18.yellow(`Warning: Validator ${validator.name} failed:`), error instanceof Error ? error.message : error);
4584
+ console.error(chalk19.yellow(`Warning: Validator ${validator.name} failed:`), error instanceof Error ? error.message : error);
4375
4585
  }
4376
4586
  }
4377
4587
  }
@@ -4440,7 +4650,7 @@ async function scanDocuments(dirPath) {
4440
4650
  async function scanRecursive(currentPath) {
4441
4651
  const entries = await fs9.readdir(currentPath, { withFileTypes: true });
4442
4652
  for (const entry of entries) {
4443
- const fullPath = path4.join(currentPath, entry.name);
4653
+ const fullPath = path15.join(currentPath, entry.name);
4444
4654
  if (entry.isDirectory()) {
4445
4655
  if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
4446
4656
  await scanRecursive(fullPath);
@@ -4806,7 +5016,7 @@ async function showBoard(options) {
4806
5016
  })
4807
5017
  );
4808
5018
  if (specs.length === 0) {
4809
- console.log(chalk18.dim("No specs found."));
5019
+ console.log(chalk19.dim("No specs found."));
4810
5020
  return;
4811
5021
  }
4812
5022
  const columns = {
@@ -4821,12 +5031,12 @@ async function showBoard(options) {
4821
5031
  columns[status].push(spec);
4822
5032
  }
4823
5033
  }
4824
- console.log(chalk18.bold.cyan("\u{1F4CB} Spec Kanban Board"));
5034
+ console.log(chalk19.bold.cyan("\u{1F4CB} Spec Kanban Board"));
4825
5035
  if (options.tag || options.assignee) {
4826
5036
  const filterParts = [];
4827
5037
  if (options.tag) filterParts.push(`tag=${options.tag}`);
4828
5038
  if (options.assignee) filterParts.push(`assignee=${options.assignee}`);
4829
- console.log(chalk18.dim(`Filtered by: ${filterParts.join(", ")}`));
5039
+ console.log(chalk19.dim(`Filtered by: ${filterParts.join(", ")}`));
4830
5040
  }
4831
5041
  console.log("");
4832
5042
  if (!options.simple) {
@@ -4841,12 +5051,12 @@ async function showBoard(options) {
4841
5051
  const padding = boxWidth - 2 - visibleLength;
4842
5052
  return content + " ".repeat(Math.max(0, padding));
4843
5053
  };
4844
- console.log(chalk18.dim(topBorder));
4845
- const headerLine = chalk18.bold(" Project Overview");
4846
- console.log(chalk18.dim("\u2551") + padLine(headerLine) + chalk18.dim("\u2551"));
4847
- const percentageColor = completionMetrics.score >= 70 ? chalk18.green : completionMetrics.score >= 40 ? chalk18.yellow : chalk18.red;
5054
+ console.log(chalk19.dim(topBorder));
5055
+ const headerLine = chalk19.bold(" Project Overview");
5056
+ console.log(chalk19.dim("\u2551") + padLine(headerLine) + chalk19.dim("\u2551"));
5057
+ const percentageColor = completionMetrics.score >= 70 ? chalk19.green : completionMetrics.score >= 40 ? chalk19.yellow : chalk19.red;
4848
5058
  const line1 = ` ${completionMetrics.totalSpecs} total \xB7 ${completionMetrics.activeSpecs} active \xB7 ${completionMetrics.completeSpecs} complete ${percentageColor("(" + completionMetrics.score + "%)")}`;
4849
- console.log(chalk18.dim("\u2551") + padLine(line1) + chalk18.dim("\u2551"));
5059
+ console.log(chalk19.dim("\u2551") + padLine(line1) + chalk19.dim("\u2551"));
4850
5060
  if (completionMetrics.criticalIssues.length > 0 || completionMetrics.warnings.length > 0) {
4851
5061
  const alerts = [];
4852
5062
  if (completionMetrics.criticalIssues.length > 0) {
@@ -4855,27 +5065,27 @@ async function showBoard(options) {
4855
5065
  if (completionMetrics.warnings.length > 0) {
4856
5066
  alerts.push(`${completionMetrics.warnings.length} specs WIP > 7 days`);
4857
5067
  }
4858
- const alertLine = ` ${chalk18.yellow("\u26A0\uFE0F " + alerts.join(" \xB7 "))}`;
4859
- console.log(chalk18.dim("\u2551") + padLine(alertLine) + chalk18.dim("\u2551"));
5068
+ const alertLine = ` ${chalk19.yellow("\u26A0\uFE0F " + alerts.join(" \xB7 "))}`;
5069
+ console.log(chalk19.dim("\u2551") + padLine(alertLine) + chalk19.dim("\u2551"));
4860
5070
  }
4861
- const velocityLine = ` ${chalk18.cyan("\u{1F680} Velocity:")} ${velocityMetrics.cycleTime.average.toFixed(1)}d avg cycle \xB7 ${(velocityMetrics.throughput.perWeek / 7 * 7).toFixed(1)}/wk throughput`;
4862
- console.log(chalk18.dim("\u2551") + padLine(velocityLine) + chalk18.dim("\u2551"));
4863
- console.log(chalk18.dim(bottomBorder));
5071
+ const velocityLine = ` ${chalk19.cyan("\u{1F680} Velocity:")} ${velocityMetrics.cycleTime.average.toFixed(1)}d avg cycle \xB7 ${(velocityMetrics.throughput.perWeek / 7 * 7).toFixed(1)}/wk throughput`;
5072
+ console.log(chalk19.dim("\u2551") + padLine(velocityLine) + chalk19.dim("\u2551"));
5073
+ console.log(chalk19.dim(bottomBorder));
4864
5074
  console.log("");
4865
5075
  if (options.completionOnly) {
4866
5076
  return;
4867
5077
  }
4868
5078
  }
4869
5079
  renderColumn(STATUS_CONFIG.planned.label, STATUS_CONFIG.planned.emoji, columns.planned, true, STATUS_CONFIG.planned.colorFn);
4870
- console.log(chalk18.dim("\u2501".repeat(70)));
5080
+ console.log(chalk19.dim("\u2501".repeat(70)));
4871
5081
  console.log("");
4872
5082
  renderColumn(STATUS_CONFIG["in-progress"].label, STATUS_CONFIG["in-progress"].emoji, columns["in-progress"], true, STATUS_CONFIG["in-progress"].colorFn);
4873
- console.log(chalk18.dim("\u2501".repeat(70)));
5083
+ console.log(chalk19.dim("\u2501".repeat(70)));
4874
5084
  console.log("");
4875
5085
  renderColumn(STATUS_CONFIG.complete.label, STATUS_CONFIG.complete.emoji, columns.complete, options.showComplete || false, STATUS_CONFIG.complete.colorFn);
4876
5086
  }
4877
5087
  function renderColumn(title, emoji, specs, expanded, colorFn) {
4878
- console.log(`${emoji} ${colorFn(chalk18.bold(`${title} (${specs.length})`))}`);
5088
+ console.log(`${emoji} ${colorFn(chalk19.bold(`${title} (${specs.length})`))}`);
4879
5089
  console.log("");
4880
5090
  if (expanded && specs.length > 0) {
4881
5091
  const priorityGroups = {
@@ -4900,30 +5110,30 @@ function renderColumn(title, emoji, specs, expanded, colorFn) {
4900
5110
  firstGroup = false;
4901
5111
  const priorityLabel = priority === "none" ? "No Priority" : priority.charAt(0).toUpperCase() + priority.slice(1);
4902
5112
  const priorityEmoji = priority === "none" ? "\u26AA" : PRIORITY_CONFIG[priority].emoji;
4903
- const priorityColor = priority === "none" ? chalk18.dim : PRIORITY_CONFIG[priority].colorFn;
4904
- console.log(` ${priorityColor(`${priorityEmoji} ${chalk18.bold(priorityLabel)} ${chalk18.dim(`(${groupSpecs.length})`)}`)}`);
5113
+ const priorityColor = priority === "none" ? chalk19.dim : PRIORITY_CONFIG[priority].colorFn;
5114
+ console.log(` ${priorityColor(`${priorityEmoji} ${chalk19.bold(priorityLabel)} ${chalk19.dim(`(${groupSpecs.length})`)}`)}`);
4905
5115
  for (const spec of groupSpecs) {
4906
5116
  let assigneeStr = "";
4907
5117
  if (spec.frontmatter.assignee) {
4908
- assigneeStr = " " + chalk18.cyan(`@${sanitizeUserInput(spec.frontmatter.assignee)}`);
5118
+ assigneeStr = " " + chalk19.cyan(`@${sanitizeUserInput(spec.frontmatter.assignee)}`);
4909
5119
  }
4910
5120
  let tagsStr = "";
4911
5121
  if (spec.frontmatter.tags?.length) {
4912
5122
  const tags = Array.isArray(spec.frontmatter.tags) ? spec.frontmatter.tags : [];
4913
5123
  if (tags.length > 0) {
4914
5124
  const tagStr = tags.map((tag) => `#${sanitizeUserInput(tag)}`).join(" ");
4915
- tagsStr = " " + chalk18.dim(chalk18.magenta(tagStr));
5125
+ tagsStr = " " + chalk19.dim(chalk19.magenta(tagStr));
4916
5126
  }
4917
5127
  }
4918
- console.log(` ${chalk18.cyan(sanitizeUserInput(spec.path))}${assigneeStr}${tagsStr}`);
5128
+ console.log(` ${chalk19.cyan(sanitizeUserInput(spec.path))}${assigneeStr}${tagsStr}`);
4919
5129
  }
4920
5130
  }
4921
5131
  console.log("");
4922
5132
  } else if (!expanded && specs.length > 0) {
4923
- console.log(` ${chalk18.dim("(collapsed, use --complete to expand)")}`);
5133
+ console.log(` ${chalk19.dim("(collapsed, use --complete to expand)")}`);
4924
5134
  console.log("");
4925
5135
  } else {
4926
- console.log(` ${chalk18.dim("(empty)")}`);
5136
+ console.log(` ${chalk19.dim("(empty)")}`);
4927
5137
  console.log("");
4928
5138
  }
4929
5139
  }
@@ -5092,26 +5302,26 @@ async function showStats(options) {
5092
5302
  console.log(JSON.stringify(data, null, 2));
5093
5303
  return;
5094
5304
  }
5095
- console.log(chalk18.bold.cyan("\u{1F4CA} Spec Stats"));
5305
+ console.log(chalk19.bold.cyan("\u{1F4CA} Spec Stats"));
5096
5306
  console.log("");
5097
5307
  if (options.tag || options.assignee) {
5098
5308
  const filterParts = [];
5099
5309
  if (options.tag) filterParts.push(`tag=${options.tag}`);
5100
5310
  if (options.assignee) filterParts.push(`assignee=${options.assignee}`);
5101
- console.log(chalk18.dim(`Filtered by: ${filterParts.join(", ")}`));
5311
+ console.log(chalk19.dim(`Filtered by: ${filterParts.join(", ")}`));
5102
5312
  console.log("");
5103
5313
  }
5104
5314
  if (showSimplified) {
5105
- console.log(chalk18.bold("\u{1F4C8} Overview"));
5315
+ console.log(chalk19.bold("\u{1F4C8} Overview"));
5106
5316
  console.log("");
5107
5317
  const completionStatus = getCompletionStatus(completionMetrics.score);
5108
- const completionColor = completionStatus.color === "green" ? chalk18.green : completionStatus.color === "yellow" ? chalk18.yellow : chalk18.red;
5109
- console.log(` Total Specs ${chalk18.cyan(completionMetrics.totalSpecs)}`);
5110
- console.log(` Active (Planned+WIP) ${chalk18.yellow(completionMetrics.activeSpecs)}`);
5111
- console.log(` Complete ${chalk18.green(completionMetrics.completeSpecs)}`);
5318
+ const completionColor = completionStatus.color === "green" ? chalk19.green : completionStatus.color === "yellow" ? chalk19.yellow : chalk19.red;
5319
+ console.log(` Total Specs ${chalk19.cyan(completionMetrics.totalSpecs)}`);
5320
+ console.log(` Active (Planned+WIP) ${chalk19.yellow(completionMetrics.activeSpecs)}`);
5321
+ console.log(` Complete ${chalk19.green(completionMetrics.completeSpecs)}`);
5112
5322
  console.log(` Completion Rate ${completionColor(`${completionMetrics.score}% ${completionStatus.emoji}`)}`);
5113
5323
  console.log("");
5114
- console.log(chalk18.bold("\u{1F4CA} Status"));
5324
+ console.log(chalk19.bold("\u{1F4CA} Status"));
5115
5325
  console.log("");
5116
5326
  const labelWidth2 = 15;
5117
5327
  const barWidth2 = 20;
@@ -5120,19 +5330,19 @@ async function showStats(options) {
5120
5330
  const width = Math.round(count / maxCount * barWidth2);
5121
5331
  const filledWidth = Math.min(width, barWidth2);
5122
5332
  const emptyWidth = barWidth2 - filledWidth;
5123
- return char.repeat(filledWidth) + chalk18.dim("\u2591").repeat(emptyWidth);
5333
+ return char.repeat(filledWidth) + chalk19.dim("\u2591").repeat(emptyWidth);
5124
5334
  };
5125
- console.log(` \u{1F4C5} ${"Planned".padEnd(labelWidth2)} ${chalk18.cyan(createBar2(statusCounts.planned, maxStatusCount))} ${chalk18.cyan(statusCounts.planned)}`);
5126
- console.log(` \u23F3 ${"In Progress".padEnd(labelWidth2)} ${chalk18.yellow(createBar2(statusCounts["in-progress"], maxStatusCount))} ${chalk18.yellow(statusCounts["in-progress"])}`);
5127
- console.log(` \u2705 ${"Complete".padEnd(labelWidth2)} ${chalk18.green(createBar2(statusCounts.complete, maxStatusCount))} ${chalk18.green(statusCounts.complete)}`);
5335
+ console.log(` \u{1F4C5} ${"Planned".padEnd(labelWidth2)} ${chalk19.cyan(createBar2(statusCounts.planned, maxStatusCount))} ${chalk19.cyan(statusCounts.planned)}`);
5336
+ console.log(` \u23F3 ${"In Progress".padEnd(labelWidth2)} ${chalk19.yellow(createBar2(statusCounts["in-progress"], maxStatusCount))} ${chalk19.yellow(statusCounts["in-progress"])}`);
5337
+ console.log(` \u2705 ${"Complete".padEnd(labelWidth2)} ${chalk19.green(createBar2(statusCounts.complete, maxStatusCount))} ${chalk19.green(statusCounts.complete)}`);
5128
5338
  if (statusCounts.archived > 0) {
5129
- console.log(` \u{1F4E6} ${"Archived".padEnd(labelWidth2)} ${chalk18.dim(createBar2(statusCounts.archived, maxStatusCount))} ${chalk18.dim(statusCounts.archived)}`);
5339
+ console.log(` \u{1F4E6} ${"Archived".padEnd(labelWidth2)} ${chalk19.dim(createBar2(statusCounts.archived, maxStatusCount))} ${chalk19.dim(statusCounts.archived)}`);
5130
5340
  }
5131
5341
  console.log("");
5132
5342
  const criticalCount = priorityCounts.critical || 0;
5133
5343
  const highCount = priorityCounts.high || 0;
5134
5344
  if (criticalCount > 0 || highCount > 0) {
5135
- console.log(chalk18.bold("\u{1F3AF} Priority Focus"));
5345
+ console.log(chalk19.bold("\u{1F3AF} Priority Focus"));
5136
5346
  console.log("");
5137
5347
  if (criticalCount > 0) {
5138
5348
  const criticalPlanned = specs.filter((s) => s.frontmatter.priority === "critical" && s.frontmatter.status === "planned").length;
@@ -5142,11 +5352,11 @@ async function showStats(options) {
5142
5352
  (s) => s.frontmatter.priority === "critical" && s.frontmatter.due && dayjs3(s.frontmatter.due).isBefore(dayjs3(), "day") && s.frontmatter.status !== "complete"
5143
5353
  ).length;
5144
5354
  const parts = [];
5145
- if (criticalPlanned > 0) parts.push(chalk18.dim(`${criticalPlanned} planned`));
5355
+ if (criticalPlanned > 0) parts.push(chalk19.dim(`${criticalPlanned} planned`));
5146
5356
  if (criticalInProgress > 0) parts.push(`${criticalInProgress} in-progress`);
5147
- if (criticalComplete > 0) parts.push(chalk18.green(`${criticalComplete} complete`));
5148
- if (criticalOverdue > 0) parts.push(chalk18.red(`${criticalOverdue} overdue!`));
5149
- console.log(` \u{1F534} Critical ${chalk18.red(criticalCount)} specs${parts.length > 0 ? ` (${parts.join(", ")})` : ""}`);
5357
+ if (criticalComplete > 0) parts.push(chalk19.green(`${criticalComplete} complete`));
5358
+ if (criticalOverdue > 0) parts.push(chalk19.red(`${criticalOverdue} overdue!`));
5359
+ console.log(` \u{1F534} Critical ${chalk19.red(criticalCount)} specs${parts.length > 0 ? ` (${parts.join(", ")})` : ""}`);
5150
5360
  }
5151
5361
  if (highCount > 0) {
5152
5362
  const highPlanned = specs.filter((s) => s.frontmatter.priority === "high" && s.frontmatter.status === "planned").length;
@@ -5156,52 +5366,52 @@ async function showStats(options) {
5156
5366
  (s) => s.frontmatter.priority === "high" && s.frontmatter.due && dayjs3(s.frontmatter.due).isBefore(dayjs3(), "day") && s.frontmatter.status !== "complete"
5157
5367
  ).length;
5158
5368
  const parts = [];
5159
- if (highPlanned > 0) parts.push(chalk18.dim(`${highPlanned} planned`));
5369
+ if (highPlanned > 0) parts.push(chalk19.dim(`${highPlanned} planned`));
5160
5370
  if (highInProgress > 0) parts.push(`${highInProgress} in-progress`);
5161
- if (highComplete > 0) parts.push(chalk18.green(`${highComplete} complete`));
5162
- if (highOverdue > 0) parts.push(chalk18.yellow(`${highOverdue} overdue`));
5163
- console.log(` \u{1F7E0} High ${chalk18.hex("#FFA500")(highCount)} specs${parts.length > 0 ? ` (${parts.join(", ")})` : ""}`);
5371
+ if (highComplete > 0) parts.push(chalk19.green(`${highComplete} complete`));
5372
+ if (highOverdue > 0) parts.push(chalk19.yellow(`${highOverdue} overdue`));
5373
+ console.log(` \u{1F7E0} High ${chalk19.hex("#FFA500")(highCount)} specs${parts.length > 0 ? ` (${parts.join(", ")})` : ""}`);
5164
5374
  }
5165
5375
  console.log("");
5166
5376
  }
5167
5377
  if (insights.length > 0) {
5168
- console.log(chalk18.bold.yellow("\u26A0\uFE0F Needs Attention"));
5378
+ console.log(chalk19.bold.yellow("\u26A0\uFE0F Needs Attention"));
5169
5379
  console.log("");
5170
5380
  for (const insight of insights) {
5171
- const color = insight.severity === "critical" ? chalk18.red : insight.severity === "warning" ? chalk18.yellow : chalk18.cyan;
5381
+ const color = insight.severity === "critical" ? chalk19.red : insight.severity === "warning" ? chalk19.yellow : chalk19.cyan;
5172
5382
  console.log(` ${color("\u2022")} ${insight.message}`);
5173
5383
  for (const specPath of insight.specs.slice(0, 3)) {
5174
5384
  const spec = specs.find((s) => s.path === specPath);
5175
5385
  const details = spec ? getSpecInsightDetails(spec) : null;
5176
- console.log(` ${chalk18.dim(specPath)}${details ? chalk18.dim(` (${details})`) : ""}`);
5386
+ console.log(` ${chalk19.dim(specPath)}${details ? chalk19.dim(` (${details})`) : ""}`);
5177
5387
  }
5178
5388
  if (insight.specs.length > 3) {
5179
- console.log(` ${chalk18.dim(`...and ${insight.specs.length - 3} more`)}`);
5389
+ console.log(` ${chalk19.dim(`...and ${insight.specs.length - 3} more`)}`);
5180
5390
  }
5181
5391
  }
5182
5392
  console.log("");
5183
5393
  } else if (completionMetrics.activeSpecs === 0 && completionMetrics.completeSpecs > 0) {
5184
- console.log(chalk18.bold.green("\u{1F389} All Specs Complete!"));
5394
+ console.log(chalk19.bold.green("\u{1F389} All Specs Complete!"));
5185
5395
  console.log("");
5186
- console.log(` ${chalk18.dim("Great work! All active specs are complete.")}`);
5396
+ console.log(` ${chalk19.dim("Great work! All active specs are complete.")}`);
5187
5397
  console.log("");
5188
5398
  } else if (completionMetrics.activeSpecs > 0) {
5189
- console.log(chalk18.bold.green("\u2728 All Clear!"));
5399
+ console.log(chalk19.bold.green("\u2728 All Clear!"));
5190
5400
  console.log("");
5191
- console.log(` ${chalk18.dim("No critical issues detected. Keep up the good work!")}`);
5401
+ console.log(` ${chalk19.dim("No critical issues detected. Keep up the good work!")}`);
5192
5402
  console.log("");
5193
5403
  }
5194
- console.log(chalk18.bold("\u{1F680} Velocity Summary"));
5404
+ console.log(chalk19.bold("\u{1F680} Velocity Summary"));
5195
5405
  console.log("");
5196
- const cycleTimeStatus = velocityMetrics.cycleTime.average <= 7 ? chalk18.green("\u2713") : chalk18.yellow("\u26A0");
5197
- const throughputTrend = velocityMetrics.throughput.trend === "up" ? chalk18.green("\u2191") : velocityMetrics.throughput.trend === "down" ? chalk18.red("\u2193") : chalk18.yellow("\u2192");
5198
- console.log(` Avg Cycle Time ${chalk18.cyan(velocityMetrics.cycleTime.average.toFixed(1))} days ${cycleTimeStatus}${velocityMetrics.cycleTime.average <= 7 ? chalk18.dim(" (target: 7d)") : ""}`);
5199
- console.log(` Throughput ${chalk18.cyan((velocityMetrics.throughput.perWeek / 7 * 7).toFixed(1))}/week ${throughputTrend}`);
5200
- console.log(` WIP ${chalk18.yellow(velocityMetrics.wip.current)} specs`);
5406
+ const cycleTimeStatus = velocityMetrics.cycleTime.average <= 7 ? chalk19.green("\u2713") : chalk19.yellow("\u26A0");
5407
+ const throughputTrend = velocityMetrics.throughput.trend === "up" ? chalk19.green("\u2191") : velocityMetrics.throughput.trend === "down" ? chalk19.red("\u2193") : chalk19.yellow("\u2192");
5408
+ console.log(` Avg Cycle Time ${chalk19.cyan(velocityMetrics.cycleTime.average.toFixed(1))} days ${cycleTimeStatus}${velocityMetrics.cycleTime.average <= 7 ? chalk19.dim(" (target: 7d)") : ""}`);
5409
+ console.log(` Throughput ${chalk19.cyan((velocityMetrics.throughput.perWeek / 7 * 7).toFixed(1))}/week ${throughputTrend}`);
5410
+ console.log(` WIP ${chalk19.yellow(velocityMetrics.wip.current)} specs`);
5201
5411
  console.log("");
5202
- console.log(chalk18.dim("\u{1F4A1} Use `lean-spec stats --full` for detailed analytics"));
5203
- console.log(chalk18.dim(" Use `lean-spec stats --velocity` for velocity breakdown"));
5204
- console.log(chalk18.dim(" Use `lean-spec stats --timeline` for activity timeline"));
5412
+ console.log(chalk19.dim("\u{1F4A1} Use `lean-spec stats --full` for detailed analytics"));
5413
+ console.log(chalk19.dim(" Use `lean-spec stats --velocity` for velocity breakdown"));
5414
+ console.log(chalk19.dim(" Use `lean-spec stats --timeline` for activity timeline"));
5205
5415
  console.log("");
5206
5416
  return;
5207
5417
  }
@@ -5217,97 +5427,97 @@ async function showStats(options) {
5217
5427
  (sum, count) => sum + count,
5218
5428
  0
5219
5429
  );
5220
- console.log(chalk18.bold("\u{1F4C8} Overview"));
5430
+ console.log(chalk19.bold("\u{1F4C8} Overview"));
5221
5431
  console.log("");
5222
5432
  console.log(
5223
5433
  ` ${"Metric".padEnd(labelWidth)} ${"Value".padStart(valueWidth)}`
5224
5434
  );
5225
5435
  console.log(
5226
- ` ${chalk18.dim("\u2500".repeat(labelWidth))} ${chalk18.dim("\u2500".repeat(valueWidth))}`
5436
+ ` ${chalk19.dim("\u2500".repeat(labelWidth))} ${chalk19.dim("\u2500".repeat(valueWidth))}`
5227
5437
  );
5228
5438
  console.log(
5229
- ` ${"Total Specs".padEnd(labelWidth)} ${chalk18.green(specs.length.toString().padStart(valueWidth))}`
5439
+ ` ${"Total Specs".padEnd(labelWidth)} ${chalk19.green(specs.length.toString().padStart(valueWidth))}`
5230
5440
  );
5231
5441
  console.log(
5232
- ` ${"With Priority".padEnd(labelWidth)} ${chalk18.cyan(totalWithPriority.toString().padStart(valueWidth))}`
5442
+ ` ${"With Priority".padEnd(labelWidth)} ${chalk19.cyan(totalWithPriority.toString().padStart(valueWidth))}`
5233
5443
  );
5234
5444
  console.log(
5235
- ` ${"Unique Tags".padEnd(labelWidth)} ${chalk18.magenta(Object.keys(tagCounts).length.toString().padStart(valueWidth))}`
5445
+ ` ${"Unique Tags".padEnd(labelWidth)} ${chalk19.magenta(Object.keys(tagCounts).length.toString().padStart(valueWidth))}`
5236
5446
  );
5237
5447
  console.log("");
5238
- console.log(chalk18.bold("\u{1F4CA} Status Distribution"));
5448
+ console.log(chalk19.bold("\u{1F4CA} Status Distribution"));
5239
5449
  console.log("");
5240
5450
  const maxStatusCount = Math.max(...Object.values(statusCounts));
5241
5451
  const colWidth = barWidth + 3;
5242
5452
  console.log(
5243
- ` ${"Status".padEnd(labelWidth)} ${chalk18.cyan("Count".padEnd(colWidth))}`
5453
+ ` ${"Status".padEnd(labelWidth)} ${chalk19.cyan("Count".padEnd(colWidth))}`
5244
5454
  );
5245
5455
  console.log(
5246
- ` ${chalk18.dim("\u2500".repeat(labelWidth))} ${chalk18.dim("\u2500".repeat(colWidth))}`
5456
+ ` ${chalk19.dim("\u2500".repeat(labelWidth))} ${chalk19.dim("\u2500".repeat(colWidth))}`
5247
5457
  );
5248
5458
  console.log(
5249
- ` \u{1F4CB} ${"Planned".padEnd(labelWidth - 3)} ${chalk18.cyan(createBar(statusCounts.planned, maxStatusCount).padEnd(barWidth))}${chalk18.cyan(statusCounts.planned.toString().padStart(3))}`
5459
+ ` \u{1F4CB} ${"Planned".padEnd(labelWidth - 3)} ${chalk19.cyan(createBar(statusCounts.planned, maxStatusCount).padEnd(barWidth))}${chalk19.cyan(statusCounts.planned.toString().padStart(3))}`
5250
5460
  );
5251
5461
  console.log(
5252
- ` \u23F3 ${"In Progress".padEnd(labelWidth - 3)} ${chalk18.yellow(createBar(statusCounts["in-progress"], maxStatusCount).padEnd(barWidth))}${chalk18.yellow(statusCounts["in-progress"].toString().padStart(3))}`
5462
+ ` \u23F3 ${"In Progress".padEnd(labelWidth - 3)} ${chalk19.yellow(createBar(statusCounts["in-progress"], maxStatusCount).padEnd(barWidth))}${chalk19.yellow(statusCounts["in-progress"].toString().padStart(3))}`
5253
5463
  );
5254
5464
  console.log(
5255
- ` \u2705 ${"Complete".padEnd(labelWidth - 3)} ${chalk18.green(createBar(statusCounts.complete, maxStatusCount).padEnd(barWidth))}${chalk18.green(statusCounts.complete.toString().padStart(3))}`
5465
+ ` \u2705 ${"Complete".padEnd(labelWidth - 3)} ${chalk19.green(createBar(statusCounts.complete, maxStatusCount).padEnd(barWidth))}${chalk19.green(statusCounts.complete.toString().padStart(3))}`
5256
5466
  );
5257
5467
  console.log(
5258
- ` \u{1F4E6} ${"Archived".padEnd(labelWidth - 3)} ${chalk18.dim(createBar(statusCounts.archived, maxStatusCount).padEnd(barWidth))}${chalk18.dim(statusCounts.archived.toString().padStart(3))}`
5468
+ ` \u{1F4E6} ${"Archived".padEnd(labelWidth - 3)} ${chalk19.dim(createBar(statusCounts.archived, maxStatusCount).padEnd(barWidth))}${chalk19.dim(statusCounts.archived.toString().padStart(3))}`
5259
5469
  );
5260
5470
  console.log("");
5261
5471
  if (totalWithPriority > 0) {
5262
- console.log(chalk18.bold("\u{1F3AF} Priority Breakdown"));
5472
+ console.log(chalk19.bold("\u{1F3AF} Priority Breakdown"));
5263
5473
  console.log("");
5264
5474
  const maxPriorityCount = Math.max(
5265
5475
  ...Object.values(priorityCounts).filter((c) => c > 0)
5266
5476
  );
5267
5477
  console.log(
5268
- ` ${"Priority".padEnd(labelWidth)} ${chalk18.cyan("Count".padEnd(colWidth))}`
5478
+ ` ${"Priority".padEnd(labelWidth)} ${chalk19.cyan("Count".padEnd(colWidth))}`
5269
5479
  );
5270
5480
  console.log(
5271
- ` ${chalk18.dim("\u2500".repeat(labelWidth))} ${chalk18.dim("\u2500".repeat(colWidth))}`
5481
+ ` ${chalk19.dim("\u2500".repeat(labelWidth))} ${chalk19.dim("\u2500".repeat(colWidth))}`
5272
5482
  );
5273
5483
  if (priorityCounts.critical > 0) {
5274
5484
  console.log(
5275
- ` \u{1F534} ${"Critical".padEnd(labelWidth - 3)} ${chalk18.red(createBar(priorityCounts.critical, maxPriorityCount).padEnd(barWidth))}${chalk18.red(priorityCounts.critical.toString().padStart(3))}`
5485
+ ` \u{1F534} ${"Critical".padEnd(labelWidth - 3)} ${chalk19.red(createBar(priorityCounts.critical, maxPriorityCount).padEnd(barWidth))}${chalk19.red(priorityCounts.critical.toString().padStart(3))}`
5276
5486
  );
5277
5487
  }
5278
5488
  if (priorityCounts.high > 0) {
5279
5489
  console.log(
5280
- ` \u{1F7E0} ${"High".padEnd(labelWidth - 3)} ${chalk18.hex("#FFA500")(createBar(priorityCounts.high, maxPriorityCount).padEnd(barWidth))}${chalk18.hex("#FFA500")(priorityCounts.high.toString().padStart(3))}`
5490
+ ` \u{1F7E0} ${"High".padEnd(labelWidth - 3)} ${chalk19.hex("#FFA500")(createBar(priorityCounts.high, maxPriorityCount).padEnd(barWidth))}${chalk19.hex("#FFA500")(priorityCounts.high.toString().padStart(3))}`
5281
5491
  );
5282
5492
  }
5283
5493
  if (priorityCounts.medium > 0) {
5284
5494
  console.log(
5285
- ` \u{1F7E1} ${"Medium".padEnd(labelWidth - 3)} ${chalk18.yellow(createBar(priorityCounts.medium, maxPriorityCount).padEnd(barWidth))}${chalk18.yellow(priorityCounts.medium.toString().padStart(3))}`
5495
+ ` \u{1F7E1} ${"Medium".padEnd(labelWidth - 3)} ${chalk19.yellow(createBar(priorityCounts.medium, maxPriorityCount).padEnd(barWidth))}${chalk19.yellow(priorityCounts.medium.toString().padStart(3))}`
5286
5496
  );
5287
5497
  }
5288
5498
  if (priorityCounts.low > 0) {
5289
5499
  console.log(
5290
- ` \u{1F7E2} ${"Low".padEnd(labelWidth - 3)} ${chalk18.green(createBar(priorityCounts.low, maxPriorityCount).padEnd(barWidth))}${chalk18.green(priorityCounts.low.toString().padStart(3))}`
5500
+ ` \u{1F7E2} ${"Low".padEnd(labelWidth - 3)} ${chalk19.green(createBar(priorityCounts.low, maxPriorityCount).padEnd(barWidth))}${chalk19.green(priorityCounts.low.toString().padStart(3))}`
5291
5501
  );
5292
5502
  }
5293
5503
  console.log("");
5294
5504
  }
5295
5505
  const topTags = Object.entries(tagCounts).sort((a, b) => b[1] - a[1]).slice(0, 5);
5296
5506
  if (topTags.length > 0) {
5297
- console.log(chalk18.bold("\u{1F3F7}\uFE0F Popular Tags"));
5507
+ console.log(chalk19.bold("\u{1F3F7}\uFE0F Popular Tags"));
5298
5508
  console.log("");
5299
5509
  const maxTagCount = Math.max(...topTags.map(([, count]) => count));
5300
5510
  console.log(
5301
- ` ${"Tag".padEnd(labelWidth)} ${chalk18.magenta("Count".padEnd(colWidth))}`
5511
+ ` ${"Tag".padEnd(labelWidth)} ${chalk19.magenta("Count".padEnd(colWidth))}`
5302
5512
  );
5303
5513
  console.log(
5304
- ` ${chalk18.dim("\u2500".repeat(labelWidth))} ${chalk18.dim("\u2500".repeat(colWidth))}`
5514
+ ` ${chalk19.dim("\u2500".repeat(labelWidth))} ${chalk19.dim("\u2500".repeat(colWidth))}`
5305
5515
  );
5306
5516
  for (const [tag, count] of topTags) {
5307
5517
  const truncatedTag = tag.length > labelWidth ? tag.substring(0, labelWidth - 1) + "\u2026" : tag;
5308
5518
  const bar = createBar(count, maxTagCount);
5309
5519
  console.log(
5310
- ` ${truncatedTag.padEnd(labelWidth)} ${chalk18.magenta(bar.padEnd(barWidth))}${chalk18.magenta(count.toString().padStart(3))}`
5520
+ ` ${truncatedTag.padEnd(labelWidth)} ${chalk19.magenta(bar.padEnd(barWidth))}${chalk19.magenta(count.toString().padStart(3))}`
5311
5521
  );
5312
5522
  }
5313
5523
  console.log("");
@@ -5339,14 +5549,14 @@ async function showStats(options) {
5339
5549
  ]);
5340
5550
  const sortedDates = Array.from(allDates).sort();
5341
5551
  if (sortedDates.length > 0) {
5342
- console.log(chalk18.bold(`\u{1F4C5} Activity (Last ${days} Days)`));
5552
+ console.log(chalk19.bold(`\u{1F4C5} Activity (Last ${days} Days)`));
5343
5553
  console.log("");
5344
5554
  const colWidth = barWidth + 3;
5345
5555
  console.log(
5346
- ` ${"Date".padEnd(15)} ${chalk18.cyan("Created".padEnd(colWidth))} ${chalk18.green("Completed".padEnd(colWidth))}`
5556
+ ` ${"Date".padEnd(15)} ${chalk19.cyan("Created".padEnd(colWidth))} ${chalk19.green("Completed".padEnd(colWidth))}`
5347
5557
  );
5348
5558
  console.log(
5349
- ` ${chalk18.dim("\u2500".repeat(15))} ${chalk18.dim("\u2500".repeat(colWidth))} ${chalk18.dim("\u2500".repeat(colWidth))}`
5559
+ ` ${chalk19.dim("\u2500".repeat(15))} ${chalk19.dim("\u2500".repeat(colWidth))} ${chalk19.dim("\u2500".repeat(colWidth))}`
5350
5560
  );
5351
5561
  const maxCount = Math.max(
5352
5562
  ...Object.values(createdByDate),
@@ -5360,85 +5570,85 @@ async function showStats(options) {
5360
5570
  const createdCol = `${createdBar.padEnd(barWidth)}${created.toString().padStart(3)}`;
5361
5571
  const completedCol = `${completedBar.padEnd(barWidth)}${completed.toString().padStart(3)}`;
5362
5572
  console.log(
5363
- ` ${chalk18.dim(date.padEnd(15))} ${chalk18.cyan(createdCol)} ${chalk18.green(completedCol)}`
5573
+ ` ${chalk19.dim(date.padEnd(15))} ${chalk19.cyan(createdCol)} ${chalk19.green(completedCol)}`
5364
5574
  );
5365
5575
  }
5366
5576
  console.log("");
5367
5577
  }
5368
5578
  }
5369
5579
  if (showVelocity) {
5370
- console.log(chalk18.bold("\u{1F680} Velocity Metrics"));
5580
+ console.log(chalk19.bold("\u{1F680} Velocity Metrics"));
5371
5581
  console.log("");
5372
- console.log(chalk18.bold("\u23F1\uFE0F Cycle Time (Created \u2192 Completed)"));
5582
+ console.log(chalk19.bold("\u23F1\uFE0F Cycle Time (Created \u2192 Completed)"));
5373
5583
  console.log("");
5374
5584
  console.log(
5375
5585
  ` ${"Metric".padEnd(labelWidth)} ${"Days".padStart(valueWidth)}`
5376
5586
  );
5377
5587
  console.log(
5378
- ` ${chalk18.dim("\u2500".repeat(labelWidth))} ${chalk18.dim("\u2500".repeat(valueWidth))}`
5588
+ ` ${chalk19.dim("\u2500".repeat(labelWidth))} ${chalk19.dim("\u2500".repeat(valueWidth))}`
5379
5589
  );
5380
5590
  console.log(
5381
- ` ${"Average".padEnd(labelWidth)} ${chalk18.cyan(velocityMetrics.cycleTime.average.toFixed(1).padStart(valueWidth))}`
5591
+ ` ${"Average".padEnd(labelWidth)} ${chalk19.cyan(velocityMetrics.cycleTime.average.toFixed(1).padStart(valueWidth))}`
5382
5592
  );
5383
5593
  console.log(
5384
- ` ${"Median".padEnd(labelWidth)} ${chalk18.cyan(velocityMetrics.cycleTime.median.toFixed(1).padStart(valueWidth))}`
5594
+ ` ${"Median".padEnd(labelWidth)} ${chalk19.cyan(velocityMetrics.cycleTime.median.toFixed(1).padStart(valueWidth))}`
5385
5595
  );
5386
5596
  console.log(
5387
- ` ${"90th Percentile".padEnd(labelWidth)} ${chalk18.yellow(velocityMetrics.cycleTime.p90.toFixed(1).padStart(valueWidth))}`
5597
+ ` ${"90th Percentile".padEnd(labelWidth)} ${chalk19.yellow(velocityMetrics.cycleTime.p90.toFixed(1).padStart(valueWidth))}`
5388
5598
  );
5389
5599
  console.log("");
5390
- console.log(chalk18.bold("\u{1F4E6} Throughput"));
5600
+ console.log(chalk19.bold("\u{1F4E6} Throughput"));
5391
5601
  console.log("");
5392
5602
  console.log(
5393
5603
  ` ${"Period".padEnd(labelWidth)} ${"Specs".padStart(valueWidth)}`
5394
5604
  );
5395
5605
  console.log(
5396
- ` ${chalk18.dim("\u2500".repeat(labelWidth))} ${chalk18.dim("\u2500".repeat(valueWidth))}`
5606
+ ` ${chalk19.dim("\u2500".repeat(labelWidth))} ${chalk19.dim("\u2500".repeat(valueWidth))}`
5397
5607
  );
5398
5608
  console.log(
5399
- ` ${"Last 7 days".padEnd(labelWidth)} ${chalk18.green(velocityMetrics.throughput.perWeek.toString().padStart(valueWidth))}`
5609
+ ` ${"Last 7 days".padEnd(labelWidth)} ${chalk19.green(velocityMetrics.throughput.perWeek.toString().padStart(valueWidth))}`
5400
5610
  );
5401
5611
  console.log(
5402
- ` ${"Last 30 days".padEnd(labelWidth)} ${chalk18.green(velocityMetrics.throughput.perMonth.toString().padStart(valueWidth))}`
5612
+ ` ${"Last 30 days".padEnd(labelWidth)} ${chalk19.green(velocityMetrics.throughput.perMonth.toString().padStart(valueWidth))}`
5403
5613
  );
5404
- const trendColor = velocityMetrics.throughput.trend === "up" ? chalk18.green : velocityMetrics.throughput.trend === "down" ? chalk18.red : chalk18.yellow;
5614
+ const trendColor = velocityMetrics.throughput.trend === "up" ? chalk19.green : velocityMetrics.throughput.trend === "down" ? chalk19.red : chalk19.yellow;
5405
5615
  const trendSymbol = velocityMetrics.throughput.trend === "up" ? "\u2191" : velocityMetrics.throughput.trend === "down" ? "\u2193" : "\u2192";
5406
5616
  console.log(
5407
5617
  ` ${"Trend".padEnd(labelWidth)} ${trendColor(trendSymbol + " " + velocityMetrics.throughput.trend.padStart(valueWidth - 2))}`
5408
5618
  );
5409
5619
  console.log("");
5410
- console.log(chalk18.bold("\u{1F504} Work In Progress"));
5620
+ console.log(chalk19.bold("\u{1F504} Work In Progress"));
5411
5621
  console.log("");
5412
5622
  console.log(
5413
5623
  ` ${"Metric".padEnd(labelWidth)} ${"Specs".padStart(valueWidth)}`
5414
5624
  );
5415
5625
  console.log(
5416
- ` ${chalk18.dim("\u2500".repeat(labelWidth))} ${chalk18.dim("\u2500".repeat(valueWidth))}`
5626
+ ` ${chalk19.dim("\u2500".repeat(labelWidth))} ${chalk19.dim("\u2500".repeat(valueWidth))}`
5417
5627
  );
5418
5628
  console.log(
5419
- ` ${"Current".padEnd(labelWidth)} ${chalk18.yellow(velocityMetrics.wip.current.toString().padStart(valueWidth))}`
5629
+ ` ${"Current".padEnd(labelWidth)} ${chalk19.yellow(velocityMetrics.wip.current.toString().padStart(valueWidth))}`
5420
5630
  );
5421
5631
  console.log(
5422
- ` ${"30-day Average".padEnd(labelWidth)} ${chalk18.cyan(velocityMetrics.wip.average.toFixed(1).padStart(valueWidth))}`
5632
+ ` ${"30-day Average".padEnd(labelWidth)} ${chalk19.cyan(velocityMetrics.wip.average.toFixed(1).padStart(valueWidth))}`
5423
5633
  );
5424
5634
  console.log("");
5425
5635
  if (velocityMetrics.leadTime.plannedToInProgress > 0 || velocityMetrics.leadTime.inProgressToComplete > 0) {
5426
- console.log(chalk18.bold("\u{1F500} Lead Time by Stage"));
5636
+ console.log(chalk19.bold("\u{1F500} Lead Time by Stage"));
5427
5637
  console.log("");
5428
5638
  console.log(
5429
5639
  ` ${"Stage".padEnd(labelWidth)} ${"Days".padStart(valueWidth)}`
5430
5640
  );
5431
5641
  console.log(
5432
- ` ${chalk18.dim("\u2500".repeat(labelWidth))} ${chalk18.dim("\u2500".repeat(valueWidth))}`
5642
+ ` ${chalk19.dim("\u2500".repeat(labelWidth))} ${chalk19.dim("\u2500".repeat(valueWidth))}`
5433
5643
  );
5434
5644
  if (velocityMetrics.leadTime.plannedToInProgress > 0) {
5435
5645
  console.log(
5436
- ` ${"Planned \u2192 In Progress".padEnd(labelWidth)} ${chalk18.cyan(velocityMetrics.leadTime.plannedToInProgress.toFixed(1).padStart(valueWidth))}`
5646
+ ` ${"Planned \u2192 In Progress".padEnd(labelWidth)} ${chalk19.cyan(velocityMetrics.leadTime.plannedToInProgress.toFixed(1).padStart(valueWidth))}`
5437
5647
  );
5438
5648
  }
5439
5649
  if (velocityMetrics.leadTime.inProgressToComplete > 0) {
5440
5650
  console.log(
5441
- ` ${"In Progress \u2192 Complete".padEnd(labelWidth)} ${chalk18.green(velocityMetrics.leadTime.inProgressToComplete.toFixed(1).padStart(valueWidth))}`
5651
+ ` ${"In Progress \u2192 Complete".padEnd(labelWidth)} ${chalk19.green(velocityMetrics.leadTime.inProgressToComplete.toFixed(1).padStart(valueWidth))}`
5442
5652
  );
5443
5653
  }
5444
5654
  console.log("");
@@ -5494,34 +5704,34 @@ async function performSearch(query, options) {
5494
5704
  const { results, metadata } = searchResult;
5495
5705
  if (results.length === 0) {
5496
5706
  console.log("");
5497
- console.log(chalk18.yellow(`\u{1F50D} No specs found matching "${sanitizeUserInput(query)}"`));
5707
+ console.log(chalk19.yellow(`\u{1F50D} No specs found matching "${sanitizeUserInput(query)}"`));
5498
5708
  if (Object.keys(filter).length > 0) {
5499
5709
  const filters = [];
5500
5710
  if (options.status) filters.push(`status=${sanitizeUserInput(options.status)}`);
5501
5711
  if (options.tag) filters.push(`tag=${sanitizeUserInput(options.tag)}`);
5502
5712
  if (options.priority) filters.push(`priority=${sanitizeUserInput(options.priority)}`);
5503
5713
  if (options.assignee) filters.push(`assignee=${sanitizeUserInput(options.assignee)}`);
5504
- console.log(chalk18.gray(`With filters: ${filters.join(", ")}`));
5714
+ console.log(chalk19.gray(`With filters: ${filters.join(", ")}`));
5505
5715
  }
5506
5716
  console.log("");
5507
5717
  return;
5508
5718
  }
5509
5719
  console.log("");
5510
- console.log(chalk18.green(`\u{1F50D} Found ${results.length} spec${results.length === 1 ? "" : "s"} matching "${sanitizeUserInput(query)}"`));
5511
- console.log(chalk18.gray(` Searched ${metadata.specsSearched} specs in ${metadata.searchTime}ms`));
5720
+ console.log(chalk19.green(`\u{1F50D} Found ${results.length} spec${results.length === 1 ? "" : "s"} matching "${sanitizeUserInput(query)}"`));
5721
+ console.log(chalk19.gray(` Searched ${metadata.specsSearched} specs in ${metadata.searchTime}ms`));
5512
5722
  if (Object.keys(filter).length > 0) {
5513
5723
  const filters = [];
5514
5724
  if (options.status) filters.push(`status=${sanitizeUserInput(options.status)}`);
5515
5725
  if (options.tag) filters.push(`tag=${sanitizeUserInput(options.tag)}`);
5516
5726
  if (options.priority) filters.push(`priority=${sanitizeUserInput(options.priority)}`);
5517
5727
  if (options.assignee) filters.push(`assignee=${sanitizeUserInput(options.assignee)}`);
5518
- console.log(chalk18.gray(` With filters: ${filters.join(", ")}`));
5728
+ console.log(chalk19.gray(` With filters: ${filters.join(", ")}`));
5519
5729
  }
5520
5730
  console.log("");
5521
5731
  for (const result of results) {
5522
5732
  const { spec, matches, score, totalMatches } = result;
5523
5733
  const statusEmoji = spec.status === "in-progress" ? "\u{1F528}" : spec.status === "complete" ? "\u2705" : "\u{1F4C5}";
5524
- console.log(chalk18.cyan(`${statusEmoji} ${sanitizeUserInput(spec.path)} ${chalk18.gray(`(${score}% match)`)}`));
5734
+ console.log(chalk19.cyan(`${statusEmoji} ${sanitizeUserInput(spec.path)} ${chalk19.gray(`(${score}% match)`)}`));
5525
5735
  const meta = [];
5526
5736
  if (spec.priority) {
5527
5737
  const priorityEmoji = spec.priority === "critical" ? "\u{1F534}" : spec.priority === "high" ? "\u{1F7E1}" : spec.priority === "medium" ? "\u{1F7E0}" : "\u{1F7E2}";
@@ -5531,30 +5741,30 @@ async function performSearch(query, options) {
5531
5741
  meta.push(`[${spec.tags.map((tag) => sanitizeUserInput(tag)).join(", ")}]`);
5532
5742
  }
5533
5743
  if (meta.length > 0) {
5534
- console.log(chalk18.gray(` ${meta.join(" \u2022 ")}`));
5744
+ console.log(chalk19.gray(` ${meta.join(" \u2022 ")}`));
5535
5745
  }
5536
5746
  const titleMatch = matches.find((m) => m.field === "title");
5537
5747
  if (titleMatch) {
5538
- console.log(` ${chalk18.bold("Title:")} ${highlightMatches(titleMatch.text, titleMatch.highlights)}`);
5748
+ console.log(` ${chalk19.bold("Title:")} ${highlightMatches(titleMatch.text, titleMatch.highlights)}`);
5539
5749
  }
5540
5750
  const descMatch = matches.find((m) => m.field === "description");
5541
5751
  if (descMatch) {
5542
- console.log(` ${chalk18.bold("Description:")} ${highlightMatches(descMatch.text, descMatch.highlights)}`);
5752
+ console.log(` ${chalk19.bold("Description:")} ${highlightMatches(descMatch.text, descMatch.highlights)}`);
5543
5753
  }
5544
5754
  const tagMatches = matches.filter((m) => m.field === "tags");
5545
5755
  if (tagMatches.length > 0) {
5546
- console.log(` ${chalk18.bold("Tags:")} ${tagMatches.map((m) => highlightMatches(m.text, m.highlights)).join(", ")}`);
5756
+ console.log(` ${chalk19.bold("Tags:")} ${tagMatches.map((m) => highlightMatches(m.text, m.highlights)).join(", ")}`);
5547
5757
  }
5548
5758
  const contentMatches = matches.filter((m) => m.field === "content");
5549
5759
  if (contentMatches.length > 0) {
5550
- console.log(` ${chalk18.bold("Content matches:")}`);
5760
+ console.log(` ${chalk19.bold("Content matches:")}`);
5551
5761
  for (const match of contentMatches) {
5552
- const lineInfo = match.lineNumber ? chalk18.gray(`[L${match.lineNumber}]`) : "";
5762
+ const lineInfo = match.lineNumber ? chalk19.gray(`[L${match.lineNumber}]`) : "";
5553
5763
  console.log(` ${lineInfo} ${highlightMatches(match.text, match.highlights)}`);
5554
5764
  }
5555
5765
  }
5556
5766
  if (totalMatches > matches.length) {
5557
- console.log(chalk18.gray(` ... and ${totalMatches - matches.length} more match${totalMatches - matches.length === 1 ? "" : "es"}`));
5767
+ console.log(chalk19.gray(` ... and ${totalMatches - matches.length} more match${totalMatches - matches.length === 1 ? "" : "es"}`));
5558
5768
  }
5559
5769
  console.log("");
5560
5770
  }
@@ -5565,7 +5775,7 @@ function highlightMatches(text, highlights) {
5565
5775
  let lastEnd = 0;
5566
5776
  for (const [start, end] of highlights) {
5567
5777
  result += text.substring(lastEnd, start);
5568
- result += chalk18.yellow(text.substring(start, end));
5778
+ result += chalk19.yellow(text.substring(start, end));
5569
5779
  lastEnd = end;
5570
5780
  }
5571
5781
  result += text.substring(lastEnd);
@@ -5583,7 +5793,7 @@ async function showDeps(specPath, options = {}) {
5583
5793
  await autoCheckIfEnabled();
5584
5794
  const config = await loadConfig();
5585
5795
  const cwd = process.cwd();
5586
- const specsDir = path4.join(cwd, config.specsDir);
5796
+ const specsDir = path15.join(cwd, config.specsDir);
5587
5797
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
5588
5798
  if (!resolvedPath) {
5589
5799
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);
@@ -5647,17 +5857,17 @@ async function showDeps(specPath, options = {}) {
5647
5857
  return;
5648
5858
  }
5649
5859
  console.log("");
5650
- console.log(chalk18.green(`\u{1F4E6} Dependencies for ${chalk18.cyan(sanitizeUserInput(spec.path))}`));
5860
+ console.log(chalk19.green(`\u{1F4E6} Dependencies for ${chalk19.cyan(sanitizeUserInput(spec.path))}`));
5651
5861
  console.log("");
5652
5862
  const hasAnyRelationships = dependsOn.length > 0 || requiredBy.length > 0 || related.length > 0;
5653
5863
  if (!hasAnyRelationships) {
5654
- console.log(chalk18.gray(" No dependencies or relationships"));
5864
+ console.log(chalk19.gray(" No dependencies or relationships"));
5655
5865
  console.log("");
5656
5866
  return;
5657
5867
  }
5658
5868
  if ((mode === "complete" || mode === "upstream" || mode === "impact") && dependsOn.length > 0) {
5659
5869
  const label = mode === "complete" ? "Depends On" : mode === "upstream" ? "Upstream Dependencies" : "Upstream (Impact)";
5660
- console.log(chalk18.bold(`${label}:`));
5870
+ console.log(chalk19.bold(`${label}:`));
5661
5871
  for (const dep of dependsOn) {
5662
5872
  const status = getStatusIndicator(dep.frontmatter.status);
5663
5873
  console.log(` \u2192 ${sanitizeUserInput(dep.path)} ${status}`);
@@ -5666,7 +5876,7 @@ async function showDeps(specPath, options = {}) {
5666
5876
  }
5667
5877
  if ((mode === "complete" || mode === "downstream" || mode === "impact") && requiredBy.length > 0) {
5668
5878
  const label = mode === "complete" ? "Required By" : mode === "downstream" ? "Downstream Dependents" : "Downstream (Impact)";
5669
- console.log(chalk18.bold(`${label}:`));
5879
+ console.log(chalk19.bold(`${label}:`));
5670
5880
  for (const blocked of requiredBy) {
5671
5881
  const status = getStatusIndicator(blocked.frontmatter.status);
5672
5882
  console.log(` \u2190 ${sanitizeUserInput(blocked.path)} ${status}`);
@@ -5674,7 +5884,7 @@ async function showDeps(specPath, options = {}) {
5674
5884
  console.log("");
5675
5885
  }
5676
5886
  if ((mode === "complete" || mode === "impact") && related.length > 0) {
5677
- console.log(chalk18.bold("Related Specs:"));
5887
+ console.log(chalk19.bold("Related Specs:"));
5678
5888
  for (const rel of related) {
5679
5889
  const status = getStatusIndicator(rel.frontmatter.status);
5680
5890
  console.log(` \u27F7 ${sanitizeUserInput(rel.path)} ${status}`);
@@ -5682,15 +5892,15 @@ async function showDeps(specPath, options = {}) {
5682
5892
  console.log("");
5683
5893
  }
5684
5894
  if (mode === "complete" && (options.graph || dependsOn.length > 0)) {
5685
- console.log(chalk18.bold("Dependency Chain:"));
5895
+ console.log(chalk19.bold("Dependency Chain:"));
5686
5896
  const chain = buildDependencyChain(spec, specMap, options.depth || 3);
5687
5897
  displayChain(chain, 0);
5688
5898
  console.log("");
5689
5899
  }
5690
5900
  if (mode === "impact") {
5691
5901
  const total = dependsOn.length + requiredBy.length + related.length;
5692
- console.log(chalk18.bold(`Impact Summary:`));
5693
- console.log(` Changing this spec affects ${chalk18.yellow(total)} specs total`);
5902
+ console.log(chalk19.bold(`Impact Summary:`));
5903
+ console.log(` Changing this spec affects ${chalk19.yellow(total)} specs total`);
5694
5904
  console.log(` Upstream: ${dependsOn.length} | Downstream: ${requiredBy.length} | Related: ${related.length}`);
5695
5905
  console.log("");
5696
5906
  }
@@ -5720,7 +5930,7 @@ function buildDependencyChain(spec, specMap, maxDepth, currentDepth = 0, visited
5720
5930
  function displayChain(node, level) {
5721
5931
  const indent = " ".repeat(level);
5722
5932
  const status = getStatusIndicator(node.spec.frontmatter.status);
5723
- const name = level === 0 ? chalk18.cyan(node.spec.path) : node.spec.path;
5933
+ const name = level === 0 ? chalk19.cyan(node.spec.path) : node.spec.path;
5724
5934
  console.log(`${indent}${name} ${status}`);
5725
5935
  for (const dep of node.dependencies) {
5726
5936
  const prefix = " ".repeat(level) + "\u2514\u2500 ";
@@ -5771,19 +5981,19 @@ async function showTimeline(options) {
5771
5981
  }
5772
5982
  }
5773
5983
  }
5774
- console.log(chalk18.bold.cyan("\u{1F4C8} Spec Timeline"));
5984
+ console.log(chalk19.bold.cyan("\u{1F4C8} Spec Timeline"));
5775
5985
  console.log("");
5776
5986
  const allDates = /* @__PURE__ */ new Set([...Object.keys(createdByDate), ...Object.keys(completedByDate)]);
5777
5987
  const sortedDates = Array.from(allDates).sort();
5778
5988
  if (sortedDates.length > 0) {
5779
- console.log(chalk18.bold(`\u{1F4C5} Activity (Last ${days} Days)`));
5989
+ console.log(chalk19.bold(`\u{1F4C5} Activity (Last ${days} Days)`));
5780
5990
  console.log("");
5781
5991
  const labelWidth2 = 15;
5782
5992
  const barWidth = 20;
5783
5993
  const specsWidth = 3;
5784
5994
  const colWidth = barWidth + specsWidth;
5785
- console.log(` ${"Date".padEnd(labelWidth2)} ${chalk18.cyan("Created".padEnd(colWidth))} ${chalk18.green("Completed".padEnd(colWidth))}`);
5786
- console.log(` ${chalk18.dim("\u2500".repeat(labelWidth2))} ${chalk18.dim("\u2500".repeat(colWidth))} ${chalk18.dim("\u2500".repeat(colWidth))}`);
5995
+ console.log(` ${"Date".padEnd(labelWidth2)} ${chalk19.cyan("Created".padEnd(colWidth))} ${chalk19.green("Completed".padEnd(colWidth))}`);
5996
+ console.log(` ${chalk19.dim("\u2500".repeat(labelWidth2))} ${chalk19.dim("\u2500".repeat(colWidth))} ${chalk19.dim("\u2500".repeat(colWidth))}`);
5787
5997
  const maxCount = Math.max(...Object.values(createdByDate), ...Object.values(completedByDate));
5788
5998
  for (const date of sortedDates) {
5789
5999
  const created = createdByDate[date] || 0;
@@ -5792,7 +6002,7 @@ async function showTimeline(options) {
5792
6002
  const completedBar = createBar(completed, maxCount, barWidth);
5793
6003
  const createdCol = `${createdBar.padEnd(barWidth)}${created.toString().padStart(specsWidth)}`;
5794
6004
  const completedCol = `${completedBar.padEnd(barWidth)}${completed.toString().padStart(specsWidth)}`;
5795
- console.log(` ${chalk18.dim(date.padEnd(labelWidth2))} ${chalk18.cyan(createdCol)} ${chalk18.green(completedCol)}`);
6005
+ console.log(` ${chalk19.dim(date.padEnd(labelWidth2))} ${chalk19.cyan(createdCol)} ${chalk19.green(completedCol)}`);
5796
6006
  }
5797
6007
  console.log("");
5798
6008
  }
@@ -5802,18 +6012,18 @@ async function showTimeline(options) {
5802
6012
  return dateB.diff(dateA);
5803
6013
  }).slice(0, 6);
5804
6014
  if (sortedMonths.length > 0) {
5805
- console.log(chalk18.bold("\u{1F4CA} Monthly Overview"));
6015
+ console.log(chalk19.bold("\u{1F4CA} Monthly Overview"));
5806
6016
  console.log("");
5807
6017
  const labelWidth2 = 15;
5808
6018
  const barWidth = 20;
5809
6019
  const specsWidth = 3;
5810
6020
  const colWidth = barWidth + specsWidth;
5811
- console.log(` ${"Month".padEnd(labelWidth2)} ${chalk18.magenta("Specs".padEnd(colWidth))}`);
5812
- console.log(` ${chalk18.dim("\u2500".repeat(labelWidth2))} ${chalk18.dim("\u2500".repeat(colWidth))}`);
6021
+ console.log(` ${"Month".padEnd(labelWidth2)} ${chalk19.magenta("Specs".padEnd(colWidth))}`);
6022
+ console.log(` ${chalk19.dim("\u2500".repeat(labelWidth2))} ${chalk19.dim("\u2500".repeat(colWidth))}`);
5813
6023
  const maxCount = Math.max(...sortedMonths.map(([, count]) => count));
5814
6024
  for (const [month, count] of sortedMonths) {
5815
6025
  const bar = createBar(count, maxCount, barWidth);
5816
- console.log(` ${month.padEnd(labelWidth2)} ${chalk18.magenta(bar.padEnd(barWidth))}${chalk18.magenta(count.toString().padStart(specsWidth))}`);
6026
+ console.log(` ${month.padEnd(labelWidth2)} ${chalk19.magenta(bar.padEnd(barWidth))}${chalk19.magenta(count.toString().padStart(specsWidth))}`);
5817
6027
  }
5818
6028
  console.log("");
5819
6029
  }
@@ -5827,14 +6037,14 @@ async function showTimeline(options) {
5827
6037
  const completed = dayjs3(s.frontmatter.completed);
5828
6038
  return completed.isAfter(today.subtract(30, "day"));
5829
6039
  }).length;
5830
- console.log(chalk18.bold("\u2705 Completion Rate"));
6040
+ console.log(chalk19.bold("\u2705 Completion Rate"));
5831
6041
  console.log("");
5832
6042
  const labelWidth = 15;
5833
6043
  const valueWidth = 5;
5834
6044
  console.log(` ${"Period".padEnd(labelWidth)} ${"Specs".padStart(valueWidth)}`);
5835
- console.log(` ${chalk18.dim("\u2500".repeat(labelWidth))} ${chalk18.dim("\u2500".repeat(valueWidth))}`);
5836
- console.log(` ${"Last 7 days".padEnd(labelWidth)} ${chalk18.green(last7Days.toString().padStart(valueWidth))}`);
5837
- console.log(` ${"Last 30 days".padEnd(labelWidth)} ${chalk18.green(last30Days.toString().padStart(valueWidth))}`);
6045
+ console.log(` ${chalk19.dim("\u2500".repeat(labelWidth))} ${chalk19.dim("\u2500".repeat(valueWidth))}`);
6046
+ console.log(` ${"Last 7 days".padEnd(labelWidth)} ${chalk19.green(last7Days.toString().padStart(valueWidth))}`);
6047
+ console.log(` ${"Last 30 days".padEnd(labelWidth)} ${chalk19.green(last30Days.toString().padStart(valueWidth))}`);
5838
6048
  console.log("");
5839
6049
  if (options.byTag) {
5840
6050
  const tagStats = {};
@@ -5856,9 +6066,9 @@ async function showTimeline(options) {
5856
6066
  }
5857
6067
  const sortedTags = Object.entries(tagStats).sort((a, b) => b[1].created - a[1].created).slice(0, 10);
5858
6068
  if (sortedTags.length > 0) {
5859
- console.log(chalk18.bold("\u{1F3F7}\uFE0F By Tag"));
6069
+ console.log(chalk19.bold("\u{1F3F7}\uFE0F By Tag"));
5860
6070
  for (const [tag, stats] of sortedTags) {
5861
- console.log(` ${chalk18.dim("#")}${tag.padEnd(20)} ${chalk18.cyan(stats.created)} created \xB7 ${chalk18.green(stats.completed)} completed`);
6071
+ console.log(` ${chalk19.dim("#")}${tag.padEnd(20)} ${chalk19.cyan(stats.created)} created \xB7 ${chalk19.green(stats.completed)} completed`);
5862
6072
  }
5863
6073
  console.log("");
5864
6074
  }
@@ -5883,9 +6093,9 @@ async function showTimeline(options) {
5883
6093
  }
5884
6094
  const sortedAssignees = Object.entries(assigneeStats).sort((a, b) => b[1].created - a[1].created);
5885
6095
  if (sortedAssignees.length > 0) {
5886
- console.log(chalk18.bold("\u{1F464} By Assignee"));
6096
+ console.log(chalk19.bold("\u{1F464} By Assignee"));
5887
6097
  for (const [assignee, stats] of sortedAssignees) {
5888
- console.log(` ${chalk18.dim("@")}${assignee.padEnd(20)} ${chalk18.cyan(stats.created)} created \xB7 ${chalk18.green(stats.completed)} completed`);
6098
+ console.log(` ${chalk19.dim("@")}${assignee.padEnd(20)} ${chalk19.cyan(stats.created)} created \xB7 ${chalk19.green(stats.completed)} completed`);
5889
6099
  }
5890
6100
  console.log("");
5891
6101
  }
@@ -5903,10 +6113,10 @@ var STATUS_CONFIG2 = {
5903
6113
  archived: { emoji: "\u{1F4E6}", color: "gray" }
5904
6114
  };
5905
6115
  var PRIORITY_CONFIG3 = {
5906
- critical: { emoji: "\u{1F534}", label: "CRITICAL", colorFn: chalk18.red },
5907
- high: { emoji: "\u{1F7E0}", label: "HIGH", colorFn: chalk18.hex("#FFA500") },
5908
- medium: { emoji: "\u{1F7E1}", label: "MEDIUM", colorFn: chalk18.yellow },
5909
- low: { emoji: "\u{1F7E2}", label: "LOW", colorFn: chalk18.green }
6116
+ critical: { emoji: "\u{1F534}", label: "CRITICAL", colorFn: chalk19.red },
6117
+ high: { emoji: "\u{1F7E0}", label: "HIGH", colorFn: chalk19.hex("#FFA500") },
6118
+ medium: { emoji: "\u{1F7E1}", label: "MEDIUM", colorFn: chalk19.yellow },
6119
+ low: { emoji: "\u{1F7E2}", label: "LOW", colorFn: chalk19.green }
5910
6120
  };
5911
6121
  function ganttCommand() {
5912
6122
  return new Command("gantt").description("Show timeline with dependencies").option("--weeks <n>", "Show N weeks (default: 4)", parseInt).option("--show-complete", "Include completed specs").option("--critical-path", "Highlight critical path").action(async (options) => {
@@ -5934,8 +6144,8 @@ async function showGantt(options) {
5934
6144
  return spec.frontmatter.status !== "archived";
5935
6145
  });
5936
6146
  if (relevantSpecs.length === 0) {
5937
- console.log(chalk18.dim("No active specs found."));
5938
- console.log(chalk18.dim("Tip: Use --show-complete to include completed specs."));
6147
+ console.log(chalk19.dim("No active specs found."));
6148
+ console.log(chalk19.dim("Tip: Use --show-complete to include completed specs."));
5939
6149
  return;
5940
6150
  }
5941
6151
  const groupedSpecs = {
@@ -5971,7 +6181,7 @@ async function showGantt(options) {
5971
6181
  const overdue = relevantSpecs.filter(
5972
6182
  (s) => s.frontmatter.due && dayjs3(s.frontmatter.due).isBefore(today) && s.frontmatter.status !== "complete"
5973
6183
  ).length;
5974
- console.log(chalk18.bold.cyan(`\u{1F4C5} Gantt Chart (${weeks} weeks from ${startDate.format("MMM D, YYYY")})`));
6184
+ console.log(chalk19.bold.cyan(`\u{1F4C5} Gantt Chart (${weeks} weeks from ${startDate.format("MMM D, YYYY")})`));
5975
6185
  console.log("");
5976
6186
  const specHeader = "Spec".padEnd(SPEC_COLUMN_WIDTH);
5977
6187
  const timelineHeader = "Timeline";
@@ -5983,17 +6193,17 @@ async function showGantt(options) {
5983
6193
  calendarDates.push(dateStr);
5984
6194
  }
5985
6195
  const dateRow = " ".repeat(SPEC_COLUMN_WIDTH) + COLUMN_SEPARATOR + calendarDates.join("");
5986
- console.log(chalk18.dim(dateRow));
6196
+ console.log(chalk19.dim(dateRow));
5987
6197
  const specSeparator = "\u2500".repeat(SPEC_COLUMN_WIDTH);
5988
6198
  const timelineSeparator = "\u2500".repeat(timelineColumnWidth);
5989
- console.log(chalk18.dim(specSeparator + COLUMN_SEPARATOR + timelineSeparator));
6199
+ console.log(chalk19.dim(specSeparator + COLUMN_SEPARATOR + timelineSeparator));
5990
6200
  const todayWeekOffset = today.diff(startDate, "week");
5991
6201
  const todayMarkerPos = todayWeekOffset * 8;
5992
6202
  let todayMarker = " ".repeat(SPEC_COLUMN_WIDTH) + COLUMN_SEPARATOR;
5993
6203
  if (todayMarkerPos >= 0 && todayMarkerPos < timelineColumnWidth) {
5994
6204
  todayMarker += " ".repeat(todayMarkerPos) + "\u2502 Today";
5995
6205
  }
5996
- console.log(chalk18.dim(todayMarker));
6206
+ console.log(chalk19.dim(todayMarker));
5997
6207
  console.log("");
5998
6208
  const priorities = ["critical", "high", "medium", "low"];
5999
6209
  for (const priority of priorities) {
@@ -6011,9 +6221,9 @@ async function showGantt(options) {
6011
6221
  const summaryParts = [];
6012
6222
  if (inProgress > 0) summaryParts.push(`${inProgress} in-progress`);
6013
6223
  if (planned > 0) summaryParts.push(`${planned} planned`);
6014
- if (overdue > 0) summaryParts.push(chalk18.red(`${overdue} overdue`));
6015
- console.log(chalk18.bold("Summary: ") + summaryParts.join(" \xB7 "));
6016
- console.log(chalk18.dim('\u{1F4A1} Tip: Add "due: YYYY-MM-DD" to frontmatter for timeline planning'));
6224
+ if (overdue > 0) summaryParts.push(chalk19.red(`${overdue} overdue`));
6225
+ console.log(chalk19.bold("Summary: ") + summaryParts.join(" \xB7 "));
6226
+ console.log(chalk19.dim('\u{1F4A1} Tip: Add "due: YYYY-MM-DD" to frontmatter for timeline planning'));
6017
6227
  }
6018
6228
  function renderSpecRow(spec, startDate, endDate, weeks, today) {
6019
6229
  const statusConfig = STATUS_CONFIG2[spec.frontmatter.status];
@@ -6026,7 +6236,7 @@ function renderSpecRow(spec, startDate, endDate, weeks, today) {
6026
6236
  const specColumn = `${SPEC_INDENT}${emoji} ${specName}`.padEnd(SPEC_COLUMN_WIDTH);
6027
6237
  let timelineColumn;
6028
6238
  if (!spec.frontmatter.due) {
6029
- timelineColumn = chalk18.dim("(no due date set)");
6239
+ timelineColumn = chalk19.dim("(no due date set)");
6030
6240
  } else {
6031
6241
  timelineColumn = renderTimelineBar(spec, startDate, endDate, weeks, today);
6032
6242
  }
@@ -6049,13 +6259,13 @@ function renderTimelineBar(spec, startDate, endDate, weeks, today) {
6049
6259
  result += " ".repeat(barStart);
6050
6260
  }
6051
6261
  if (spec.frontmatter.status === "complete") {
6052
- result += chalk18.green(FILLED_BAR_CHAR.repeat(barLength));
6262
+ result += chalk19.green(FILLED_BAR_CHAR.repeat(barLength));
6053
6263
  } else if (spec.frontmatter.status === "in-progress") {
6054
6264
  const halfLength = Math.floor(barLength / 2);
6055
- result += chalk18.yellow(FILLED_BAR_CHAR.repeat(halfLength));
6056
- result += chalk18.dim(EMPTY_BAR_CHAR.repeat(barLength - halfLength));
6265
+ result += chalk19.yellow(FILLED_BAR_CHAR.repeat(halfLength));
6266
+ result += chalk19.dim(EMPTY_BAR_CHAR.repeat(barLength - halfLength));
6057
6267
  } else {
6058
- result += chalk18.dim(EMPTY_BAR_CHAR.repeat(barLength));
6268
+ result += chalk19.dim(EMPTY_BAR_CHAR.repeat(barLength));
6059
6269
  }
6060
6270
  const trailingSpace = totalChars - barEnd;
6061
6271
  if (trailingSpace > 0) {
@@ -6081,12 +6291,12 @@ async function countSpecTokens(specPath, options = {}) {
6081
6291
  try {
6082
6292
  const config = await loadConfig();
6083
6293
  const cwd = process.cwd();
6084
- const specsDir = path4.join(cwd, config.specsDir);
6294
+ const specsDir = path15.join(cwd, config.specsDir);
6085
6295
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
6086
6296
  if (!resolvedPath) {
6087
6297
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);
6088
6298
  }
6089
- const specName = path4.basename(resolvedPath);
6299
+ const specName = path15.basename(resolvedPath);
6090
6300
  const result = await counter.countSpec(resolvedPath, {
6091
6301
  detailed: options.detailed,
6092
6302
  includeSubSpecs: options.includeSubSpecs
@@ -6099,42 +6309,42 @@ async function countSpecTokens(specPath, options = {}) {
6099
6309
  }, null, 2));
6100
6310
  return;
6101
6311
  }
6102
- console.log(chalk18.bold.cyan(`\u{1F4CA} Token Count: ${specName}`));
6312
+ console.log(chalk19.bold.cyan(`\u{1F4CA} Token Count: ${specName}`));
6103
6313
  console.log("");
6104
6314
  const indicators = counter.getPerformanceIndicators(result.total);
6105
6315
  const levelEmoji = indicators.level === "excellent" ? "\u2705" : indicators.level === "good" ? "\u{1F44D}" : indicators.level === "warning" ? "\u26A0\uFE0F" : "\u{1F534}";
6106
- console.log(` Total: ${chalk18.cyan(result.total.toLocaleString())} tokens ${levelEmoji}`);
6316
+ console.log(` Total: ${chalk19.cyan(result.total.toLocaleString())} tokens ${levelEmoji}`);
6107
6317
  console.log("");
6108
6318
  if (result.files.length > 1 || options.detailed) {
6109
- console.log(chalk18.bold("Files:"));
6319
+ console.log(chalk19.bold("Files:"));
6110
6320
  console.log("");
6111
6321
  for (const file of result.files) {
6112
- const lineInfo = file.lines ? chalk18.dim(` (${file.lines} lines)`) : "";
6113
- console.log(` ${file.path.padEnd(25)} ${chalk18.cyan(file.tokens.toLocaleString().padStart(6))} tokens${lineInfo}`);
6322
+ const lineInfo = file.lines ? chalk19.dim(` (${file.lines} lines)`) : "";
6323
+ console.log(` ${file.path.padEnd(25)} ${chalk19.cyan(file.tokens.toLocaleString().padStart(6))} tokens${lineInfo}`);
6114
6324
  }
6115
6325
  console.log("");
6116
6326
  }
6117
6327
  if (options.detailed && result.breakdown) {
6118
6328
  const b = result.breakdown;
6119
6329
  const total = b.code + b.prose + b.tables + b.frontmatter;
6120
- console.log(chalk18.bold("Content Breakdown:"));
6330
+ console.log(chalk19.bold("Content Breakdown:"));
6121
6331
  console.log("");
6122
- console.log(` Prose ${chalk18.cyan(b.prose.toLocaleString().padStart(6))} tokens ${chalk18.dim(`(${Math.round(b.prose / total * 100)}%)`)}`);
6123
- console.log(` Code ${chalk18.cyan(b.code.toLocaleString().padStart(6))} tokens ${chalk18.dim(`(${Math.round(b.code / total * 100)}%)`)}`);
6124
- console.log(` Tables ${chalk18.cyan(b.tables.toLocaleString().padStart(6))} tokens ${chalk18.dim(`(${Math.round(b.tables / total * 100)}%)`)}`);
6125
- console.log(` Frontmatter ${chalk18.cyan(b.frontmatter.toLocaleString().padStart(6))} tokens ${chalk18.dim(`(${Math.round(b.frontmatter / total * 100)}%)`)}`);
6332
+ console.log(` Prose ${chalk19.cyan(b.prose.toLocaleString().padStart(6))} tokens ${chalk19.dim(`(${Math.round(b.prose / total * 100)}%)`)}`);
6333
+ console.log(` Code ${chalk19.cyan(b.code.toLocaleString().padStart(6))} tokens ${chalk19.dim(`(${Math.round(b.code / total * 100)}%)`)}`);
6334
+ console.log(` Tables ${chalk19.cyan(b.tables.toLocaleString().padStart(6))} tokens ${chalk19.dim(`(${Math.round(b.tables / total * 100)}%)`)}`);
6335
+ console.log(` Frontmatter ${chalk19.cyan(b.frontmatter.toLocaleString().padStart(6))} tokens ${chalk19.dim(`(${Math.round(b.frontmatter / total * 100)}%)`)}`);
6126
6336
  console.log("");
6127
6337
  }
6128
- console.log(chalk18.bold("Performance Indicators:"));
6338
+ console.log(chalk19.bold("Performance Indicators:"));
6129
6339
  console.log("");
6130
- const costColor = indicators.costMultiplier < 2 ? chalk18.green : indicators.costMultiplier < 4 ? chalk18.yellow : chalk18.red;
6131
- const effectivenessColor = indicators.effectiveness >= 95 ? chalk18.green : indicators.effectiveness >= 85 ? chalk18.yellow : chalk18.red;
6132
- console.log(` Cost multiplier: ${costColor(`${indicators.costMultiplier}x`)} ${chalk18.dim("vs 1,200 token baseline")}`);
6133
- console.log(` AI effectiveness: ${effectivenessColor(`~${indicators.effectiveness}%`)} ${chalk18.dim("(hypothesis)")}`);
6340
+ const costColor = indicators.costMultiplier < 2 ? chalk19.green : indicators.costMultiplier < 4 ? chalk19.yellow : chalk19.red;
6341
+ const effectivenessColor = indicators.effectiveness >= 95 ? chalk19.green : indicators.effectiveness >= 85 ? chalk19.yellow : chalk19.red;
6342
+ console.log(` Cost multiplier: ${costColor(`${indicators.costMultiplier}x`)} ${chalk19.dim("vs 1,200 token baseline")}`);
6343
+ console.log(` AI effectiveness: ${effectivenessColor(`~${indicators.effectiveness}%`)} ${chalk19.dim("(hypothesis)")}`);
6134
6344
  console.log(` Context Economy: ${levelEmoji} ${indicators.recommendation}`);
6135
6345
  console.log("");
6136
6346
  if (!options.includeSubSpecs && result.files.length === 1) {
6137
- console.log(chalk18.dim("\u{1F4A1} Use `--include-sub-specs` to count all sub-spec files"));
6347
+ console.log(chalk19.dim("\u{1F4A1} Use `--include-sub-specs` to count all sub-spec files"));
6138
6348
  }
6139
6349
  } finally {
6140
6350
  counter.dispose();
@@ -6180,46 +6390,46 @@ async function tokensAllCommand(options = {}) {
6180
6390
  console.log(JSON.stringify(results, null, 2));
6181
6391
  return;
6182
6392
  }
6183
- console.log(chalk18.bold.cyan("\u{1F4CA} Token Counts"));
6393
+ console.log(chalk19.bold.cyan("\u{1F4CA} Token Counts"));
6184
6394
  console.log("");
6185
- console.log(chalk18.dim(`Sorted by: ${sortBy}`));
6395
+ console.log(chalk19.dim(`Sorted by: ${sortBy}`));
6186
6396
  console.log("");
6187
6397
  const totalTokens = results.reduce((sum, r) => sum + r.tokens, 0);
6188
6398
  const avgTokens = Math.round(totalTokens / results.length);
6189
6399
  const warningCount = results.filter((r) => r.level === "warning" || r.level === "problem").length;
6190
- console.log(chalk18.bold("Summary:"));
6400
+ console.log(chalk19.bold("Summary:"));
6191
6401
  console.log("");
6192
- console.log(` Total specs: ${chalk18.cyan(results.length)}`);
6193
- console.log(` Total tokens: ${chalk18.cyan(totalTokens.toLocaleString())}`);
6194
- console.log(` Average tokens: ${chalk18.cyan(avgTokens.toLocaleString())}`);
6402
+ console.log(` Total specs: ${chalk19.cyan(results.length)}`);
6403
+ console.log(` Total tokens: ${chalk19.cyan(totalTokens.toLocaleString())}`);
6404
+ console.log(` Average tokens: ${chalk19.cyan(avgTokens.toLocaleString())}`);
6195
6405
  if (warningCount > 0) {
6196
- console.log(` Needs review: ${chalk18.yellow(warningCount)} specs ${chalk18.dim("(\u26A0\uFE0F or \u{1F534})")}`);
6406
+ console.log(` Needs review: ${chalk19.yellow(warningCount)} specs ${chalk19.dim("(\u26A0\uFE0F or \u{1F534})")}`);
6197
6407
  }
6198
6408
  console.log("");
6199
6409
  const nameCol = 35;
6200
6410
  const tokensCol = 10;
6201
6411
  const linesCol = 8;
6202
- console.log(chalk18.bold(
6412
+ console.log(chalk19.bold(
6203
6413
  "Spec".padEnd(nameCol) + "Tokens".padStart(tokensCol) + "Lines".padStart(linesCol) + " Status"
6204
6414
  ));
6205
- console.log(chalk18.dim("\u2500".repeat(nameCol + tokensCol + linesCol + 10)));
6415
+ console.log(chalk19.dim("\u2500".repeat(nameCol + tokensCol + linesCol + 10)));
6206
6416
  const displayCount = options.all ? results.length : Math.min(20, results.length);
6207
6417
  for (let i = 0; i < displayCount; i++) {
6208
6418
  const r = results[i];
6209
6419
  const emoji = r.level === "excellent" ? "\u2705" : r.level === "good" ? "\u{1F44D}" : r.level === "warning" ? "\u26A0\uFE0F" : "\u{1F534}";
6210
- const tokensColor = r.level === "excellent" || r.level === "good" ? chalk18.cyan : r.level === "warning" ? chalk18.yellow : chalk18.red;
6420
+ const tokensColor = r.level === "excellent" || r.level === "good" ? chalk19.cyan : r.level === "warning" ? chalk19.yellow : chalk19.red;
6211
6421
  const name = r.name.length > nameCol - 2 ? r.name.substring(0, nameCol - 3) + "\u2026" : r.name;
6212
6422
  console.log(
6213
- name.padEnd(nameCol) + tokensColor(r.tokens.toLocaleString().padStart(tokensCol)) + chalk18.dim(r.lines.toString().padStart(linesCol)) + ` ${emoji}`
6423
+ name.padEnd(nameCol) + tokensColor(r.tokens.toLocaleString().padStart(tokensCol)) + chalk19.dim(r.lines.toString().padStart(linesCol)) + ` ${emoji}`
6214
6424
  );
6215
6425
  }
6216
6426
  if (results.length > displayCount) {
6217
6427
  console.log("");
6218
- console.log(chalk18.dim(`... and ${results.length - displayCount} more specs`));
6219
- console.log(chalk18.dim(`Use --all to show all specs`));
6428
+ console.log(chalk19.dim(`... and ${results.length - displayCount} more specs`));
6429
+ console.log(chalk19.dim(`Use --all to show all specs`));
6220
6430
  }
6221
6431
  console.log("");
6222
- console.log(chalk18.dim("Legend: \u2705 excellent (<2K) | \u{1F44D} good (<3.5K) | \u26A0\uFE0F warning (<5K) | \u{1F534} problem (>5K)"));
6432
+ console.log(chalk19.dim("Legend: \u2705 excellent (<2K) | \u{1F44D} good (<3.5K) | \u26A0\uFE0F warning (<5K) | \u{1F534} problem (>5K)"));
6223
6433
  console.log("");
6224
6434
  }
6225
6435
  function analyzeCommand() {
@@ -6233,13 +6443,13 @@ async function analyzeSpec(specPath, options = {}) {
6233
6443
  try {
6234
6444
  const config = await loadConfig();
6235
6445
  const cwd = process.cwd();
6236
- const specsDir = path4.join(cwd, config.specsDir);
6446
+ const specsDir = path15.join(cwd, config.specsDir);
6237
6447
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
6238
6448
  if (!resolvedPath) {
6239
6449
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);
6240
6450
  }
6241
- const specName = path4.basename(resolvedPath);
6242
- const readmePath = path4.join(resolvedPath, "README.md");
6451
+ const specName = path15.basename(resolvedPath);
6452
+ const readmePath = path15.join(resolvedPath, "README.md");
6243
6453
  const content = await readFile(readmePath, "utf-8");
6244
6454
  const structure = analyzeMarkdownStructure(content);
6245
6455
  const tokenResult = await counter.countSpec(resolvedPath, {
@@ -6342,44 +6552,44 @@ function getThresholdLimit(level) {
6342
6552
  }
6343
6553
  }
6344
6554
  function displayAnalysis(result, verbose) {
6345
- console.log(chalk18.bold.cyan(`\u{1F4CA} Spec Analysis: ${result.spec}`));
6555
+ console.log(chalk19.bold.cyan(`\u{1F4CA} Spec Analysis: ${result.spec}`));
6346
6556
  console.log("");
6347
6557
  const statusEmoji = result.threshold.status === "excellent" ? "\u2705" : result.threshold.status === "good" ? "\u{1F44D}" : result.threshold.status === "warning" ? "\u26A0\uFE0F" : "\u{1F534}";
6348
- const tokenColor = result.threshold.status === "excellent" || result.threshold.status === "good" ? chalk18.cyan : result.threshold.status === "warning" ? chalk18.yellow : chalk18.red;
6349
- console.log(chalk18.bold("Token Count:"), tokenColor(result.metrics.tokens.toLocaleString()), "tokens", statusEmoji);
6350
- console.log(chalk18.dim(` Threshold: ${result.threshold.limit.toLocaleString()} tokens`));
6351
- console.log(chalk18.dim(` Status: ${result.threshold.message}`));
6558
+ const tokenColor = result.threshold.status === "excellent" || result.threshold.status === "good" ? chalk19.cyan : result.threshold.status === "warning" ? chalk19.yellow : chalk19.red;
6559
+ console.log(chalk19.bold("Token Count:"), tokenColor(result.metrics.tokens.toLocaleString()), "tokens", statusEmoji);
6560
+ console.log(chalk19.dim(` Threshold: ${result.threshold.limit.toLocaleString()} tokens`));
6561
+ console.log(chalk19.dim(` Status: ${result.threshold.message}`));
6352
6562
  console.log("");
6353
- console.log(chalk18.bold("Structure:"));
6354
- console.log(` Lines: ${chalk18.cyan(result.metrics.lines.toLocaleString())}`);
6355
- console.log(` Sections: ${chalk18.cyan(result.metrics.sections.total)} (H1:${result.metrics.sections.h1}, H2:${result.metrics.sections.h2}, H3:${result.metrics.sections.h3}, H4:${result.metrics.sections.h4})`);
6356
- console.log(` Code blocks: ${chalk18.cyan(result.metrics.codeBlocks)}`);
6357
- console.log(` Max nesting: ${chalk18.cyan(result.metrics.maxNesting)} levels`);
6563
+ console.log(chalk19.bold("Structure:"));
6564
+ console.log(` Lines: ${chalk19.cyan(result.metrics.lines.toLocaleString())}`);
6565
+ console.log(` Sections: ${chalk19.cyan(result.metrics.sections.total)} (H1:${result.metrics.sections.h1}, H2:${result.metrics.sections.h2}, H3:${result.metrics.sections.h3}, H4:${result.metrics.sections.h4})`);
6566
+ console.log(` Code blocks: ${chalk19.cyan(result.metrics.codeBlocks)}`);
6567
+ console.log(` Max nesting: ${chalk19.cyan(result.metrics.maxNesting)} levels`);
6358
6568
  console.log("");
6359
6569
  if (verbose && result.structure.length > 0) {
6360
6570
  const topSections = result.structure.filter((s) => s.level <= 2).sort((a, b) => b.tokens - a.tokens).slice(0, 5);
6361
- console.log(chalk18.bold("Top Sections by Size:"));
6571
+ console.log(chalk19.bold("Top Sections by Size:"));
6362
6572
  console.log("");
6363
6573
  for (let i = 0; i < topSections.length; i++) {
6364
6574
  const s = topSections[i];
6365
6575
  const percentage = Math.round(s.tokens / result.metrics.tokens * 100);
6366
6576
  const indent = " ".repeat(s.level - 1);
6367
6577
  console.log(` ${i + 1}. ${indent}${s.section}`);
6368
- console.log(` ${chalk18.cyan(s.tokens.toLocaleString())} tokens / ${s.lineRange[1] - s.lineRange[0] + 1} lines ${chalk18.dim(`(${percentage}%)`)}`);
6369
- console.log(chalk18.dim(` Lines ${s.lineRange[0]}-${s.lineRange[1]}`));
6578
+ console.log(` ${chalk19.cyan(s.tokens.toLocaleString())} tokens / ${s.lineRange[1] - s.lineRange[0] + 1} lines ${chalk19.dim(`(${percentage}%)`)}`);
6579
+ console.log(chalk19.dim(` Lines ${s.lineRange[0]}-${s.lineRange[1]}`));
6370
6580
  }
6371
6581
  console.log("");
6372
6582
  }
6373
- const actionColor = result.recommendation.action === "none" ? chalk18.green : result.recommendation.action === "compact" ? chalk18.yellow : result.recommendation.action === "split" ? chalk18.red : chalk18.blue;
6374
- console.log(chalk18.bold("Recommendation:"), actionColor(result.recommendation.action.toUpperCase()));
6375
- console.log(chalk18.dim(` ${result.recommendation.reason}`));
6376
- console.log(chalk18.dim(` Confidence: ${result.recommendation.confidence}`));
6583
+ const actionColor = result.recommendation.action === "none" ? chalk19.green : result.recommendation.action === "compact" ? chalk19.yellow : result.recommendation.action === "split" ? chalk19.red : chalk19.blue;
6584
+ console.log(chalk19.bold("Recommendation:"), actionColor(result.recommendation.action.toUpperCase()));
6585
+ console.log(chalk19.dim(` ${result.recommendation.reason}`));
6586
+ console.log(chalk19.dim(` Confidence: ${result.recommendation.confidence}`));
6377
6587
  console.log("");
6378
6588
  if (result.recommendation.action === "split") {
6379
- console.log(chalk18.dim("\u{1F4A1} Use `lean-spec split` to partition into sub-specs"));
6380
- console.log(chalk18.dim("\u{1F4A1} Consider splitting by H2 sections (concerns)"));
6589
+ console.log(chalk19.dim("\u{1F4A1} Use `lean-spec split` to partition into sub-specs"));
6590
+ console.log(chalk19.dim("\u{1F4A1} Consider splitting by H2 sections (concerns)"));
6381
6591
  } else if (result.recommendation.action === "compact") {
6382
- console.log(chalk18.dim("\u{1F4A1} Use `lean-spec compact` to remove redundancy"));
6592
+ console.log(chalk19.dim("\u{1F4A1} Use `lean-spec compact` to remove redundancy"));
6383
6593
  }
6384
6594
  console.log("");
6385
6595
  }
@@ -6411,13 +6621,13 @@ async function splitSpec(specPath, options) {
6411
6621
  }
6412
6622
  const config = await loadConfig();
6413
6623
  const cwd = process.cwd();
6414
- const specsDir = path4.join(cwd, config.specsDir);
6624
+ const specsDir = path15.join(cwd, config.specsDir);
6415
6625
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
6416
6626
  if (!resolvedPath) {
6417
6627
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);
6418
6628
  }
6419
- const specName = path4.basename(resolvedPath);
6420
- const readmePath = path4.join(resolvedPath, "README.md");
6629
+ const specName = path15.basename(resolvedPath);
6630
+ const readmePath = path15.join(resolvedPath, "README.md");
6421
6631
  const content = await readFile(readmePath, "utf-8");
6422
6632
  const parsedOutputs = parseOutputSpecs(options.outputs);
6423
6633
  validateNoOverlaps(parsedOutputs);
@@ -6440,7 +6650,7 @@ async function splitSpec(specPath, options) {
6440
6650
  await executeSplit(resolvedPath, specName, content, extractions, options);
6441
6651
  } catch (error) {
6442
6652
  if (error instanceof Error) {
6443
- console.error(chalk18.red(`Error: ${error.message}`));
6653
+ console.error(chalk19.red(`Error: ${error.message}`));
6444
6654
  }
6445
6655
  throw error;
6446
6656
  }
@@ -6478,30 +6688,30 @@ function validateNoOverlaps(outputs) {
6478
6688
  }
6479
6689
  }
6480
6690
  async function displayDryRun(specName, extractions) {
6481
- console.log(chalk18.bold.cyan(`\u{1F4CB} Split Preview: ${specName}`));
6691
+ console.log(chalk19.bold.cyan(`\u{1F4CB} Split Preview: ${specName}`));
6482
6692
  console.log("");
6483
- console.log(chalk18.bold("Would create:"));
6693
+ console.log(chalk19.bold("Would create:"));
6484
6694
  console.log("");
6485
6695
  for (const ext of extractions) {
6486
- console.log(` ${chalk18.cyan(ext.file)}`);
6696
+ console.log(` ${chalk19.cyan(ext.file)}`);
6487
6697
  console.log(` Lines: ${ext.lines}`);
6488
6698
  const previewLines = ext.content.split("\n").slice(0, 3);
6489
- console.log(chalk18.dim(" Preview:"));
6699
+ console.log(chalk19.dim(" Preview:"));
6490
6700
  for (const line of previewLines) {
6491
- console.log(chalk18.dim(` ${line.substring(0, 60)}${line.length > 60 ? "..." : ""}`));
6701
+ console.log(chalk19.dim(` ${line.substring(0, 60)}${line.length > 60 ? "..." : ""}`));
6492
6702
  }
6493
6703
  console.log("");
6494
6704
  }
6495
- console.log(chalk18.dim("No files modified (dry run)"));
6496
- console.log(chalk18.dim("Run without --dry-run to apply changes"));
6705
+ console.log(chalk19.dim("No files modified (dry run)"));
6706
+ console.log(chalk19.dim("Run without --dry-run to apply changes"));
6497
6707
  console.log("");
6498
6708
  }
6499
6709
  async function executeSplit(specPath, specName, originalContent, extractions, options) {
6500
- console.log(chalk18.bold.cyan(`\u2702\uFE0F Splitting: ${specName}`));
6710
+ console.log(chalk19.bold.cyan(`\u2702\uFE0F Splitting: ${specName}`));
6501
6711
  console.log("");
6502
6712
  const frontmatter = parseFrontmatterFromString(originalContent);
6503
6713
  for (const ext of extractions) {
6504
- const outputPath = path4.join(specPath, ext.file);
6714
+ const outputPath = path15.join(specPath, ext.file);
6505
6715
  let finalContent = ext.content;
6506
6716
  if (ext.file === "README.md" && frontmatter) {
6507
6717
  const { content: contentWithFrontmatter } = createUpdatedFrontmatter(
@@ -6511,21 +6721,21 @@ async function executeSplit(specPath, specName, originalContent, extractions, op
6511
6721
  finalContent = contentWithFrontmatter;
6512
6722
  }
6513
6723
  await writeFile(outputPath, finalContent, "utf-8");
6514
- console.log(chalk18.green(`\u2713 Created ${ext.file} (${ext.lines} lines)`));
6724
+ console.log(chalk19.green(`\u2713 Created ${ext.file} (${ext.lines} lines)`));
6515
6725
  }
6516
6726
  if (options.updateRefs) {
6517
- const readmePath = path4.join(specPath, "README.md");
6727
+ const readmePath = path15.join(specPath, "README.md");
6518
6728
  const readmeContent = await readFile(readmePath, "utf-8");
6519
6729
  const updatedReadme = await addSubSpecLinks(
6520
6730
  readmeContent,
6521
6731
  extractions.map((e) => e.file).filter((f) => f !== "README.md")
6522
6732
  );
6523
6733
  await writeFile(readmePath, updatedReadme, "utf-8");
6524
- console.log(chalk18.green(`\u2713 Updated README.md with sub-spec links`));
6734
+ console.log(chalk19.green(`\u2713 Updated README.md with sub-spec links`));
6525
6735
  }
6526
6736
  console.log("");
6527
- console.log(chalk18.bold.green("Split complete!"));
6528
- console.log(chalk18.dim(`Created ${extractions.length} files in ${specName}`));
6737
+ console.log(chalk19.bold.green("Split complete!"));
6738
+ console.log(chalk19.dim(`Created ${extractions.length} files in ${specName}`));
6529
6739
  console.log("");
6530
6740
  }
6531
6741
  async function addSubSpecLinks(content, subSpecs) {
@@ -6593,13 +6803,13 @@ async function compactSpec(specPath, options) {
6593
6803
  }
6594
6804
  const config = await loadConfig();
6595
6805
  const cwd = process.cwd();
6596
- const specsDir = path4.join(cwd, config.specsDir);
6806
+ const specsDir = path15.join(cwd, config.specsDir);
6597
6807
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
6598
6808
  if (!resolvedPath) {
6599
6809
  throw new Error(`Spec not found: ${sanitizeUserInput(specPath)}`);
6600
6810
  }
6601
- const specName = path4.basename(resolvedPath);
6602
- const readmePath = path4.join(resolvedPath, "README.md");
6811
+ const specName = path15.basename(resolvedPath);
6812
+ const readmePath = path15.join(resolvedPath, "README.md");
6603
6813
  const content = await readFile(readmePath, "utf-8");
6604
6814
  const parsedRemoves = parseRemoveSpecs(options.removes);
6605
6815
  validateNoOverlaps2(parsedRemoves);
@@ -6610,7 +6820,7 @@ async function compactSpec(specPath, options) {
6610
6820
  await executeCompact(readmePath, specName, content, parsedRemoves);
6611
6821
  } catch (error) {
6612
6822
  if (error instanceof Error) {
6613
- console.error(chalk18.red(`Error: ${error.message}`));
6823
+ console.error(chalk19.red(`Error: ${error.message}`));
6614
6824
  }
6615
6825
  throw error;
6616
6826
  }
@@ -6649,9 +6859,9 @@ function validateNoOverlaps2(removes) {
6649
6859
  }
6650
6860
  }
6651
6861
  async function displayDryRun2(specName, content, removes) {
6652
- console.log(chalk18.bold.cyan(`\u{1F4CB} Compact Preview: ${specName}`));
6862
+ console.log(chalk19.bold.cyan(`\u{1F4CB} Compact Preview: ${specName}`));
6653
6863
  console.log("");
6654
- console.log(chalk18.bold("Would remove:"));
6864
+ console.log(chalk19.bold("Would remove:"));
6655
6865
  console.log("");
6656
6866
  let totalLines = 0;
6657
6867
  for (const remove of removes) {
@@ -6660,29 +6870,29 @@ async function displayDryRun2(specName, content, removes) {
6660
6870
  const removedContent = extractLines(content, remove.startLine, remove.endLine);
6661
6871
  const previewLines = removedContent.split("\n").slice(0, 3);
6662
6872
  console.log(` Lines ${remove.startLine}-${remove.endLine} (${lineCount} lines)`);
6663
- console.log(chalk18.dim(" Preview:"));
6873
+ console.log(chalk19.dim(" Preview:"));
6664
6874
  for (const line of previewLines) {
6665
- console.log(chalk18.dim(` ${line.substring(0, 60)}${line.length > 60 ? "..." : ""}`));
6875
+ console.log(chalk19.dim(` ${line.substring(0, 60)}${line.length > 60 ? "..." : ""}`));
6666
6876
  }
6667
6877
  if (removedContent.split("\n").length > 3) {
6668
- console.log(chalk18.dim(` ... (${removedContent.split("\n").length - 3} more lines)`));
6878
+ console.log(chalk19.dim(` ... (${removedContent.split("\n").length - 3} more lines)`));
6669
6879
  }
6670
6880
  console.log("");
6671
6881
  }
6672
6882
  const originalLines = countLines(content);
6673
6883
  const remainingLines = originalLines - totalLines;
6674
6884
  const percentage = Math.round(totalLines / originalLines * 100);
6675
- console.log(chalk18.bold("Summary:"));
6676
- console.log(` Original lines: ${chalk18.cyan(originalLines)}`);
6677
- console.log(` Removing: ${chalk18.yellow(totalLines)} lines (${percentage}%)`);
6678
- console.log(` Remaining lines: ${chalk18.cyan(remainingLines)}`);
6885
+ console.log(chalk19.bold("Summary:"));
6886
+ console.log(` Original lines: ${chalk19.cyan(originalLines)}`);
6887
+ console.log(` Removing: ${chalk19.yellow(totalLines)} lines (${percentage}%)`);
6888
+ console.log(` Remaining lines: ${chalk19.cyan(remainingLines)}`);
6679
6889
  console.log("");
6680
- console.log(chalk18.dim("No files modified (dry run)"));
6681
- console.log(chalk18.dim("Run without --dry-run to apply changes"));
6890
+ console.log(chalk19.dim("No files modified (dry run)"));
6891
+ console.log(chalk19.dim("Run without --dry-run to apply changes"));
6682
6892
  console.log("");
6683
6893
  }
6684
6894
  async function executeCompact(readmePath, specName, content, removes) {
6685
- console.log(chalk18.bold.cyan(`\u{1F5DC}\uFE0F Compacting: ${specName}`));
6895
+ console.log(chalk19.bold.cyan(`\u{1F5DC}\uFE0F Compacting: ${specName}`));
6686
6896
  console.log("");
6687
6897
  const sorted = [...removes].sort((a, b) => b.startLine - a.startLine);
6688
6898
  let updatedContent = content;
@@ -6691,22 +6901,22 @@ async function executeCompact(readmePath, specName, content, removes) {
6691
6901
  const lineCount = remove.endLine - remove.startLine + 1;
6692
6902
  updatedContent = removeLines(updatedContent, remove.startLine, remove.endLine);
6693
6903
  totalRemoved += lineCount;
6694
- console.log(chalk18.green(`\u2713 Removed lines ${remove.startLine}-${remove.endLine} (${lineCount} lines)`));
6904
+ console.log(chalk19.green(`\u2713 Removed lines ${remove.startLine}-${remove.endLine} (${lineCount} lines)`));
6695
6905
  }
6696
6906
  await writeFile(readmePath, updatedContent, "utf-8");
6697
6907
  const originalLines = countLines(content);
6698
6908
  const finalLines = countLines(updatedContent);
6699
6909
  const percentage = Math.round(totalRemoved / originalLines * 100);
6700
6910
  console.log("");
6701
- console.log(chalk18.bold.green("Compaction complete!"));
6702
- console.log(chalk18.dim(`Removed ${totalRemoved} lines (${percentage}%)`));
6703
- console.log(chalk18.dim(`${originalLines} \u2192 ${finalLines} lines`));
6911
+ console.log(chalk19.bold.green("Compaction complete!"));
6912
+ console.log(chalk19.dim(`Removed ${totalRemoved} lines (${percentage}%)`));
6913
+ console.log(chalk19.dim(`${originalLines} \u2192 ${finalLines} lines`));
6704
6914
  console.log("");
6705
6915
  }
6706
6916
  marked.use(markedTerminal());
6707
6917
  async function readSpecContent(specPath, cwd = process.cwd()) {
6708
6918
  const config = await loadConfig(cwd);
6709
- const specsDir = path4.join(cwd, config.specsDir);
6919
+ const specsDir = path15.join(cwd, config.specsDir);
6710
6920
  let resolvedPath = null;
6711
6921
  let targetFile = null;
6712
6922
  const pathParts = specPath.split("/").filter((p) => p);
@@ -6715,7 +6925,7 @@ async function readSpecContent(specPath, cwd = process.cwd()) {
6715
6925
  const filePart = pathParts[pathParts.length - 1];
6716
6926
  resolvedPath = await resolveSpecPath(specPart, cwd, specsDir);
6717
6927
  if (resolvedPath) {
6718
- targetFile = path4.join(resolvedPath, filePart);
6928
+ targetFile = path15.join(resolvedPath, filePart);
6719
6929
  try {
6720
6930
  await fs9.access(targetFile);
6721
6931
  } catch {
@@ -6737,7 +6947,7 @@ async function readSpecContent(specPath, cwd = process.cwd()) {
6737
6947
  return null;
6738
6948
  }
6739
6949
  const rawContent = await fs9.readFile(targetFile, "utf-8");
6740
- const fileName = path4.basename(targetFile);
6950
+ const fileName = path15.basename(targetFile);
6741
6951
  const isSubSpec = fileName !== config.structure.defaultFile;
6742
6952
  let frontmatter = null;
6743
6953
  if (!isSubSpec) {
@@ -6766,7 +6976,7 @@ async function readSpecContent(specPath, cwd = process.cwd()) {
6766
6976
  }
6767
6977
  }
6768
6978
  const content = lines.slice(contentStartIndex).join("\n").trim();
6769
- const specName = path4.basename(resolvedPath);
6979
+ const specName = path15.basename(resolvedPath);
6770
6980
  const displayName = isSubSpec ? `${specName}/${fileName}` : specName;
6771
6981
  return {
6772
6982
  frontmatter,
@@ -6789,7 +6999,7 @@ function formatFrontmatter(frontmatter) {
6789
6999
  archived: "\u{1F4E6}"
6790
7000
  };
6791
7001
  const statusEmoji = statusEmojis[frontmatter.status] || "\u{1F4C4}";
6792
- lines.push(chalk18.bold(`${statusEmoji} Status: `) + chalk18.cyan(frontmatter.status));
7002
+ lines.push(chalk19.bold(`${statusEmoji} Status: `) + chalk19.cyan(frontmatter.status));
6793
7003
  if (frontmatter.priority) {
6794
7004
  const priorityEmojis = {
6795
7005
  low: "\u{1F7E2}",
@@ -6798,25 +7008,25 @@ function formatFrontmatter(frontmatter) {
6798
7008
  critical: "\u{1F534}"
6799
7009
  };
6800
7010
  const priorityEmoji = priorityEmojis[frontmatter.priority] || "";
6801
- lines.push(chalk18.bold(`${priorityEmoji} Priority: `) + chalk18.yellow(frontmatter.priority));
7011
+ lines.push(chalk19.bold(`${priorityEmoji} Priority: `) + chalk19.yellow(frontmatter.priority));
6802
7012
  }
6803
7013
  if (frontmatter.created) {
6804
- lines.push(chalk18.bold("\u{1F4C6} Created: ") + chalk18.gray(String(frontmatter.created)));
7014
+ lines.push(chalk19.bold("\u{1F4C6} Created: ") + chalk19.gray(String(frontmatter.created)));
6805
7015
  }
6806
7016
  if (frontmatter.tags && frontmatter.tags.length > 0) {
6807
- const tagStr = frontmatter.tags.map((tag) => chalk18.blue(`#${tag}`)).join(" ");
6808
- lines.push(chalk18.bold("\u{1F3F7}\uFE0F Tags: ") + tagStr);
7017
+ const tagStr = frontmatter.tags.map((tag) => chalk19.blue(`#${tag}`)).join(" ");
7018
+ lines.push(chalk19.bold("\u{1F3F7}\uFE0F Tags: ") + tagStr);
6809
7019
  }
6810
7020
  if (frontmatter.assignee) {
6811
- lines.push(chalk18.bold("\u{1F464} Assignee: ") + chalk18.green(frontmatter.assignee));
7021
+ lines.push(chalk19.bold("\u{1F464} Assignee: ") + chalk19.green(frontmatter.assignee));
6812
7022
  }
6813
7023
  const standardFields = ["status", "priority", "created", "tags", "assignee"];
6814
7024
  const customFields = Object.entries(frontmatter).filter(([key]) => !standardFields.includes(key)).filter(([_, value]) => value !== void 0 && value !== null);
6815
7025
  if (customFields.length > 0) {
6816
7026
  lines.push("");
6817
- lines.push(chalk18.bold("Custom Fields:"));
7027
+ lines.push(chalk19.bold("Custom Fields:"));
6818
7028
  for (const [key, value] of customFields) {
6819
- lines.push(` ${chalk18.gray(key)}: ${chalk18.white(String(value))}`);
7029
+ lines.push(` ${chalk19.gray(key)}: ${chalk19.white(String(value))}`);
6820
7030
  }
6821
7031
  }
6822
7032
  return lines.join("\n");
@@ -6824,11 +7034,11 @@ function formatFrontmatter(frontmatter) {
6824
7034
  function displayFormattedSpec(spec) {
6825
7035
  const output = [];
6826
7036
  output.push("");
6827
- output.push(chalk18.bold.cyan(`\u2501\u2501\u2501 ${spec.name} \u2501\u2501\u2501`));
7037
+ output.push(chalk19.bold.cyan(`\u2501\u2501\u2501 ${spec.name} \u2501\u2501\u2501`));
6828
7038
  output.push("");
6829
7039
  output.push(formatFrontmatter(spec.frontmatter));
6830
7040
  output.push("");
6831
- output.push(chalk18.gray("\u2500".repeat(60)));
7041
+ output.push(chalk19.gray("\u2500".repeat(60)));
6832
7042
  output.push("");
6833
7043
  return output.join("\n");
6834
7044
  }
@@ -6890,7 +7100,7 @@ function openCommand(specPath, options = {}) {
6890
7100
  async function openSpec(specPath, options = {}) {
6891
7101
  const cwd = process.cwd();
6892
7102
  const config = await loadConfig(cwd);
6893
- const specsDir = path4.join(cwd, config.specsDir);
7103
+ const specsDir = path15.join(cwd, config.specsDir);
6894
7104
  let resolvedPath = null;
6895
7105
  let targetFile = null;
6896
7106
  const pathParts = specPath.split("/").filter((p) => p);
@@ -6899,7 +7109,7 @@ async function openSpec(specPath, options = {}) {
6899
7109
  const filePart = pathParts[pathParts.length - 1];
6900
7110
  resolvedPath = await resolveSpecPath(specPart, cwd, specsDir);
6901
7111
  if (resolvedPath) {
6902
- targetFile = path4.join(resolvedPath, filePart);
7112
+ targetFile = path15.join(resolvedPath, filePart);
6903
7113
  try {
6904
7114
  await fs9.access(targetFile);
6905
7115
  } catch {
@@ -6933,7 +7143,7 @@ async function openSpec(specPath, options = {}) {
6933
7143
  editor = "xdg-open";
6934
7144
  }
6935
7145
  }
6936
- console.log(chalk18.gray(`Opening ${targetFile} with ${editor}...`));
7146
+ console.log(chalk19.gray(`Opening ${targetFile} with ${editor}...`));
6937
7147
  const child = spawn(editor, [targetFile], {
6938
7148
  stdio: "inherit",
6939
7149
  shell: true
@@ -6979,7 +7189,7 @@ async function startMcpServer() {
6979
7189
  process.exit(1);
6980
7190
  }
6981
7191
  }
6982
- function detectPackageManager(baseDir = process.cwd()) {
7192
+ function detectPackageManager2(baseDir = process.cwd()) {
6983
7193
  const userAgent = process.env.npm_config_user_agent || "";
6984
7194
  if (userAgent.includes("pnpm")) {
6985
7195
  return "pnpm";
@@ -7015,8 +7225,8 @@ function uiCommand() {
7015
7225
  async function startUi(options) {
7016
7226
  const portNum = parseInt(options.port, 10);
7017
7227
  if (isNaN(portNum) || portNum < 1 || portNum > 65535) {
7018
- console.error(chalk18.red(`\u2717 Invalid port number: ${options.port}`));
7019
- console.log(chalk18.dim("Port must be between 1 and 65535"));
7228
+ console.error(chalk19.red(`\u2717 Invalid port number: ${options.port}`));
7229
+ console.log(chalk19.dim("Port must be between 1 and 65535"));
7020
7230
  throw new Error(`Invalid port: ${options.port}`);
7021
7231
  }
7022
7232
  const cwd = process.cwd();
@@ -7030,24 +7240,24 @@ async function startUi(options) {
7030
7240
  specsDir = join(cwd, config.specsDir);
7031
7241
  }
7032
7242
  if (!existsSync(specsDir)) {
7033
- console.error(chalk18.red(`\u2717 Specs directory not found: ${specsDir}`));
7034
- console.log(chalk18.dim("\nRun `lean-spec init` to initialize LeanSpec in this directory."));
7243
+ console.error(chalk19.red(`\u2717 Specs directory not found: ${specsDir}`));
7244
+ console.log(chalk19.dim("\nRun `lean-spec init` to initialize LeanSpec in this directory."));
7035
7245
  throw new Error(`Specs directory not found: ${specsDir}`);
7036
7246
  }
7037
7247
  } else {
7038
- console.log(chalk18.cyan("\u2192 Multi-project mode enabled"));
7248
+ console.log(chalk19.cyan("\u2192 Multi-project mode enabled"));
7039
7249
  if (options.addProject) {
7040
- console.log(chalk18.dim(` Adding project: ${options.addProject}`));
7250
+ console.log(chalk19.dim(` Adding project: ${options.addProject}`));
7041
7251
  }
7042
7252
  if (options.discover) {
7043
- console.log(chalk18.dim(` Will discover projects in: ${options.discover}`));
7253
+ console.log(chalk19.dim(` Will discover projects in: ${options.discover}`));
7044
7254
  }
7045
7255
  }
7046
7256
  if (options.dev) {
7047
7257
  const isLeanSpecMonorepo = checkIsLeanSpecMonorepo(cwd);
7048
7258
  if (!isLeanSpecMonorepo) {
7049
- console.error(chalk18.red(`\u2717 Development mode only works in the LeanSpec monorepo`));
7050
- console.log(chalk18.dim("Remove --dev flag to use production mode"));
7259
+ console.error(chalk19.red(`\u2717 Development mode only works in the LeanSpec monorepo`));
7260
+ console.log(chalk19.dim("Remove --dev flag to use production mode"));
7051
7261
  throw new Error("Not in LeanSpec monorepo");
7052
7262
  }
7053
7263
  const localUiDir = join(cwd, "packages/ui");
@@ -7069,15 +7279,15 @@ function checkIsLeanSpecMonorepo(cwd) {
7069
7279
  }
7070
7280
  }
7071
7281
  async function runLocalWeb(uiDir, specsDir, specsMode, options) {
7072
- console.log(chalk18.dim("\u2192 Detected LeanSpec monorepo, using local ui package\n"));
7282
+ console.log(chalk19.dim("\u2192 Detected LeanSpec monorepo, using local ui package\n"));
7073
7283
  const repoRoot = resolve(uiDir, "..", "..");
7074
- const packageManager = detectPackageManager(repoRoot);
7284
+ const packageManager = detectPackageManager2(repoRoot);
7075
7285
  if (options.dryRun) {
7076
- console.log(chalk18.cyan("Would run:"));
7077
- console.log(chalk18.dim(` cd ${uiDir}`));
7078
- console.log(chalk18.dim(` SPECS_MODE=${specsMode} SPECS_DIR=${specsDir} PORT=${options.port} ${packageManager} run dev`));
7286
+ console.log(chalk19.cyan("Would run:"));
7287
+ console.log(chalk19.dim(` cd ${uiDir}`));
7288
+ console.log(chalk19.dim(` SPECS_MODE=${specsMode} SPECS_DIR=${specsDir} PORT=${options.port} ${packageManager} run dev`));
7079
7289
  if (options.open) {
7080
- console.log(chalk18.dim(` open http://localhost:${options.port}`));
7290
+ console.log(chalk19.dim(` open http://localhost:${options.port}`));
7081
7291
  }
7082
7292
  return;
7083
7293
  }
@@ -7096,11 +7306,11 @@ async function runLocalWeb(uiDir, specsDir, specsMode, options) {
7096
7306
  });
7097
7307
  const readyTimeout = setTimeout(async () => {
7098
7308
  spinner.succeed("Web UI running");
7099
- console.log(chalk18.green(`
7309
+ console.log(chalk19.green(`
7100
7310
  \u2728 LeanSpec UI: http://localhost:${options.port}
7101
7311
  `));
7102
7312
  if (options.multiProject) {
7103
- console.log(chalk18.cyan("Multi-project mode is active"));
7313
+ console.log(chalk19.cyan("Multi-project mode is active"));
7104
7314
  if (options.addProject) {
7105
7315
  try {
7106
7316
  const res = await fetch(`http://localhost:${options.port}/api/projects`, {
@@ -7109,16 +7319,16 @@ async function runLocalWeb(uiDir, specsDir, specsMode, options) {
7109
7319
  body: JSON.stringify({ path: options.addProject })
7110
7320
  });
7111
7321
  if (res.ok) {
7112
- console.log(chalk18.green(` \u2713 Added project: ${options.addProject}`));
7322
+ console.log(chalk19.green(` \u2713 Added project: ${options.addProject}`));
7113
7323
  } else {
7114
- console.error(chalk18.red(` \u2717 Failed to add project: ${options.addProject}`));
7324
+ console.error(chalk19.red(` \u2717 Failed to add project: ${options.addProject}`));
7115
7325
  }
7116
7326
  } catch (e) {
7117
- console.error(chalk18.red(` \u2717 Failed to connect to server for adding project`));
7327
+ console.error(chalk19.red(` \u2717 Failed to connect to server for adding project`));
7118
7328
  }
7119
7329
  }
7120
7330
  if (options.discover) {
7121
- console.log(chalk18.dim(` Discovering projects in: ${options.discover}...`));
7331
+ console.log(chalk19.dim(` Discovering projects in: ${options.discover}...`));
7122
7332
  try {
7123
7333
  const res = await fetch(`http://localhost:${options.port}/api/local-projects/discover`, {
7124
7334
  method: "POST",
@@ -7128,7 +7338,7 @@ async function runLocalWeb(uiDir, specsDir, specsMode, options) {
7128
7338
  if (res.ok) {
7129
7339
  const data = await res.json();
7130
7340
  const discovered = data.discovered || [];
7131
- console.log(chalk18.green(` \u2713 Found ${discovered.length} projects`));
7341
+ console.log(chalk19.green(` \u2713 Found ${discovered.length} projects`));
7132
7342
  for (const p of discovered) {
7133
7343
  const addRes = await fetch(`http://localhost:${options.port}/api/projects`, {
7134
7344
  method: "POST",
@@ -7136,27 +7346,27 @@ async function runLocalWeb(uiDir, specsDir, specsMode, options) {
7136
7346
  body: JSON.stringify({ path: p.path })
7137
7347
  });
7138
7348
  if (addRes.ok) {
7139
- console.log(chalk18.dim(` + Added: ${p.name} (${p.path})`));
7349
+ console.log(chalk19.dim(` + Added: ${p.name} (${p.path})`));
7140
7350
  }
7141
7351
  }
7142
7352
  } else {
7143
- console.error(chalk18.red(` \u2717 Failed to discover projects`));
7353
+ console.error(chalk19.red(` \u2717 Failed to discover projects`));
7144
7354
  }
7145
7355
  } catch (e) {
7146
- console.error(chalk18.red(` \u2717 Failed to connect to server for discovery`));
7356
+ console.error(chalk19.red(` \u2717 Failed to connect to server for discovery`));
7147
7357
  }
7148
7358
  }
7149
7359
  }
7150
- console.log(chalk18.dim("\nPress Ctrl+C to stop\n"));
7360
+ console.log(chalk19.dim("\nPress Ctrl+C to stop\n"));
7151
7361
  if (options.open) {
7152
7362
  try {
7153
7363
  const openModule = await import('open');
7154
7364
  const open = openModule.default;
7155
7365
  await open(`http://localhost:${options.port}`);
7156
7366
  } catch (error) {
7157
- console.log(chalk18.yellow("\u26A0 Could not open browser automatically"));
7158
- console.log(chalk18.dim("Please visit the URL above manually\n"));
7159
- console.error(chalk18.dim(`Debug: ${error instanceof Error ? error.message : String(error)}`));
7367
+ console.log(chalk19.yellow("\u26A0 Could not open browser automatically"));
7368
+ console.log(chalk19.dim("Please visit the URL above manually\n"));
7369
+ console.error(chalk19.dim(`Debug: ${error instanceof Error ? error.message : String(error)}`));
7160
7370
  }
7161
7371
  }
7162
7372
  }, 3e3);
@@ -7173,7 +7383,7 @@ async function runLocalWeb(uiDir, specsDir, specsMode, options) {
7173
7383
  }
7174
7384
  } catch (err) {
7175
7385
  }
7176
- console.log(chalk18.dim("\n\u2713 Web UI stopped"));
7386
+ console.log(chalk19.dim("\n\u2713 Web UI stopped"));
7177
7387
  process.exit(0);
7178
7388
  };
7179
7389
  process.once("SIGINT", () => shutdown("SIGINT"));
@@ -7187,7 +7397,7 @@ async function runLocalWeb(uiDir, specsDir, specsMode, options) {
7187
7397
  spinner.stop();
7188
7398
  if (code !== 0 && code !== null) {
7189
7399
  spinner.fail("Web UI failed to start");
7190
- console.error(chalk18.red(`
7400
+ console.error(chalk19.red(`
7191
7401
  Process exited with code ${code}`));
7192
7402
  process.exit(code);
7193
7403
  }
@@ -7195,12 +7405,12 @@ Process exited with code ${code}`));
7195
7405
  });
7196
7406
  }
7197
7407
  async function runPublishedUI(cwd, specsDir, specsMode, options) {
7198
- console.log(chalk18.dim("\u2192 Using published @leanspec/ui package\n"));
7199
- const packageManager = detectPackageManager(cwd);
7408
+ console.log(chalk19.dim("\u2192 Using published @leanspec/ui package\n"));
7409
+ const packageManager = detectPackageManager2(cwd);
7200
7410
  const { command, args, preview } = buildUiRunner(packageManager, specsDir, specsMode, options.port, options.open, options.multiProject);
7201
7411
  if (options.dryRun) {
7202
- console.log(chalk18.cyan("Would run:"));
7203
- console.log(chalk18.dim(` ${preview}`));
7412
+ console.log(chalk19.cyan("Would run:"));
7413
+ console.log(chalk19.dim(` ${preview}`));
7204
7414
  return;
7205
7415
  }
7206
7416
  const child = spawn(command, args, {
@@ -7219,7 +7429,7 @@ async function runPublishedUI(cwd, specsDir, specsMode, options) {
7219
7429
  }
7220
7430
  } catch (err) {
7221
7431
  }
7222
- console.log(chalk18.dim("\n\u2713 Web UI stopped"));
7432
+ console.log(chalk19.dim("\n\u2713 Web UI stopped"));
7223
7433
  process.exit(0);
7224
7434
  };
7225
7435
  process.once("SIGINT", () => shutdownPublished("SIGINT"));
@@ -7233,14 +7443,14 @@ async function runPublishedUI(cwd, specsDir, specsMode, options) {
7233
7443
  process.exit(0);
7234
7444
  return;
7235
7445
  }
7236
- console.error(chalk18.red(`
7446
+ console.error(chalk19.red(`
7237
7447
  @leanspec/ui exited with code ${code}`));
7238
- console.log(chalk18.dim("Make sure npm can download @leanspec/ui (https://www.npmjs.com/package/@leanspec/ui)."));
7448
+ console.log(chalk19.dim("Make sure npm can download @leanspec/ui (https://www.npmjs.com/package/@leanspec/ui)."));
7239
7449
  process.exit(code);
7240
7450
  });
7241
7451
  child.on("error", (error) => {
7242
- console.error(chalk18.red(`Failed to launch @leanspec/ui: ${error instanceof Error ? error.message : String(error)}`));
7243
- console.log(chalk18.dim("You can also run it manually with `npx @leanspec/ui --specs <dir>`"));
7452
+ console.error(chalk19.red(`Failed to launch @leanspec/ui: ${error instanceof Error ? error.message : String(error)}`));
7453
+ console.log(chalk19.dim("You can also run it manually with `npx @leanspec/ui --specs <dir>`"));
7244
7454
  process.exit(1);
7245
7455
  });
7246
7456
  }
@@ -7583,7 +7793,7 @@ function createTool() {
7583
7793
  async function getDepsData(specPath, mode = "complete") {
7584
7794
  const config = await loadConfig();
7585
7795
  const cwd = process.cwd();
7586
- const specsDir = path4.join(cwd, config.specsDir);
7796
+ const specsDir = path15.join(cwd, config.specsDir);
7587
7797
  const resolvedPath = await resolveSpecPath(specPath, cwd, specsDir);
7588
7798
  if (!resolvedPath) {
7589
7799
  throw new Error(`Spec not found: ${specPath}`);
@@ -8031,7 +8241,7 @@ function tokensTool() {
8031
8241
  try {
8032
8242
  const config = await loadConfig();
8033
8243
  const cwd = process.cwd();
8034
- const specsDir = path4.join(cwd, config.specsDir);
8244
+ const specsDir = path15.join(cwd, config.specsDir);
8035
8245
  const resolvedPath = await resolveSpecPath(input.specPath, cwd, specsDir);
8036
8246
  if (!resolvedPath) {
8037
8247
  return {
@@ -8042,7 +8252,7 @@ function tokensTool() {
8042
8252
  isError: true
8043
8253
  };
8044
8254
  }
8045
- const specName = path4.basename(resolvedPath);
8255
+ const specName = path15.basename(resolvedPath);
8046
8256
  const result = await counter.countSpec(resolvedPath, {
8047
8257
  detailed: input.detailed,
8048
8258
  includeSubSpecs: input.includeSubSpecs
@@ -8581,6 +8791,6 @@ if (import.meta.url === `file://${process.argv[1]}`) {
8581
8791
  main().catch(console.error);
8582
8792
  }
8583
8793
 
8584
- export { analyzeCommand, archiveCommand, backfillCommand, boardCommand, checkCommand, compactCommand, createCommand, createMcpServer, depsCommand, filesCommand, ganttCommand, initCommand, linkCommand, listCommand, mcpCommand, migrateCommand, openCommand, searchCommand, splitCommand, statsCommand, templatesCommand, timelineCommand, tokensCommand, uiCommand, unlinkCommand, updateCommand, validateCommand, viewCommand };
8585
- //# sourceMappingURL=chunk-IGNO4GX2.js.map
8586
- //# sourceMappingURL=chunk-IGNO4GX2.js.map
8794
+ export { analyzeCommand, archiveCommand, backfillCommand, boardCommand, checkCommand, compactCommand, createCommand, createMcpServer, depsCommand, examplesCommand, filesCommand, ganttCommand, initCommand, linkCommand, listCommand, mcpCommand, migrateCommand, openCommand, searchCommand, splitCommand, statsCommand, templatesCommand, timelineCommand, tokensCommand, uiCommand, unlinkCommand, updateCommand, validateCommand, viewCommand };
8795
+ //# sourceMappingURL=chunk-YKBICZNR.js.map
8796
+ //# sourceMappingURL=chunk-YKBICZNR.js.map