workflow-agent-cli 2.3.0 → 2.4.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
@@ -5,7 +5,7 @@ import {
5
5
  runAllChecks,
6
6
  runAllSetups,
7
7
  stageAllChanges
8
- } from "../chunk-YI3LBZ7I.js";
8
+ } from "../chunk-WXXFUPYO.js";
9
9
  import {
10
10
  validateBranchName,
11
11
  validateCommitMessage,
@@ -1359,12 +1359,18 @@ describe('${presetName} Scope Preset (Migrated)', () => {
1359
1359
  // src/cli/commands/verify.ts
1360
1360
  import chalk9 from "chalk";
1361
1361
  import { execa as execa2 } from "execa";
1362
+ import {
1363
+ PatternStore,
1364
+ TelemetryCollector,
1365
+ ContributorManager
1366
+ } from "@hawkinside_out/workflow-improvement-tracker";
1362
1367
  async function verifyCommand(options) {
1363
1368
  const cwd = process.cwd();
1364
1369
  const maxRetries = options.maxRetries ? parseInt(options.maxRetries, 10) : 10;
1365
1370
  const autoFix = options.fix ?? false;
1366
1371
  const shouldCommit = options.commit ?? false;
1367
1372
  const dryRun = options.dryRun ?? false;
1373
+ const learnFromFixes = options.learn ?? false;
1368
1374
  console.log(chalk9.bold.cyan("\n\u{1F50D} Workflow Agent Quality Verification\n"));
1369
1375
  if (dryRun) {
1370
1376
  console.log(chalk9.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be applied\n"));
@@ -1373,6 +1379,7 @@ async function verifyCommand(options) {
1373
1379
  console.log(chalk9.dim(` Max retries: ${maxRetries}`));
1374
1380
  console.log(chalk9.dim(` Commit on success: ${shouldCommit ? "yes" : "no"}`));
1375
1381
  console.log(chalk9.dim(` Dry-run: ${dryRun ? "yes" : "no"}`));
1382
+ console.log(chalk9.dim(` Learn from fixes: ${learnFromFixes ? "yes" : "no"}`));
1376
1383
  const startTime = Date.now();
1377
1384
  const result = await runAllChecks(cwd, {
1378
1385
  maxRetries,
@@ -1387,6 +1394,9 @@ ${"\u2501".repeat(50)}`);
1387
1394
  console.log(chalk9.dim(` Total time: ${totalTime}s`));
1388
1395
  console.log(chalk9.dim(` Validation cycles: ${result.totalAttempts}`));
1389
1396
  console.log(chalk9.dim(` Fixes applied: ${result.fixesApplied}`));
1397
+ if (learnFromFixes && result.fixesApplied > 0 && !dryRun) {
1398
+ await recordSuccessfulFixes(cwd, result);
1399
+ }
1390
1400
  if (shouldCommit) {
1391
1401
  const hasChanges = await hasUncommittedChanges(cwd);
1392
1402
  if (hasChanges) {
@@ -1441,6 +1451,132 @@ ${"\u2501".repeat(50)}`);
1441
1451
  process.exit(1);
1442
1452
  }
1443
1453
  }
1454
+ async function recordSuccessfulFixes(cwd, result) {
1455
+ try {
1456
+ const contributorManager = new ContributorManager(cwd);
1457
+ const telemetryEnabled = await contributorManager.isTelemetryEnabled();
1458
+ if (!telemetryEnabled) {
1459
+ return;
1460
+ }
1461
+ const store = new PatternStore(cwd);
1462
+ const telemetry = new TelemetryCollector(cwd);
1463
+ let framework = "unknown";
1464
+ let frameworkVersion = "0.0.0";
1465
+ try {
1466
+ const fs2 = await import("fs");
1467
+ const path2 = await import("path");
1468
+ const packageJsonPath = path2.join(cwd, "package.json");
1469
+ const packageJson = JSON.parse(
1470
+ await fs2.promises.readFile(packageJsonPath, "utf-8")
1471
+ );
1472
+ const deps = {
1473
+ ...packageJson.dependencies,
1474
+ ...packageJson.devDependencies
1475
+ };
1476
+ if (deps["next"]) {
1477
+ framework = "next";
1478
+ frameworkVersion = deps["next"].replace(/[\^~]/, "");
1479
+ } else if (deps["react"]) {
1480
+ framework = "react";
1481
+ frameworkVersion = deps["react"].replace(/[\^~]/, "");
1482
+ } else if (deps["vue"]) {
1483
+ framework = "vue";
1484
+ frameworkVersion = deps["vue"].replace(/[\^~]/, "");
1485
+ } else if (deps["express"]) {
1486
+ framework = "express";
1487
+ frameworkVersion = deps["express"].replace(/[\^~]/, "");
1488
+ }
1489
+ } catch {
1490
+ }
1491
+ if (result.appliedFixes && result.appliedFixes.length > 0) {
1492
+ console.log(chalk9.cyan("\n\u{1F4DA} Recording successful fixes for learning...\n"));
1493
+ for (const fix of result.appliedFixes) {
1494
+ const patternName = `Auto-fix: ${fix.displayName}`;
1495
+ const patternId = crypto.randomUUID();
1496
+ const existingPatterns = await store.listFixPatterns({
1497
+ tags: [{ category: "tool", name: fix.checkName }]
1498
+ });
1499
+ if (existingPatterns.success && existingPatterns.data && existingPatterns.data.length > 0) {
1500
+ const existingPattern = existingPatterns.data[0];
1501
+ await store.updateFixMetrics(existingPattern.id, true);
1502
+ await telemetry.recordSuccess(
1503
+ existingPattern.id,
1504
+ "fix",
1505
+ framework,
1506
+ frameworkVersion
1507
+ );
1508
+ console.log(chalk9.dim(` \u2713 Updated: ${existingPattern.name}`));
1509
+ } else {
1510
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1511
+ const newPattern = {
1512
+ id: patternId,
1513
+ name: patternName,
1514
+ description: `Auto-fix pattern for ${fix.displayName} using command: ${fix.command}`,
1515
+ category: "config",
1516
+ tags: [
1517
+ { category: "tool", name: fix.checkName },
1518
+ { category: "framework", name: framework }
1519
+ ],
1520
+ trigger: {
1521
+ errorPattern: fix.checkName,
1522
+ errorMessage: `${fix.checkName} check failed`,
1523
+ filePattern: "**/*"
1524
+ },
1525
+ solution: {
1526
+ type: "command",
1527
+ steps: [
1528
+ {
1529
+ order: 1,
1530
+ action: "run",
1531
+ target: fix.command,
1532
+ description: `Run ${fix.command}`
1533
+ }
1534
+ ]
1535
+ },
1536
+ compatibility: {
1537
+ framework,
1538
+ frameworkVersion: `>=${frameworkVersion}`,
1539
+ runtime: "node",
1540
+ runtimeVersion: ">=18.0.0",
1541
+ dependencies: []
1542
+ },
1543
+ metrics: {
1544
+ applications: 1,
1545
+ successes: 1,
1546
+ failures: 0,
1547
+ successRate: 100,
1548
+ lastUsed: now,
1549
+ lastSuccessful: now
1550
+ },
1551
+ source: "verify-fix",
1552
+ isPrivate: true,
1553
+ createdAt: now,
1554
+ updatedAt: now
1555
+ };
1556
+ const saveResult = await store.saveFixPattern(newPattern);
1557
+ if (saveResult.success) {
1558
+ await telemetry.recordSuccess(
1559
+ patternId,
1560
+ "fix",
1561
+ framework,
1562
+ frameworkVersion
1563
+ );
1564
+ console.log(chalk9.dim(` \u2713 Recorded: ${patternName}`));
1565
+ }
1566
+ }
1567
+ }
1568
+ console.log(
1569
+ chalk9.dim(`
1570
+ Use 'workflow learn:list' to see recorded patterns.`)
1571
+ );
1572
+ }
1573
+ } catch (error) {
1574
+ console.log(
1575
+ chalk9.dim(`
1576
+ Note: Could not record learning patterns: ${error.message}`)
1577
+ );
1578
+ }
1579
+ }
1444
1580
 
1445
1581
  // src/cli/commands/auto-setup-command.ts
1446
1582
  import * as p6 from "@clack/prompts";
@@ -1588,6 +1724,596 @@ function formatAuditReportColored(report) {
1588
1724
  return lines.join("\n");
1589
1725
  }
1590
1726
 
1727
+ // src/cli/commands/learn.ts
1728
+ import chalk11 from "chalk";
1729
+ 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;
1773
+ }
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);
1788
+ }
1789
+ name = nameInput;
1790
+ }
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);
1805
+ }
1806
+ description = descInput;
1807
+ }
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"
1813
+ });
1814
+ if (p7.isCancel(fwInput)) {
1815
+ p7.cancel("Recording cancelled");
1816
+ process.exit(0);
1817
+ }
1818
+ framework = fwInput;
1819
+ }
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"
1826
+ });
1827
+ if (p7.isCancel(versionInput)) {
1828
+ p7.cancel("Recording cancelled");
1829
+ process.exit(0);
1830
+ }
1831
+ version = versionInput;
1832
+ }
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" }
1848
+ ]
1849
+ });
1850
+ if (p7.isCancel(catChoice)) {
1851
+ p7.cancel("Recording cancelled");
1852
+ process.exit(0);
1853
+ }
1854
+ category = catChoice;
1855
+ }
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
+ }
1867
+ }
1868
+ }
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);
1923
+ }
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",
1934
+ runtime: "node",
1935
+ packageManager: "pnpm",
1936
+ dependencies: [],
1937
+ devDependencies: []
1938
+ },
1939
+ structure: {
1940
+ directories: [],
1941
+ keyFiles: []
1942
+ },
1943
+ setup: {
1944
+ prerequisites: [],
1945
+ steps: [],
1946
+ configs: []
1947
+ },
1948
+ compatibility: {
1949
+ framework,
1950
+ frameworkVersion: version,
1951
+ runtime: "node",
1952
+ runtimeVersion: ">=18.0.0",
1953
+ dependencies: []
1954
+ },
1955
+ metrics: {
1956
+ applications: 0,
1957
+ successes: 0,
1958
+ failures: 0,
1959
+ successRate: 0
1960
+ },
1961
+ relatedPatterns: [],
1962
+ isPrivate: true,
1963
+ createdAt: now,
1964
+ updatedAt: now
1965
+ };
1966
+ const result = await store.saveBlueprint(blueprint);
1967
+ 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}`));
1972
+ } else {
1973
+ console.log(chalk11.red("\n\u274C Failed to record blueprint"));
1974
+ console.log(chalk11.dim(` Error: ${result.error}`));
1975
+ process.exit(1);
1976
+ }
1977
+ }
1978
+ }
1979
+ async function learnListCommand(options) {
1980
+ const cwd = getWorkspacePath();
1981
+ const store = new PatternStore2(cwd);
1982
+ const patternType = options.type ?? "all";
1983
+ const showDeprecated = options.deprecated ?? false;
1984
+ console.log(chalk11.cyan("\n\u{1F4DA} Recorded Learning Patterns\n"));
1985
+ if (patternType === "all" || patternType === "fix") {
1986
+ const fixResult = await store.listFixPatterns({
1987
+ tags: options.tag ? [{ category: "framework", name: options.tag }] : void 0,
1988
+ framework: options.framework,
1989
+ includeDeprecated: showDeprecated
1990
+ });
1991
+ if (fixResult.success && fixResult.data && fixResult.data.length > 0) {
1992
+ console.log(chalk11.bold.yellow("\u{1F527} Fix Patterns:\n"));
1993
+ for (const pattern of fixResult.data) {
1994
+ const isDeprecated = pattern.deprecatedAt !== void 0;
1995
+ const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
1996
+ const nameColor = isDeprecated ? chalk11.dim : chalk11.white;
1997
+ 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)}`));
2001
+ console.log(
2002
+ chalk11.dim(
2003
+ ` Success Rate: ${(pattern.metrics.successRate * 100).toFixed(0)}% (${pattern.metrics.successes}/${pattern.metrics.applications})`
2004
+ )
2005
+ );
2006
+ if (pattern.tags.length > 0) {
2007
+ console.log(chalk11.dim(` Tags: ${formatTags(pattern.tags)}`));
2008
+ }
2009
+ console.log("");
2010
+ }
2011
+ } else if (patternType === "fix") {
2012
+ console.log(chalk11.dim(" No fix patterns found.\n"));
2013
+ }
2014
+ }
2015
+ if (patternType === "all" || patternType === "blueprint") {
2016
+ const bpResult = await store.listBlueprints({
2017
+ tags: options.tag ? [{ category: "framework", name: options.tag }] : void 0,
2018
+ framework: options.framework,
2019
+ includeDeprecated: showDeprecated
2020
+ });
2021
+ if (bpResult.success && bpResult.data && bpResult.data.length > 0) {
2022
+ console.log(chalk11.bold.blue("\u{1F4D0} Blueprints:\n"));
2023
+ for (const blueprint of bpResult.data) {
2024
+ const isDeprecated = blueprint.deprecatedAt !== void 0;
2025
+ const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
2026
+ const nameColor = isDeprecated ? chalk11.dim : chalk11.white;
2027
+ 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)}`));
2031
+ console.log(
2032
+ chalk11.dim(
2033
+ ` Success Rate: ${(blueprint.metrics.successRate * 100).toFixed(0)}% (${blueprint.metrics.successes}/${blueprint.metrics.applications})`
2034
+ )
2035
+ );
2036
+ if (blueprint.tags.length > 0) {
2037
+ console.log(chalk11.dim(` Tags: ${formatTags(blueprint.tags)}`));
2038
+ }
2039
+ console.log("");
2040
+ }
2041
+ } else if (patternType === "blueprint") {
2042
+ console.log(chalk11.dim(" No blueprints found.\n"));
2043
+ }
2044
+ }
2045
+ const stats = await store.getStats();
2046
+ const totalPatterns = stats.totalFixes + stats.totalBlueprints;
2047
+ 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}`));
2053
+ console.log("");
2054
+ }
2055
+ async function learnApplyCommand(patternId, options) {
2056
+ const cwd = getWorkspacePath();
2057
+ const store = new PatternStore2(cwd);
2058
+ const telemetry = new TelemetryCollector2(cwd);
2059
+ console.log(chalk11.cyan("\n\u{1F527} Apply Learning Pattern\n"));
2060
+ let pattern = await store.getFixPattern(patternId);
2061
+ let patternType = "fix";
2062
+ if (!pattern.success || !pattern.data) {
2063
+ const bpResult = await store.getBlueprint(patternId);
2064
+ if (bpResult.success && bpResult.data) {
2065
+ pattern = bpResult;
2066
+ patternType = "blueprint";
2067
+ } else {
2068
+ console.log(chalk11.red(`
2069
+ \u274C Pattern not found: ${patternId}`));
2070
+ console.log(chalk11.dim(" Use 'workflow learn:list' to see available patterns"));
2071
+ process.exit(1);
2072
+ }
2073
+ }
2074
+ 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}`));
2078
+ if (options.dryRun) {
2079
+ console.log(chalk11.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n"));
2080
+ }
2081
+ const framework = options.framework ?? patternData.compatibility.frameworks[0]?.name ?? "unknown";
2082
+ const version = options.version ?? patternData.compatibility.frameworks[0]?.version ?? "0.0.0";
2083
+ await telemetry.recordApplication(patternId, patternType, framework, version);
2084
+ if (patternType === "fix") {
2085
+ const fixPattern = patternData;
2086
+ console.log(chalk11.cyan("\n\u{1F4CB} Solution Steps:\n"));
2087
+ if (fixPattern.solution.steps) {
2088
+ for (let i = 0; i < fixPattern.solution.steps.length; i++) {
2089
+ const step = fixPattern.solution.steps[i];
2090
+ console.log(chalk11.white(` ${i + 1}. [${step.action}] ${step.description}`));
2091
+ if (step.file) {
2092
+ console.log(chalk11.dim(` File: ${step.file}`));
2093
+ }
2094
+ }
2095
+ }
2096
+ } else {
2097
+ const blueprint = patternData;
2098
+ console.log(chalk11.cyan("\n\u{1F4CB} Setup Steps:\n"));
2099
+ if (blueprint.setup.steps) {
2100
+ for (let i = 0; i < blueprint.setup.steps.length; i++) {
2101
+ const step = blueprint.setup.steps[i];
2102
+ console.log(chalk11.white(` ${i + 1}. ${step.description}`));
2103
+ if (step.command) {
2104
+ console.log(chalk11.dim(` Command: ${step.command}`));
2105
+ }
2106
+ }
2107
+ }
2108
+ }
2109
+ if (!options.dryRun) {
2110
+ const confirmed = await p7.confirm({
2111
+ message: "Mark this pattern as successfully applied?",
2112
+ initialValue: true
2113
+ });
2114
+ if (p7.isCancel(confirmed)) {
2115
+ p7.cancel("Application cancelled");
2116
+ process.exit(0);
2117
+ }
2118
+ if (confirmed) {
2119
+ await store.updatePatternMetrics(patternId, patternType, true);
2120
+ await telemetry.recordSuccess(patternId, patternType, framework, version);
2121
+ console.log(chalk11.green("\n\u2705 Pattern marked as successfully applied!"));
2122
+ } else {
2123
+ 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."));
2126
+ }
2127
+ }
2128
+ }
2129
+ async function learnSyncCommand(options) {
2130
+ const cwd = getWorkspacePath();
2131
+ const contributorManager = new ContributorManager2(cwd);
2132
+ console.log(chalk11.cyan("\n\u{1F504} Sync Learning Patterns\n"));
2133
+ const config = await contributorManager.getConfig();
2134
+ 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."));
2139
+ process.exit(0);
2140
+ }
2141
+ if (options.dryRun) {
2142
+ console.log(chalk11.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be synced\n"));
2143
+ }
2144
+ const store = new PatternStore2(cwd);
2145
+ const anonymizer = new PatternAnonymizer();
2146
+ const { fixes, blueprints } = await store.getPatternsForSync();
2147
+ console.log(chalk11.dim(` Patterns ready to sync: ${fixes.length} fixes, ${blueprints.length} blueprints`));
2148
+ if (options.push) {
2149
+ console.log(chalk11.cyan("\n\u{1F4E4} Pushing patterns...\n"));
2150
+ let anonymizedFixes = 0;
2151
+ let anonymizedBlueprints = 0;
2152
+ for (const fix of fixes) {
2153
+ const result = anonymizer.anonymizeFixPattern(fix);
2154
+ if (result.success) {
2155
+ anonymizedFixes++;
2156
+ if (!options.dryRun) {
2157
+ console.log(chalk11.dim(` \u2713 Anonymized: ${fix.name}`));
2158
+ }
2159
+ }
2160
+ }
2161
+ for (const bp of blueprints) {
2162
+ const result = anonymizer.anonymizeBlueprint(bp);
2163
+ if (result.success) {
2164
+ anonymizedBlueprints++;
2165
+ if (!options.dryRun) {
2166
+ console.log(chalk11.dim(` \u2713 Anonymized: ${bp.name}`));
2167
+ }
2168
+ }
2169
+ }
2170
+ console.log(
2171
+ chalk11.green(`
2172
+ \u2705 Ready to push ${anonymizedFixes} fixes and ${anonymizedBlueprints} blueprints`)
2173
+ );
2174
+ console.log(chalk11.dim(" (Registry push not yet implemented)"));
2175
+ }
2176
+ 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)"));
2179
+ }
2180
+ if (!options.push && !options.pull) {
2181
+ console.log(chalk11.dim(" Specify --push to upload or --pull to download patterns.\n"));
2182
+ }
2183
+ }
2184
+ async function learnConfigCommand(options) {
2185
+ const cwd = getWorkspacePath();
2186
+ const contributorManager = new ContributorManager2(cwd);
2187
+ console.log(chalk11.cyan("\n\u2699\uFE0F Learning Configuration\n"));
2188
+ if (options.enableSync) {
2189
+ const result = await contributorManager.enableSync();
2190
+ if (result.success) {
2191
+ console.log(chalk11.green("\u2705 Sync enabled"));
2192
+ console.log(chalk11.dim(" Your patterns will be anonymized before sharing."));
2193
+ } else {
2194
+ console.log(chalk11.red(`\u274C Failed: ${result.error}`));
2195
+ }
2196
+ return;
2197
+ }
2198
+ if (options.disableSync) {
2199
+ const result = await contributorManager.disableSync();
2200
+ if (result.success) {
2201
+ console.log(chalk11.green("\u2705 Sync disabled"));
2202
+ } else {
2203
+ console.log(chalk11.red(`\u274C Failed: ${result.error}`));
2204
+ }
2205
+ return;
2206
+ }
2207
+ if (options.enableTelemetry) {
2208
+ const result = await contributorManager.enableTelemetry();
2209
+ if (result.success) {
2210
+ console.log(chalk11.green("\u2705 Telemetry enabled"));
2211
+ console.log(chalk11.dim(" Anonymous usage data helps improve pattern recommendations."));
2212
+ } else {
2213
+ console.log(chalk11.red(`\u274C Failed: ${result.error}`));
2214
+ }
2215
+ return;
2216
+ }
2217
+ if (options.disableTelemetry) {
2218
+ const result = await contributorManager.disableTelemetry();
2219
+ if (result.success) {
2220
+ console.log(chalk11.green("\u2705 Telemetry disabled"));
2221
+ } else {
2222
+ console.log(chalk11.red(`\u274C Failed: ${result.error}`));
2223
+ }
2224
+ return;
2225
+ }
2226
+ if (options.resetId) {
2227
+ const confirmed = await p7.confirm({
2228
+ message: "Are you sure you want to reset your contributor ID? This cannot be undone.",
2229
+ initialValue: false
2230
+ });
2231
+ if (p7.isCancel(confirmed) || !confirmed) {
2232
+ p7.cancel("Reset cancelled");
2233
+ return;
2234
+ }
2235
+ const result = await contributorManager.resetId();
2236
+ if (result.success) {
2237
+ console.log(chalk11.green("\u2705 Contributor ID reset"));
2238
+ console.log(chalk11.dim(` New ID: ${result.data?.id}`));
2239
+ } else {
2240
+ console.log(chalk11.red(`\u274C Failed: ${result.error}`));
2241
+ }
2242
+ return;
2243
+ }
2244
+ const config = await contributorManager.getConfig();
2245
+ 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"}`));
2251
+ if (config.data.syncEnabledAt) {
2252
+ console.log(chalk11.dim(` Sync Enabled At: ${formatDate(config.data.syncEnabledAt)}`));
2253
+ }
2254
+ } else {
2255
+ console.log(chalk11.dim(" No configuration found. Settings will be created on first use.\n"));
2256
+ }
2257
+ }
2258
+ async function learnDeprecateCommand(patternId, reason) {
2259
+ const cwd = getWorkspacePath();
2260
+ const store = new PatternStore2(cwd);
2261
+ console.log(chalk11.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
2262
+ let patternType = "fix";
2263
+ let pattern = await store.getFixPattern(patternId);
2264
+ if (!pattern.success || !pattern.data) {
2265
+ const bpResult = await store.getBlueprint(patternId);
2266
+ if (bpResult.success && bpResult.data) {
2267
+ pattern = bpResult;
2268
+ patternType = "blueprint";
2269
+ } else {
2270
+ console.log(chalk11.red(`
2271
+ \u274C Pattern not found: ${patternId}`));
2272
+ process.exit(1);
2273
+ }
2274
+ }
2275
+ console.log(chalk11.white(` Pattern: ${pattern.data.name}`));
2276
+ console.log(chalk11.dim(` Reason: ${reason}`));
2277
+ const confirmed = await p7.confirm({
2278
+ message: "Are you sure you want to deprecate this pattern?",
2279
+ initialValue: false
2280
+ });
2281
+ if (p7.isCancel(confirmed) || !confirmed) {
2282
+ p7.cancel("Deprecation cancelled");
2283
+ return;
2284
+ }
2285
+ const result = await store.deprecatePattern(patternId, patternType, reason);
2286
+ if (result.success) {
2287
+ console.log(chalk11.green("\n\u2705 Pattern deprecated successfully"));
2288
+ } else {
2289
+ console.log(chalk11.red(`
2290
+ \u274C Failed: ${result.error}`));
2291
+ process.exit(1);
2292
+ }
2293
+ }
2294
+ async function learnStatsCommand() {
2295
+ const cwd = getWorkspacePath();
2296
+ const store = new PatternStore2(cwd);
2297
+ const telemetry = new TelemetryCollector2(cwd);
2298
+ console.log(chalk11.cyan("\n\u{1F4CA} Learning Statistics\n"));
2299
+ const storeStats = await store.getStats();
2300
+ const totalPatterns = storeStats.totalFixes + storeStats.totalBlueprints;
2301
+ 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}`));
2307
+ 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}`));
2311
+ if (telemetryStats.lastFlushAt) {
2312
+ console.log(chalk11.dim(` Last Flush: ${formatDate(telemetryStats.lastFlushAt)}`));
2313
+ }
2314
+ console.log("");
2315
+ }
2316
+
1591
2317
  // src/cli/index.ts
1592
2318
  var program = new Command();
1593
2319
  program.name("workflow").description(
@@ -1616,7 +2342,14 @@ program.command("scope:create").description("Create a custom scope package").opt
1616
2342
  "Comma-separated scopes (format: name:description:emoji:category)"
1617
2343
  ).option("--preset-name <preset>", "Preset display name").option("--output-dir <dir>", "Output directory").option("--no-test", "Skip test file generation").action(scopeCreateCommand);
1618
2344
  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);
1619
- 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").action(verifyCommand);
2345
+ 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);
1620
2346
  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);
2347
+ 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);
2348
+ 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);
2349
+ 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);
2350
+ 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);
2351
+ 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);
2352
+ program.command("learn:deprecate <patternId> <reason>").description("Deprecate an outdated pattern").argument("<patternId>", "Pattern ID to deprecate").argument("<reason>", "Reason for deprecation").action(learnDeprecateCommand);
2353
+ program.command("learn:stats").description("Show learning statistics").action(learnStatsCommand);
1621
2354
  program.parse();
1622
2355
  //# sourceMappingURL=index.js.map