workflow-agent-cli 2.4.3 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ analyzeProject,
4
+ detectPackageManager,
3
5
  generateAuditReport,
4
6
  hasUncommittedChanges,
7
+ isMonorepo,
5
8
  runAllChecks,
6
9
  runAllSetups,
7
10
  stageAllChanges
8
- } from "../chunk-WXXFUPYO.js";
11
+ } from "../chunk-6NWQLGHI.js";
9
12
  import {
10
13
  validateBranchName,
11
14
  validateCommitMessage,
@@ -15,7 +18,13 @@ import {
15
18
  hasConfig,
16
19
  loadConfig,
17
20
  validateScopeDefinitions
18
- } from "../chunk-RDVTKGQV.js";
21
+ } from "../chunk-DEAF7P4L.js";
22
+ import {
23
+ SCRIPT_CATEGORIES,
24
+ TOTAL_SCRIPTS,
25
+ WORKFLOW_SCRIPTS,
26
+ generateCopilotInstructions
27
+ } from "../chunk-HKRWHFVI.js";
19
28
 
20
29
  // src/cli/index.ts
21
30
  import { Command } from "commander";
@@ -302,10 +311,10 @@ async function initCommand(options) {
302
311
  try {
303
312
  const presetModule = await import(`@workflow/scopes-${preset}`);
304
313
  scopes = presetModule.scopes || presetModule.default.scopes;
305
- const spinner6 = p.spinner();
306
- spinner6.start(`Loading ${presetModule.default?.name || preset} preset`);
314
+ const spinner8 = p.spinner();
315
+ spinner8.start(`Loading ${presetModule.default?.name || preset} preset`);
307
316
  await new Promise((resolve2) => setTimeout(resolve2, 500));
308
- spinner6.stop(`\u2713 Loaded ${scopes.length} scopes from preset`);
317
+ spinner8.stop(`\u2713 Loaded ${scopes.length} scopes from preset`);
309
318
  } catch (error) {
310
319
  console.log(
311
320
  chalk.yellow(
@@ -352,8 +361,8 @@ async function initCommand(options) {
352
361
  process.exit(0);
353
362
  }
354
363
  if (shouldGenerateGuidelines) {
355
- const spinner6 = p.spinner();
356
- spinner6.start("Generating guidelines...");
364
+ const spinner8 = p.spinner();
365
+ spinner8.start("Generating guidelines...");
357
366
  try {
358
367
  const templatesDir = join(__dirname, "../../templates");
359
368
  await validateTemplateDirectory(templatesDir);
@@ -365,9 +374,17 @@ async function initCommand(options) {
365
374
  guidelinesDir,
366
375
  context
367
376
  );
368
- spinner6.stop(`\u2713 Generated ${renderedFiles.length} guideline documents`);
377
+ spinner8.stop(`\u2713 Generated ${renderedFiles.length} guideline documents`);
378
+ const instructionsSpinner = p.spinner();
379
+ instructionsSpinner.start("Generating AI agent instructions...");
380
+ const result = generateCopilotInstructions(cwd, { silent: true });
381
+ if (result.success) {
382
+ instructionsSpinner.stop(`\u2713 Generated .github/copilot-instructions.md`);
383
+ } else {
384
+ instructionsSpinner.stop("\u26A0\uFE0F Could not generate copilot instructions");
385
+ }
369
386
  } catch (error) {
370
- spinner6.stop("\u26A0\uFE0F Could not generate guidelines");
387
+ spinner8.stop("\u26A0\uFE0F Could not generate guidelines");
371
388
  console.log(
372
389
  chalk.yellow(
373
390
  `
@@ -590,12 +607,6 @@ import * as p3 from "@clack/prompts";
590
607
  import chalk6 from "chalk";
591
608
  import { readFileSync, writeFileSync, existsSync as existsSync2 } from "fs";
592
609
  import { join as join2 } from "path";
593
- var WORKFLOW_SCRIPTS = {
594
- "workflow:init": "workflow-agent init",
595
- "workflow:validate": "workflow-agent validate",
596
- "workflow:suggest": "workflow-agent suggest",
597
- "workflow:doctor": "workflow-agent doctor"
598
- };
599
610
  async function setupCommand() {
600
611
  p3.intro(chalk6.bgBlue(" workflow-agent setup "));
601
612
  const cwd = process.cwd();
@@ -609,53 +620,77 @@ async function setupCommand() {
609
620
  if (!packageJson.scripts) {
610
621
  packageJson.scripts = {};
611
622
  }
612
- const existingScripts = [];
613
- const scriptsToAdd = {};
623
+ const addedScripts = [];
624
+ const updatedScripts = [];
614
625
  for (const [scriptName, scriptCommand] of Object.entries(WORKFLOW_SCRIPTS)) {
615
- if (packageJson.scripts[scriptName]) {
616
- existingScripts.push(scriptName);
617
- } else {
618
- scriptsToAdd[scriptName] = scriptCommand;
626
+ if (!packageJson.scripts[scriptName]) {
627
+ packageJson.scripts[scriptName] = scriptCommand;
628
+ addedScripts.push(scriptName);
629
+ } else if (packageJson.scripts[scriptName] !== scriptCommand) {
630
+ packageJson.scripts[scriptName] = scriptCommand;
631
+ updatedScripts.push(scriptName);
619
632
  }
620
633
  }
621
- if (Object.keys(scriptsToAdd).length === 0) {
622
- p3.outro(chalk6.green("\u2713 All workflow scripts are already configured!"));
634
+ const totalChanges = addedScripts.length + updatedScripts.length;
635
+ if (totalChanges === 0) {
636
+ p3.outro(
637
+ chalk6.green(
638
+ `\u2713 All ${TOTAL_SCRIPTS} workflow scripts are already configured!`
639
+ )
640
+ );
623
641
  return;
624
642
  }
625
- console.log(chalk6.dim("\nScripts to add:"));
626
- for (const [scriptName, scriptCommand] of Object.entries(scriptsToAdd)) {
627
- console.log(chalk6.dim(` ${scriptName}: ${scriptCommand}`));
628
- }
629
- if (existingScripts.length > 0) {
630
- console.log(chalk6.yellow("\nExisting scripts (will be skipped):"));
631
- existingScripts.forEach((name) => {
632
- console.log(chalk6.yellow(` ${name}`));
633
- });
634
- }
635
- const shouldAdd = await p3.confirm({
636
- message: "Add these scripts to package.json?",
637
- initialValue: true
638
- });
639
- if (p3.isCancel(shouldAdd) || !shouldAdd) {
640
- p3.cancel("Setup cancelled");
641
- process.exit(0);
642
- }
643
- for (const [scriptName, scriptCommand] of Object.entries(scriptsToAdd)) {
644
- packageJson.scripts[scriptName] = scriptCommand;
645
- }
646
643
  writeFileSync(
647
644
  packageJsonPath,
648
645
  JSON.stringify(packageJson, null, 2) + "\n",
649
646
  "utf-8"
650
647
  );
648
+ const summaryParts = [];
649
+ if (addedScripts.length > 0) {
650
+ summaryParts.push(`${addedScripts.length} new`);
651
+ }
652
+ if (updatedScripts.length > 0) {
653
+ summaryParts.push(`${updatedScripts.length} updated`);
654
+ }
655
+ console.log(
656
+ chalk6.green(
657
+ `
658
+ \u2713 Workflow scripts configured (${summaryParts.join(", ")}):
659
+ `
660
+ )
661
+ );
662
+ for (const [category, scripts] of Object.entries(SCRIPT_CATEGORIES)) {
663
+ console.log(chalk6.cyan(` ${category}:`));
664
+ for (const script of scripts) {
665
+ const isNew = addedScripts.includes(script);
666
+ const isUpdated = updatedScripts.includes(script);
667
+ const marker = isNew ? chalk6.green(" (new)") : isUpdated ? chalk6.yellow(" (updated)") : "";
668
+ console.log(chalk6.dim(` - ${script}`) + marker);
669
+ }
670
+ }
651
671
  p3.outro(
652
672
  chalk6.green(
653
- `\u2713 Added ${Object.keys(scriptsToAdd).length} workflow scripts to package.json!`
673
+ `\u2713 ${TOTAL_SCRIPTS} workflow scripts available in package.json!`
654
674
  )
655
675
  );
656
676
  console.log(chalk6.dim("\nRun them with:"));
657
677
  console.log(chalk6.dim(" pnpm run workflow:init"));
658
678
  console.log(chalk6.dim(" npm run workflow:init\n"));
679
+ const guidelinesDir = join2(cwd, "guidelines");
680
+ if (existsSync2(guidelinesDir)) {
681
+ const result = generateCopilotInstructions(cwd, { silent: false });
682
+ if (result.success) {
683
+ const status = result.isNew ? "Generated" : "Updated";
684
+ console.log(
685
+ chalk6.green(
686
+ `\u2713 ${status} .github/copilot-instructions.md from ${result.guidelinesCount} guidelines`
687
+ )
688
+ );
689
+ if (result.preservedCustomContent) {
690
+ console.log(chalk6.dim(" (Custom content preserved)"));
691
+ }
692
+ }
693
+ }
659
694
  }
660
695
 
661
696
  // src/cli/commands/scope-create.ts
@@ -668,8 +703,8 @@ async function scopeCreateCommand(options) {
668
703
  console.log(chalk7.bold.cyan("\n\u{1F3A8} Create Custom Scope Package\n"));
669
704
  const cwd = process.cwd();
670
705
  const isNonInteractive = !!(options.name && options.scopes && options.presetName);
671
- const isMonorepo = existsSync3(join3(cwd, "pnpm-workspace.yaml"));
672
- if (isMonorepo) {
706
+ const isMonorepo2 = existsSync3(join3(cwd, "pnpm-workspace.yaml"));
707
+ if (isMonorepo2) {
673
708
  console.log(chalk7.dim("\u2713 Detected monorepo workspace\n"));
674
709
  }
675
710
  const packageNameInput = isNonInteractive ? options.name : await p4.text({
@@ -813,7 +848,7 @@ async function scopeCreateCommand(options) {
813
848
  let outputDir;
814
849
  if (options.outputDir) {
815
850
  outputDir = options.outputDir;
816
- } else if (isMonorepo) {
851
+ } else if (isMonorepo2) {
817
852
  outputDir = join3(cwd, "packages", `scopes-${packageName}`);
818
853
  } else {
819
854
  const customDir = await p4.text({
@@ -837,8 +872,8 @@ async function scopeCreateCommand(options) {
837
872
  process.exit(0);
838
873
  }
839
874
  }
840
- const spinner6 = p4.spinner();
841
- spinner6.start("Creating package structure...");
875
+ const spinner8 = p4.spinner();
876
+ spinner8.start("Creating package structure...");
842
877
  try {
843
878
  await mkdir2(join3(outputDir, "src"), { recursive: true });
844
879
  const packageJson = {
@@ -969,8 +1004,8 @@ describe('${presetName} Scope Preset', () => {
969
1004
  "utf-8"
970
1005
  );
971
1006
  }
972
- spinner6.stop("\u2713 Package structure created");
973
- if (isMonorepo) {
1007
+ spinner8.stop("\u2713 Package structure created");
1008
+ if (isMonorepo2) {
974
1009
  const workspaceFile = join3(cwd, "pnpm-workspace.yaml");
975
1010
  const workspaceContent = await readFile(workspaceFile, "utf-8");
976
1011
  const packagePath = `packages/scopes-${packageName}`;
@@ -1021,7 +1056,7 @@ describe('${presetName} Scope Preset', () => {
1021
1056
  );
1022
1057
  }
1023
1058
  } catch (error) {
1024
- spinner6.stop("\u2717 Failed to create package");
1059
+ spinner8.stop("\u2717 Failed to create package");
1025
1060
  console.error(chalk7.red("\nError:"), error);
1026
1061
  process.exit(1);
1027
1062
  }
@@ -1076,8 +1111,8 @@ async function scopeMigrateCommand(options) {
1076
1111
  p5.cancel("Migration cancelled");
1077
1112
  process.exit(0);
1078
1113
  }
1079
- const isMonorepo = existsSync4(join4(cwd, "pnpm-workspace.yaml"));
1080
- if (isMonorepo) {
1114
+ const isMonorepo2 = existsSync4(join4(cwd, "pnpm-workspace.yaml"));
1115
+ if (isMonorepo2) {
1081
1116
  console.log(chalk8.dim("\n\u2713 Detected monorepo workspace\n"));
1082
1117
  }
1083
1118
  const packageNameInput = options.name || await p5.text({
@@ -1125,7 +1160,7 @@ async function scopeMigrateCommand(options) {
1125
1160
  let outputDir;
1126
1161
  if (options.outputDir) {
1127
1162
  outputDir = options.outputDir;
1128
- } else if (isMonorepo) {
1163
+ } else if (isMonorepo2) {
1129
1164
  outputDir = join4(cwd, "packages", `scopes-${packageName}`);
1130
1165
  } else {
1131
1166
  const customDir = await p5.text({
@@ -1149,8 +1184,8 @@ async function scopeMigrateCommand(options) {
1149
1184
  process.exit(0);
1150
1185
  }
1151
1186
  }
1152
- const spinner6 = p5.spinner();
1153
- spinner6.start("Migrating scopes to package...");
1187
+ const spinner8 = p5.spinner();
1188
+ spinner8.start("Migrating scopes to package...");
1154
1189
  try {
1155
1190
  await mkdir3(join4(outputDir, "src"), { recursive: true });
1156
1191
  const packageJson = {
@@ -1278,8 +1313,8 @@ describe('${presetName} Scope Preset (Migrated)', () => {
1278
1313
  });
1279
1314
  `;
1280
1315
  await writeFile3(join4(outputDir, "src", "index.test.ts"), testFile, "utf-8");
1281
- spinner6.stop("\u2713 Package created from migrated scopes");
1282
- if (isMonorepo) {
1316
+ spinner8.stop("\u2713 Package created from migrated scopes");
1317
+ if (isMonorepo2) {
1283
1318
  const workspaceFile = join4(cwd, "pnpm-workspace.yaml");
1284
1319
  const workspaceContent = await readFile2(workspaceFile, "utf-8");
1285
1320
  const packagePath = `packages/scopes-${packageName}`;
@@ -1350,7 +1385,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
1350
1385
  )
1351
1386
  );
1352
1387
  } catch (error) {
1353
- spinner6.stop("\u2717 Migration failed");
1388
+ spinner8.stop("\u2717 Migration failed");
1354
1389
  console.error(chalk8.red("\nError:"), error);
1355
1390
  process.exit(1);
1356
1391
  }
@@ -1379,7 +1414,9 @@ async function verifyCommand(options) {
1379
1414
  console.log(chalk9.dim(` Max retries: ${maxRetries}`));
1380
1415
  console.log(chalk9.dim(` Commit on success: ${shouldCommit ? "yes" : "no"}`));
1381
1416
  console.log(chalk9.dim(` Dry-run: ${dryRun ? "yes" : "no"}`));
1382
- console.log(chalk9.dim(` Learn from fixes: ${learnFromFixes ? "yes" : "no"}`));
1417
+ console.log(
1418
+ chalk9.dim(` Learn from fixes: ${learnFromFixes ? "yes" : "no"}`)
1419
+ );
1383
1420
  const startTime = Date.now();
1384
1421
  const result = await runAllChecks(cwd, {
1385
1422
  maxRetries,
@@ -1489,7 +1526,9 @@ async function recordSuccessfulFixes(cwd, result) {
1489
1526
  } catch {
1490
1527
  }
1491
1528
  if (result.appliedFixes && result.appliedFixes.length > 0) {
1492
- console.log(chalk9.cyan("\n\u{1F4DA} Recording successful fixes for learning...\n"));
1529
+ console.log(
1530
+ chalk9.cyan("\n\u{1F4DA} Recording successful fixes for learning...\n")
1531
+ );
1493
1532
  for (const fix of result.appliedFixes) {
1494
1533
  const patternName = `Auto-fix: ${fix.displayName}`;
1495
1534
  const patternId = crypto.randomUUID();
@@ -1572,8 +1611,10 @@ async function recordSuccessfulFixes(cwd, result) {
1572
1611
  }
1573
1612
  } catch (error) {
1574
1613
  console.log(
1575
- chalk9.dim(`
1576
- Note: Could not record learning patterns: ${error.message}`)
1614
+ chalk9.dim(
1615
+ `
1616
+ Note: Could not record learning patterns: ${error.message}`
1617
+ )
1577
1618
  );
1578
1619
  }
1579
1620
  }
@@ -1584,14 +1625,14 @@ import chalk10 from "chalk";
1584
1625
  async function autoSetupCommand(options) {
1585
1626
  console.log(chalk10.bold.cyan("\n\u{1F527} Workflow Agent Auto-Setup\n"));
1586
1627
  const cwd = process.cwd();
1587
- const spinner6 = p6.spinner();
1588
- spinner6.start("Analyzing project...");
1628
+ const spinner8 = p6.spinner();
1629
+ spinner8.start("Analyzing project...");
1589
1630
  let report;
1590
1631
  try {
1591
1632
  report = await generateAuditReport(cwd);
1592
- spinner6.stop("\u2713 Project analysis complete");
1633
+ spinner8.stop("\u2713 Project analysis complete");
1593
1634
  } catch (error) {
1594
- spinner6.stop("\u2717 Failed to analyze project");
1635
+ spinner8.stop("\u2717 Failed to analyze project");
1595
1636
  console.error(
1596
1637
  chalk10.red(
1597
1638
  `Error: ${error instanceof Error ? error.message : String(error)}`
@@ -1724,213 +1765,2934 @@ function formatAuditReportColored(report) {
1724
1765
  return lines.join("\n");
1725
1766
  }
1726
1767
 
1727
- // src/cli/commands/learn.ts
1728
- import chalk11 from "chalk";
1768
+ // src/cli/commands/advisory.ts
1729
1769
  import * as p7 from "@clack/prompts";
1730
- import {
1731
- PatternStore as PatternStore2,
1732
- ContributorManager as ContributorManager2,
1733
- PatternAnonymizer,
1734
- TelemetryCollector as TelemetryCollector2
1735
- } from "@hawkinside_out/workflow-improvement-tracker";
1736
- function getWorkspacePath() {
1737
- return process.cwd();
1738
- }
1739
- function formatDate(isoString) {
1740
- return new Date(isoString).toLocaleDateString("en-US", {
1741
- year: "numeric",
1742
- month: "short",
1743
- day: "numeric"
1744
- });
1745
- }
1746
- function formatTags(tags) {
1747
- return tags.map((t) => `${t.category}:${t.name}`).join(", ");
1748
- }
1749
- async function learnRecordCommand(options) {
1750
- const cwd = getWorkspacePath();
1751
- const store = new PatternStore2(cwd);
1752
- console.log(chalk11.cyan("\n\u{1F4DA} Record a Learning Pattern\n"));
1753
- let patternType = options.type;
1754
- if (!patternType) {
1755
- const typeChoice = await p7.select({
1756
- message: "What type of pattern are you recording?",
1757
- options: [
1758
- {
1759
- value: "fix",
1760
- label: "\u{1F527} Fix Pattern - A specific solution to a problem"
1761
- },
1762
- {
1763
- value: "blueprint",
1764
- label: "\u{1F4D0} Blueprint - A project structure template"
1765
- }
1766
- ]
1767
- });
1768
- if (p7.isCancel(typeChoice)) {
1769
- p7.cancel("Recording cancelled");
1770
- process.exit(0);
1771
- }
1772
- patternType = typeChoice;
1770
+ import chalk11 from "chalk";
1771
+ import { existsSync as existsSync6 } from "fs";
1772
+ import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir4 } from "fs/promises";
1773
+ import { join as join6 } from "path";
1774
+
1775
+ // src/utils/advisory-analyzer.ts
1776
+ import { existsSync as existsSync5 } from "fs";
1777
+ import { readFile as readFile3 } from "fs/promises";
1778
+ import { join as join5 } from "path";
1779
+ import fg from "fast-glob";
1780
+ var AdvisoryAnalyzer = class {
1781
+ options;
1782
+ constructor(options) {
1783
+ this.options = options;
1773
1784
  }
1774
- let name = options.name;
1775
- if (!name) {
1776
- const nameInput = await p7.text({
1777
- message: "Pattern name:",
1778
- placeholder: "e.g., Next.js App Router Migration",
1779
- validate: (value) => {
1780
- if (!value || value.length < 3) return "Name must be at least 3 characters";
1781
- if (value.length > 100) return "Name must be less than 100 characters";
1782
- return void 0;
1783
- }
1784
- });
1785
- if (p7.isCancel(nameInput)) {
1786
- p7.cancel("Recording cancelled");
1787
- process.exit(0);
1785
+ /**
1786
+ * Run analysis at specified depth level
1787
+ */
1788
+ async analyze() {
1789
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
1790
+ const { depth } = this.options;
1791
+ const project = await this.analyzeProject();
1792
+ if (depth === "executive") {
1793
+ return this.analyzeExecutive(timestamp, project);
1788
1794
  }
1789
- name = nameInput;
1795
+ const technology = await this.analyzeTechnology();
1796
+ const packages = await this.analyzePackages();
1797
+ const risks = await this.assessRisks(project, technology, packages);
1798
+ const opportunities = await this.assessOpportunities(
1799
+ project,
1800
+ technology,
1801
+ packages
1802
+ );
1803
+ if (depth === "quick") {
1804
+ return {
1805
+ depth,
1806
+ timestamp,
1807
+ project,
1808
+ technology,
1809
+ packages,
1810
+ risks,
1811
+ opportunities
1812
+ };
1813
+ }
1814
+ const architecture = await this.analyzeArchitecture();
1815
+ if (depth === "standard") {
1816
+ const health2 = this.options.includeHealth ? await this.analyzeHealth() : void 0;
1817
+ return {
1818
+ depth,
1819
+ timestamp,
1820
+ project,
1821
+ technology,
1822
+ packages,
1823
+ architecture,
1824
+ risks,
1825
+ opportunities,
1826
+ health: health2
1827
+ };
1828
+ }
1829
+ const codePatterns = await this.analyzeCodePatterns();
1830
+ const health = this.options.includeHealth ? await this.analyzeHealth() : void 0;
1831
+ return {
1832
+ depth,
1833
+ timestamp,
1834
+ project,
1835
+ technology,
1836
+ packages,
1837
+ architecture,
1838
+ codePatterns,
1839
+ risks,
1840
+ opportunities,
1841
+ health
1842
+ };
1790
1843
  }
1791
- let description = options.description;
1792
- if (!description) {
1793
- const descInput = await p7.text({
1794
- message: "Description:",
1795
- placeholder: "What does this pattern solve?",
1796
- validate: (value) => {
1797
- if (!value || value.length < 10) return "Description must be at least 10 characters";
1798
- if (value.length > 500) return "Description must be less than 500 characters";
1799
- return void 0;
1800
- }
1801
- });
1802
- if (p7.isCancel(descInput)) {
1803
- p7.cancel("Recording cancelled");
1804
- process.exit(0);
1844
+ /**
1845
+ * Executive depth: High-level business summary only
1846
+ */
1847
+ async analyzeExecutive(timestamp, project) {
1848
+ const packageJson = await this.readPackageJson();
1849
+ const deps = packageJson.dependencies || {};
1850
+ const devDeps = packageJson.devDependencies || {};
1851
+ const techCategories = this.categorizeTechnologies(deps, devDeps);
1852
+ const risks = this.calculateExecutiveRisks(project, techCategories);
1853
+ const opportunities = this.calculateExecutiveOpportunities(
1854
+ project,
1855
+ techCategories
1856
+ );
1857
+ return {
1858
+ depth: "executive",
1859
+ timestamp,
1860
+ project,
1861
+ technology: {
1862
+ language: this.detectLanguage(deps, devDeps),
1863
+ runtime: this.detectRuntime(deps, devDeps),
1864
+ buildTools: this.detectBuildTools(devDeps),
1865
+ platforms: this.detectPlatforms(deps),
1866
+ infrastructure: this.detectInfrastructure(deps, devDeps)
1867
+ },
1868
+ packages: {
1869
+ total: Object.keys(deps).length + Object.keys(devDeps).length,
1870
+ production: [],
1871
+ development: [],
1872
+ categories: techCategories,
1873
+ outdated: [],
1874
+ security: []
1875
+ },
1876
+ risks,
1877
+ opportunities
1878
+ };
1879
+ }
1880
+ /**
1881
+ * Analyze project overview
1882
+ */
1883
+ async analyzeProject() {
1884
+ const packageJson = await this.readPackageJson();
1885
+ const isMonorepoProject = await isMonorepo(this.options.cwd);
1886
+ const fileCount = await this.countFiles();
1887
+ const totalLines = await this.countTotalLines();
1888
+ let workspaceCount;
1889
+ if (isMonorepoProject && packageJson.workspaces) {
1890
+ workspaceCount = Array.isArray(packageJson.workspaces) ? packageJson.workspaces.length : 0;
1805
1891
  }
1806
- description = descInput;
1892
+ return {
1893
+ name: packageJson.name || "Unknown Project",
1894
+ version: packageJson.version || "0.0.0",
1895
+ description: packageJson.description,
1896
+ isMonorepo: isMonorepoProject,
1897
+ packageManager: await detectPackageManager(this.options.cwd),
1898
+ workspaceCount,
1899
+ fileCount,
1900
+ totalLines
1901
+ };
1807
1902
  }
1808
- let framework = options.framework;
1809
- if (!framework) {
1810
- const fwInput = await p7.text({
1811
- message: "Framework:",
1812
- placeholder: "e.g., next, react, vue, express"
1903
+ /**
1904
+ * Analyze technology stack
1905
+ */
1906
+ async analyzeTechnology() {
1907
+ const packageJson = await this.readPackageJson();
1908
+ const deps = packageJson.dependencies || {};
1909
+ const devDeps = packageJson.devDependencies || {};
1910
+ const projectAnalysis = await analyzeProject(this.options.cwd);
1911
+ return {
1912
+ framework: projectAnalysis.framework,
1913
+ frameworkVersion: deps[projectAnalysis.framework || ""] || devDeps[projectAnalysis.framework || ""],
1914
+ language: this.detectLanguage(deps, devDeps),
1915
+ runtime: this.detectRuntime(deps, devDeps),
1916
+ buildTools: this.detectBuildTools(devDeps),
1917
+ platforms: this.detectPlatforms(deps),
1918
+ infrastructure: this.detectInfrastructure(deps, devDeps)
1919
+ };
1920
+ }
1921
+ /**
1922
+ * Analyze packages in detail
1923
+ */
1924
+ async analyzePackages() {
1925
+ const packageJson = await this.readPackageJson();
1926
+ const deps = packageJson.dependencies || {};
1927
+ const devDeps = packageJson.devDependencies || {};
1928
+ const production = this.analyzeDependencies(deps, "production");
1929
+ const development = this.analyzeDependencies(devDeps, "development");
1930
+ const categories = this.categorizeTechnologies(deps, devDeps);
1931
+ return {
1932
+ total: Object.keys(deps).length + Object.keys(devDeps).length,
1933
+ production,
1934
+ development,
1935
+ categories,
1936
+ outdated: [],
1937
+ // TODO: Implement outdated check
1938
+ security: []
1939
+ // TODO: Implement security audit
1940
+ };
1941
+ }
1942
+ /**
1943
+ * Analyze dependencies and categorize them
1944
+ */
1945
+ analyzeDependencies(deps, _type) {
1946
+ return Object.entries(deps).map(([name, version]) => {
1947
+ const category = this.categorizeDependency(name);
1948
+ const info = this.getDependencyInfo(name, category);
1949
+ return {
1950
+ name,
1951
+ version,
1952
+ category,
1953
+ ...info
1954
+ };
1813
1955
  });
1814
- if (p7.isCancel(fwInput)) {
1815
- p7.cancel("Recording cancelled");
1816
- process.exit(0);
1956
+ }
1957
+ /**
1958
+ * Categorize a dependency
1959
+ */
1960
+ categorizeDependency(name) {
1961
+ if (["react", "vue", "angular", "svelte", "solid-js"].some(
1962
+ (fw) => name.includes(fw)
1963
+ )) {
1964
+ return "UI Framework";
1817
1965
  }
1818
- framework = fwInput;
1966
+ if (["next", "nuxt", "remix", "sveltekit", "astro"].some(
1967
+ (fw) => name.includes(fw)
1968
+ )) {
1969
+ return "Meta-Framework";
1970
+ }
1971
+ if (["redux", "zustand", "jotai", "recoil", "mobx", "pinia"].includes(name)) {
1972
+ return "State Management";
1973
+ }
1974
+ if ([
1975
+ "axios",
1976
+ "fetch",
1977
+ "swr",
1978
+ "react-query",
1979
+ "@tanstack/react-query",
1980
+ "apollo",
1981
+ "urql"
1982
+ ].some((lib) => name.includes(lib))) {
1983
+ return "API/Data Fetching";
1984
+ }
1985
+ if (["react-router", "vue-router", "@tanstack/router"].some(
1986
+ (r) => name.includes(r)
1987
+ )) {
1988
+ return "Routing";
1989
+ }
1990
+ if (["formik", "react-hook-form", "final-form"].some((f) => name.includes(f))) {
1991
+ return "Forms";
1992
+ }
1993
+ if ([
1994
+ "styled-components",
1995
+ "emotion",
1996
+ "tailwind",
1997
+ "sass",
1998
+ "less",
1999
+ "@mui",
2000
+ "antd",
2001
+ "chakra-ui"
2002
+ ].some((s) => name.includes(s))) {
2003
+ return "Styling/UI Components";
2004
+ }
2005
+ if ([
2006
+ "vitest",
2007
+ "jest",
2008
+ "mocha",
2009
+ "chai",
2010
+ "testing-library",
2011
+ "playwright",
2012
+ "cypress"
2013
+ ].some((t) => name.includes(t))) {
2014
+ return "Testing";
2015
+ }
2016
+ if (["vite", "webpack", "rollup", "esbuild", "turbo", "tsup"].includes(name)) {
2017
+ return "Build Tools";
2018
+ }
2019
+ if (["eslint", "prettier", "stylelint"].some((l) => name.includes(l))) {
2020
+ return "Code Quality";
2021
+ }
2022
+ if (["prisma", "drizzle", "mongoose", "sequelize", "typeorm", "knex"].some(
2023
+ (db) => name.includes(db)
2024
+ )) {
2025
+ return "Database ORM";
2026
+ }
2027
+ if (["next-auth", "auth0", "supabase", "clerk"].some((a) => name.includes(a))) {
2028
+ return "Authentication";
2029
+ }
2030
+ if (["vercel", "netlify", "aws-sdk", "@google-cloud"].some(
2031
+ (d) => name.includes(d)
2032
+ )) {
2033
+ return "Infrastructure";
2034
+ }
2035
+ if (["@analytics", "posthog", "mixpanel", "segment"].some(
2036
+ (a) => name.includes(a)
2037
+ )) {
2038
+ return "Analytics";
2039
+ }
2040
+ return "Other";
1819
2041
  }
1820
- let version = options.version;
1821
- if (!version) {
1822
- const versionInput = await p7.text({
1823
- message: "Framework version (semver range):",
1824
- placeholder: "e.g., >=14.0.0, ^18.0.0",
1825
- initialValue: ">=1.0.0"
2042
+ /**
2043
+ * Get detailed info about a dependency
2044
+ */
2045
+ getDependencyInfo(name, category) {
2046
+ const defaultInfo = {
2047
+ purpose: `${category} library`,
2048
+ businessValue: "Supports application functionality",
2049
+ usagePatterns: ["Used throughout the application"]
2050
+ };
2051
+ const knownPackages = {
2052
+ react: {
2053
+ purpose: "Core UI library for building component-based interfaces",
2054
+ businessValue: "Enables fast, interactive user experiences with reusable components",
2055
+ usagePatterns: [
2056
+ "Component rendering",
2057
+ "State management",
2058
+ "Event handling"
2059
+ ],
2060
+ alternatives: ["Vue", "Svelte", "Solid"]
2061
+ },
2062
+ next: {
2063
+ purpose: "React meta-framework with SSR, routing, and optimization",
2064
+ businessValue: "Improves SEO, performance, and developer productivity",
2065
+ usagePatterns: [
2066
+ "Server-side rendering",
2067
+ "API routes",
2068
+ "File-based routing"
2069
+ ],
2070
+ alternatives: ["Remix", "Gatsby"]
2071
+ },
2072
+ typescript: {
2073
+ purpose: "Static type checking for JavaScript",
2074
+ businessValue: "Reduces bugs, improves code quality, and enhances developer experience",
2075
+ usagePatterns: ["Type definitions", "Compile-time checks"]
2076
+ }
2077
+ // Add more as needed
2078
+ };
2079
+ return knownPackages[name] || defaultInfo;
2080
+ }
2081
+ /**
2082
+ * Categorize technologies at high level
2083
+ */
2084
+ categorizeTechnologies(deps, devDeps) {
2085
+ const allDeps = { ...deps, ...devDeps };
2086
+ const categories = /* @__PURE__ */ new Map();
2087
+ Object.keys(allDeps).forEach((name) => {
2088
+ const category = this.categorizeDependency(name);
2089
+ if (!categories.has(category)) {
2090
+ categories.set(category, []);
2091
+ }
2092
+ categories.get(category).push(name);
1826
2093
  });
1827
- if (p7.isCancel(versionInput)) {
1828
- p7.cancel("Recording cancelled");
1829
- process.exit(0);
2094
+ return Array.from(categories.entries()).map(([name, packages]) => ({
2095
+ name,
2096
+ count: packages.length,
2097
+ packages,
2098
+ businessImpact: this.getCategoryBusinessImpact(name)
2099
+ }));
2100
+ }
2101
+ /**
2102
+ * Get business impact description for a category
2103
+ */
2104
+ getCategoryBusinessImpact(category) {
2105
+ const impacts = {
2106
+ "UI Framework": "Core user experience - directly impacts customer satisfaction and engagement",
2107
+ "Meta-Framework": "Application performance and SEO - affects discoverability and user retention",
2108
+ "State Management": "Data consistency - ensures reliable application behavior",
2109
+ "API/Data Fetching": "Backend integration - enables core business functionality",
2110
+ Routing: "Navigation - affects user flow and conversion rates",
2111
+ Forms: "Data collection - critical for user onboarding and conversions",
2112
+ "Styling/UI Components": "Visual design - impacts brand perception and usability",
2113
+ Testing: "Quality assurance - reduces production bugs and support costs",
2114
+ "Build Tools": "Development efficiency - affects time-to-market for new features",
2115
+ "Code Quality": "Maintainability - reduces technical debt and long-term costs",
2116
+ "Database ORM": "Data persistence - ensures business data integrity",
2117
+ Authentication: "Security and user management - protects business and customer data",
2118
+ Infrastructure: "Hosting and scalability - affects uptime and operational costs",
2119
+ Analytics: "Business intelligence - enables data-driven decision making"
2120
+ };
2121
+ return impacts[category] || "Supports various application features";
2122
+ }
2123
+ /**
2124
+ * Analyze architecture patterns
2125
+ */
2126
+ async analyzeArchitecture() {
2127
+ const files = await this.getProjectFiles();
2128
+ const entryPoints = this.detectEntryPoints(files);
2129
+ const pattern = this.detectArchitecturePattern(files);
2130
+ const layers = this.detectLayers(files);
2131
+ return {
2132
+ pattern,
2133
+ layers,
2134
+ entryPoints,
2135
+ dataFlow: this.analyzeDataFlow(files),
2136
+ keyDecisions: this.extractKeyDecisions(files)
2137
+ };
2138
+ }
2139
+ /**
2140
+ * Analyze code patterns in detail
2141
+ */
2142
+ async analyzeCodePatterns() {
2143
+ const files = await this.getProjectFiles();
2144
+ return {
2145
+ components: await this.analyzeComponents(files),
2146
+ services: await this.analyzeServices(files),
2147
+ utilities: await this.analyzeUtilities(files),
2148
+ tests: await this.analyzeTests(files),
2149
+ customPatterns: await this.detectCustomPatterns(files)
2150
+ };
2151
+ }
2152
+ /**
2153
+ * Assess risks
2154
+ */
2155
+ async assessRisks(project, technology, packages) {
2156
+ const categories = [];
2157
+ const critical = [];
2158
+ const high = [];
2159
+ const medium = [];
2160
+ const low = [];
2161
+ const depRisk = this.assessDependencyRisk(packages);
2162
+ categories.push(depRisk);
2163
+ this.categorizeRiskItems(depRisk, critical, high, medium, low);
2164
+ const techRisk = this.assessTechnologyRisk(technology);
2165
+ categories.push(techRisk);
2166
+ this.categorizeRiskItems(techRisk, critical, high, medium, low);
2167
+ const complexityRisk = this.assessComplexityRisk(project);
2168
+ categories.push(complexityRisk);
2169
+ this.categorizeRiskItems(complexityRisk, critical, high, medium, low);
2170
+ const overall = categories.reduce((sum, cat) => sum + cat.score, 0) / categories.length;
2171
+ return { overall, categories, critical, high, medium, low };
2172
+ }
2173
+ /**
2174
+ * Assess opportunities
2175
+ */
2176
+ async assessOpportunities(project, technology, packages) {
2177
+ const categories = [];
2178
+ const immediate = [];
2179
+ const shortTerm = [];
2180
+ const longTerm = [];
2181
+ const modernization = this.assessModernizationOpportunities(
2182
+ technology,
2183
+ packages
2184
+ );
2185
+ categories.push(modernization);
2186
+ this.categorizeOpportunityItems(
2187
+ modernization,
2188
+ immediate,
2189
+ shortTerm,
2190
+ longTerm
2191
+ );
2192
+ const optimization = this.assessOptimizationOpportunities(project);
2193
+ categories.push(optimization);
2194
+ this.categorizeOpportunityItems(
2195
+ optimization,
2196
+ immediate,
2197
+ shortTerm,
2198
+ longTerm
2199
+ );
2200
+ const growth = this.assessGrowthOpportunities(technology, packages);
2201
+ categories.push(growth);
2202
+ this.categorizeOpportunityItems(growth, immediate, shortTerm, longTerm);
2203
+ const overall = categories.reduce((sum, cat) => sum + cat.potential, 0) / categories.length;
2204
+ return { overall, categories, immediate, shortTerm, longTerm };
2205
+ }
2206
+ /**
2207
+ * Analyze health metrics
2208
+ */
2209
+ async analyzeHealth() {
2210
+ return {
2211
+ typecheck: false,
2212
+ lint: false,
2213
+ tests: false,
2214
+ build: false,
2215
+ issues: 0
2216
+ };
2217
+ }
2218
+ // ============================================================================
2219
+ // Helper Methods
2220
+ // ============================================================================
2221
+ async readPackageJson() {
2222
+ const pkgPath = join5(this.options.cwd, "package.json");
2223
+ if (!existsSync5(pkgPath)) {
2224
+ throw new Error("package.json not found");
1830
2225
  }
1831
- version = versionInput;
2226
+ const content = await readFile3(pkgPath, "utf-8");
2227
+ return JSON.parse(content);
1832
2228
  }
1833
- let category = options.category;
1834
- if (patternType === "fix" && !category) {
1835
- const catChoice = await p7.select({
1836
- message: "Category:",
1837
- options: [
1838
- { value: "migration", label: "\u{1F504} Migration" },
1839
- { value: "security", label: "\u{1F512} Security" },
1840
- { value: "performance", label: "\u26A1 Performance" },
1841
- { value: "compatibility", label: "\u{1F517} Compatibility" },
1842
- { value: "deprecation", label: "\u26A0\uFE0F Deprecation" },
1843
- { value: "configuration", label: "\u2699\uFE0F Configuration" },
1844
- { value: "best-practice", label: "\u2728 Best Practice" },
1845
- { value: "error-handling", label: "\u{1F6A8} Error Handling" },
1846
- { value: "testing", label: "\u{1F9EA} Testing" },
1847
- { value: "other", label: "\u{1F4E6} Other" }
2229
+ async countFiles() {
2230
+ const patterns = ["**/*.{ts,tsx,js,jsx,py,go,rs,java}"];
2231
+ const files = await fg(patterns, {
2232
+ cwd: this.options.cwd,
2233
+ ignore: [
2234
+ "node_modules/**",
2235
+ "dist/**",
2236
+ "build/**",
2237
+ ".next/**",
2238
+ "coverage/**"
1848
2239
  ]
1849
2240
  });
1850
- if (p7.isCancel(catChoice)) {
1851
- p7.cancel("Recording cancelled");
1852
- process.exit(0);
2241
+ return files.length;
2242
+ }
2243
+ async countTotalLines() {
2244
+ const fileCount = await this.countFiles();
2245
+ return fileCount * 50;
2246
+ }
2247
+ detectLanguage(deps, devDeps) {
2248
+ if (devDeps.typescript || deps.typescript) return "TypeScript";
2249
+ if (Object.keys(deps).some((d) => d.includes("react") || d.includes("vue"))) {
2250
+ return "JavaScript";
1853
2251
  }
1854
- category = catChoice;
2252
+ return "JavaScript";
1855
2253
  }
1856
- const tags = [];
1857
- if (options.tags) {
1858
- const tagPairs = options.tags.split(",").map((t) => t.trim());
1859
- for (const pair of tagPairs) {
1860
- const [cat, val] = pair.split(":");
1861
- if (cat && val) {
1862
- tags.push({
1863
- category: cat,
1864
- name: val
1865
- });
1866
- }
2254
+ detectRuntime(deps, devDeps) {
2255
+ if (deps.next || devDeps.next) return "Node.js (Next.js)";
2256
+ if (Object.keys(deps).some((d) => d.includes("react"))) {
2257
+ return "Browser + Node.js";
1867
2258
  }
2259
+ return "Node.js";
1868
2260
  }
1869
- tags.push({ category: "framework", name: framework });
1870
- if (patternType === "fix") {
1871
- const now = (/* @__PURE__ */ new Date()).toISOString();
1872
- const fixPattern = {
1873
- id: crypto.randomUUID(),
1874
- name,
1875
- description,
1876
- category,
1877
- tags,
1878
- trigger: {
1879
- errorPattern: ".*",
1880
- errorMessage: "Generic error pattern",
1881
- filePattern: "**/*"
1882
- },
1883
- solution: {
1884
- type: "command",
1885
- steps: [
1886
- {
1887
- order: 1,
1888
- action: "run",
1889
- target: "npm run fix",
1890
- description: "Follow the pattern instructions"
1891
- }
1892
- ]
1893
- },
1894
- compatibility: {
1895
- framework,
1896
- frameworkVersion: version,
1897
- runtime: "node",
1898
- runtimeVersion: ">=18.0.0",
1899
- dependencies: []
1900
- },
1901
- metrics: {
1902
- applications: 0,
1903
- successes: 0,
1904
- failures: 0,
1905
- successRate: 0
1906
- },
1907
- source: "manual",
1908
- isPrivate: true,
1909
- createdAt: now,
1910
- updatedAt: now
1911
- };
1912
- const result = await store.saveFixPattern(fixPattern);
1913
- if (result.success) {
1914
- console.log(chalk11.green("\n\u2705 Fix pattern recorded successfully!\n"));
1915
- console.log(chalk11.dim(` ID: ${fixPattern.id}`));
1916
- console.log(chalk11.dim(` Name: ${name}`));
1917
- console.log(chalk11.dim(` Category: ${category}`));
1918
- console.log(chalk11.dim(` Framework: ${framework} ${version}`));
1919
- } else {
1920
- console.log(chalk11.red("\n\u274C Failed to record pattern"));
1921
- console.log(chalk11.dim(` Error: ${result.error}`));
1922
- process.exit(1);
2261
+ detectBuildTools(devDeps) {
2262
+ const tools = [];
2263
+ if (devDeps.vite) tools.push("Vite");
2264
+ if (devDeps.webpack) tools.push("Webpack");
2265
+ if (devDeps.rollup) tools.push("Rollup");
2266
+ if (devDeps.esbuild) tools.push("esbuild");
2267
+ if (devDeps.turbo || devDeps.turborepo) tools.push("Turborepo");
2268
+ if (devDeps.tsup) tools.push("tsup");
2269
+ return tools;
2270
+ }
2271
+ detectPlatforms(deps) {
2272
+ const platforms = [];
2273
+ if (deps.react || deps.next) platforms.push("Web");
2274
+ if (deps["react-native"]) platforms.push("Mobile (React Native)");
2275
+ if (deps.electron) platforms.push("Desktop (Electron)");
2276
+ return platforms.length > 0 ? platforms : ["Web"];
2277
+ }
2278
+ detectInfrastructure(deps, devDeps) {
2279
+ const infra = [];
2280
+ const allDeps = { ...deps, ...devDeps };
2281
+ if (allDeps.vercel || allDeps["@vercel/node"]) infra.push("Vercel");
2282
+ if (Object.keys(allDeps).some((d) => d.includes("aws-"))) {
2283
+ infra.push("AWS");
1923
2284
  }
1924
- } else {
1925
- const now = (/* @__PURE__ */ new Date()).toISOString();
1926
- const blueprint = {
1927
- id: crypto.randomUUID(),
1928
- name,
1929
- description,
1930
- tags,
1931
- stack: {
1932
- framework,
1933
- language: "typescript",
2285
+ if (Object.keys(allDeps).some((d) => d.includes("@google-cloud"))) {
2286
+ infra.push("Google Cloud");
2287
+ }
2288
+ if (allDeps.netlify) infra.push("Netlify");
2289
+ if (allDeps.supabase || allDeps["@supabase/supabase-js"]) {
2290
+ infra.push("Supabase");
2291
+ }
2292
+ if (allDeps.firebase || allDeps["firebase-admin"]) infra.push("Firebase");
2293
+ return infra;
2294
+ }
2295
+ calculateExecutiveRisks(project, categories) {
2296
+ const risks = [];
2297
+ let overallScore = 0;
2298
+ if (project.fileCount > 1e3) {
2299
+ risks.push(
2300
+ "Large codebase may require significant maintenance resources"
2301
+ );
2302
+ overallScore += 0.3;
2303
+ }
2304
+ if (categories.length > 15) {
2305
+ risks.push(
2306
+ "High number of technology categories indicates potential complexity"
2307
+ );
2308
+ overallScore += 0.2;
2309
+ }
2310
+ const totalPackages = categories.reduce((sum, cat) => sum + cat.count, 0);
2311
+ if (totalPackages > 100) {
2312
+ risks.push(
2313
+ "Large dependency footprint increases security and maintenance burden"
2314
+ );
2315
+ overallScore += 0.3;
2316
+ }
2317
+ overallScore = Math.min(overallScore, 1);
2318
+ return {
2319
+ overall: overallScore,
2320
+ categories: [
2321
+ {
2322
+ name: "Technical Complexity",
2323
+ score: overallScore,
2324
+ issues: risks,
2325
+ impact: "May affect development velocity and operational costs"
2326
+ }
2327
+ ],
2328
+ critical: [],
2329
+ high: overallScore > 0.7 ? risks : [],
2330
+ medium: overallScore > 0.4 && overallScore <= 0.7 ? risks : [],
2331
+ low: overallScore <= 0.4 ? risks : []
2332
+ };
2333
+ }
2334
+ calculateExecutiveOpportunities(_project, categories) {
2335
+ const opportunities = [];
2336
+ let overallScore = 0.5;
2337
+ const hasModernFramework = categories.some(
2338
+ (cat) => cat.name.includes("Meta-Framework")
2339
+ );
2340
+ if (hasModernFramework) {
2341
+ opportunities.push(
2342
+ "Modern framework provides foundation for rapid feature development"
2343
+ );
2344
+ overallScore += 0.2;
2345
+ }
2346
+ const hasTestingTools = categories.some((cat) => cat.name === "Testing");
2347
+ if (hasTestingTools) {
2348
+ opportunities.push(
2349
+ "Testing infrastructure enables quality-driven expansion"
2350
+ );
2351
+ overallScore += 0.1;
2352
+ }
2353
+ return {
2354
+ overall: Math.min(overallScore, 1),
2355
+ categories: [
2356
+ {
2357
+ name: "Growth Potential",
2358
+ potential: overallScore,
2359
+ recommendations: opportunities,
2360
+ businessValue: "Strong foundation for scaling features and market reach"
2361
+ }
2362
+ ],
2363
+ immediate: [],
2364
+ shortTerm: opportunities,
2365
+ longTerm: []
2366
+ };
2367
+ }
2368
+ assessDependencyRisk(packages) {
2369
+ let score = 0;
2370
+ const issues = [];
2371
+ if (packages.total > 100) {
2372
+ score += 0.3;
2373
+ issues.push(`High dependency count (${packages.total} packages)`);
2374
+ }
2375
+ if (packages.outdated.length > 10) {
2376
+ score += 0.3;
2377
+ issues.push(`${packages.outdated.length} outdated packages`);
2378
+ }
2379
+ if (packages.security.length > 0) {
2380
+ score += 0.4;
2381
+ issues.push(`${packages.security.length} security vulnerabilities`);
2382
+ }
2383
+ return {
2384
+ name: "Dependency Management",
2385
+ score: Math.min(score, 1),
2386
+ issues,
2387
+ impact: "Affects security, stability, and maintenance costs"
2388
+ };
2389
+ }
2390
+ assessTechnologyRisk(technology) {
2391
+ let score = 0;
2392
+ const issues = [];
2393
+ const legacyFrameworks = ["angular.js", "backbone", "ember"];
2394
+ if (technology.framework && legacyFrameworks.some((f) => technology.framework?.includes(f))) {
2395
+ score += 0.5;
2396
+ issues.push("Legacy framework may limit future development");
2397
+ }
2398
+ return {
2399
+ name: "Technology Stack",
2400
+ score,
2401
+ issues,
2402
+ impact: "May affect ability to attract talent and adopt new features"
2403
+ };
2404
+ }
2405
+ assessComplexityRisk(project) {
2406
+ let score = 0;
2407
+ const issues = [];
2408
+ if (project.fileCount > 1e3) {
2409
+ score += 0.2;
2410
+ issues.push("Large codebase requires careful management");
2411
+ }
2412
+ if (project.isMonorepo && (project.workspaceCount || 0) > 10) {
2413
+ score += 0.2;
2414
+ issues.push("Complex monorepo structure");
2415
+ }
2416
+ return {
2417
+ name: "Project Complexity",
2418
+ score,
2419
+ issues,
2420
+ impact: "Affects onboarding time and development velocity"
2421
+ };
2422
+ }
2423
+ assessModernizationOpportunities(_technology, packages) {
2424
+ const recommendations = [];
2425
+ let potential = 0.5;
2426
+ if (packages.outdated.length > 0) {
2427
+ recommendations.push(
2428
+ "Upgrade dependencies to access new features and improvements"
2429
+ );
2430
+ potential += 0.2;
2431
+ }
2432
+ return {
2433
+ name: "Modernization",
2434
+ potential: Math.min(potential, 1),
2435
+ recommendations,
2436
+ businessValue: "Improved performance, security, and developer experience"
2437
+ };
2438
+ }
2439
+ assessOptimizationOpportunities(project) {
2440
+ const recommendations = [];
2441
+ if (project.fileCount > 500) {
2442
+ recommendations.push(
2443
+ "Consider code splitting and lazy loading strategies"
2444
+ );
2445
+ }
2446
+ return {
2447
+ name: "Performance Optimization",
2448
+ potential: 0.6,
2449
+ recommendations,
2450
+ businessValue: "Faster load times and better user experience"
2451
+ };
2452
+ }
2453
+ assessGrowthOpportunities(_technology, packages) {
2454
+ const recommendations = [];
2455
+ let potential = 0.5;
2456
+ const hasAnalytics = packages.categories.some(
2457
+ (cat) => cat.name.includes("Analytics")
2458
+ );
2459
+ if (!hasAnalytics) {
2460
+ recommendations.push("Add analytics to enable data-driven decisions");
2461
+ potential += 0.2;
2462
+ }
2463
+ return {
2464
+ name: "Growth & Expansion",
2465
+ potential: Math.min(potential, 1),
2466
+ recommendations,
2467
+ businessValue: "Data-driven growth and improved user insights"
2468
+ };
2469
+ }
2470
+ categorizeRiskItems(risk, critical, high, medium, low) {
2471
+ if (risk.score > 0.7) {
2472
+ critical.push(...risk.issues);
2473
+ } else if (risk.score > 0.5) {
2474
+ high.push(...risk.issues);
2475
+ } else if (risk.score > 0.3) {
2476
+ medium.push(...risk.issues);
2477
+ } else {
2478
+ low.push(...risk.issues);
2479
+ }
2480
+ }
2481
+ categorizeOpportunityItems(opportunity, immediate, shortTerm, longTerm) {
2482
+ if (opportunity.potential > 0.7) {
2483
+ immediate.push(...opportunity.recommendations);
2484
+ } else if (opportunity.potential > 0.5) {
2485
+ shortTerm.push(...opportunity.recommendations);
2486
+ } else {
2487
+ longTerm.push(...opportunity.recommendations);
2488
+ }
2489
+ }
2490
+ async getProjectFiles() {
2491
+ const patterns = ["**/*.{ts,tsx,js,jsx}"];
2492
+ return await fg(patterns, {
2493
+ cwd: this.options.cwd,
2494
+ ignore: this.options.excludePatterns || [
2495
+ "node_modules/**",
2496
+ "dist/**",
2497
+ "build/**",
2498
+ ".next/**",
2499
+ "coverage/**"
2500
+ ]
2501
+ });
2502
+ }
2503
+ detectEntryPoints(files) {
2504
+ const entryPoints = files.filter(
2505
+ (f) => f.includes("index.") || f.includes("main.") || f.includes("app.") || f.includes("_app.") || f.includes("layout.")
2506
+ );
2507
+ return entryPoints.slice(0, 5);
2508
+ }
2509
+ detectArchitecturePattern(files) {
2510
+ const hasComponents = files.some((f) => f.includes("components/"));
2511
+ const hasPages = files.some(
2512
+ (f) => f.includes("pages/") || f.includes("app/")
2513
+ );
2514
+ const hasServices = files.some((f) => f.includes("services/"));
2515
+ if (hasComponents && hasPages && hasServices) {
2516
+ return "Layered Architecture (Pages \u2192 Components \u2192 Services)";
2517
+ }
2518
+ if (hasComponents && hasPages) {
2519
+ return "Component-Based Architecture";
2520
+ }
2521
+ return "Standard Application Structure";
2522
+ }
2523
+ detectLayers(files) {
2524
+ const layers = [];
2525
+ if (files.some((f) => f.includes("pages/") || f.includes("app/"))) {
2526
+ layers.push("Presentation (Pages/Routes)");
2527
+ }
2528
+ if (files.some((f) => f.includes("components/"))) {
2529
+ layers.push("UI Components");
2530
+ }
2531
+ if (files.some((f) => f.includes("services/") || f.includes("api/"))) {
2532
+ layers.push("Business Logic/Services");
2533
+ }
2534
+ if (files.some((f) => f.includes("lib/") || f.includes("utils/"))) {
2535
+ layers.push("Utilities/Helpers");
2536
+ }
2537
+ if (files.some((f) => f.includes("models/") || f.includes("types/"))) {
2538
+ layers.push("Data Models");
2539
+ }
2540
+ return layers;
2541
+ }
2542
+ analyzeDataFlow(files) {
2543
+ const hasStateManagement = files.some(
2544
+ (f) => f.includes("store") || f.includes("context")
2545
+ );
2546
+ const hasApi = files.some(
2547
+ (f) => f.includes("api") || f.includes("services")
2548
+ );
2549
+ if (hasStateManagement && hasApi) {
2550
+ return "API \u2192 Services \u2192 State Management \u2192 Components";
2551
+ }
2552
+ if (hasApi) {
2553
+ return "API \u2192 Components (Direct)";
2554
+ }
2555
+ return "Props-based Component Communication";
2556
+ }
2557
+ extractKeyDecisions(files) {
2558
+ const decisions = [];
2559
+ if (files.some((f) => f.includes(".ts") || f.includes(".tsx"))) {
2560
+ decisions.push("TypeScript for type safety");
2561
+ }
2562
+ if (files.some((f) => f.includes("app/") && !f.includes("pages/"))) {
2563
+ decisions.push("App Router architecture (Next.js)");
2564
+ }
2565
+ if (files.some((f) => f.includes("server") || f.includes("api"))) {
2566
+ decisions.push("API routes for backend functionality");
2567
+ }
2568
+ return decisions;
2569
+ }
2570
+ async analyzeComponents(files) {
2571
+ const components = files.filter((f) => f.includes("components/"));
2572
+ const patterns = [];
2573
+ const ui = components.filter(
2574
+ (f) => f.includes("/ui/") || f.includes("/common/")
2575
+ );
2576
+ const feature = components.filter(
2577
+ (f) => ["features/", "modules/"].some((dir) => f.includes(dir))
2578
+ );
2579
+ if (ui.length > 0) {
2580
+ patterns.push({
2581
+ type: "UI Components",
2582
+ count: ui.length,
2583
+ examples: ui.slice(0, 3),
2584
+ conventions: ["Reusable", "Presentation-focused"]
2585
+ });
2586
+ }
2587
+ if (feature.length > 0) {
2588
+ patterns.push({
2589
+ type: "Feature Components",
2590
+ count: feature.length,
2591
+ examples: feature.slice(0, 3),
2592
+ conventions: ["Business logic", "Domain-specific"]
2593
+ });
2594
+ }
2595
+ return patterns;
2596
+ }
2597
+ async analyzeServices(files) {
2598
+ const services = files.filter(
2599
+ (f) => f.includes("services/") || f.includes("api/")
2600
+ );
2601
+ return services.slice(0, 5).map((file) => ({
2602
+ name: file,
2603
+ purpose: "API integration or business logic",
2604
+ integrations: []
2605
+ }));
2606
+ }
2607
+ async analyzeUtilities(files) {
2608
+ const utils = files.filter(
2609
+ (f) => f.includes("utils/") || f.includes("lib/")
2610
+ );
2611
+ return [
2612
+ {
2613
+ category: "Utilities",
2614
+ count: utils.length,
2615
+ usage: "Helper functions and shared utilities"
2616
+ }
2617
+ ];
2618
+ }
2619
+ async analyzeTests(files) {
2620
+ const tests = files.filter(
2621
+ (f) => f.includes(".test.") || f.includes(".spec.")
2622
+ );
2623
+ const hasVitest = tests.some((f) => f.includes("vitest"));
2624
+ const hasJest = tests.some((f) => f.includes("jest"));
2625
+ return {
2626
+ framework: hasVitest ? "Vitest" : hasJest ? "Jest" : "Unknown",
2627
+ count: tests.length,
2628
+ types: ["Unit tests"]
2629
+ };
2630
+ }
2631
+ async detectCustomPatterns(files) {
2632
+ const patterns = [];
2633
+ if (files.some((f) => f.includes("hooks/"))) {
2634
+ patterns.push("Custom React Hooks");
2635
+ }
2636
+ if (files.some((f) => f.includes("middleware"))) {
2637
+ patterns.push("Middleware Pattern");
2638
+ }
2639
+ if (files.some((f) => f.includes("providers"))) {
2640
+ patterns.push("Context Providers");
2641
+ }
2642
+ return patterns;
2643
+ }
2644
+ };
2645
+
2646
+ // src/utils/question-generator.ts
2647
+ var QuestionGenerator = class {
2648
+ analysis;
2649
+ config;
2650
+ constructor(analysis, config) {
2651
+ this.analysis = analysis;
2652
+ this.config = config;
2653
+ }
2654
+ /**
2655
+ * Generate all advisory board questions
2656
+ */
2657
+ generate() {
2658
+ const questions = [];
2659
+ questions.push(...this.generateTechnologyQuestions());
2660
+ questions.push(...this.generatePackageQuestions());
2661
+ questions.push(...this.generatePlatformQuestions());
2662
+ questions.push(...this.generateBusinessQuestions());
2663
+ questions.push(...this.generateTechnicalDebtQuestions());
2664
+ questions.push(...this.generateGrowthQuestions());
2665
+ if (this.config?.customQuestions) {
2666
+ questions.push(
2667
+ ...this.formatCustomQuestions(this.config.customQuestions)
2668
+ );
2669
+ }
2670
+ const sorted = this.sortByPriority(questions);
2671
+ return {
2672
+ questions: sorted,
2673
+ summary: this.generateSummary(sorted)
2674
+ };
2675
+ }
2676
+ /**
2677
+ * Technology Decisions questions
2678
+ */
2679
+ generateTechnologyQuestions() {
2680
+ const questions = [];
2681
+ const { technology, project } = this.analysis;
2682
+ if (technology.framework) {
2683
+ questions.push({
2684
+ category: "Technology Decisions",
2685
+ question: `Why was ${technology.framework} chosen as the primary framework, and does it still align with our strategic goals?`,
2686
+ context: `Project uses ${technology.framework}${technology.frameworkVersion ? ` v${technology.frameworkVersion}` : ""} as the foundation`,
2687
+ findings: [
2688
+ `Framework: ${technology.framework}`,
2689
+ `Language: ${technology.language}`,
2690
+ `Runtime: ${technology.runtime}`
2691
+ ],
2692
+ recommendations: [
2693
+ "Validate framework continues to meet performance and scalability needs",
2694
+ "Assess community support and long-term viability",
2695
+ "Consider migration costs vs. benefits if alternatives exist"
2696
+ ],
2697
+ priority: "high",
2698
+ businessImpact: "Framework choice affects development velocity, talent acquisition, and long-term maintenance costs"
2699
+ });
2700
+ }
2701
+ if (technology.buildTools && technology.buildTools.length > 0) {
2702
+ questions.push({
2703
+ category: "Technology Decisions",
2704
+ question: `How are our build tools (${technology.buildTools.join(", ")}) optimizing development workflow and deployment efficiency?`,
2705
+ context: `Build pipeline uses ${technology.buildTools.join(", ")}`,
2706
+ findings: technology.buildTools.map(
2707
+ (tool) => `Using ${tool} for build process`
2708
+ ),
2709
+ recommendations: [
2710
+ "Measure build time impacts on CI/CD pipeline",
2711
+ "Evaluate if modern alternatives could improve developer experience",
2712
+ "Consider caching strategies to optimize build performance"
2713
+ ],
2714
+ priority: "medium",
2715
+ businessImpact: "Build efficiency directly impacts time-to-market for new features"
2716
+ });
2717
+ }
2718
+ if (project.isMonorepo) {
2719
+ questions.push({
2720
+ category: "Technology Decisions",
2721
+ question: `Is the monorepo structure providing expected benefits in code sharing and deployment coordination?`,
2722
+ context: `Project uses monorepo with ${project.workspaceCount || "multiple"} workspaces`,
2723
+ findings: [
2724
+ `Monorepo with ${project.workspaceCount} packages`,
2725
+ `Total ${project.fileCount} files managed`
2726
+ ],
2727
+ recommendations: [
2728
+ "Assess if shared code is properly abstracted and reused",
2729
+ "Evaluate build caching and selective deployment strategies",
2730
+ "Consider workspace organization for scaling"
2731
+ ],
2732
+ priority: "medium",
2733
+ businessImpact: "Monorepo architecture affects team collaboration and deployment complexity"
2734
+ });
2735
+ }
2736
+ return questions;
2737
+ }
2738
+ /**
2739
+ * Package Utilization questions
2740
+ */
2741
+ generatePackageQuestions() {
2742
+ const questions = [];
2743
+ const { packages } = this.analysis;
2744
+ if (packages.total > 80) {
2745
+ questions.push({
2746
+ category: "Package Utilization",
2747
+ question: `With ${packages.total} dependencies, are we maintaining optimal balance between functionality and maintenance burden?`,
2748
+ context: `Project has ${packages.production.length} production and ${packages.development.length} development dependencies`,
2749
+ findings: [
2750
+ `Total packages: ${packages.total}`,
2751
+ `Production: ${packages.production.length}`,
2752
+ `Development: ${packages.development.length}`
2753
+ ],
2754
+ recommendations: [
2755
+ "Audit for unused or redundant packages",
2756
+ "Evaluate if critical functionality should be internalized",
2757
+ "Implement dependency update strategy"
2758
+ ],
2759
+ priority: packages.total > 150 ? "high" : "medium",
2760
+ businessImpact: "Dependency count affects security surface area and maintenance costs"
2761
+ });
2762
+ }
2763
+ if (packages.categories.length > 0) {
2764
+ const topCategories = packages.categories.sort((a, b) => b.count - a.count).slice(0, 3);
2765
+ topCategories.forEach((cat) => {
2766
+ if (cat.count > 5) {
2767
+ questions.push({
2768
+ category: "Package Utilization",
2769
+ question: `How are we leveraging our ${cat.count} ${cat.name} packages to deliver business value?`,
2770
+ context: `${cat.name}: ${cat.packages.slice(0, 3).join(", ")}${cat.count > 3 ? `, +${cat.count - 3} more` : ""}`,
2771
+ findings: [
2772
+ `${cat.count} packages in ${cat.name} category`,
2773
+ cat.businessImpact
2774
+ ],
2775
+ recommendations: this.getCategoryRecommendations(cat),
2776
+ priority: this.getCategoryPriority(cat),
2777
+ businessImpact: cat.businessImpact
2778
+ });
2779
+ }
2780
+ });
2781
+ }
2782
+ if (packages.security && packages.security.length > 0) {
2783
+ const criticalCount = packages.security.filter(
2784
+ (s) => s.severity === "critical"
2785
+ ).length;
2786
+ questions.push({
2787
+ category: "Package Utilization",
2788
+ question: `What is our strategy for addressing ${packages.security.length} identified security vulnerabilities${criticalCount > 0 ? ` (${criticalCount} critical)` : ""}?`,
2789
+ context: "Security audit identified vulnerabilities in dependencies",
2790
+ findings: packages.security.map(
2791
+ (s) => `${s.package}: ${s.severity} - ${s.issue}`
2792
+ ),
2793
+ recommendations: packages.security.map((s) => s.recommendation),
2794
+ priority: criticalCount > 0 ? "high" : "medium",
2795
+ businessImpact: "Security vulnerabilities pose risk to customer data and business operations"
2796
+ });
2797
+ }
2798
+ return questions;
2799
+ }
2800
+ /**
2801
+ * Platform Strategy questions
2802
+ */
2803
+ generatePlatformQuestions() {
2804
+ const questions = [];
2805
+ const { technology } = this.analysis;
2806
+ if (technology.platforms && technology.platforms.length > 0) {
2807
+ questions.push({
2808
+ category: "Platform Strategy",
2809
+ question: `Are our platform choices (${technology.platforms.join(", ")}) aligned with target market and growth plans?`,
2810
+ context: `Currently deployed on ${technology.platforms.join(" + ")}`,
2811
+ findings: technology.platforms.map((p11) => `Supports ${p11} platform`),
2812
+ recommendations: [
2813
+ "Validate platform coverage matches user demographics",
2814
+ "Assess cross-platform development efficiency",
2815
+ "Consider platform-specific optimization opportunities"
2816
+ ],
2817
+ priority: "medium",
2818
+ businessImpact: "Platform strategy determines market reach and development costs"
2819
+ });
2820
+ }
2821
+ if (technology.infrastructure && technology.infrastructure.length > 0) {
2822
+ questions.push({
2823
+ category: "Platform Strategy",
2824
+ question: `How is our infrastructure choice (${technology.infrastructure.join(", ")}) supporting scalability and cost efficiency?`,
2825
+ context: `Infrastructure: ${technology.infrastructure.join(", ")}`,
2826
+ findings: technology.infrastructure.map((i) => `Deployed on ${i}`),
2827
+ recommendations: [
2828
+ "Monitor infrastructure costs vs. usage patterns",
2829
+ "Evaluate auto-scaling and redundancy capabilities",
2830
+ "Consider multi-region deployment for global users"
2831
+ ],
2832
+ priority: "high",
2833
+ businessImpact: "Infrastructure directly impacts operational costs, uptime, and scalability"
2834
+ });
2835
+ }
2836
+ return questions;
2837
+ }
2838
+ /**
2839
+ * Business Alignment questions
2840
+ */
2841
+ generateBusinessQuestions() {
2842
+ const questions = [];
2843
+ const { packages } = this.analysis;
2844
+ const hasAnalytics = packages.categories.some(
2845
+ (cat) => cat.name.toLowerCase().includes("analytics")
2846
+ );
2847
+ if (!hasAnalytics) {
2848
+ questions.push({
2849
+ category: "Business Alignment",
2850
+ question: "Why don't we have analytics infrastructure, and how are we making data-driven product decisions?",
2851
+ context: "No analytics packages detected in the project",
2852
+ findings: ["Missing analytics implementation"],
2853
+ recommendations: [
2854
+ "Implement analytics to track user behavior and feature adoption",
2855
+ "Set up conversion funnels and key metric tracking",
2856
+ "Enable A/B testing capabilities for product experiments"
2857
+ ],
2858
+ priority: "high",
2859
+ businessImpact: "Lack of analytics limits ability to measure ROI and optimize user experience"
2860
+ });
2861
+ }
2862
+ const hasAuth = packages.categories.some(
2863
+ (cat) => cat.name.toLowerCase().includes("auth")
2864
+ );
2865
+ if (hasAuth) {
2866
+ const authCat = packages.categories.find(
2867
+ (cat) => cat.name.toLowerCase().includes("auth")
2868
+ );
2869
+ questions.push({
2870
+ category: "Business Alignment",
2871
+ question: `How is our authentication solution (${authCat.packages.join(", ")}) supporting user onboarding and security requirements?`,
2872
+ context: `Using ${authCat.packages.join(" + ")} for authentication`,
2873
+ findings: authCat.packages.map((p11) => `Auth provider: ${p11}`),
2874
+ recommendations: [
2875
+ "Measure authentication success rates and friction points",
2876
+ "Ensure compliance with security standards (SOC2, GDPR, etc.)",
2877
+ "Evaluate social login options to reduce signup friction"
2878
+ ],
2879
+ priority: "high",
2880
+ businessImpact: "Authentication affects conversion rates and security posture"
2881
+ });
2882
+ }
2883
+ const hasTestingtools = packages.categories.some(
2884
+ (cat) => cat.name.toLowerCase().includes("testing")
2885
+ );
2886
+ if (hasTestingtools) {
2887
+ questions.push({
2888
+ category: "Business Alignment",
2889
+ question: "How is our testing strategy contributing to product quality and customer satisfaction?",
2890
+ context: "Testing infrastructure is in place",
2891
+ findings: ["Testing tools available"],
2892
+ recommendations: [
2893
+ "Set coverage targets aligned with quality goals",
2894
+ "Implement testing in CI/CD for every release",
2895
+ "Track bugs-in-production as quality metric"
2896
+ ],
2897
+ priority: "medium",
2898
+ businessImpact: "Quality assurance directly affects customer satisfaction and support costs"
2899
+ });
2900
+ }
2901
+ return questions;
2902
+ }
2903
+ /**
2904
+ * Technical Debt questions
2905
+ */
2906
+ generateTechnicalDebtQuestions() {
2907
+ const questions = [];
2908
+ const { risks, packages } = this.analysis;
2909
+ if (risks.high && risks.high.length > 0) {
2910
+ questions.push({
2911
+ category: "Technical Debt",
2912
+ question: `What is our strategy for addressing ${risks.high.length} high-priority technical risks?`,
2913
+ context: "Analysis identified significant technical risks",
2914
+ findings: risks.high,
2915
+ recommendations: [
2916
+ "Prioritize risks by business impact",
2917
+ "Allocate dedicated time for technical debt in sprints",
2918
+ "Track debt reduction as OKR/KPI"
2919
+ ],
2920
+ priority: "high",
2921
+ businessImpact: "Unaddressed technical debt slows feature velocity and increases costs"
2922
+ });
2923
+ }
2924
+ if (packages.outdated && packages.outdated.length > 10) {
2925
+ const breakingCount = packages.outdated.filter((p11) => p11.breaking).length;
2926
+ questions.push({
2927
+ category: "Technical Debt",
2928
+ question: `How should we prioritize updating ${packages.outdated.length} outdated packages${breakingCount > 0 ? ` (${breakingCount} with breaking changes)` : ""}?`,
2929
+ context: "Dependency audit found outdated packages",
2930
+ findings: packages.outdated.slice(0, 5).map((p11) => `${p11.name}: ${p11.current} \u2192 ${p11.latest}`),
2931
+ recommendations: [
2932
+ "Create update roadmap starting with non-breaking changes",
2933
+ "Test breaking changes in feature branches",
2934
+ "Consider automated dependency updates (Dependabot, Renovate)"
2935
+ ],
2936
+ priority: breakingCount > 5 ? "high" : "medium",
2937
+ businessImpact: "Outdated dependencies miss performance improvements and security patches"
2938
+ });
2939
+ }
2940
+ const complexityRisk = risks.categories.find(
2941
+ (c) => c.name.includes("Complexity")
2942
+ );
2943
+ if (complexityRisk && complexityRisk.score > 0.5) {
2944
+ questions.push({
2945
+ category: "Technical Debt",
2946
+ question: "How are we managing codebase complexity to maintain development velocity?",
2947
+ context: `Complexity score: ${(complexityRisk.score * 100).toFixed(0)}%`,
2948
+ findings: complexityRisk.issues,
2949
+ recommendations: [
2950
+ "Implement code quality metrics and monitoring",
2951
+ "Establish refactoring goals for each sprint",
2952
+ "Consider modularization strategies"
2953
+ ],
2954
+ priority: complexityRisk.score > 0.7 ? "high" : "medium",
2955
+ businessImpact: "High complexity slows new feature development and increases bugs"
2956
+ });
2957
+ }
2958
+ return questions;
2959
+ }
2960
+ /**
2961
+ * Growth Opportunities questions
2962
+ */
2963
+ generateGrowthQuestions() {
2964
+ const questions = [];
2965
+ const { opportunities } = this.analysis;
2966
+ if (opportunities.immediate && opportunities.immediate.length > 0) {
2967
+ questions.push({
2968
+ category: "Growth Opportunities",
2969
+ question: "Which immediate technical opportunities should we prioritize for maximum business impact?",
2970
+ context: `${opportunities.immediate.length} immediate opportunities identified`,
2971
+ findings: opportunities.immediate,
2972
+ recommendations: [
2973
+ "Evaluate ROI and effort for each opportunity",
2974
+ "Align opportunities with business OKRs",
2975
+ "Quick wins can build momentum for larger initiatives"
2976
+ ],
2977
+ priority: "high",
2978
+ businessImpact: "Immediate opportunities can deliver quick ROI with minimal investment"
2979
+ });
2980
+ }
2981
+ opportunities.categories.forEach((cat) => {
2982
+ if (cat.potential > 0.6) {
2983
+ questions.push({
2984
+ category: "Growth Opportunities",
2985
+ question: `How can we capitalize on ${cat.name.toLowerCase()} opportunities to drive business growth?`,
2986
+ context: `Potential score: ${(cat.potential * 100).toFixed(0)}%`,
2987
+ findings: cat.recommendations,
2988
+ recommendations: [
2989
+ "Develop roadmap for implementing recommendations",
2990
+ "Assign owners and timelines",
2991
+ "Define success metrics"
2992
+ ],
2993
+ priority: cat.potential > 0.8 ? "high" : "medium",
2994
+ businessImpact: cat.businessValue
2995
+ });
2996
+ }
2997
+ });
2998
+ return questions;
2999
+ }
3000
+ /**
3001
+ * Format custom questions from config
3002
+ */
3003
+ formatCustomQuestions(customQuestions) {
3004
+ return customQuestions.map((q) => ({
3005
+ category: q.category,
3006
+ question: q.question,
3007
+ context: q.context || "Custom advisory question",
3008
+ findings: [],
3009
+ recommendations: [],
3010
+ priority: q.priority || "medium",
3011
+ businessImpact: "Custom question defined by organization"
3012
+ }));
3013
+ }
3014
+ /**
3015
+ * Sort questions by priority
3016
+ */
3017
+ sortByPriority(questions) {
3018
+ const priorityOrder = { high: 0, medium: 1, low: 2 };
3019
+ return questions.sort(
3020
+ (a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]
3021
+ );
3022
+ }
3023
+ /**
3024
+ * Generate summary of questions
3025
+ */
3026
+ generateSummary(questions) {
3027
+ const categories = Array.from(new Set(questions.map((q) => q.category)));
3028
+ return {
3029
+ totalQuestions: questions.length,
3030
+ highPriority: questions.filter((q) => q.priority === "high").length,
3031
+ mediumPriority: questions.filter((q) => q.priority === "medium").length,
3032
+ lowPriority: questions.filter((q) => q.priority === "low").length,
3033
+ categories
3034
+ };
3035
+ }
3036
+ /**
3037
+ * Get recommendations for a package category
3038
+ */
3039
+ getCategoryRecommendations(cat) {
3040
+ const recommendations = [];
3041
+ if (cat.name.includes("UI") || cat.name.includes("Styling")) {
3042
+ recommendations.push(
3043
+ "Ensure design system consistency across components"
3044
+ );
3045
+ recommendations.push("Consider component library optimization");
3046
+ } else if (cat.name.includes("API") || cat.name.includes("Data")) {
3047
+ recommendations.push("Implement proper error handling and retry logic");
3048
+ recommendations.push("Consider caching strategies for performance");
3049
+ } else if (cat.name.includes("Testing")) {
3050
+ recommendations.push("Increase test coverage for critical paths");
3051
+ recommendations.push("Automate testing in CI/CD pipeline");
3052
+ } else if (cat.name.includes("Database") || cat.name.includes("ORM")) {
3053
+ recommendations.push("Optimize queries and indexes");
3054
+ recommendations.push("Implement database migration strategy");
3055
+ }
3056
+ if (recommendations.length === 0) {
3057
+ recommendations.push("Review usage patterns for optimization");
3058
+ recommendations.push("Consider if functionality meets current needs");
3059
+ }
3060
+ return recommendations;
3061
+ }
3062
+ /**
3063
+ * Get priority for a package category
3064
+ */
3065
+ getCategoryPriority(cat) {
3066
+ if (["Authentication", "Database", "Infrastructure", "API"].some(
3067
+ (key) => cat.name.includes(key)
3068
+ )) {
3069
+ return "high";
3070
+ }
3071
+ if (["UI", "Testing", "State Management", "Forms"].some(
3072
+ (key) => cat.name.includes(key)
3073
+ )) {
3074
+ return "medium";
3075
+ }
3076
+ return "low";
3077
+ }
3078
+ };
3079
+
3080
+ // src/utils/report-comparator.ts
3081
+ var ReportComparator = class {
3082
+ baseline;
3083
+ current;
3084
+ constructor(baseline, current) {
3085
+ this.baseline = baseline;
3086
+ this.current = current;
3087
+ }
3088
+ /**
3089
+ * Compare two reports and generate diff
3090
+ */
3091
+ compare() {
3092
+ const baselineSummary = this.extractSummary(this.baseline);
3093
+ const currentSummary = this.extractSummary(this.current);
3094
+ const changes = this.calculateChanges(baselineSummary, currentSummary);
3095
+ const details = this.analyzeDetailedChanges();
3096
+ return {
3097
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3098
+ baseline: baselineSummary,
3099
+ current: currentSummary,
3100
+ changes,
3101
+ details
3102
+ };
3103
+ }
3104
+ /**
3105
+ * Extract summary from analysis
3106
+ */
3107
+ extractSummary(analysis) {
3108
+ return {
3109
+ timestamp: analysis.timestamp,
3110
+ depth: analysis.depth,
3111
+ projectName: analysis.project.name,
3112
+ overallRiskScore: analysis.risks.overall,
3113
+ overallOpportunityScore: analysis.opportunities.overall,
3114
+ packageCount: analysis.packages.total
3115
+ };
3116
+ }
3117
+ /**
3118
+ * Calculate high-level changes
3119
+ */
3120
+ calculateChanges(baseline, current) {
3121
+ const riskScoreChange = current.overallRiskScore - baseline.overallRiskScore;
3122
+ const opportunityScoreChange = current.overallOpportunityScore - baseline.overallOpportunityScore;
3123
+ const packageCountChange = current.packageCount - baseline.packageCount;
3124
+ const baselineHighRisks = new Set(this.baseline.risks.high);
3125
+ const currentHighRisks = new Set(this.current.risks.high);
3126
+ const newHighRisks = Array.from(currentHighRisks).filter(
3127
+ (risk) => !baselineHighRisks.has(risk)
3128
+ ).length;
3129
+ const resolvedHighRisks = Array.from(baselineHighRisks).filter(
3130
+ (risk) => !currentHighRisks.has(risk)
3131
+ ).length;
3132
+ const baselineImmediate = new Set(this.baseline.opportunities.immediate);
3133
+ const currentImmediate = new Set(this.current.opportunities.immediate);
3134
+ const newOpportunities = Array.from(currentImmediate).filter(
3135
+ (opp) => !baselineImmediate.has(opp)
3136
+ ).length;
3137
+ return {
3138
+ riskScoreChange,
3139
+ opportunityScoreChange,
3140
+ packageCountChange,
3141
+ newHighRisks,
3142
+ resolvedHighRisks,
3143
+ newOpportunities
3144
+ };
3145
+ }
3146
+ /**
3147
+ * Analyze detailed changes
3148
+ */
3149
+ analyzeDetailedChanges() {
3150
+ return {
3151
+ risks: this.compareRisks(),
3152
+ opportunities: this.compareOpportunities(),
3153
+ packages: this.comparePackages(),
3154
+ technology: this.compareTechnology()
3155
+ };
3156
+ }
3157
+ /**
3158
+ * Compare risks between reports
3159
+ */
3160
+ compareRisks() {
3161
+ const baselineRisks = /* @__PURE__ */ new Set([
3162
+ ...this.baseline.risks.critical,
3163
+ ...this.baseline.risks.high,
3164
+ ...this.baseline.risks.medium
3165
+ ]);
3166
+ const currentRisks = /* @__PURE__ */ new Set([
3167
+ ...this.current.risks.critical,
3168
+ ...this.current.risks.high,
3169
+ ...this.current.risks.medium
3170
+ ]);
3171
+ const newRisks = Array.from(currentRisks).filter(
3172
+ (risk) => !baselineRisks.has(risk)
3173
+ );
3174
+ const resolved = Array.from(baselineRisks).filter(
3175
+ (risk) => !currentRisks.has(risk)
3176
+ );
3177
+ const changed = [];
3178
+ const baselineCatMap = new Map(
3179
+ this.baseline.risks.categories.map((c) => [c.name, c])
3180
+ );
3181
+ const currentCatMap = new Map(
3182
+ this.current.risks.categories.map((c) => [c.name, c])
3183
+ );
3184
+ for (const [name, current] of currentCatMap) {
3185
+ const baseline = baselineCatMap.get(name);
3186
+ if (baseline && Math.abs(current.score - baseline.score) > 0.05) {
3187
+ changed.push({
3188
+ category: name,
3189
+ before: baseline.score,
3190
+ after: current.score,
3191
+ change: current.score - baseline.score
3192
+ });
3193
+ }
3194
+ }
3195
+ return { new: newRisks, resolved, changed };
3196
+ }
3197
+ /**
3198
+ * Compare opportunities between reports
3199
+ */
3200
+ compareOpportunities() {
3201
+ const baselineOpps = /* @__PURE__ */ new Set([
3202
+ ...this.baseline.opportunities.immediate,
3203
+ ...this.baseline.opportunities.shortTerm
3204
+ ]);
3205
+ const currentOpps = /* @__PURE__ */ new Set([
3206
+ ...this.current.opportunities.immediate,
3207
+ ...this.current.opportunities.shortTerm
3208
+ ]);
3209
+ const newOpps = Array.from(currentOpps).filter(
3210
+ (opp) => !baselineOpps.has(opp)
3211
+ );
3212
+ const completed = Array.from(baselineOpps).filter(
3213
+ (opp) => !currentOpps.has(opp)
3214
+ );
3215
+ const changed = [];
3216
+ const baselineCatMap = new Map(
3217
+ this.baseline.opportunities.categories.map((c) => [c.name, c])
3218
+ );
3219
+ const currentCatMap = new Map(
3220
+ this.current.opportunities.categories.map((c) => [c.name, c])
3221
+ );
3222
+ for (const [name, current] of currentCatMap) {
3223
+ const baseline = baselineCatMap.get(name);
3224
+ if (baseline && Math.abs(current.potential - baseline.potential) > 0.05) {
3225
+ changed.push({
3226
+ category: name,
3227
+ before: baseline.potential,
3228
+ after: current.potential,
3229
+ change: current.potential - baseline.potential
3230
+ });
3231
+ }
3232
+ }
3233
+ return { new: newOpps, completed, changed };
3234
+ }
3235
+ /**
3236
+ * Compare packages between reports
3237
+ */
3238
+ comparePackages() {
3239
+ const baselineProduction = new Map(
3240
+ this.baseline.packages.production.map((p11) => [p11.name, p11])
3241
+ );
3242
+ const currentProduction = new Map(
3243
+ this.current.packages.production.map((p11) => [p11.name, p11])
3244
+ );
3245
+ const added = [];
3246
+ const removed = [];
3247
+ const updated = [];
3248
+ for (const [name, pkg] of currentProduction) {
3249
+ if (!baselineProduction.has(name)) {
3250
+ added.push({
3251
+ name,
3252
+ version: pkg.version,
3253
+ category: pkg.category
3254
+ });
3255
+ }
3256
+ }
3257
+ for (const [name, baselinePkg] of baselineProduction) {
3258
+ const currentPkg = currentProduction.get(name);
3259
+ if (!currentPkg) {
3260
+ removed.push({
3261
+ name,
3262
+ version: baselinePkg.version,
3263
+ category: baselinePkg.category
3264
+ });
3265
+ } else if (baselinePkg.version !== currentPkg.version) {
3266
+ updated.push({
3267
+ name,
3268
+ version: currentPkg.version,
3269
+ previousVersion: baselinePkg.version,
3270
+ category: currentPkg.category
3271
+ });
3272
+ }
3273
+ }
3274
+ const baselineDev = new Map(
3275
+ this.baseline.packages.development.map((p11) => [p11.name, p11])
3276
+ );
3277
+ const currentDev = new Map(
3278
+ this.current.packages.development.map((p11) => [p11.name, p11])
3279
+ );
3280
+ for (const [name, pkg] of currentDev) {
3281
+ if (!baselineDev.has(name)) {
3282
+ added.push({
3283
+ name,
3284
+ version: pkg.version,
3285
+ category: pkg.category
3286
+ });
3287
+ }
3288
+ }
3289
+ for (const [name, baselinePkg] of baselineDev) {
3290
+ const currentPkg = currentDev.get(name);
3291
+ if (!currentPkg) {
3292
+ removed.push({
3293
+ name,
3294
+ version: baselinePkg.version,
3295
+ category: baselinePkg.category
3296
+ });
3297
+ } else if (baselinePkg.version !== currentPkg.version) {
3298
+ updated.push({
3299
+ name,
3300
+ version: currentPkg.version,
3301
+ previousVersion: baselinePkg.version,
3302
+ category: currentPkg.category
3303
+ });
3304
+ }
3305
+ }
3306
+ return { added, removed, updated };
3307
+ }
3308
+ /**
3309
+ * Compare technology stack between reports
3310
+ */
3311
+ compareTechnology() {
3312
+ const baselineTech = this.baseline.technology;
3313
+ const currentTech = this.current.technology;
3314
+ const frameworkChanged = baselineTech.framework !== currentTech.framework || baselineTech.frameworkVersion !== currentTech.frameworkVersion;
3315
+ const baselineTools = new Set(baselineTech.buildTools);
3316
+ const currentTools = new Set(currentTech.buildTools);
3317
+ const newBuildTools = currentTech.buildTools.filter(
3318
+ (tool) => !baselineTools.has(tool)
3319
+ );
3320
+ const removedTools = baselineTech.buildTools.filter(
3321
+ (tool) => !currentTools.has(tool)
3322
+ );
3323
+ const baselineInfra = new Set(baselineTech.infrastructure);
3324
+ const newInfrastructure = currentTech.infrastructure.filter(
3325
+ (infra) => !baselineInfra.has(infra)
3326
+ );
3327
+ return {
3328
+ frameworkChanged,
3329
+ newBuildTools,
3330
+ newInfrastructure,
3331
+ removedTools
3332
+ };
3333
+ }
3334
+ /**
3335
+ * Generate markdown summary of changes
3336
+ */
3337
+ generateMarkdownSummary() {
3338
+ const comparison = this.compare();
3339
+ const { changes, details } = comparison;
3340
+ let md = `# Advisory Report Comparison
3341
+
3342
+ `;
3343
+ md += `**Baseline:** ${new Date(comparison.baseline.timestamp).toLocaleDateString()}
3344
+ `;
3345
+ md += `**Current:** ${new Date(comparison.current.timestamp).toLocaleDateString()}
3346
+
3347
+ `;
3348
+ md += `## Executive Summary
3349
+
3350
+ `;
3351
+ const riskChange = changes.riskScoreChange;
3352
+ const riskEmoji = riskChange < 0 ? "\u2705" : riskChange > 0 ? "\u26A0\uFE0F" : "\u2796";
3353
+ md += `${riskEmoji} **Risk Score:** ${(comparison.baseline.overallRiskScore * 100).toFixed(0)}% \u2192 ${(comparison.current.overallRiskScore * 100).toFixed(0)}% `;
3354
+ md += `(${riskChange > 0 ? "+" : ""}${(riskChange * 100).toFixed(0)}%)
3355
+ `;
3356
+ const oppChange = changes.opportunityScoreChange;
3357
+ const oppEmoji = oppChange > 0 ? "\u2705" : oppChange < 0 ? "\u26A0\uFE0F" : "\u2796";
3358
+ md += `${oppEmoji} **Opportunity Score:** ${(comparison.baseline.overallOpportunityScore * 100).toFixed(0)}% \u2192 ${(comparison.current.overallOpportunityScore * 100).toFixed(0)}% `;
3359
+ md += `(${oppChange > 0 ? "+" : ""}${(oppChange * 100).toFixed(0)}%)
3360
+ `;
3361
+ md += `\u{1F4E6} **Packages:** ${comparison.baseline.packageCount} \u2192 ${comparison.current.packageCount} `;
3362
+ md += `(${changes.packageCountChange > 0 ? "+" : ""}${changes.packageCountChange})
3363
+
3364
+ `;
3365
+ md += `## Key Changes
3366
+
3367
+ `;
3368
+ if (changes.newHighRisks > 0) {
3369
+ md += `\u26A0\uFE0F **${changes.newHighRisks}** new high-priority risks identified
3370
+ `;
3371
+ }
3372
+ if (changes.resolvedHighRisks > 0) {
3373
+ md += `\u2705 **${changes.resolvedHighRisks}** high-priority risks resolved
3374
+ `;
3375
+ }
3376
+ if (changes.newOpportunities > 0) {
3377
+ md += `\u{1F31F} **${changes.newOpportunities}** new opportunities identified
3378
+ `;
3379
+ }
3380
+ if (details.technology.frameworkChanged) {
3381
+ md += `\u{1F504} Framework changed: ${comparison.baseline.projectName}
3382
+ `;
3383
+ }
3384
+ md += `
3385
+ ---
3386
+
3387
+ `;
3388
+ if (details.risks.new.length > 0 || details.risks.resolved.length > 0) {
3389
+ md += `## Risk Changes
3390
+
3391
+ `;
3392
+ if (details.risks.new.length > 0) {
3393
+ md += `### New Risks
3394
+
3395
+ `;
3396
+ details.risks.new.forEach((risk) => {
3397
+ md += `- ${risk}
3398
+ `;
3399
+ });
3400
+ md += `
3401
+ `;
3402
+ }
3403
+ if (details.risks.resolved.length > 0) {
3404
+ md += `### Resolved Risks
3405
+
3406
+ `;
3407
+ details.risks.resolved.forEach((risk) => {
3408
+ md += `- ~~${risk}~~
3409
+ `;
3410
+ });
3411
+ md += `
3412
+ `;
3413
+ }
3414
+ if (details.risks.changed.length > 0) {
3415
+ md += `### Risk Score Changes
3416
+
3417
+ `;
3418
+ md += `| Category | Before | After | Change |
3419
+ `;
3420
+ md += `|----------|--------|-------|--------|
3421
+ `;
3422
+ details.risks.changed.forEach((change) => {
3423
+ const changeStr = change.change > 0 ? `+${(change.change * 100).toFixed(0)}%` : `${(change.change * 100).toFixed(0)}%`;
3424
+ md += `| ${change.category} | ${(change.before * 100).toFixed(0)}% | ${(change.after * 100).toFixed(0)}% | ${changeStr} |
3425
+ `;
3426
+ });
3427
+ md += `
3428
+ `;
3429
+ }
3430
+ }
3431
+ if (details.packages.added.length > 0 || details.packages.removed.length > 0 || details.packages.updated.length > 0) {
3432
+ md += `## Package Changes
3433
+
3434
+ `;
3435
+ if (details.packages.added.length > 0) {
3436
+ md += `### Added (${details.packages.added.length})
3437
+
3438
+ `;
3439
+ details.packages.added.slice(0, 10).forEach((pkg) => {
3440
+ md += `- **${pkg.name}** \`${pkg.version}\` (${pkg.category})
3441
+ `;
3442
+ });
3443
+ if (details.packages.added.length > 10) {
3444
+ md += `
3445
+ _...and ${details.packages.added.length - 10} more_
3446
+ `;
3447
+ }
3448
+ md += `
3449
+ `;
3450
+ }
3451
+ if (details.packages.removed.length > 0) {
3452
+ md += `### Removed (${details.packages.removed.length})
3453
+
3454
+ `;
3455
+ details.packages.removed.slice(0, 10).forEach((pkg) => {
3456
+ md += `- ~~${pkg.name}~~ \`${pkg.version}\`
3457
+ `;
3458
+ });
3459
+ if (details.packages.removed.length > 10) {
3460
+ md += `
3461
+ _...and ${details.packages.removed.length - 10} more_
3462
+ `;
3463
+ }
3464
+ md += `
3465
+ `;
3466
+ }
3467
+ if (details.packages.updated.length > 0) {
3468
+ md += `### Updated (${details.packages.updated.length})
3469
+
3470
+ `;
3471
+ details.packages.updated.slice(0, 10).forEach((pkg) => {
3472
+ md += `- **${pkg.name}** \`${pkg.previousVersion}\` \u2192 \`${pkg.version}\`
3473
+ `;
3474
+ });
3475
+ if (details.packages.updated.length > 10) {
3476
+ md += `
3477
+ _...and ${details.packages.updated.length - 10} more_
3478
+ `;
3479
+ }
3480
+ md += `
3481
+ `;
3482
+ }
3483
+ }
3484
+ return md;
3485
+ }
3486
+ };
3487
+
3488
+ // src/cli/commands/advisory.ts
3489
+ async function advisoryCommand(options) {
3490
+ console.log(chalk11.bold.cyan("\n\u{1F3AF} Advisory Board Analysis\n"));
3491
+ const cwd = process.cwd();
3492
+ let config;
3493
+ try {
3494
+ config = await loadConfig(cwd);
3495
+ } catch (error) {
3496
+ config = void 0;
3497
+ }
3498
+ const advisoryConfig = config?.advisory;
3499
+ const isInteractive = options.interactive || !options.depth && !options.ci;
3500
+ let depth = options.depth || advisoryConfig?.defaultDepth || "standard";
3501
+ let outputDir = options.output || advisoryConfig?.outputDir || "docs/advisory";
3502
+ let includeHealth = options.includeHealth ?? advisoryConfig?.includeHealthMetrics ?? false;
3503
+ if (isInteractive && !options.depth) {
3504
+ const depthChoice = await p7.select({
3505
+ message: "Select analysis depth:",
3506
+ options: [
3507
+ {
3508
+ value: "executive",
3509
+ label: "\u{1F4CA} Executive - Business summary for non-technical stakeholders",
3510
+ hint: "High-level overview only"
3511
+ },
3512
+ {
3513
+ value: "quick",
3514
+ label: "\u26A1 Quick - Package scan and framework detection",
3515
+ hint: "~30 seconds"
3516
+ },
3517
+ {
3518
+ value: "standard",
3519
+ label: "\u{1F50D} Standard - Includes architecture analysis",
3520
+ hint: "~1-2 minutes (recommended)"
3521
+ },
3522
+ {
3523
+ value: "comprehensive",
3524
+ label: "\u{1F52C} Comprehensive - Full code-level pattern detection",
3525
+ hint: "~3-5 minutes"
3526
+ }
3527
+ ],
3528
+ initialValue: "standard"
3529
+ });
3530
+ if (p7.isCancel(depthChoice)) {
3531
+ p7.cancel("Analysis cancelled");
3532
+ process.exit(0);
3533
+ }
3534
+ depth = depthChoice;
3535
+ }
3536
+ if (isInteractive && !options.output) {
3537
+ const outputChoice = await p7.text({
3538
+ message: "Output directory:",
3539
+ placeholder: "docs/advisory",
3540
+ defaultValue: outputDir
3541
+ });
3542
+ if (p7.isCancel(outputChoice)) {
3543
+ p7.cancel("Analysis cancelled");
3544
+ process.exit(0);
3545
+ }
3546
+ outputDir = outputChoice;
3547
+ }
3548
+ if (isInteractive && !options.includeHealth) {
3549
+ const healthChoice = await p7.confirm({
3550
+ message: "Include code health metrics?",
3551
+ initialValue: includeHealth
3552
+ });
3553
+ if (p7.isCancel(healthChoice)) {
3554
+ p7.cancel("Analysis cancelled");
3555
+ process.exit(0);
3556
+ }
3557
+ includeHealth = healthChoice;
3558
+ }
3559
+ const analyzer = new AdvisoryAnalyzer({
3560
+ depth,
3561
+ cwd,
3562
+ config,
3563
+ includeHealth,
3564
+ excludePatterns: advisoryConfig?.excludePatterns
3565
+ });
3566
+ const spinner8 = p7.spinner();
3567
+ const depthLabels = {
3568
+ executive: "executive summary",
3569
+ quick: "quick scan",
3570
+ standard: "standard analysis",
3571
+ comprehensive: "comprehensive analysis"
3572
+ };
3573
+ spinner8.start(`Running ${depthLabels[depth]}...`);
3574
+ let analysis;
3575
+ try {
3576
+ analysis = await analyzer.analyze();
3577
+ spinner8.stop(`\u2713 Analysis complete`);
3578
+ } catch (error) {
3579
+ spinner8.stop("\u2717 Analysis failed");
3580
+ console.error(
3581
+ chalk11.red(
3582
+ `Error: ${error instanceof Error ? error.message : String(error)}`
3583
+ )
3584
+ );
3585
+ process.exit(1);
3586
+ }
3587
+ const questionGenerator = new QuestionGenerator(analysis, advisoryConfig);
3588
+ const questions = questionGenerator.generate();
3589
+ console.log("");
3590
+ displaySummary(analysis, questions);
3591
+ let comparisonReport;
3592
+ let comparator;
3593
+ if (options.compare) {
3594
+ const comparisonPath = options.compare.endsWith(".json") ? join6(cwd, options.compare) : join6(cwd, options.compare, "analysis.json");
3595
+ if (existsSync6(comparisonPath)) {
3596
+ spinner8.start("Comparing with previous report...");
3597
+ try {
3598
+ const previousContent = await readFile4(comparisonPath, "utf-8");
3599
+ const previousAnalysis = JSON.parse(previousContent);
3600
+ comparator = new ReportComparator(previousAnalysis, analysis);
3601
+ comparisonReport = comparator.compare();
3602
+ spinner8.stop("\u2713 Comparison complete");
3603
+ console.log("");
3604
+ displayComparisonSummary(comparisonReport);
3605
+ } catch (error) {
3606
+ spinner8.stop("\u26A0 Comparison failed");
3607
+ console.warn(chalk11.yellow(`Could not compare reports: ${error}`));
3608
+ }
3609
+ } else {
3610
+ console.warn(
3611
+ chalk11.yellow(
3612
+ `
3613
+ \u26A0 No previous report found at ${comparisonPath}. Skipping comparison.
3614
+ `
3615
+ )
3616
+ );
3617
+ }
3618
+ }
3619
+ if (options.dryRun) {
3620
+ console.log(chalk11.dim("\n--dry-run mode: No files written.\n"));
3621
+ return;
3622
+ }
3623
+ const fullOutputDir = join6(cwd, outputDir);
3624
+ await mkdir4(fullOutputDir, { recursive: true });
3625
+ spinner8.start("Generating reports...");
3626
+ try {
3627
+ const timestamp = options.timestamp ? (/* @__PURE__ */ new Date()).toISOString().split("T")[0] : "";
3628
+ if (options.format === "json") {
3629
+ await writeAnalysisJson(fullOutputDir, analysis, questions, timestamp);
3630
+ } else {
3631
+ await writeMarkdownReports(
3632
+ fullOutputDir,
3633
+ analysis,
3634
+ questions,
3635
+ comparator,
3636
+ timestamp
3637
+ );
3638
+ }
3639
+ spinner8.stop("\u2713 Reports generated");
3640
+ } catch (error) {
3641
+ spinner8.stop("\u2717 Failed to write reports");
3642
+ console.error(chalk11.red(`Error: ${error}`));
3643
+ process.exit(1);
3644
+ }
3645
+ console.log("");
3646
+ console.log(chalk11.green("\u{1F4DD} Reports written to:"));
3647
+ const suffix = options.timestamp ? `-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}` : "";
3648
+ if (options.format === "json") {
3649
+ console.log(chalk11.dim(` ${join6(outputDir, `analysis${suffix}.json`)}`));
3650
+ console.log(chalk11.dim(` ${join6(outputDir, `questions${suffix}.json`)}`));
3651
+ } else {
3652
+ console.log(
3653
+ chalk11.dim(` ${join6(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`)}`)
3654
+ );
3655
+ console.log(
3656
+ chalk11.dim(` ${join6(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`)}`)
3657
+ );
3658
+ console.log(
3659
+ chalk11.dim(` ${join6(outputDir, `STRATEGIC_ROADMAP${suffix}.md`)}`)
3660
+ );
3661
+ console.log(
3662
+ chalk11.dim(` ${join6(outputDir, `BOARD_QUESTIONS${suffix}.md`)}`)
3663
+ );
3664
+ if (comparisonReport) {
3665
+ console.log(
3666
+ chalk11.dim(` ${join6(outputDir, `DIFF_REPORT${suffix}.md`)}`)
3667
+ );
3668
+ }
3669
+ }
3670
+ if (options.ci) {
3671
+ console.log("");
3672
+ const exitCode = checkCIThresholds(analysis, advisoryConfig);
3673
+ if (exitCode !== 0) {
3674
+ console.log(chalk11.red(`
3675
+ \u274C CI check failed (exit code ${exitCode})
3676
+ `));
3677
+ process.exit(exitCode);
3678
+ } else {
3679
+ console.log(chalk11.green("\n\u2713 CI check passed\n"));
3680
+ }
3681
+ }
3682
+ p7.outro(chalk11.green("\u2713 Advisory analysis complete!"));
3683
+ }
3684
+ function displaySummary(analysis, questions) {
3685
+ console.log(chalk11.bold("\u{1F4CA} Analysis Summary\n"));
3686
+ console.log(
3687
+ chalk11.dim(`Project: ${analysis.project.name} v${analysis.project.version}`)
3688
+ );
3689
+ console.log(
3690
+ chalk11.dim(
3691
+ `Framework: ${analysis.technology.framework || "N/A"} (${analysis.technology.language})`
3692
+ )
3693
+ );
3694
+ console.log(chalk11.dim(`Total Packages: ${analysis.packages.total}`));
3695
+ console.log(chalk11.dim(`Files Analyzed: ${analysis.project.fileCount}`));
3696
+ console.log("");
3697
+ const riskScore = (analysis.risks.overall * 100).toFixed(0);
3698
+ const riskColor = analysis.risks.overall > 0.7 ? chalk11.red : analysis.risks.overall > 0.4 ? chalk11.yellow : chalk11.green;
3699
+ console.log(riskColor(`\u26A0\uFE0F Risk Score: ${riskScore}%`));
3700
+ const oppScore = (analysis.opportunities.overall * 100).toFixed(0);
3701
+ const oppColor = analysis.opportunities.overall > 0.7 ? chalk11.green : analysis.opportunities.overall > 0.5 ? chalk11.yellow : chalk11.dim;
3702
+ console.log(oppColor(`\u{1F31F} Opportunity Score: ${oppScore}%`));
3703
+ console.log("");
3704
+ console.log(chalk11.bold("\u2753 Advisory Questions\n"));
3705
+ console.log(
3706
+ chalk11.dim(`Total Questions: ${questions.summary.totalQuestions}`)
3707
+ );
3708
+ console.log(chalk11.red(` High Priority: ${questions.summary.highPriority}`));
3709
+ console.log(
3710
+ chalk11.yellow(` Medium Priority: ${questions.summary.mediumPriority}`)
3711
+ );
3712
+ console.log(chalk11.dim(` Low Priority: ${questions.summary.lowPriority}`));
3713
+ console.log("");
3714
+ const highPriorityQuestions = questions.questions.filter(
3715
+ (q) => q.priority === "high"
3716
+ );
3717
+ if (highPriorityQuestions.length > 0) {
3718
+ console.log(chalk11.bold.yellow("\u{1F525} Top Priority Questions:\n"));
3719
+ highPriorityQuestions.slice(0, 3).forEach((q, i) => {
3720
+ console.log(chalk11.yellow(`${i + 1}. ${q.question}`));
3721
+ console.log(chalk11.dim(` Category: ${q.category}`));
3722
+ console.log("");
3723
+ });
3724
+ }
3725
+ }
3726
+ function displayComparisonSummary(comparison) {
3727
+ console.log(chalk11.bold("\u{1F4C8} Changes Since Last Report\n"));
3728
+ const riskChange = comparison.changes.riskScoreChange;
3729
+ const riskEmoji = riskChange < 0 ? "\u2705" : riskChange > 0 ? "\u26A0\uFE0F" : "\u2796";
3730
+ console.log(
3731
+ `${riskEmoji} Risk Score: ${(riskChange * 100).toFixed(0)}% change`
3732
+ );
3733
+ const oppChange = comparison.changes.opportunityScoreChange;
3734
+ const oppEmoji = oppChange > 0 ? "\u2705" : oppChange < 0 ? "\u26A0\uFE0F" : "\u2796";
3735
+ console.log(
3736
+ `${oppEmoji} Opportunity Score: ${(oppChange * 100).toFixed(0)}% change`
3737
+ );
3738
+ console.log(
3739
+ `\u{1F4E6} Packages: ${comparison.changes.packageCountChange > 0 ? "+" : ""}${comparison.changes.packageCountChange}`
3740
+ );
3741
+ if (comparison.changes.newHighRisks > 0) {
3742
+ console.log(
3743
+ chalk11.red(
3744
+ `\u26A0\uFE0F ${comparison.changes.newHighRisks} new high-priority risks`
3745
+ )
3746
+ );
3747
+ }
3748
+ if (comparison.changes.resolvedHighRisks > 0) {
3749
+ console.log(
3750
+ chalk11.green(
3751
+ `\u2705 ${comparison.changes.resolvedHighRisks} high-priority risks resolved`
3752
+ )
3753
+ );
3754
+ }
3755
+ console.log("");
3756
+ }
3757
+ async function writeAnalysisJson(outputDir, analysis, questions, timestamp) {
3758
+ const suffix = timestamp ? `-${timestamp}` : "";
3759
+ await writeFile4(
3760
+ join6(outputDir, `analysis${suffix}.json`),
3761
+ JSON.stringify(analysis, null, 2),
3762
+ "utf-8"
3763
+ );
3764
+ await writeFile4(
3765
+ join6(outputDir, `questions${suffix}.json`),
3766
+ JSON.stringify(questions, null, 2),
3767
+ "utf-8"
3768
+ );
3769
+ }
3770
+ async function writeMarkdownReports(outputDir, analysis, questions, comparator, timestamp) {
3771
+ const suffix = timestamp ? `-${timestamp}` : "";
3772
+ await writeFile4(
3773
+ join6(outputDir, `analysis.json`),
3774
+ JSON.stringify(analysis, null, 2),
3775
+ "utf-8"
3776
+ );
3777
+ await writeFile4(
3778
+ join6(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`),
3779
+ generateExecutiveSummary(analysis, questions),
3780
+ "utf-8"
3781
+ );
3782
+ await writeFile4(
3783
+ join6(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`),
3784
+ generateTechnologyAudit(analysis),
3785
+ "utf-8"
3786
+ );
3787
+ await writeFile4(
3788
+ join6(outputDir, `STRATEGIC_ROADMAP${suffix}.md`),
3789
+ generateStrategicRoadmap(analysis, questions),
3790
+ "utf-8"
3791
+ );
3792
+ await writeFile4(
3793
+ join6(outputDir, `BOARD_QUESTIONS${suffix}.md`),
3794
+ generateBoardQuestions(questions),
3795
+ "utf-8"
3796
+ );
3797
+ if (comparator) {
3798
+ await writeFile4(
3799
+ join6(outputDir, `DIFF_REPORT${suffix}.md`),
3800
+ comparator.generateMarkdownSummary(),
3801
+ "utf-8"
3802
+ );
3803
+ }
3804
+ }
3805
+ function generateExecutiveSummary(analysis, questions) {
3806
+ let md = `# Executive Summary
3807
+
3808
+ `;
3809
+ md += `> **Generated:** ${new Date(analysis.timestamp).toLocaleDateString()}
3810
+
3811
+ `;
3812
+ md += `---
3813
+
3814
+ `;
3815
+ md += `## Project Overview
3816
+
3817
+ `;
3818
+ md += `**${analysis.project.name}** is a ${analysis.technology.framework || "modern"} application `;
3819
+ md += `built with ${analysis.technology.language}. `;
3820
+ if (analysis.project.description) {
3821
+ md += `${analysis.project.description}
3822
+
3823
+ `;
3824
+ } else {
3825
+ md += `
3826
+
3827
+ `;
3828
+ }
3829
+ md += `### Key Metrics
3830
+
3831
+ `;
3832
+ md += `| Metric | Value |
3833
+ `;
3834
+ md += `|--------|-------|
3835
+ `;
3836
+ md += `| Version | ${analysis.project.version} |
3837
+ `;
3838
+ md += `| Dependencies | ${analysis.packages.total} packages |
3839
+ `;
3840
+ md += `| Codebase Size | ${analysis.project.fileCount} files (~${(analysis.project.totalLines / 1e3).toFixed(0)}K lines) |
3841
+ `;
3842
+ md += `| Architecture | ${analysis.project.isMonorepo ? "Monorepo" : "Single repository"} |
3843
+ `;
3844
+ md += `
3845
+ `;
3846
+ md += `## Strategic Assessment
3847
+
3848
+ `;
3849
+ const riskScore = analysis.risks.overall;
3850
+ const oppScore = analysis.opportunities.overall;
3851
+ md += `### Risk & Opportunity Matrix
3852
+
3853
+ `;
3854
+ md += `| Category | Score | Status |
3855
+ `;
3856
+ md += `|----------|-------|--------|
3857
+ `;
3858
+ md += `| **Technical Risk** | ${(riskScore * 100).toFixed(0)}% | ${getRiskLabel(riskScore)} |
3859
+ `;
3860
+ md += `| **Growth Opportunity** | ${(oppScore * 100).toFixed(0)}% | ${getOpportunityLabel(oppScore)} |
3861
+ `;
3862
+ md += `
3863
+ `;
3864
+ md += `### Technology Foundation
3865
+
3866
+ `;
3867
+ md += `**Primary Stack:**
3868
+ `;
3869
+ md += `- Framework: ${analysis.technology.framework || "N/A"}
3870
+ `;
3871
+ md += `- Language: ${analysis.technology.language}
3872
+ `;
3873
+ md += `- Runtime: ${analysis.technology.runtime}
3874
+ `;
3875
+ if (analysis.technology.platforms.length > 0) {
3876
+ md += `- Platforms: ${analysis.technology.platforms.join(", ")}
3877
+ `;
3878
+ }
3879
+ md += `
3880
+ `;
3881
+ if (analysis.technology.infrastructure.length > 0) {
3882
+ md += `**Infrastructure:** ${analysis.technology.infrastructure.join(", ")}
3883
+
3884
+ `;
3885
+ }
3886
+ if (analysis.packages.categories.length > 0) {
3887
+ md += `### Technology Categories
3888
+
3889
+ `;
3890
+ const topCategories = analysis.packages.categories.sort((a, b) => b.count - a.count).slice(0, 5);
3891
+ topCategories.forEach((cat) => {
3892
+ md += `- **${cat.name}** (${cat.count} packages) - ${cat.businessImpact}
3893
+ `;
3894
+ });
3895
+ md += `
3896
+ `;
3897
+ }
3898
+ md += `## Key Strategic Questions
3899
+
3900
+ `;
3901
+ const highPriorityQuestions = questions.questions.filter(
3902
+ (q) => q.priority === "high"
3903
+ );
3904
+ if (highPriorityQuestions.length > 0) {
3905
+ highPriorityQuestions.slice(0, 5).forEach((q, i) => {
3906
+ md += `### ${i + 1}. ${q.question}
3907
+
3908
+ `;
3909
+ md += `**Context:** ${q.context}
3910
+
3911
+ `;
3912
+ md += `**Business Impact:** ${q.businessImpact}
3913
+
3914
+ `;
3915
+ });
3916
+ }
3917
+ if (analysis.risks.critical && analysis.risks.critical.length > 0) {
3918
+ md += `## Critical Risks
3919
+
3920
+ `;
3921
+ analysis.risks.critical.forEach((risk) => {
3922
+ md += `- \u26A0\uFE0F ${risk}
3923
+ `;
3924
+ });
3925
+ md += `
3926
+ `;
3927
+ }
3928
+ if (analysis.opportunities.immediate && analysis.opportunities.immediate.length > 0) {
3929
+ md += `## Immediate Opportunities
3930
+
3931
+ `;
3932
+ analysis.opportunities.immediate.slice(0, 5).forEach((opp) => {
3933
+ md += `- \u{1F31F} ${opp}
3934
+ `;
3935
+ });
3936
+ md += `
3937
+ `;
3938
+ }
3939
+ md += `---
3940
+
3941
+ `;
3942
+ md += `*For detailed technical analysis, see [TECHNOLOGY_AUDIT.md](TECHNOLOGY_AUDIT.md)*
3943
+ `;
3944
+ md += `*For strategic recommendations, see [STRATEGIC_ROADMAP.md](STRATEGIC_ROADMAP.md)*
3945
+ `;
3946
+ return md;
3947
+ }
3948
+ function generateTechnologyAudit(analysis) {
3949
+ let md = `# Technology Audit
3950
+
3951
+ `;
3952
+ md += `> **Generated:** ${new Date(analysis.timestamp).toLocaleDateString()}
3953
+ `;
3954
+ md += `> **Analysis Depth:** ${analysis.depth}
3955
+
3956
+ `;
3957
+ md += `---
3958
+
3959
+ `;
3960
+ md += `## Project Details
3961
+
3962
+ `;
3963
+ md += `| Property | Value |
3964
+ `;
3965
+ md += `|----------|-------|
3966
+ `;
3967
+ md += `| Name | ${analysis.project.name} |
3968
+ `;
3969
+ md += `| Version | ${analysis.project.version} |
3970
+ `;
3971
+ md += `| Package Manager | ${analysis.project.packageManager} |
3972
+ `;
3973
+ md += `| Repository Type | ${analysis.project.isMonorepo ? "Monorepo" : "Single"} |
3974
+ `;
3975
+ if (analysis.project.workspaceCount) {
3976
+ md += `| Workspaces | ${analysis.project.workspaceCount} |
3977
+ `;
3978
+ }
3979
+ md += `| Total Files | ${analysis.project.fileCount} |
3980
+ `;
3981
+ md += `| Estimated Lines | ${analysis.project.totalLines.toLocaleString()} |
3982
+ `;
3983
+ md += `
3984
+ `;
3985
+ md += `## Technology Stack
3986
+
3987
+ `;
3988
+ md += `### Core Technologies
3989
+
3990
+ `;
3991
+ md += `| Component | Technology |
3992
+ `;
3993
+ md += `|-----------|------------|
3994
+ `;
3995
+ md += `| Framework | ${analysis.technology.framework || "N/A"} ${analysis.technology.frameworkVersion || ""} |
3996
+ `;
3997
+ md += `| Language | ${analysis.technology.language} |
3998
+ `;
3999
+ md += `| Runtime | ${analysis.technology.runtime} |
4000
+ `;
4001
+ md += `| Platforms | ${analysis.technology.platforms.join(", ")} |
4002
+ `;
4003
+ md += `
4004
+ `;
4005
+ if (analysis.technology.buildTools.length > 0) {
4006
+ md += `### Build Tools
4007
+
4008
+ `;
4009
+ analysis.technology.buildTools.forEach((tool) => {
4010
+ md += `- ${tool}
4011
+ `;
4012
+ });
4013
+ md += `
4014
+ `;
4015
+ }
4016
+ if (analysis.technology.infrastructure.length > 0) {
4017
+ md += `### Infrastructure
4018
+
4019
+ `;
4020
+ analysis.technology.infrastructure.forEach((infra) => {
4021
+ md += `- ${infra}
4022
+ `;
4023
+ });
4024
+ md += `
4025
+ `;
4026
+ }
4027
+ md += `## Dependency Analysis
4028
+
4029
+ `;
4030
+ md += `### Overview
4031
+
4032
+ `;
4033
+ md += `- **Total Packages:** ${analysis.packages.total}
4034
+ `;
4035
+ md += `- **Production:** ${analysis.packages.production.length}
4036
+ `;
4037
+ md += `- **Development:** ${analysis.packages.development.length}
4038
+ `;
4039
+ md += `
4040
+ `;
4041
+ if (analysis.packages.categories.length > 0) {
4042
+ md += `### Package Categories
4043
+
4044
+ `;
4045
+ md += `| Category | Count | Business Impact |
4046
+ `;
4047
+ md += `|----------|-------|----------------|
4048
+ `;
4049
+ analysis.packages.categories.sort((a, b) => b.count - a.count).forEach((cat) => {
4050
+ md += `| ${cat.name} | ${cat.count} | ${cat.businessImpact} |
4051
+ `;
4052
+ });
4053
+ md += `
4054
+ `;
4055
+ }
4056
+ if (analysis.packages.production.length > 0) {
4057
+ md += `### Key Production Dependencies
4058
+
4059
+ `;
4060
+ md += `| Package | Version | Category | Purpose |
4061
+ `;
4062
+ md += `|---------|---------|----------|--------|
4063
+ `;
4064
+ analysis.packages.production.slice(0, 15).forEach((pkg) => {
4065
+ md += `| ${pkg.name} | \`${pkg.version}\` | ${pkg.category} | ${pkg.purpose} |
4066
+ `;
4067
+ });
4068
+ if (analysis.packages.production.length > 15) {
4069
+ md += `
4070
+ *...and ${analysis.packages.production.length - 15} more*
4071
+ `;
4072
+ }
4073
+ md += `
4074
+ `;
4075
+ }
4076
+ if (analysis.architecture) {
4077
+ md += `## Architecture Overview
4078
+
4079
+ `;
4080
+ md += `**Pattern:** ${analysis.architecture.pattern}
4081
+
4082
+ `;
4083
+ md += `### Layers
4084
+
4085
+ `;
4086
+ analysis.architecture.layers.forEach((layer) => {
4087
+ md += `- ${layer}
4088
+ `;
4089
+ });
4090
+ md += `
4091
+ `;
4092
+ md += `**Data Flow:** ${analysis.architecture.dataFlow}
4093
+
4094
+ `;
4095
+ if (analysis.architecture.keyDecisions.length > 0) {
4096
+ md += `### Key Architecture Decisions
4097
+
4098
+ `;
4099
+ analysis.architecture.keyDecisions.forEach((decision) => {
4100
+ md += `- ${decision}
4101
+ `;
4102
+ });
4103
+ md += `
4104
+ `;
4105
+ }
4106
+ }
4107
+ if (analysis.codePatterns) {
4108
+ md += `## Code Patterns
4109
+
4110
+ `;
4111
+ if (analysis.codePatterns.components.length > 0) {
4112
+ md += `### Components
4113
+
4114
+ `;
4115
+ analysis.codePatterns.components.forEach((comp) => {
4116
+ md += `**${comp.type}** (${comp.count})
4117
+ `;
4118
+ md += `- Conventions: ${comp.conventions.join(", ")}
4119
+ `;
4120
+ md += `
4121
+ `;
4122
+ });
4123
+ }
4124
+ if (analysis.codePatterns.tests) {
4125
+ md += `### Testing
4126
+
4127
+ `;
4128
+ md += `- Framework: ${analysis.codePatterns.tests.framework}
4129
+ `;
4130
+ md += `- Test Count: ${analysis.codePatterns.tests.count}
4131
+ `;
4132
+ md += `- Types: ${analysis.codePatterns.tests.types.join(", ")}
4133
+ `;
4134
+ if (analysis.codePatterns.tests.coverage) {
4135
+ md += `- Coverage: ${analysis.codePatterns.tests.coverage}%
4136
+ `;
4137
+ }
4138
+ md += `
4139
+ `;
4140
+ }
4141
+ }
4142
+ if (analysis.health) {
4143
+ md += `## Code Health
4144
+
4145
+ `;
4146
+ md += `| Check | Status |
4147
+ `;
4148
+ md += `|-------|--------|
4149
+ `;
4150
+ md += `| TypeScript | ${analysis.health.typecheck ? "\u2705 Passing" : "\u274C Failing"} |
4151
+ `;
4152
+ md += `| Linting | ${analysis.health.lint ? "\u2705 Passing" : "\u274C Failing"} |
4153
+ `;
4154
+ md += `| Tests | ${analysis.health.tests ? "\u2705 Passing" : "\u274C Failing"} |
4155
+ `;
4156
+ md += `| Build | ${analysis.health.build ? "\u2705 Passing" : "\u274C Failing"} |
4157
+ `;
4158
+ if (analysis.health.coverage) {
4159
+ md += `| Coverage | ${analysis.health.coverage}% |
4160
+ `;
4161
+ }
4162
+ md += `
4163
+ `;
4164
+ }
4165
+ return md;
4166
+ }
4167
+ function generateStrategicRoadmap(analysis, questions) {
4168
+ let md = `# Strategic Roadmap
4169
+
4170
+ `;
4171
+ md += `> **Generated:** ${new Date(analysis.timestamp).toLocaleDateString()}
4172
+
4173
+ `;
4174
+ md += `---
4175
+
4176
+ `;
4177
+ md += `## Overview
4178
+
4179
+ `;
4180
+ md += `This roadmap outlines strategic recommendations based on the technical analysis of ${analysis.project.name}. `;
4181
+ md += `Recommendations are prioritized by business impact and feasibility.
4182
+
4183
+ `;
4184
+ md += `## Risk Management
4185
+
4186
+ `;
4187
+ if (analysis.risks.critical.length > 0) {
4188
+ md += `### \u{1F534} Critical Priorities
4189
+
4190
+ `;
4191
+ analysis.risks.critical.forEach((risk, i) => {
4192
+ md += `${i + 1}. ${risk}
4193
+ `;
4194
+ });
4195
+ md += `
4196
+ `;
4197
+ }
4198
+ if (analysis.risks.high.length > 0) {
4199
+ md += `### \u{1F7E1} High Priority
4200
+
4201
+ `;
4202
+ analysis.risks.high.forEach((risk, i) => {
4203
+ md += `${i + 1}. ${risk}
4204
+ `;
4205
+ });
4206
+ md += `
4207
+ `;
4208
+ }
4209
+ md += `## Growth Opportunities
4210
+
4211
+ `;
4212
+ if (analysis.opportunities.immediate.length > 0) {
4213
+ md += `### \u26A1 Immediate (0-30 days)
4214
+
4215
+ `;
4216
+ analysis.opportunities.immediate.forEach((opp, i) => {
4217
+ md += `${i + 1}. ${opp}
4218
+ `;
4219
+ });
4220
+ md += `
4221
+ `;
4222
+ }
4223
+ if (analysis.opportunities.shortTerm.length > 0) {
4224
+ md += `### \u{1F4C5} Short-term (1-3 months)
4225
+
4226
+ `;
4227
+ analysis.opportunities.shortTerm.forEach((opp, i) => {
4228
+ md += `${i + 1}. ${opp}
4229
+ `;
4230
+ });
4231
+ md += `
4232
+ `;
4233
+ }
4234
+ if (analysis.opportunities.longTerm.length > 0) {
4235
+ md += `### \u{1F3AF} Long-term (3-12 months)
4236
+
4237
+ `;
4238
+ analysis.opportunities.longTerm.forEach((opp, i) => {
4239
+ md += `${i + 1}. ${opp}
4240
+ `;
4241
+ });
4242
+ md += `
4243
+ `;
4244
+ }
4245
+ md += `## Detailed Recommendations
4246
+
4247
+ `;
4248
+ const categoryMap = /* @__PURE__ */ new Map();
4249
+ questions.questions.forEach((q) => {
4250
+ if (!categoryMap.has(q.category)) {
4251
+ categoryMap.set(q.category, []);
4252
+ }
4253
+ categoryMap.get(q.category).push(q);
4254
+ });
4255
+ for (const [category, qs] of categoryMap) {
4256
+ md += `### ${category}
4257
+
4258
+ `;
4259
+ qs.forEach((q) => {
4260
+ md += `#### ${q.question}
4261
+
4262
+ `;
4263
+ if (q.findings.length > 0) {
4264
+ md += `**Current State:**
4265
+ `;
4266
+ q.findings.forEach((f) => {
4267
+ md += `- ${f}
4268
+ `;
4269
+ });
4270
+ md += `
4271
+ `;
4272
+ }
4273
+ if (q.recommendations.length > 0) {
4274
+ md += `**Recommendations:**
4275
+ `;
4276
+ q.recommendations.forEach((r) => {
4277
+ md += `- ${r}
4278
+ `;
4279
+ });
4280
+ md += `
4281
+ `;
4282
+ }
4283
+ md += `**Business Impact:** ${q.businessImpact}
4284
+
4285
+ `;
4286
+ md += `**Priority:** ${q.priority.toUpperCase()}
4287
+
4288
+ `;
4289
+ md += `---
4290
+
4291
+ `;
4292
+ });
4293
+ }
4294
+ return md;
4295
+ }
4296
+ function generateBoardQuestions(questions) {
4297
+ let md = `# Advisory Board Questions
4298
+
4299
+ `;
4300
+ md += `> **Total Questions:** ${questions.summary.totalQuestions}
4301
+ `;
4302
+ md += `> **High Priority:** ${questions.summary.highPriority} | `;
4303
+ md += `**Medium:** ${questions.summary.mediumPriority} | `;
4304
+ md += `**Low:** ${questions.summary.lowPriority}
4305
+
4306
+ `;
4307
+ md += `---
4308
+
4309
+ `;
4310
+ md += `## Table of Contents
4311
+
4312
+ `;
4313
+ questions.summary.categories.forEach((cat) => {
4314
+ const slug = cat.toLowerCase().replace(/\s+/g, "-");
4315
+ md += `- [${cat}](#${slug})
4316
+ `;
4317
+ });
4318
+ md += `
4319
+ ---
4320
+
4321
+ `;
4322
+ const categoryMap = /* @__PURE__ */ new Map();
4323
+ questions.questions.forEach((q) => {
4324
+ if (!categoryMap.has(q.category)) {
4325
+ categoryMap.set(q.category, []);
4326
+ }
4327
+ categoryMap.get(q.category).push(q);
4328
+ });
4329
+ for (const [category, qs] of categoryMap) {
4330
+ const slug = category.toLowerCase().replace(/\s+/g, "-");
4331
+ md += `## ${category}
4332
+
4333
+ `;
4334
+ md += `<a id="${slug}"></a>
4335
+
4336
+ `;
4337
+ qs.forEach((q, i) => {
4338
+ const priorityEmoji = q.priority === "high" ? "\u{1F534}" : q.priority === "medium" ? "\u{1F7E1}" : "\u{1F7E2}";
4339
+ md += `### ${i + 1}. ${priorityEmoji} ${q.question}
4340
+
4341
+ `;
4342
+ md += `**Context:** ${q.context}
4343
+
4344
+ `;
4345
+ if (q.findings.length > 0) {
4346
+ md += `**Findings:**
4347
+ `;
4348
+ q.findings.forEach((f) => {
4349
+ md += `- ${f}
4350
+ `;
4351
+ });
4352
+ md += `
4353
+ `;
4354
+ }
4355
+ if (q.recommendations.length > 0) {
4356
+ md += `**Recommendations:**
4357
+ `;
4358
+ q.recommendations.forEach((r) => {
4359
+ md += `- ${r}
4360
+ `;
4361
+ });
4362
+ md += `
4363
+ `;
4364
+ }
4365
+ md += `**Business Impact:** ${q.businessImpact}
4366
+
4367
+ `;
4368
+ md += `---
4369
+
4370
+ `;
4371
+ });
4372
+ }
4373
+ return md;
4374
+ }
4375
+ function getRiskLabel(score) {
4376
+ if (score > 0.7) return "\u{1F534} High Risk";
4377
+ if (score > 0.4) return "\u{1F7E1} Moderate Risk";
4378
+ return "\u{1F7E2} Low Risk";
4379
+ }
4380
+ function getOpportunityLabel(score) {
4381
+ if (score > 0.7) return "\u{1F31F} High Potential";
4382
+ if (score > 0.5) return "\u{1F4C8} Moderate Potential";
4383
+ return "\u{1F4A1} Identified";
4384
+ }
4385
+ function checkCIThresholds(analysis, config) {
4386
+ const thresholds = config?.riskThresholds || {
4387
+ high: 0.7,
4388
+ medium: 0.4
4389
+ };
4390
+ const riskScore = analysis.risks.overall;
4391
+ if (riskScore >= thresholds.high) {
4392
+ console.log(
4393
+ chalk11.red(
4394
+ `High risk threshold exceeded: ${(riskScore * 100).toFixed(0)}%`
4395
+ )
4396
+ );
4397
+ return 1;
4398
+ }
4399
+ if (analysis.packages.security && analysis.packages.security.length > 0) {
4400
+ const criticalCount = analysis.packages.security.filter(
4401
+ (s) => s.severity === "critical"
4402
+ ).length;
4403
+ if (criticalCount > 0) {
4404
+ console.log(
4405
+ chalk11.red(`Critical security vulnerabilities found: ${criticalCount}`)
4406
+ );
4407
+ return 1;
4408
+ }
4409
+ }
4410
+ return 0;
4411
+ }
4412
+
4413
+ // src/cli/commands/generate-instructions.ts
4414
+ import * as p8 from "@clack/prompts";
4415
+ import chalk12 from "chalk";
4416
+ import { existsSync as existsSync7 } from "fs";
4417
+ import { join as join7 } from "path";
4418
+ async function generateInstructionsCommand(options) {
4419
+ p8.intro(chalk12.bgBlue(" workflow-agent generate-instructions "));
4420
+ const cwd = process.cwd();
4421
+ const guidelinesDir = join7(cwd, "guidelines");
4422
+ const outputPath = join7(cwd, ".github", "copilot-instructions.md");
4423
+ if (!existsSync7(guidelinesDir)) {
4424
+ p8.cancel(
4425
+ "No guidelines directory found. Run 'workflow init' first to generate guidelines."
4426
+ );
4427
+ process.exit(1);
4428
+ }
4429
+ if (existsSync7(outputPath) && !options.force) {
4430
+ const shouldRegenerate = await p8.confirm({
4431
+ message: ".github/copilot-instructions.md already exists. Regenerate? (Custom content will be preserved)",
4432
+ initialValue: true
4433
+ });
4434
+ if (p8.isCancel(shouldRegenerate) || !shouldRegenerate) {
4435
+ p8.cancel("Generation cancelled");
4436
+ process.exit(0);
4437
+ }
4438
+ }
4439
+ const spinner8 = p8.spinner();
4440
+ spinner8.start("Generating AI agent instructions from guidelines...");
4441
+ try {
4442
+ const result = generateCopilotInstructions(cwd, {
4443
+ force: true,
4444
+ silent: false
4445
+ });
4446
+ if (result.success) {
4447
+ const status = result.isNew ? "Generated" : "Regenerated";
4448
+ spinner8.stop(
4449
+ chalk12.green(
4450
+ `\u2713 ${status} .github/copilot-instructions.md from ${result.guidelinesCount} guidelines`
4451
+ )
4452
+ );
4453
+ if (result.preservedCustomContent) {
4454
+ console.log(chalk12.dim(" Custom content between markers was preserved."));
4455
+ }
4456
+ console.log(chalk12.dim(`
4457
+ Output: ${result.filePath}`));
4458
+ console.log(
4459
+ chalk12.dim(
4460
+ "\n \u{1F4A1} Tip: Add project-specific instructions between the CUSTOM markers."
4461
+ )
4462
+ );
4463
+ } else {
4464
+ spinner8.stop(chalk12.red("\u2717 Failed to generate instructions"));
4465
+ console.log(chalk12.yellow(`
4466
+ Reason: ${result.error}`));
4467
+ }
4468
+ } catch (error) {
4469
+ spinner8.stop(chalk12.red("\u2717 Error generating instructions"));
4470
+ console.log(
4471
+ chalk12.yellow(
4472
+ `
4473
+ Reason: ${error instanceof Error ? error.message : String(error)}`
4474
+ )
4475
+ );
4476
+ process.exit(1);
4477
+ }
4478
+ p8.outro(chalk12.green("\u2713 AI agent instructions ready!"));
4479
+ console.log(chalk12.dim("\nThe .github/copilot-instructions.md file:"));
4480
+ console.log(chalk12.dim(" - Is read by GitHub Copilot and other AI agents"));
4481
+ console.log(chalk12.dim(" - Summarizes all guidelines with links to full docs"));
4482
+ console.log(chalk12.dim(" - Includes your project scopes and conventions"));
4483
+ console.log(chalk12.dim(" - Preserves custom instructions you add between markers\n"));
4484
+ }
4485
+
4486
+ // src/cli/commands/learn.ts
4487
+ import chalk13 from "chalk";
4488
+ import * as p9 from "@clack/prompts";
4489
+ import {
4490
+ PatternStore as PatternStore2,
4491
+ ContributorManager as ContributorManager2,
4492
+ PatternAnonymizer,
4493
+ TelemetryCollector as TelemetryCollector2
4494
+ } from "@hawkinside_out/workflow-improvement-tracker";
4495
+ function getWorkspacePath() {
4496
+ return process.cwd();
4497
+ }
4498
+ function formatDate(isoString) {
4499
+ return new Date(isoString).toLocaleDateString("en-US", {
4500
+ year: "numeric",
4501
+ month: "short",
4502
+ day: "numeric"
4503
+ });
4504
+ }
4505
+ function formatTags(tags) {
4506
+ return tags.map((t) => `${t.category}:${t.name}`).join(", ");
4507
+ }
4508
+ async function learnRecordCommand(options) {
4509
+ const cwd = getWorkspacePath();
4510
+ const store = new PatternStore2(cwd);
4511
+ console.log(chalk13.cyan("\n\u{1F4DA} Record a Learning Pattern\n"));
4512
+ let patternType = options.type;
4513
+ if (!patternType) {
4514
+ const typeChoice = await p9.select({
4515
+ message: "What type of pattern are you recording?",
4516
+ options: [
4517
+ {
4518
+ value: "fix",
4519
+ label: "\u{1F527} Fix Pattern - A specific solution to a problem"
4520
+ },
4521
+ {
4522
+ value: "blueprint",
4523
+ label: "\u{1F4D0} Blueprint - A project structure template"
4524
+ }
4525
+ ]
4526
+ });
4527
+ if (p9.isCancel(typeChoice)) {
4528
+ p9.cancel("Recording cancelled");
4529
+ process.exit(0);
4530
+ }
4531
+ patternType = typeChoice;
4532
+ }
4533
+ let name = options.name;
4534
+ if (!name) {
4535
+ const nameInput = await p9.text({
4536
+ message: "Pattern name:",
4537
+ placeholder: "e.g., Next.js App Router Migration",
4538
+ validate: (value) => {
4539
+ if (!value || value.length < 3)
4540
+ return "Name must be at least 3 characters";
4541
+ if (value.length > 100) return "Name must be less than 100 characters";
4542
+ return void 0;
4543
+ }
4544
+ });
4545
+ if (p9.isCancel(nameInput)) {
4546
+ p9.cancel("Recording cancelled");
4547
+ process.exit(0);
4548
+ }
4549
+ name = nameInput;
4550
+ }
4551
+ let description = options.description;
4552
+ if (!description) {
4553
+ const descInput = await p9.text({
4554
+ message: "Description:",
4555
+ placeholder: "What does this pattern solve?",
4556
+ validate: (value) => {
4557
+ if (!value || value.length < 10)
4558
+ return "Description must be at least 10 characters";
4559
+ if (value.length > 500)
4560
+ return "Description must be less than 500 characters";
4561
+ return void 0;
4562
+ }
4563
+ });
4564
+ if (p9.isCancel(descInput)) {
4565
+ p9.cancel("Recording cancelled");
4566
+ process.exit(0);
4567
+ }
4568
+ description = descInput;
4569
+ }
4570
+ let framework = options.framework;
4571
+ if (!framework) {
4572
+ const fwInput = await p9.text({
4573
+ message: "Framework:",
4574
+ placeholder: "e.g., next, react, vue, express"
4575
+ });
4576
+ if (p9.isCancel(fwInput)) {
4577
+ p9.cancel("Recording cancelled");
4578
+ process.exit(0);
4579
+ }
4580
+ framework = fwInput;
4581
+ }
4582
+ let version = options.version;
4583
+ if (!version) {
4584
+ const versionInput = await p9.text({
4585
+ message: "Framework version (semver range):",
4586
+ placeholder: "e.g., >=14.0.0, ^18.0.0",
4587
+ initialValue: ">=1.0.0"
4588
+ });
4589
+ if (p9.isCancel(versionInput)) {
4590
+ p9.cancel("Recording cancelled");
4591
+ process.exit(0);
4592
+ }
4593
+ version = versionInput;
4594
+ }
4595
+ let category = options.category;
4596
+ if (patternType === "fix" && !category) {
4597
+ const catChoice = await p9.select({
4598
+ message: "Category:",
4599
+ options: [
4600
+ { value: "migration", label: "\u{1F504} Migration" },
4601
+ { value: "security", label: "\u{1F512} Security" },
4602
+ { value: "performance", label: "\u26A1 Performance" },
4603
+ { value: "compatibility", label: "\u{1F517} Compatibility" },
4604
+ { value: "deprecation", label: "\u26A0\uFE0F Deprecation" },
4605
+ { value: "configuration", label: "\u2699\uFE0F Configuration" },
4606
+ { value: "best-practice", label: "\u2728 Best Practice" },
4607
+ { value: "error-handling", label: "\u{1F6A8} Error Handling" },
4608
+ { value: "testing", label: "\u{1F9EA} Testing" },
4609
+ { value: "other", label: "\u{1F4E6} Other" }
4610
+ ]
4611
+ });
4612
+ if (p9.isCancel(catChoice)) {
4613
+ p9.cancel("Recording cancelled");
4614
+ process.exit(0);
4615
+ }
4616
+ category = catChoice;
4617
+ }
4618
+ const tags = [];
4619
+ if (options.tags) {
4620
+ const tagPairs = options.tags.split(",").map((t) => t.trim());
4621
+ for (const pair of tagPairs) {
4622
+ const [cat, val] = pair.split(":");
4623
+ if (cat && val) {
4624
+ tags.push({
4625
+ category: cat,
4626
+ name: val
4627
+ });
4628
+ }
4629
+ }
4630
+ }
4631
+ tags.push({ category: "framework", name: framework });
4632
+ if (patternType === "fix") {
4633
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4634
+ const fixPattern = {
4635
+ id: crypto.randomUUID(),
4636
+ name,
4637
+ description,
4638
+ category,
4639
+ tags,
4640
+ trigger: {
4641
+ errorPattern: ".*",
4642
+ errorMessage: "Generic error pattern",
4643
+ filePattern: "**/*"
4644
+ },
4645
+ solution: {
4646
+ type: "command",
4647
+ steps: [
4648
+ {
4649
+ order: 1,
4650
+ action: "run",
4651
+ target: "npm run fix",
4652
+ description: "Follow the pattern instructions"
4653
+ }
4654
+ ]
4655
+ },
4656
+ compatibility: {
4657
+ framework,
4658
+ frameworkVersion: version,
4659
+ runtime: "node",
4660
+ runtimeVersion: ">=18.0.0",
4661
+ dependencies: []
4662
+ },
4663
+ metrics: {
4664
+ applications: 0,
4665
+ successes: 0,
4666
+ failures: 0,
4667
+ successRate: 0
4668
+ },
4669
+ source: "manual",
4670
+ isPrivate: true,
4671
+ createdAt: now,
4672
+ updatedAt: now
4673
+ };
4674
+ const result = await store.saveFixPattern(fixPattern);
4675
+ if (result.success) {
4676
+ console.log(chalk13.green("\n\u2705 Fix pattern recorded successfully!\n"));
4677
+ console.log(chalk13.dim(` ID: ${fixPattern.id}`));
4678
+ console.log(chalk13.dim(` Name: ${name}`));
4679
+ console.log(chalk13.dim(` Category: ${category}`));
4680
+ console.log(chalk13.dim(` Framework: ${framework} ${version}`));
4681
+ } else {
4682
+ console.log(chalk13.red("\n\u274C Failed to record pattern"));
4683
+ console.log(chalk13.dim(` Error: ${result.error}`));
4684
+ process.exit(1);
4685
+ }
4686
+ } else {
4687
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4688
+ const blueprint = {
4689
+ id: crypto.randomUUID(),
4690
+ name,
4691
+ description,
4692
+ tags,
4693
+ stack: {
4694
+ framework,
4695
+ language: "typescript",
1934
4696
  runtime: "node",
1935
4697
  packageManager: "pnpm",
1936
4698
  dependencies: [],
@@ -1965,13 +4727,13 @@ async function learnRecordCommand(options) {
1965
4727
  };
1966
4728
  const result = await store.saveBlueprint(blueprint);
1967
4729
  if (result.success) {
1968
- console.log(chalk11.green("\n\u2705 Blueprint recorded successfully!\n"));
1969
- console.log(chalk11.dim(` ID: ${blueprint.id}`));
1970
- console.log(chalk11.dim(` Name: ${name}`));
1971
- console.log(chalk11.dim(` Framework: ${framework} ${version}`));
4730
+ console.log(chalk13.green("\n\u2705 Blueprint recorded successfully!\n"));
4731
+ console.log(chalk13.dim(` ID: ${blueprint.id}`));
4732
+ console.log(chalk13.dim(` Name: ${name}`));
4733
+ console.log(chalk13.dim(` Framework: ${framework} ${version}`));
1972
4734
  } else {
1973
- console.log(chalk11.red("\n\u274C Failed to record blueprint"));
1974
- console.log(chalk11.dim(` Error: ${result.error}`));
4735
+ console.log(chalk13.red("\n\u274C Failed to record blueprint"));
4736
+ console.log(chalk13.dim(` Error: ${result.error}`));
1975
4737
  process.exit(1);
1976
4738
  }
1977
4739
  }
@@ -1981,7 +4743,7 @@ async function learnListCommand(options) {
1981
4743
  const store = new PatternStore2(cwd);
1982
4744
  const patternType = options.type ?? "all";
1983
4745
  const showDeprecated = options.deprecated ?? false;
1984
- console.log(chalk11.cyan("\n\u{1F4DA} Recorded Learning Patterns\n"));
4746
+ console.log(chalk13.cyan("\n\u{1F4DA} Recorded Learning Patterns\n"));
1985
4747
  if (patternType === "all" || patternType === "fix") {
1986
4748
  const fixResult = await store.listFixPatterns({
1987
4749
  tags: options.tag ? [{ category: "framework", name: options.tag }] : void 0,
@@ -1989,27 +4751,29 @@ async function learnListCommand(options) {
1989
4751
  includeDeprecated: showDeprecated
1990
4752
  });
1991
4753
  if (fixResult.success && fixResult.data && fixResult.data.length > 0) {
1992
- console.log(chalk11.bold.yellow("\u{1F527} Fix Patterns:\n"));
4754
+ console.log(chalk13.bold.yellow("\u{1F527} Fix Patterns:\n"));
1993
4755
  for (const pattern of fixResult.data) {
1994
4756
  const isDeprecated = pattern.deprecatedAt !== void 0;
1995
4757
  const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
1996
- const nameColor = isDeprecated ? chalk11.dim : chalk11.white;
4758
+ const nameColor = isDeprecated ? chalk13.dim : chalk13.white;
1997
4759
  console.log(` ${statusIcon} ${nameColor(pattern.name)}`);
1998
- console.log(chalk11.dim(` ID: ${pattern.id}`));
1999
- console.log(chalk11.dim(` Category: ${pattern.category}`));
2000
- console.log(chalk11.dim(` Created: ${formatDate(pattern.createdAt)}`));
4760
+ console.log(chalk13.dim(` ID: ${pattern.id}`));
4761
+ console.log(chalk13.dim(` Category: ${pattern.category}`));
4762
+ console.log(
4763
+ chalk13.dim(` Created: ${formatDate(pattern.createdAt)}`)
4764
+ );
2001
4765
  console.log(
2002
- chalk11.dim(
4766
+ chalk13.dim(
2003
4767
  ` Success Rate: ${(pattern.metrics.successRate * 100).toFixed(0)}% (${pattern.metrics.successes}/${pattern.metrics.applications})`
2004
4768
  )
2005
4769
  );
2006
4770
  if (pattern.tags.length > 0) {
2007
- console.log(chalk11.dim(` Tags: ${formatTags(pattern.tags)}`));
4771
+ console.log(chalk13.dim(` Tags: ${formatTags(pattern.tags)}`));
2008
4772
  }
2009
4773
  console.log("");
2010
4774
  }
2011
4775
  } else if (patternType === "fix") {
2012
- console.log(chalk11.dim(" No fix patterns found.\n"));
4776
+ console.log(chalk13.dim(" No fix patterns found.\n"));
2013
4777
  }
2014
4778
  }
2015
4779
  if (patternType === "all" || patternType === "blueprint") {
@@ -2019,44 +4783,46 @@ async function learnListCommand(options) {
2019
4783
  includeDeprecated: showDeprecated
2020
4784
  });
2021
4785
  if (bpResult.success && bpResult.data && bpResult.data.length > 0) {
2022
- console.log(chalk11.bold.blue("\u{1F4D0} Blueprints:\n"));
4786
+ console.log(chalk13.bold.blue("\u{1F4D0} Blueprints:\n"));
2023
4787
  for (const blueprint of bpResult.data) {
2024
4788
  const isDeprecated = blueprint.deprecatedAt !== void 0;
2025
4789
  const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
2026
- const nameColor = isDeprecated ? chalk11.dim : chalk11.white;
4790
+ const nameColor = isDeprecated ? chalk13.dim : chalk13.white;
2027
4791
  console.log(` ${statusIcon} ${nameColor(blueprint.name)}`);
2028
- console.log(chalk11.dim(` ID: ${blueprint.id}`));
2029
- console.log(chalk11.dim(` Language: ${blueprint.stack.language}`));
2030
- console.log(chalk11.dim(` Created: ${formatDate(blueprint.createdAt)}`));
4792
+ console.log(chalk13.dim(` ID: ${blueprint.id}`));
4793
+ console.log(chalk13.dim(` Language: ${blueprint.stack.language}`));
4794
+ console.log(
4795
+ chalk13.dim(` Created: ${formatDate(blueprint.createdAt)}`)
4796
+ );
2031
4797
  console.log(
2032
- chalk11.dim(
4798
+ chalk13.dim(
2033
4799
  ` Success Rate: ${(blueprint.metrics.successRate * 100).toFixed(0)}% (${blueprint.metrics.successes}/${blueprint.metrics.applications})`
2034
4800
  )
2035
4801
  );
2036
4802
  if (blueprint.tags.length > 0) {
2037
- console.log(chalk11.dim(` Tags: ${formatTags(blueprint.tags)}`));
4803
+ console.log(chalk13.dim(` Tags: ${formatTags(blueprint.tags)}`));
2038
4804
  }
2039
4805
  console.log("");
2040
4806
  }
2041
4807
  } else if (patternType === "blueprint") {
2042
- console.log(chalk11.dim(" No blueprints found.\n"));
4808
+ console.log(chalk13.dim(" No blueprints found.\n"));
2043
4809
  }
2044
4810
  }
2045
4811
  const stats = await store.getStats();
2046
4812
  const totalPatterns = stats.totalFixes + stats.totalBlueprints;
2047
4813
  const totalDeprecated = stats.deprecatedFixes + stats.deprecatedBlueprints;
2048
- console.log(chalk11.dim("\u2501".repeat(40)));
2049
- console.log(chalk11.dim(`Total: ${totalPatterns} patterns`));
2050
- console.log(chalk11.dim(` Fix Patterns: ${stats.totalFixes}`));
2051
- console.log(chalk11.dim(` Blueprints: ${stats.totalBlueprints}`));
2052
- console.log(chalk11.dim(` Deprecated: ${totalDeprecated}`));
4814
+ console.log(chalk13.dim("\u2501".repeat(40)));
4815
+ console.log(chalk13.dim(`Total: ${totalPatterns} patterns`));
4816
+ console.log(chalk13.dim(` Fix Patterns: ${stats.totalFixes}`));
4817
+ console.log(chalk13.dim(` Blueprints: ${stats.totalBlueprints}`));
4818
+ console.log(chalk13.dim(` Deprecated: ${totalDeprecated}`));
2053
4819
  console.log("");
2054
4820
  }
2055
4821
  async function learnApplyCommand(patternId, options) {
2056
4822
  const cwd = getWorkspacePath();
2057
4823
  const store = new PatternStore2(cwd);
2058
4824
  const telemetry = new TelemetryCollector2(cwd);
2059
- console.log(chalk11.cyan("\n\u{1F527} Apply Learning Pattern\n"));
4825
+ console.log(chalk13.cyan("\n\u{1F527} Apply Learning Pattern\n"));
2060
4826
  let pattern = await store.getFixPattern(patternId);
2061
4827
  let patternType = "fix";
2062
4828
  if (!pattern.success || !pattern.data) {
@@ -2065,88 +4831,110 @@ async function learnApplyCommand(patternId, options) {
2065
4831
  pattern = bpResult;
2066
4832
  patternType = "blueprint";
2067
4833
  } else {
2068
- console.log(chalk11.red(`
4834
+ console.log(chalk13.red(`
2069
4835
  \u274C Pattern not found: ${patternId}`));
2070
- console.log(chalk11.dim(" Use 'workflow learn:list' to see available patterns"));
4836
+ console.log(
4837
+ chalk13.dim(" Use 'workflow learn:list' to see available patterns")
4838
+ );
2071
4839
  process.exit(1);
2072
4840
  }
2073
4841
  }
2074
4842
  const patternData = pattern.data;
2075
- console.log(chalk11.white(` Pattern: ${patternData.name}`));
2076
- console.log(chalk11.dim(` Type: ${patternType}`));
2077
- console.log(chalk11.dim(` Description: ${patternData.description}`));
4843
+ console.log(chalk13.white(` Pattern: ${patternData.name}`));
4844
+ console.log(chalk13.dim(` Type: ${patternType}`));
4845
+ console.log(chalk13.dim(` Description: ${patternData.description}`));
2078
4846
  if (options.dryRun) {
2079
- console.log(chalk11.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n"));
4847
+ console.log(
4848
+ chalk13.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n")
4849
+ );
2080
4850
  }
2081
4851
  const framework = options.framework ?? patternData.compatibility.frameworks[0]?.name ?? "unknown";
2082
4852
  const version = options.version ?? patternData.compatibility.frameworks[0]?.version ?? "0.0.0";
2083
4853
  await telemetry.recordApplication(patternId, patternType, framework, version);
2084
4854
  if (patternType === "fix") {
2085
4855
  const fixPattern = patternData;
2086
- console.log(chalk11.cyan("\n\u{1F4CB} Solution Steps:\n"));
4856
+ console.log(chalk13.cyan("\n\u{1F4CB} Solution Steps:\n"));
2087
4857
  if (fixPattern.solution.steps) {
2088
4858
  for (let i = 0; i < fixPattern.solution.steps.length; i++) {
2089
4859
  const step = fixPattern.solution.steps[i];
2090
- console.log(chalk11.white(` ${i + 1}. [${step.action}] ${step.description}`));
4860
+ console.log(
4861
+ chalk13.white(` ${i + 1}. [${step.action}] ${step.description}`)
4862
+ );
2091
4863
  if (step.file) {
2092
- console.log(chalk11.dim(` File: ${step.file}`));
4864
+ console.log(chalk13.dim(` File: ${step.file}`));
2093
4865
  }
2094
4866
  }
2095
4867
  }
2096
4868
  } else {
2097
4869
  const blueprint = patternData;
2098
- console.log(chalk11.cyan("\n\u{1F4CB} Setup Steps:\n"));
4870
+ console.log(chalk13.cyan("\n\u{1F4CB} Setup Steps:\n"));
2099
4871
  if (blueprint.setup.steps) {
2100
4872
  for (let i = 0; i < blueprint.setup.steps.length; i++) {
2101
4873
  const step = blueprint.setup.steps[i];
2102
- console.log(chalk11.white(` ${i + 1}. ${step.description}`));
4874
+ console.log(chalk13.white(` ${i + 1}. ${step.description}`));
2103
4875
  if (step.command) {
2104
- console.log(chalk11.dim(` Command: ${step.command}`));
4876
+ console.log(chalk13.dim(` Command: ${step.command}`));
2105
4877
  }
2106
4878
  }
2107
4879
  }
2108
4880
  }
2109
4881
  if (!options.dryRun) {
2110
- const confirmed = await p7.confirm({
4882
+ const confirmed = await p9.confirm({
2111
4883
  message: "Mark this pattern as successfully applied?",
2112
4884
  initialValue: true
2113
4885
  });
2114
- if (p7.isCancel(confirmed)) {
2115
- p7.cancel("Application cancelled");
4886
+ if (p9.isCancel(confirmed)) {
4887
+ p9.cancel("Application cancelled");
2116
4888
  process.exit(0);
2117
4889
  }
2118
4890
  if (confirmed) {
2119
4891
  await store.updatePatternMetrics(patternId, patternType, true);
2120
4892
  await telemetry.recordSuccess(patternId, patternType, framework, version);
2121
- console.log(chalk11.green("\n\u2705 Pattern marked as successfully applied!"));
4893
+ console.log(chalk13.green("\n\u2705 Pattern marked as successfully applied!"));
2122
4894
  } else {
2123
4895
  await store.updatePatternMetrics(patternId, patternType, false);
2124
- await telemetry.recordFailure(patternId, patternType, framework, version, "unknown");
2125
- console.log(chalk11.yellow("\n\u26A0\uFE0F Pattern application marked as unsuccessful."));
4896
+ await telemetry.recordFailure(
4897
+ patternId,
4898
+ patternType,
4899
+ framework,
4900
+ version,
4901
+ "unknown"
4902
+ );
4903
+ console.log(
4904
+ chalk13.yellow("\n\u26A0\uFE0F Pattern application marked as unsuccessful.")
4905
+ );
2126
4906
  }
2127
4907
  }
2128
4908
  }
2129
4909
  async function learnSyncCommand(options) {
2130
4910
  const cwd = getWorkspacePath();
2131
4911
  const contributorManager = new ContributorManager2(cwd);
2132
- console.log(chalk11.cyan("\n\u{1F504} Sync Learning Patterns\n"));
4912
+ console.log(chalk13.cyan("\n\u{1F504} Sync Learning Patterns\n"));
2133
4913
  const config = await contributorManager.getConfig();
2134
4914
  if (!config.success || !config.data?.syncOptIn) {
2135
- console.log(chalk11.yellow("\u26A0\uFE0F Sync is not enabled.\n"));
2136
- console.log(chalk11.dim(" To enable sync, run:"));
2137
- console.log(chalk11.dim(" workflow learn:config --enable-sync\n"));
2138
- console.log(chalk11.dim(" This allows you to share anonymized patterns with the community."));
4915
+ console.log(chalk13.yellow("\u26A0\uFE0F Sync is not enabled.\n"));
4916
+ console.log(chalk13.dim(" To enable sync, run:"));
4917
+ console.log(chalk13.dim(" workflow learn:config --enable-sync\n"));
4918
+ console.log(
4919
+ chalk13.dim(
4920
+ " This allows you to share anonymized patterns with the community."
4921
+ )
4922
+ );
2139
4923
  process.exit(0);
2140
4924
  }
2141
4925
  if (options.dryRun) {
2142
- console.log(chalk11.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be synced\n"));
4926
+ console.log(chalk13.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be synced\n"));
2143
4927
  }
2144
4928
  const store = new PatternStore2(cwd);
2145
4929
  const anonymizer = new PatternAnonymizer();
2146
4930
  const { fixes, blueprints } = await store.getPatternsForSync();
2147
- console.log(chalk11.dim(` Patterns ready to sync: ${fixes.length} fixes, ${blueprints.length} blueprints`));
4931
+ console.log(
4932
+ chalk13.dim(
4933
+ ` Patterns ready to sync: ${fixes.length} fixes, ${blueprints.length} blueprints`
4934
+ )
4935
+ );
2148
4936
  if (options.push) {
2149
- console.log(chalk11.cyan("\n\u{1F4E4} Pushing patterns...\n"));
4937
+ console.log(chalk13.cyan("\n\u{1F4E4} Pushing patterns...\n"));
2150
4938
  let anonymizedFixes = 0;
2151
4939
  let anonymizedBlueprints = 0;
2152
4940
  for (const fix of fixes) {
@@ -2154,7 +4942,7 @@ async function learnSyncCommand(options) {
2154
4942
  if (result.success) {
2155
4943
  anonymizedFixes++;
2156
4944
  if (!options.dryRun) {
2157
- console.log(chalk11.dim(` \u2713 Anonymized: ${fix.name}`));
4945
+ console.log(chalk13.dim(` \u2713 Anonymized: ${fix.name}`));
2158
4946
  }
2159
4947
  }
2160
4948
  }
@@ -2163,102 +4951,126 @@ async function learnSyncCommand(options) {
2163
4951
  if (result.success) {
2164
4952
  anonymizedBlueprints++;
2165
4953
  if (!options.dryRun) {
2166
- console.log(chalk11.dim(` \u2713 Anonymized: ${bp.name}`));
4954
+ console.log(chalk13.dim(` \u2713 Anonymized: ${bp.name}`));
2167
4955
  }
2168
4956
  }
2169
4957
  }
2170
4958
  console.log(
2171
- chalk11.green(`
2172
- \u2705 Ready to push ${anonymizedFixes} fixes and ${anonymizedBlueprints} blueprints`)
4959
+ chalk13.green(
4960
+ `
4961
+ \u2705 Ready to push ${anonymizedFixes} fixes and ${anonymizedBlueprints} blueprints`
4962
+ )
2173
4963
  );
2174
- console.log(chalk11.dim(" (Registry push not yet implemented)"));
4964
+ console.log(chalk13.dim(" (Registry push not yet implemented)"));
2175
4965
  }
2176
4966
  if (options.pull) {
2177
- console.log(chalk11.cyan("\n\u{1F4E5} Pulling patterns from registry...\n"));
2178
- console.log(chalk11.dim(" (Registry pull not yet implemented)"));
4967
+ console.log(chalk13.cyan("\n\u{1F4E5} Pulling patterns from registry...\n"));
4968
+ console.log(chalk13.dim(" (Registry pull not yet implemented)"));
2179
4969
  }
2180
4970
  if (!options.push && !options.pull) {
2181
- console.log(chalk11.dim(" Specify --push to upload or --pull to download patterns.\n"));
4971
+ console.log(
4972
+ chalk13.dim(" Specify --push to upload or --pull to download patterns.\n")
4973
+ );
2182
4974
  }
2183
4975
  }
2184
4976
  async function learnConfigCommand(options) {
2185
4977
  const cwd = getWorkspacePath();
2186
4978
  const contributorManager = new ContributorManager2(cwd);
2187
- console.log(chalk11.cyan("\n\u2699\uFE0F Learning Configuration\n"));
4979
+ console.log(chalk13.cyan("\n\u2699\uFE0F Learning Configuration\n"));
2188
4980
  if (options.enableSync) {
2189
4981
  const result = await contributorManager.enableSync();
2190
4982
  if (result.success) {
2191
- console.log(chalk11.green("\u2705 Sync enabled"));
2192
- console.log(chalk11.dim(" Your patterns will be anonymized before sharing."));
4983
+ console.log(chalk13.green("\u2705 Sync enabled"));
4984
+ console.log(
4985
+ chalk13.dim(" Your patterns will be anonymized before sharing.")
4986
+ );
2193
4987
  } else {
2194
- console.log(chalk11.red(`\u274C Failed: ${result.error}`));
4988
+ console.log(chalk13.red(`\u274C Failed: ${result.error}`));
2195
4989
  }
2196
4990
  return;
2197
4991
  }
2198
4992
  if (options.disableSync) {
2199
4993
  const result = await contributorManager.disableSync();
2200
4994
  if (result.success) {
2201
- console.log(chalk11.green("\u2705 Sync disabled"));
4995
+ console.log(chalk13.green("\u2705 Sync disabled"));
2202
4996
  } else {
2203
- console.log(chalk11.red(`\u274C Failed: ${result.error}`));
4997
+ console.log(chalk13.red(`\u274C Failed: ${result.error}`));
2204
4998
  }
2205
4999
  return;
2206
5000
  }
2207
5001
  if (options.enableTelemetry) {
2208
5002
  const result = await contributorManager.enableTelemetry();
2209
5003
  if (result.success) {
2210
- console.log(chalk11.green("\u2705 Telemetry enabled"));
2211
- console.log(chalk11.dim(" Anonymous usage data helps improve pattern recommendations."));
5004
+ console.log(chalk13.green("\u2705 Telemetry enabled"));
5005
+ console.log(
5006
+ chalk13.dim(
5007
+ " Anonymous usage data helps improve pattern recommendations."
5008
+ )
5009
+ );
2212
5010
  } else {
2213
- console.log(chalk11.red(`\u274C Failed: ${result.error}`));
5011
+ console.log(chalk13.red(`\u274C Failed: ${result.error}`));
2214
5012
  }
2215
5013
  return;
2216
5014
  }
2217
5015
  if (options.disableTelemetry) {
2218
5016
  const result = await contributorManager.disableTelemetry();
2219
5017
  if (result.success) {
2220
- console.log(chalk11.green("\u2705 Telemetry disabled"));
5018
+ console.log(chalk13.green("\u2705 Telemetry disabled"));
2221
5019
  } else {
2222
- console.log(chalk11.red(`\u274C Failed: ${result.error}`));
5020
+ console.log(chalk13.red(`\u274C Failed: ${result.error}`));
2223
5021
  }
2224
5022
  return;
2225
5023
  }
2226
5024
  if (options.resetId) {
2227
- const confirmed = await p7.confirm({
5025
+ const confirmed = await p9.confirm({
2228
5026
  message: "Are you sure you want to reset your contributor ID? This cannot be undone.",
2229
5027
  initialValue: false
2230
5028
  });
2231
- if (p7.isCancel(confirmed) || !confirmed) {
2232
- p7.cancel("Reset cancelled");
5029
+ if (p9.isCancel(confirmed) || !confirmed) {
5030
+ p9.cancel("Reset cancelled");
2233
5031
  return;
2234
5032
  }
2235
5033
  const result = await contributorManager.resetId();
2236
5034
  if (result.success) {
2237
- console.log(chalk11.green("\u2705 Contributor ID reset"));
2238
- console.log(chalk11.dim(` New ID: ${result.data?.id}`));
5035
+ console.log(chalk13.green("\u2705 Contributor ID reset"));
5036
+ console.log(chalk13.dim(` New ID: ${result.data?.id}`));
2239
5037
  } else {
2240
- console.log(chalk11.red(`\u274C Failed: ${result.error}`));
5038
+ console.log(chalk13.red(`\u274C Failed: ${result.error}`));
2241
5039
  }
2242
5040
  return;
2243
5041
  }
2244
5042
  const config = await contributorManager.getConfig();
2245
5043
  if (config.success && config.data) {
2246
- console.log(chalk11.white(" Current Settings:\n"));
2247
- console.log(chalk11.dim(` Contributor ID: ${config.data.id}`));
2248
- console.log(chalk11.dim(` Created: ${formatDate(config.data.createdAt)}`));
2249
- console.log(chalk11.dim(` Sync Enabled: ${config.data.syncOptIn ? "Yes" : "No"}`));
2250
- console.log(chalk11.dim(` Telemetry Enabled: ${config.data.telemetryEnabled ? "Yes" : "No"}`));
5044
+ console.log(chalk13.white(" Current Settings:\n"));
5045
+ console.log(chalk13.dim(` Contributor ID: ${config.data.id}`));
5046
+ console.log(chalk13.dim(` Created: ${formatDate(config.data.createdAt)}`));
5047
+ console.log(
5048
+ chalk13.dim(` Sync Enabled: ${config.data.syncOptIn ? "Yes" : "No"}`)
5049
+ );
5050
+ console.log(
5051
+ chalk13.dim(
5052
+ ` Telemetry Enabled: ${config.data.telemetryEnabled ? "Yes" : "No"}`
5053
+ )
5054
+ );
2251
5055
  if (config.data.syncEnabledAt) {
2252
- console.log(chalk11.dim(` Sync Enabled At: ${formatDate(config.data.syncEnabledAt)}`));
5056
+ console.log(
5057
+ chalk13.dim(
5058
+ ` Sync Enabled At: ${formatDate(config.data.syncEnabledAt)}`
5059
+ )
5060
+ );
2253
5061
  }
2254
5062
  } else {
2255
- console.log(chalk11.dim(" No configuration found. Settings will be created on first use.\n"));
5063
+ console.log(
5064
+ chalk13.dim(
5065
+ " No configuration found. Settings will be created on first use.\n"
5066
+ )
5067
+ );
2256
5068
  }
2257
5069
  }
2258
5070
  async function learnDeprecateCommand(patternId, reason) {
2259
5071
  const cwd = getWorkspacePath();
2260
5072
  const store = new PatternStore2(cwd);
2261
- console.log(chalk11.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
5073
+ console.log(chalk13.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
2262
5074
  let patternType = "fix";
2263
5075
  let pattern = await store.getFixPattern(patternId);
2264
5076
  if (!pattern.success || !pattern.data) {
@@ -2267,26 +5079,26 @@ async function learnDeprecateCommand(patternId, reason) {
2267
5079
  pattern = bpResult;
2268
5080
  patternType = "blueprint";
2269
5081
  } else {
2270
- console.log(chalk11.red(`
5082
+ console.log(chalk13.red(`
2271
5083
  \u274C Pattern not found: ${patternId}`));
2272
5084
  process.exit(1);
2273
5085
  }
2274
5086
  }
2275
- console.log(chalk11.white(` Pattern: ${pattern.data.name}`));
2276
- console.log(chalk11.dim(` Reason: ${reason}`));
2277
- const confirmed = await p7.confirm({
5087
+ console.log(chalk13.white(` Pattern: ${pattern.data.name}`));
5088
+ console.log(chalk13.dim(` Reason: ${reason}`));
5089
+ const confirmed = await p9.confirm({
2278
5090
  message: "Are you sure you want to deprecate this pattern?",
2279
5091
  initialValue: false
2280
5092
  });
2281
- if (p7.isCancel(confirmed) || !confirmed) {
2282
- p7.cancel("Deprecation cancelled");
5093
+ if (p9.isCancel(confirmed) || !confirmed) {
5094
+ p9.cancel("Deprecation cancelled");
2283
5095
  return;
2284
5096
  }
2285
5097
  const result = await store.deprecatePattern(patternId, patternType, reason);
2286
5098
  if (result.success) {
2287
- console.log(chalk11.green("\n\u2705 Pattern deprecated successfully"));
5099
+ console.log(chalk13.green("\n\u2705 Pattern deprecated successfully"));
2288
5100
  } else {
2289
- console.log(chalk11.red(`
5101
+ console.log(chalk13.red(`
2290
5102
  \u274C Failed: ${result.error}`));
2291
5103
  process.exit(1);
2292
5104
  }
@@ -2295,28 +5107,32 @@ async function learnStatsCommand() {
2295
5107
  const cwd = getWorkspacePath();
2296
5108
  const store = new PatternStore2(cwd);
2297
5109
  const telemetry = new TelemetryCollector2(cwd);
2298
- console.log(chalk11.cyan("\n\u{1F4CA} Learning Statistics\n"));
5110
+ console.log(chalk13.cyan("\n\u{1F4CA} Learning Statistics\n"));
2299
5111
  const storeStats = await store.getStats();
2300
5112
  const totalPatterns = storeStats.totalFixes + storeStats.totalBlueprints;
2301
5113
  const totalDeprecated = storeStats.deprecatedFixes + storeStats.deprecatedBlueprints;
2302
- console.log(chalk11.bold.white(" Patterns:\n"));
2303
- console.log(chalk11.dim(` Total: ${totalPatterns}`));
2304
- console.log(chalk11.dim(` Fix Patterns: ${storeStats.totalFixes}`));
2305
- console.log(chalk11.dim(` Blueprints: ${storeStats.totalBlueprints}`));
2306
- console.log(chalk11.dim(` Deprecated: ${totalDeprecated}`));
5114
+ console.log(chalk13.bold.white(" Patterns:\n"));
5115
+ console.log(chalk13.dim(` Total: ${totalPatterns}`));
5116
+ console.log(chalk13.dim(` Fix Patterns: ${storeStats.totalFixes}`));
5117
+ console.log(chalk13.dim(` Blueprints: ${storeStats.totalBlueprints}`));
5118
+ console.log(chalk13.dim(` Deprecated: ${totalDeprecated}`));
2307
5119
  const telemetryStats = await telemetry.getStats();
2308
- console.log(chalk11.bold.white("\n Telemetry:\n"));
2309
- console.log(chalk11.dim(` Pending Events: ${telemetryStats.pendingEvents}`));
2310
- console.log(chalk11.dim(` Total Events Sent: ${telemetryStats.totalEventsSent}`));
5120
+ console.log(chalk13.bold.white("\n Telemetry:\n"));
5121
+ console.log(chalk13.dim(` Pending Events: ${telemetryStats.pendingEvents}`));
5122
+ console.log(
5123
+ chalk13.dim(` Total Events Sent: ${telemetryStats.totalEventsSent}`)
5124
+ );
2311
5125
  if (telemetryStats.lastFlushAt) {
2312
- console.log(chalk11.dim(` Last Flush: ${formatDate(telemetryStats.lastFlushAt)}`));
5126
+ console.log(
5127
+ chalk13.dim(` Last Flush: ${formatDate(telemetryStats.lastFlushAt)}`)
5128
+ );
2313
5129
  }
2314
5130
  console.log("");
2315
5131
  }
2316
5132
 
2317
5133
  // src/cli/commands/solution.ts
2318
- import chalk12 from "chalk";
2319
- import * as p8 from "@clack/prompts";
5134
+ import chalk14 from "chalk";
5135
+ import * as p10 from "@clack/prompts";
2320
5136
  import * as path2 from "path";
2321
5137
  import {
2322
5138
  PatternStore as PatternStore3,
@@ -2358,10 +5174,10 @@ function truncate(str, maxLen) {
2358
5174
  async function solutionCaptureCommand(options) {
2359
5175
  const cwd = getWorkspacePath2();
2360
5176
  const store = new PatternStore3(cwd);
2361
- console.log(chalk12.cyan("\n\u{1F4E6} Capture Solution Pattern\n"));
5177
+ console.log(chalk14.cyan("\n\u{1F4E6} Capture Solution Pattern\n"));
2362
5178
  let targetPath = options.path;
2363
5179
  if (!targetPath) {
2364
- const pathInput = await p8.text({
5180
+ const pathInput = await p10.text({
2365
5181
  message: "Path to the solution directory:",
2366
5182
  placeholder: "./src/auth",
2367
5183
  validate: (val) => {
@@ -2369,8 +5185,8 @@ async function solutionCaptureCommand(options) {
2369
5185
  return void 0;
2370
5186
  }
2371
5187
  });
2372
- if (p8.isCancel(pathInput)) {
2373
- p8.cancel("Operation cancelled");
5188
+ if (p10.isCancel(pathInput)) {
5189
+ p10.cancel("Operation cancelled");
2374
5190
  process.exit(0);
2375
5191
  }
2376
5192
  targetPath = pathInput;
@@ -2378,7 +5194,7 @@ async function solutionCaptureCommand(options) {
2378
5194
  const absolutePath = path2.isAbsolute(targetPath) ? targetPath : path2.resolve(cwd, targetPath);
2379
5195
  let name = options.name;
2380
5196
  if (!name) {
2381
- const nameInput = await p8.text({
5197
+ const nameInput = await p10.text({
2382
5198
  message: "Solution name:",
2383
5199
  placeholder: "JWT Authentication",
2384
5200
  validate: (val) => {
@@ -2386,15 +5202,15 @@ async function solutionCaptureCommand(options) {
2386
5202
  return void 0;
2387
5203
  }
2388
5204
  });
2389
- if (p8.isCancel(nameInput)) {
2390
- p8.cancel("Operation cancelled");
5205
+ if (p10.isCancel(nameInput)) {
5206
+ p10.cancel("Operation cancelled");
2391
5207
  process.exit(0);
2392
5208
  }
2393
5209
  name = nameInput;
2394
5210
  }
2395
5211
  let description = options.description;
2396
5212
  if (!description) {
2397
- const descInput = await p8.text({
5213
+ const descInput = await p10.text({
2398
5214
  message: "Solution description:",
2399
5215
  placeholder: "Complete JWT-based authentication with refresh tokens",
2400
5216
  validate: (val) => {
@@ -2403,15 +5219,15 @@ async function solutionCaptureCommand(options) {
2403
5219
  return void 0;
2404
5220
  }
2405
5221
  });
2406
- if (p8.isCancel(descInput)) {
2407
- p8.cancel("Operation cancelled");
5222
+ if (p10.isCancel(descInput)) {
5223
+ p10.cancel("Operation cancelled");
2408
5224
  process.exit(0);
2409
5225
  }
2410
5226
  description = descInput;
2411
5227
  }
2412
5228
  let category = options.category;
2413
5229
  if (!category) {
2414
- const categoryChoice = await p8.select({
5230
+ const categoryChoice = await p10.select({
2415
5231
  message: "Solution category:",
2416
5232
  options: [
2417
5233
  { value: "auth", label: "\u{1F510} Authentication" },
@@ -2430,8 +5246,8 @@ async function solutionCaptureCommand(options) {
2430
5246
  { value: "other", label: "\u{1F4E6} Other" }
2431
5247
  ]
2432
5248
  });
2433
- if (p8.isCancel(categoryChoice)) {
2434
- p8.cancel("Operation cancelled");
5249
+ if (p10.isCancel(categoryChoice)) {
5250
+ p10.cancel("Operation cancelled");
2435
5251
  process.exit(0);
2436
5252
  }
2437
5253
  category = categoryChoice;
@@ -2440,20 +5256,20 @@ async function solutionCaptureCommand(options) {
2440
5256
  if (options.keywords) {
2441
5257
  keywords = options.keywords.split(",").map((k) => k.trim());
2442
5258
  } else {
2443
- const keywordsInput = await p8.text({
5259
+ const keywordsInput = await p10.text({
2444
5260
  message: "Keywords (comma-separated):",
2445
5261
  placeholder: "jwt, authentication, login, refresh-token"
2446
5262
  });
2447
- if (p8.isCancel(keywordsInput)) {
2448
- p8.cancel("Operation cancelled");
5263
+ if (p10.isCancel(keywordsInput)) {
5264
+ p10.cancel("Operation cancelled");
2449
5265
  process.exit(0);
2450
5266
  }
2451
5267
  if (keywordsInput) {
2452
5268
  keywords = keywordsInput.split(",").map((k) => k.trim());
2453
5269
  }
2454
5270
  }
2455
- const spinner6 = p8.spinner();
2456
- spinner6.start("Analyzing solution...");
5271
+ const spinner8 = p10.spinner();
5272
+ spinner8.start("Analyzing solution...");
2457
5273
  const analyzer = new CodeAnalyzer({
2458
5274
  anonymize: options.anonymize ?? false
2459
5275
  });
@@ -2465,34 +5281,38 @@ async function solutionCaptureCommand(options) {
2465
5281
  category,
2466
5282
  keywords
2467
5283
  );
2468
- spinner6.stop("Solution analyzed");
2469
- console.log(chalk12.green("\n\u2713 Solution captured successfully!\n"));
2470
- console.log(chalk12.dim("\u2500".repeat(50)));
2471
- console.log(`${chalk12.bold("Name:")} ${pattern.name}`);
2472
- console.log(`${chalk12.bold("Category:")} ${formatCategory(pattern.category)}`);
2473
- console.log(`${chalk12.bold("Files:")} ${pattern.implementation.files.length}`);
5284
+ spinner8.stop("Solution analyzed");
5285
+ console.log(chalk14.green("\n\u2713 Solution captured successfully!\n"));
5286
+ console.log(chalk14.dim("\u2500".repeat(50)));
5287
+ console.log(`${chalk14.bold("Name:")} ${pattern.name}`);
5288
+ console.log(
5289
+ `${chalk14.bold("Category:")} ${formatCategory(pattern.category)}`
5290
+ );
2474
5291
  console.log(
2475
- `${chalk12.bold("Dependencies:")} ${pattern.implementation.dependencies.length}`
5292
+ `${chalk14.bold("Files:")} ${pattern.implementation.files.length}`
2476
5293
  );
2477
5294
  console.log(
2478
- `${chalk12.bold("Framework:")} ${pattern.compatibility.framework || "generic"}`
5295
+ `${chalk14.bold("Dependencies:")} ${pattern.implementation.dependencies.length}`
2479
5296
  );
2480
- console.log(chalk12.dim("\u2500".repeat(50)));
2481
- const confirm8 = await p8.confirm({
5297
+ console.log(
5298
+ `${chalk14.bold("Framework:")} ${pattern.compatibility.framework || "generic"}`
5299
+ );
5300
+ console.log(chalk14.dim("\u2500".repeat(50)));
5301
+ const confirm9 = await p10.confirm({
2482
5302
  message: "Save this solution pattern?",
2483
5303
  initialValue: true
2484
5304
  });
2485
- if (p8.isCancel(confirm8) || !confirm8) {
2486
- p8.cancel("Solution not saved");
5305
+ if (p10.isCancel(confirm9) || !confirm9) {
5306
+ p10.cancel("Solution not saved");
2487
5307
  process.exit(0);
2488
5308
  }
2489
5309
  await store.saveSolution(pattern);
2490
- console.log(chalk12.green(`
5310
+ console.log(chalk14.green(`
2491
5311
  \u2713 Solution saved with ID: ${pattern.id}
2492
5312
  `));
2493
5313
  } catch (error) {
2494
- spinner6.stop("Analysis failed");
2495
- console.error(chalk12.red(`
5314
+ spinner8.stop("Analysis failed");
5315
+ console.error(chalk14.red(`
2496
5316
  \u2717 Error: ${error.message}
2497
5317
  `));
2498
5318
  process.exit(1);
@@ -2501,7 +5321,7 @@ async function solutionCaptureCommand(options) {
2501
5321
  async function solutionSearchCommand(query, options) {
2502
5322
  const cwd = getWorkspacePath2();
2503
5323
  const store = new PatternStore3(cwd);
2504
- console.log(chalk12.cyan("\n\u{1F50D} Search Solution Patterns\n"));
5324
+ console.log(chalk14.cyan("\n\u{1F50D} Search Solution Patterns\n"));
2505
5325
  const keywords = query.split(/\s+/).filter((k) => k.length > 0);
2506
5326
  const result = await store.searchSolutions(keywords, {
2507
5327
  category: options.category,
@@ -2509,37 +5329,39 @@ async function solutionSearchCommand(query, options) {
2509
5329
  limit: options.limit ?? 10
2510
5330
  });
2511
5331
  if (!result.success || !result.data) {
2512
- console.error(chalk12.red(`
5332
+ console.error(chalk14.red(`
2513
5333
  \u2717 Search failed: ${result.error}
2514
5334
  `));
2515
5335
  return;
2516
5336
  }
2517
5337
  const solutions = result.data;
2518
5338
  if (solutions.length === 0) {
2519
- console.log(chalk12.yellow("No solutions found matching your query.\n"));
2520
- console.log(chalk12.dim("Try different keywords or fewer filters."));
5339
+ console.log(chalk14.yellow("No solutions found matching your query.\n"));
5340
+ console.log(chalk14.dim("Try different keywords or fewer filters."));
2521
5341
  return;
2522
5342
  }
2523
- console.log(chalk12.green(`Found ${solutions.length} solution(s):
5343
+ console.log(chalk14.green(`Found ${solutions.length} solution(s):
2524
5344
  `));
2525
- console.log(chalk12.dim("\u2500".repeat(70)));
5345
+ console.log(chalk14.dim("\u2500".repeat(70)));
2526
5346
  for (const solution of solutions) {
2527
5347
  console.log(
2528
- `${chalk12.bold(solution.name)} ${chalk12.dim(`(${solution.id.slice(0, 8)})`)}`
5348
+ `${chalk14.bold(solution.name)} ${chalk14.dim(`(${solution.id.slice(0, 8)})`)}`
2529
5349
  );
2530
5350
  console.log(` ${formatCategory(solution.category)}`);
2531
- console.log(` ${chalk12.dim(truncate(solution.description, 60))}`);
5351
+ console.log(` ${chalk14.dim(truncate(solution.description, 60))}`);
2532
5352
  console.log(
2533
5353
  ` Files: ${solution.implementation.files.length} | Framework: ${solution.compatibility.framework || "generic"} | Uses: ${solution.metrics.applications}`
2534
5354
  );
2535
- console.log(chalk12.dim("\u2500".repeat(70)));
5355
+ console.log(chalk14.dim("\u2500".repeat(70)));
2536
5356
  }
2537
- console.log(chalk12.dim("\nUse 'workflow solution:apply <id>' to apply a solution."));
5357
+ console.log(
5358
+ chalk14.dim("\nUse 'workflow solution:apply <id>' to apply a solution.")
5359
+ );
2538
5360
  }
2539
5361
  async function solutionListCommand(options) {
2540
5362
  const cwd = getWorkspacePath2();
2541
5363
  const store = new PatternStore3(cwd);
2542
- console.log(chalk12.cyan("\n\u{1F4CB} Solution Patterns\n"));
5364
+ console.log(chalk14.cyan("\n\u{1F4CB} Solution Patterns\n"));
2543
5365
  const result = await store.listSolutions({
2544
5366
  category: options.category,
2545
5367
  framework: options.framework,
@@ -2547,18 +5369,20 @@ async function solutionListCommand(options) {
2547
5369
  limit: options.limit ?? 20
2548
5370
  });
2549
5371
  if (!result.success || !result.data) {
2550
- console.error(chalk12.red(`
5372
+ console.error(chalk14.red(`
2551
5373
  \u2717 List failed: ${result.error}
2552
5374
  `));
2553
5375
  return;
2554
5376
  }
2555
5377
  const solutions = result.data;
2556
5378
  if (solutions.length === 0) {
2557
- console.log(chalk12.yellow("No solutions found.\n"));
2558
- console.log(chalk12.dim("Use 'workflow solution:capture' to capture a solution."));
5379
+ console.log(chalk14.yellow("No solutions found.\n"));
5380
+ console.log(
5381
+ chalk14.dim("Use 'workflow solution:capture' to capture a solution.")
5382
+ );
2559
5383
  return;
2560
5384
  }
2561
- console.log(chalk12.green(`${solutions.length} solution(s):
5385
+ console.log(chalk14.green(`${solutions.length} solution(s):
2562
5386
  `));
2563
5387
  const byCategory = /* @__PURE__ */ new Map();
2564
5388
  for (const solution of solutions) {
@@ -2567,33 +5391,35 @@ async function solutionListCommand(options) {
2567
5391
  byCategory.set(solution.category, list);
2568
5392
  }
2569
5393
  for (const [category, items] of byCategory) {
2570
- console.log(chalk12.bold(`
5394
+ console.log(chalk14.bold(`
2571
5395
  ${formatCategory(category)}`));
2572
- console.log(chalk12.dim("\u2500".repeat(50)));
5396
+ console.log(chalk14.dim("\u2500".repeat(50)));
2573
5397
  for (const solution of items) {
2574
- const deprecated = solution.deprecatedAt ? chalk12.red(" [DEPRECATED]") : "";
5398
+ const deprecated = solution.deprecatedAt ? chalk14.red(" [DEPRECATED]") : "";
2575
5399
  console.log(
2576
- ` ${chalk12.cyan(solution.id.slice(0, 8))} ${solution.name}${deprecated}`
5400
+ ` ${chalk14.cyan(solution.id.slice(0, 8))} ${solution.name}${deprecated}`
2577
5401
  );
2578
- console.log(` ${chalk12.dim(truncate(solution.description, 50))}`);
5402
+ console.log(` ${chalk14.dim(truncate(solution.description, 50))}`);
2579
5403
  console.log(
2580
- chalk12.dim(
5404
+ chalk14.dim(
2581
5405
  ` Created: ${formatDate2(solution.createdAt)} | Files: ${solution.implementation.files.length}`
2582
5406
  )
2583
5407
  );
2584
5408
  }
2585
5409
  }
2586
5410
  console.log(
2587
- chalk12.dim("\nUse 'workflow solution:search <query>' to find specific solutions.")
5411
+ chalk14.dim(
5412
+ "\nUse 'workflow solution:search <query>' to find specific solutions."
5413
+ )
2588
5414
  );
2589
5415
  }
2590
5416
  async function solutionApplyCommand(solutionId, options) {
2591
5417
  const cwd = getWorkspacePath2();
2592
5418
  const store = new PatternStore3(cwd);
2593
- console.log(chalk12.cyan("\n\u{1F680} Apply Solution Pattern\n"));
5419
+ console.log(chalk14.cyan("\n\u{1F680} Apply Solution Pattern\n"));
2594
5420
  const result = await store.getSolution(solutionId);
2595
5421
  if (!result.success || !result.data) {
2596
- console.error(chalk12.red(`
5422
+ console.error(chalk14.red(`
2597
5423
  \u2717 Solution not found: ${solutionId}
2598
5424
  `));
2599
5425
  process.exit(1);
@@ -2601,58 +5427,60 @@ async function solutionApplyCommand(solutionId, options) {
2601
5427
  const solution = result.data;
2602
5428
  if (solution.deprecatedAt) {
2603
5429
  console.log(
2604
- chalk12.yellow(
5430
+ chalk14.yellow(
2605
5431
  `\u26A0\uFE0F This solution is deprecated: ${solution.deprecationReason || "No reason provided"}
2606
5432
  `
2607
5433
  )
2608
5434
  );
2609
- const proceed = await p8.confirm({
5435
+ const proceed = await p10.confirm({
2610
5436
  message: "Do you want to continue?",
2611
5437
  initialValue: false
2612
5438
  });
2613
- if (p8.isCancel(proceed) || !proceed) {
2614
- p8.cancel("Operation cancelled");
5439
+ if (p10.isCancel(proceed) || !proceed) {
5440
+ p10.cancel("Operation cancelled");
2615
5441
  process.exit(0);
2616
5442
  }
2617
5443
  }
2618
- console.log(chalk12.bold(`Solution: ${solution.name}`));
2619
- console.log(chalk12.dim(solution.description));
5444
+ console.log(chalk14.bold(`Solution: ${solution.name}`));
5445
+ console.log(chalk14.dim(solution.description));
2620
5446
  console.log();
2621
- console.log(chalk12.bold("Files to create:"));
2622
- const filesToApply = options.includeTests ? solution.implementation.files : solution.implementation.files.filter((f) => f.role !== "test");
5447
+ console.log(chalk14.bold("Files to create:"));
5448
+ const filesToApply = options.includeTests ? solution.implementation.files : solution.implementation.files.filter(
5449
+ (f) => f.role !== "test"
5450
+ );
2623
5451
  for (const file of filesToApply) {
2624
- console.log(chalk12.dim(` \u2022 ${file.path} (${file.role})`));
5452
+ console.log(chalk14.dim(` \u2022 ${file.path} (${file.role})`));
2625
5453
  }
2626
5454
  console.log();
2627
5455
  if (solution.implementation.dependencies.length > 0) {
2628
- console.log(chalk12.bold("Dependencies to install:"));
5456
+ console.log(chalk14.bold("Dependencies to install:"));
2629
5457
  for (const dep of solution.implementation.dependencies) {
2630
- console.log(chalk12.dim(` \u2022 ${dep.name}@${dep.version}`));
5458
+ console.log(chalk14.dim(` \u2022 ${dep.name}@${dep.version}`));
2631
5459
  }
2632
5460
  console.log();
2633
5461
  }
2634
5462
  if (solution.implementation.envVars.length > 0) {
2635
- console.log(chalk12.bold("Environment variables needed:"));
5463
+ console.log(chalk14.bold("Environment variables needed:"));
2636
5464
  for (const env of solution.implementation.envVars) {
2637
- const required = env.required ? chalk12.red("*") : "";
2638
- console.log(chalk12.dim(` \u2022 ${env.name}${required}`));
5465
+ const required = env.required ? chalk14.red("*") : "";
5466
+ console.log(chalk14.dim(` \u2022 ${env.name}${required}`));
2639
5467
  }
2640
5468
  console.log();
2641
5469
  }
2642
5470
  if (options.dryRun) {
2643
- console.log(chalk12.yellow("Dry run mode - no files were created.\n"));
5471
+ console.log(chalk14.yellow("Dry run mode - no files were created.\n"));
2644
5472
  return;
2645
5473
  }
2646
- const confirm8 = await p8.confirm({
5474
+ const confirm9 = await p10.confirm({
2647
5475
  message: "Apply this solution?",
2648
5476
  initialValue: true
2649
5477
  });
2650
- if (p8.isCancel(confirm8) || !confirm8) {
2651
- p8.cancel("Operation cancelled");
5478
+ if (p10.isCancel(confirm9) || !confirm9) {
5479
+ p10.cancel("Operation cancelled");
2652
5480
  process.exit(0);
2653
5481
  }
2654
- const spinner6 = p8.spinner();
2655
- spinner6.start("Applying solution...");
5482
+ const spinner8 = p10.spinner();
5483
+ spinner8.start("Applying solution...");
2656
5484
  try {
2657
5485
  const outputDir = options.output || cwd;
2658
5486
  const fs2 = await import("fs");
@@ -2664,22 +5492,20 @@ async function solutionApplyCommand(solutionId, options) {
2664
5492
  await fs2.promises.writeFile(filePath, file.content);
2665
5493
  }
2666
5494
  await store.updateSolutionMetrics(solution.id, true);
2667
- spinner6.stop("Solution applied");
2668
- console.log(chalk12.green(`
5495
+ spinner8.stop("Solution applied");
5496
+ console.log(chalk14.green(`
2669
5497
  \u2713 Solution applied successfully!
2670
5498
  `));
2671
- console.log(chalk12.dim(`Created ${filesToApply.length} file(s).`));
5499
+ console.log(chalk14.dim(`Created ${filesToApply.length} file(s).`));
2672
5500
  if (solution.implementation.dependencies.length > 0) {
2673
- console.log(
2674
- chalk12.cyan("\nNext step: Install dependencies with:")
2675
- );
5501
+ console.log(chalk14.cyan("\nNext step: Install dependencies with:"));
2676
5502
  const deps = solution.implementation.dependencies.map((d) => `${d.name}@${d.version}`).join(" ");
2677
- console.log(chalk12.dim(` npm install ${deps}`));
5503
+ console.log(chalk14.dim(` npm install ${deps}`));
2678
5504
  }
2679
5505
  } catch (error) {
2680
- spinner6.stop("Application failed");
5506
+ spinner8.stop("Application failed");
2681
5507
  await store.updateSolutionMetrics(solution.id, false);
2682
- console.error(chalk12.red(`
5508
+ console.error(chalk14.red(`
2683
5509
  \u2717 Error: ${error.message}
2684
5510
  `));
2685
5511
  process.exit(1);
@@ -2688,48 +5514,48 @@ async function solutionApplyCommand(solutionId, options) {
2688
5514
  async function solutionDeprecateCommand(solutionId, reason) {
2689
5515
  const cwd = getWorkspacePath2();
2690
5516
  const store = new PatternStore3(cwd);
2691
- console.log(chalk12.cyan("\n\u26A0\uFE0F Deprecate Solution Pattern\n"));
5517
+ console.log(chalk14.cyan("\n\u26A0\uFE0F Deprecate Solution Pattern\n"));
2692
5518
  const result = await store.getSolution(solutionId);
2693
5519
  if (!result.success || !result.data) {
2694
- console.error(chalk12.red(`
5520
+ console.error(chalk14.red(`
2695
5521
  \u2717 Solution not found: ${solutionId}
2696
5522
  `));
2697
5523
  process.exit(1);
2698
5524
  }
2699
5525
  const solution = result.data;
2700
- console.log(`Solution: ${chalk12.bold(solution.name)}`);
5526
+ console.log(`Solution: ${chalk14.bold(solution.name)}`);
2701
5527
  console.log(`Reason: ${reason}
2702
5528
  `);
2703
- const confirm8 = await p8.confirm({
5529
+ const confirm9 = await p10.confirm({
2704
5530
  message: "Deprecate this solution?",
2705
5531
  initialValue: false
2706
5532
  });
2707
- if (p8.isCancel(confirm8) || !confirm8) {
2708
- p8.cancel("Operation cancelled");
5533
+ if (p10.isCancel(confirm9) || !confirm9) {
5534
+ p10.cancel("Operation cancelled");
2709
5535
  process.exit(0);
2710
5536
  }
2711
5537
  await store.deprecateSolution(solutionId, reason);
2712
- console.log(chalk12.green(`
5538
+ console.log(chalk14.green(`
2713
5539
  \u2713 Solution deprecated.
2714
5540
  `));
2715
5541
  }
2716
5542
  async function solutionStatsCommand() {
2717
5543
  const cwd = getWorkspacePath2();
2718
5544
  const store = new PatternStore3(cwd);
2719
- console.log(chalk12.cyan("\n\u{1F4CA} Solution Pattern Statistics\n"));
5545
+ console.log(chalk14.cyan("\n\u{1F4CA} Solution Pattern Statistics\n"));
2720
5546
  const stats = await store.getStats();
2721
- console.log(chalk12.dim("\u2500".repeat(40)));
2722
- console.log(`${chalk12.bold("Solutions:")} ${stats.totalSolutions}`);
5547
+ console.log(chalk14.dim("\u2500".repeat(40)));
5548
+ console.log(`${chalk14.bold("Solutions:")} ${stats.totalSolutions}`);
2723
5549
  console.log(` Active: ${stats.totalSolutions - stats.deprecatedSolutions}`);
2724
5550
  console.log(` Deprecated: ${stats.deprecatedSolutions}`);
2725
5551
  console.log(` Private: ${stats.privateSolutions}`);
2726
5552
  console.log(` Synced: ${stats.syncedSolutions}`);
2727
- console.log(chalk12.dim("\u2500".repeat(40)));
2728
- console.log(`${chalk12.bold("Fixes:")} ${stats.totalFixes}`);
2729
- console.log(`${chalk12.bold("Blueprints:")} ${stats.totalBlueprints}`);
2730
- console.log(chalk12.dim("\u2500".repeat(40)));
5553
+ console.log(chalk14.dim("\u2500".repeat(40)));
5554
+ console.log(`${chalk14.bold("Fixes:")} ${stats.totalFixes}`);
5555
+ console.log(`${chalk14.bold("Blueprints:")} ${stats.totalBlueprints}`);
5556
+ console.log(chalk14.dim("\u2500".repeat(40)));
2731
5557
  console.log(`
2732
- ${chalk12.bold("By Category:")}`);
5558
+ ${chalk14.bold("By Category:")}`);
2733
5559
  const listResult = await store.listSolutions({ limit: 1e3 });
2734
5560
  if (listResult.success && listResult.data) {
2735
5561
  const categories = /* @__PURE__ */ new Map();
@@ -2773,14 +5599,28 @@ program.command("scope:create").description("Create a custom scope package").opt
2773
5599
  program.command("scope:migrate").description("Migrate inline scopes to a custom package").option("--name <name>", "Package name for the preset").option("--output-dir <dir>", "Output directory").option("--keep-config", "Keep inline scopes in config after migration").action(scopeMigrateCommand);
2774
5600
  program.command("verify").description("Run all quality checks with fix-and-revalidate pattern").option("--fix", "Enable auto-fix for lint and format issues").option("--max-retries <n>", "Maximum retry cycles (default: 10)", "10").option("--commit", "Commit changes if all checks pass").option("--dry-run", "Preview fixes without applying them").option("--learn", "Record successful fixes as learning patterns").action(verifyCommand);
2775
5601
  program.command("auto-setup").description("Automatically configure linting, formatting, testing, and CI").option("-y, --yes", "Auto-approve all prompts").option("--audit", "Show audit report without applying changes").action(autoSetupCommand);
2776
- program.command("learn:record").description("Record a new pattern from a successful implementation").option("--name <name>", "Pattern name").option("--description <desc>", "Pattern description").option("--category <cat>", "Category (migration, security, performance, etc.)").option("--framework <fw>", "Framework (next, react, vue, etc.)").option("--version <ver>", "Framework version range").option("--tags <tags>", "Comma-separated tags (category:value)").option("--type <type>", "Pattern type (fix, blueprint)").action(learnRecordCommand);
5602
+ program.command("advisory").description("Generate advisory board analysis and documentation").option(
5603
+ "--depth <level>",
5604
+ "Analysis depth: executive, quick, standard, comprehensive"
5605
+ ).option("--output <path>", "Output directory (default: docs/advisory)").option("--interactive", "Enable interactive mode").option("--dry-run", "Preview analysis without writing files").option(
5606
+ "--format <type>",
5607
+ "Output format: markdown, json (default: markdown)"
5608
+ ).option("--timestamp", "Append timestamp to filenames").option("--include-health", "Include code health metrics from verify/doctor").option("--ci", "CI mode with exit codes on high-risk findings").option("--compare <path>", "Compare with previous report").action(advisoryCommand);
5609
+ program.command("generate-instructions").description("Generate .github/copilot-instructions.md from guidelines").option("--force", "Regenerate without confirmation").action(generateInstructionsCommand);
5610
+ program.command("learn:record").description("Record a new pattern from a successful implementation").option("--name <name>", "Pattern name").option("--description <desc>", "Pattern description").option(
5611
+ "--category <cat>",
5612
+ "Category (migration, security, performance, etc.)"
5613
+ ).option("--framework <fw>", "Framework (next, react, vue, etc.)").option("--version <ver>", "Framework version range").option("--tags <tags>", "Comma-separated tags (category:value)").option("--type <type>", "Pattern type (fix, blueprint)").action(learnRecordCommand);
2777
5614
  program.command("learn:list").description("List recorded learning patterns").option("--type <type>", "Filter by type (fix, blueprint, all)").option("--framework <fw>", "Filter by framework").option("--tag <tag>", "Filter by tag").option("--deprecated", "Include deprecated patterns").action(learnListCommand);
2778
5615
  program.command("learn:apply <patternId>").description("Apply a pattern to the current project").argument("<patternId>", "Pattern ID to apply").option("--framework <fw>", "Override framework").option("--version <ver>", "Override version").option("--dry-run", "Preview without applying").action(learnApplyCommand);
2779
5616
  program.command("learn:sync").description("Sync patterns with remote registry").option("--push", "Push local patterns to registry").option("--pull", "Pull patterns from registry").option("--dry-run", "Preview without syncing").action(learnSyncCommand);
2780
5617
  program.command("learn:config").description("Configure learning settings").option("--enable-sync", "Enable pattern sync").option("--disable-sync", "Disable pattern sync").option("--enable-telemetry", "Enable anonymous telemetry").option("--disable-telemetry", "Disable telemetry").option("--reset-id", "Reset contributor ID").option("--show", "Show current configuration").action(learnConfigCommand);
2781
5618
  program.command("learn:deprecate <patternId> <reason>").description("Deprecate an outdated pattern").argument("<patternId>", "Pattern ID to deprecate").argument("<reason>", "Reason for deprecation").action(learnDeprecateCommand);
2782
5619
  program.command("learn:stats").description("Show learning statistics").action(learnStatsCommand);
2783
- program.command("solution:capture").description("Capture a solution pattern from working code").option("--name <name>", "Solution name").option("--description <desc>", "Solution description").option("--category <cat>", "Category (auth, api, database, ui, testing, deployment, integration, performance, security, other)").option("--keywords <kw>", "Comma-separated keywords").option("--path <path>", "Path to the solution directory").option("--anonymize", "Anonymize sensitive data in code").action(solutionCaptureCommand);
5620
+ program.command("solution:capture").description("Capture a solution pattern from working code").option("--name <name>", "Solution name").option("--description <desc>", "Solution description").option(
5621
+ "--category <cat>",
5622
+ "Category (auth, api, database, ui, testing, deployment, integration, performance, security, other)"
5623
+ ).option("--keywords <kw>", "Comma-separated keywords").option("--path <path>", "Path to the solution directory").option("--anonymize", "Anonymize sensitive data in code").action(solutionCaptureCommand);
2784
5624
  program.command("solution:search <query>").description("Search for solution patterns").argument("<query>", "Search query (keywords, problem description)").option("--category <cat>", "Filter by category").option("--framework <fw>", "Filter by framework").option("--limit <n>", "Maximum results", "10").action(solutionSearchCommand);
2785
5625
  program.command("solution:list").description("List all solution patterns").option("--category <cat>", "Filter by category").option("--framework <fw>", "Filter by framework").option("--deprecated", "Include deprecated solutions").option("--limit <n>", "Maximum results", "20").action(solutionListCommand);
2786
5626
  program.command("solution:apply <solutionId>").description("Apply a solution pattern to the current project").argument("<solutionId>", "Solution ID to apply").option("--output <dir>", "Output directory").option("--dry-run", "Preview without applying").option("--include-tests", "Include test files").action(solutionApplyCommand);