workflow-agent-cli 2.8.0 → 2.9.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/{chunk-2WUPMAH3.js → chunk-Y5N3JJTU.js} +9 -2
- package/dist/chunk-Y5N3JJTU.js.map +1 -0
- package/dist/chunk-ZLDJ2OGO.js +386 -0
- package/dist/chunk-ZLDJ2OGO.js.map +1 -0
- package/dist/cli/index.js +459 -281
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +9 -1
- package/dist/scripts/postinstall.js +1 -1
- package/dist/validators/index.d.ts +32 -2
- package/dist/validators/index.js +9 -1
- package/package.json +4 -3
- package/dist/chunk-2WUPMAH3.js.map +0 -1
- package/dist/chunk-NMHWD2GA.js +0 -175
- package/dist/chunk-NMHWD2GA.js.map +0 -1
- package/dist/{schema-D0zTM83x.d.ts → schema-BUu8Cefw.d.ts} +4 -4
package/dist/cli/index.js
CHANGED
|
@@ -10,10 +10,12 @@ import {
|
|
|
10
10
|
stageAllChanges
|
|
11
11
|
} from "../chunk-6NWQLGHI.js";
|
|
12
12
|
import {
|
|
13
|
+
applyReferenceFix,
|
|
13
14
|
validateBranchName,
|
|
14
15
|
validateCommitMessage,
|
|
16
|
+
validateDocumentReferences,
|
|
15
17
|
validatePRTitle
|
|
16
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-ZLDJ2OGO.js";
|
|
17
19
|
import {
|
|
18
20
|
hasConfig,
|
|
19
21
|
loadConfig,
|
|
@@ -29,7 +31,7 @@ import {
|
|
|
29
31
|
installMandatoryTemplates,
|
|
30
32
|
templateMetadata,
|
|
31
33
|
updateTemplates
|
|
32
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-Y5N3JJTU.js";
|
|
33
35
|
|
|
34
36
|
// src/cli/index.ts
|
|
35
37
|
import { Command } from "commander";
|
|
@@ -316,10 +318,10 @@ async function initCommand(options) {
|
|
|
316
318
|
try {
|
|
317
319
|
const presetModule = await import(`@workflow/scopes-${preset}`);
|
|
318
320
|
scopes = presetModule.scopes || presetModule.default.scopes;
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
+
const spinner10 = p.spinner();
|
|
322
|
+
spinner10.start(`Loading ${presetModule.default?.name || preset} preset`);
|
|
321
323
|
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
322
|
-
|
|
324
|
+
spinner10.stop(`\u2713 Loaded ${scopes.length} scopes from preset`);
|
|
323
325
|
} catch (error) {
|
|
324
326
|
console.log(
|
|
325
327
|
chalk.yellow(
|
|
@@ -366,8 +368,8 @@ async function initCommand(options) {
|
|
|
366
368
|
process.exit(0);
|
|
367
369
|
}
|
|
368
370
|
if (shouldGenerateGuidelines) {
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
+
const spinner10 = p.spinner();
|
|
372
|
+
spinner10.start("Generating guidelines...");
|
|
371
373
|
try {
|
|
372
374
|
const templatesDir = join(__dirname, "../../templates");
|
|
373
375
|
await validateTemplateDirectory(templatesDir);
|
|
@@ -379,7 +381,7 @@ async function initCommand(options) {
|
|
|
379
381
|
guidelinesDir,
|
|
380
382
|
context
|
|
381
383
|
);
|
|
382
|
-
|
|
384
|
+
spinner10.stop(`\u2713 Generated ${renderedFiles.length} guideline documents`);
|
|
383
385
|
const instructionsSpinner = p.spinner();
|
|
384
386
|
instructionsSpinner.start("Generating AI agent instructions...");
|
|
385
387
|
const result = generateCopilotInstructions(cwd, { silent: true });
|
|
@@ -389,7 +391,7 @@ async function initCommand(options) {
|
|
|
389
391
|
instructionsSpinner.stop("\u26A0\uFE0F Could not generate copilot instructions");
|
|
390
392
|
}
|
|
391
393
|
} catch (error) {
|
|
392
|
-
|
|
394
|
+
spinner10.stop("\u26A0\uFE0F Could not generate guidelines");
|
|
393
395
|
console.log(
|
|
394
396
|
chalk.yellow(
|
|
395
397
|
`
|
|
@@ -898,8 +900,8 @@ async function scopeCreateCommand(options) {
|
|
|
898
900
|
process.exit(0);
|
|
899
901
|
}
|
|
900
902
|
}
|
|
901
|
-
const
|
|
902
|
-
|
|
903
|
+
const spinner10 = p4.spinner();
|
|
904
|
+
spinner10.start("Creating package structure...");
|
|
903
905
|
try {
|
|
904
906
|
await mkdir2(join3(outputDir, "src"), { recursive: true });
|
|
905
907
|
const packageJson = {
|
|
@@ -1030,7 +1032,7 @@ describe('${presetName} Scope Preset', () => {
|
|
|
1030
1032
|
"utf-8"
|
|
1031
1033
|
);
|
|
1032
1034
|
}
|
|
1033
|
-
|
|
1035
|
+
spinner10.stop("\u2713 Package structure created");
|
|
1034
1036
|
if (isMonorepo2) {
|
|
1035
1037
|
const workspaceFile = join3(cwd, "pnpm-workspace.yaml");
|
|
1036
1038
|
const workspaceContent = await readFile(workspaceFile, "utf-8");
|
|
@@ -1082,7 +1084,7 @@ describe('${presetName} Scope Preset', () => {
|
|
|
1082
1084
|
);
|
|
1083
1085
|
}
|
|
1084
1086
|
} catch (error) {
|
|
1085
|
-
|
|
1087
|
+
spinner10.stop("\u2717 Failed to create package");
|
|
1086
1088
|
console.error(chalk7.red("\nError:"), error);
|
|
1087
1089
|
process.exit(1);
|
|
1088
1090
|
}
|
|
@@ -1210,8 +1212,8 @@ async function scopeMigrateCommand(options) {
|
|
|
1210
1212
|
process.exit(0);
|
|
1211
1213
|
}
|
|
1212
1214
|
}
|
|
1213
|
-
const
|
|
1214
|
-
|
|
1215
|
+
const spinner10 = p5.spinner();
|
|
1216
|
+
spinner10.start("Migrating scopes to package...");
|
|
1215
1217
|
try {
|
|
1216
1218
|
await mkdir3(join4(outputDir, "src"), { recursive: true });
|
|
1217
1219
|
const packageJson = {
|
|
@@ -1339,7 +1341,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1339
1341
|
});
|
|
1340
1342
|
`;
|
|
1341
1343
|
await writeFile3(join4(outputDir, "src", "index.test.ts"), testFile, "utf-8");
|
|
1342
|
-
|
|
1344
|
+
spinner10.stop("\u2713 Package created from migrated scopes");
|
|
1343
1345
|
if (isMonorepo2) {
|
|
1344
1346
|
const workspaceFile = join4(cwd, "pnpm-workspace.yaml");
|
|
1345
1347
|
const workspaceContent = await readFile2(workspaceFile, "utf-8");
|
|
@@ -1411,7 +1413,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1411
1413
|
)
|
|
1412
1414
|
);
|
|
1413
1415
|
} catch (error) {
|
|
1414
|
-
|
|
1416
|
+
spinner10.stop("\u2717 Migration failed");
|
|
1415
1417
|
console.error(chalk8.red("\nError:"), error);
|
|
1416
1418
|
process.exit(1);
|
|
1417
1419
|
}
|
|
@@ -1651,14 +1653,14 @@ import chalk10 from "chalk";
|
|
|
1651
1653
|
async function autoSetupCommand(options) {
|
|
1652
1654
|
console.log(chalk10.bold.cyan("\n\u{1F527} Workflow Agent Auto-Setup\n"));
|
|
1653
1655
|
const cwd = process.cwd();
|
|
1654
|
-
const
|
|
1655
|
-
|
|
1656
|
+
const spinner10 = p6.spinner();
|
|
1657
|
+
spinner10.start("Analyzing project...");
|
|
1656
1658
|
let report;
|
|
1657
1659
|
try {
|
|
1658
1660
|
report = await generateAuditReport(cwd);
|
|
1659
|
-
|
|
1661
|
+
spinner10.stop("\u2713 Project analysis complete");
|
|
1660
1662
|
} catch (error) {
|
|
1661
|
-
|
|
1663
|
+
spinner10.stop("\u2717 Failed to analyze project");
|
|
1662
1664
|
console.error(
|
|
1663
1665
|
chalk10.red(
|
|
1664
1666
|
`Error: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -2834,7 +2836,7 @@ var QuestionGenerator = class {
|
|
|
2834
2836
|
category: "Platform Strategy",
|
|
2835
2837
|
question: `Are our platform choices (${technology.platforms.join(", ")}) aligned with target market and growth plans?`,
|
|
2836
2838
|
context: `Currently deployed on ${technology.platforms.join(" + ")}`,
|
|
2837
|
-
findings: technology.platforms.map((
|
|
2839
|
+
findings: technology.platforms.map((p13) => `Supports ${p13} platform`),
|
|
2838
2840
|
recommendations: [
|
|
2839
2841
|
"Validate platform coverage matches user demographics",
|
|
2840
2842
|
"Assess cross-platform development efficiency",
|
|
@@ -2896,7 +2898,7 @@ var QuestionGenerator = class {
|
|
|
2896
2898
|
category: "Business Alignment",
|
|
2897
2899
|
question: `How is our authentication solution (${authCat.packages.join(", ")}) supporting user onboarding and security requirements?`,
|
|
2898
2900
|
context: `Using ${authCat.packages.join(" + ")} for authentication`,
|
|
2899
|
-
findings: authCat.packages.map((
|
|
2901
|
+
findings: authCat.packages.map((p13) => `Auth provider: ${p13}`),
|
|
2900
2902
|
recommendations: [
|
|
2901
2903
|
"Measure authentication success rates and friction points",
|
|
2902
2904
|
"Ensure compliance with security standards (SOC2, GDPR, etc.)",
|
|
@@ -2948,12 +2950,12 @@ var QuestionGenerator = class {
|
|
|
2948
2950
|
});
|
|
2949
2951
|
}
|
|
2950
2952
|
if (packages.outdated && packages.outdated.length > 10) {
|
|
2951
|
-
const breakingCount = packages.outdated.filter((
|
|
2953
|
+
const breakingCount = packages.outdated.filter((p13) => p13.breaking).length;
|
|
2952
2954
|
questions.push({
|
|
2953
2955
|
category: "Technical Debt",
|
|
2954
2956
|
question: `How should we prioritize updating ${packages.outdated.length} outdated packages${breakingCount > 0 ? ` (${breakingCount} with breaking changes)` : ""}?`,
|
|
2955
2957
|
context: "Dependency audit found outdated packages",
|
|
2956
|
-
findings: packages.outdated.slice(0, 5).map((
|
|
2958
|
+
findings: packages.outdated.slice(0, 5).map((p13) => `${p13.name}: ${p13.current} \u2192 ${p13.latest}`),
|
|
2957
2959
|
recommendations: [
|
|
2958
2960
|
"Create update roadmap starting with non-breaking changes",
|
|
2959
2961
|
"Test breaking changes in feature branches",
|
|
@@ -3263,10 +3265,10 @@ var ReportComparator = class {
|
|
|
3263
3265
|
*/
|
|
3264
3266
|
comparePackages() {
|
|
3265
3267
|
const baselineProduction = new Map(
|
|
3266
|
-
this.baseline.packages.production.map((
|
|
3268
|
+
this.baseline.packages.production.map((p13) => [p13.name, p13])
|
|
3267
3269
|
);
|
|
3268
3270
|
const currentProduction = new Map(
|
|
3269
|
-
this.current.packages.production.map((
|
|
3271
|
+
this.current.packages.production.map((p13) => [p13.name, p13])
|
|
3270
3272
|
);
|
|
3271
3273
|
const added = [];
|
|
3272
3274
|
const removed = [];
|
|
@@ -3298,10 +3300,10 @@ var ReportComparator = class {
|
|
|
3298
3300
|
}
|
|
3299
3301
|
}
|
|
3300
3302
|
const baselineDev = new Map(
|
|
3301
|
-
this.baseline.packages.development.map((
|
|
3303
|
+
this.baseline.packages.development.map((p13) => [p13.name, p13])
|
|
3302
3304
|
);
|
|
3303
3305
|
const currentDev = new Map(
|
|
3304
|
-
this.current.packages.development.map((
|
|
3306
|
+
this.current.packages.development.map((p13) => [p13.name, p13])
|
|
3305
3307
|
);
|
|
3306
3308
|
for (const [name, pkg] of currentDev) {
|
|
3307
3309
|
if (!baselineDev.has(name)) {
|
|
@@ -3589,20 +3591,20 @@ async function advisoryCommand(options) {
|
|
|
3589
3591
|
includeHealth,
|
|
3590
3592
|
excludePatterns: advisoryConfig?.excludePatterns
|
|
3591
3593
|
});
|
|
3592
|
-
const
|
|
3594
|
+
const spinner10 = p7.spinner();
|
|
3593
3595
|
const depthLabels = {
|
|
3594
3596
|
executive: "executive summary",
|
|
3595
3597
|
quick: "quick scan",
|
|
3596
3598
|
standard: "standard analysis",
|
|
3597
3599
|
comprehensive: "comprehensive analysis"
|
|
3598
3600
|
};
|
|
3599
|
-
|
|
3601
|
+
spinner10.start(`Running ${depthLabels[depth]}...`);
|
|
3600
3602
|
let analysis;
|
|
3601
3603
|
try {
|
|
3602
3604
|
analysis = await analyzer.analyze();
|
|
3603
|
-
|
|
3605
|
+
spinner10.stop(`\u2713 Analysis complete`);
|
|
3604
3606
|
} catch (error) {
|
|
3605
|
-
|
|
3607
|
+
spinner10.stop("\u2717 Analysis failed");
|
|
3606
3608
|
console.error(
|
|
3607
3609
|
chalk11.red(
|
|
3608
3610
|
`Error: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -3619,17 +3621,17 @@ async function advisoryCommand(options) {
|
|
|
3619
3621
|
if (options.compare) {
|
|
3620
3622
|
const comparisonPath = options.compare.endsWith(".json") ? join6(cwd, options.compare) : join6(cwd, options.compare, "analysis.json");
|
|
3621
3623
|
if (existsSync6(comparisonPath)) {
|
|
3622
|
-
|
|
3624
|
+
spinner10.start("Comparing with previous report...");
|
|
3623
3625
|
try {
|
|
3624
3626
|
const previousContent = await readFile4(comparisonPath, "utf-8");
|
|
3625
3627
|
const previousAnalysis = JSON.parse(previousContent);
|
|
3626
3628
|
comparator = new ReportComparator(previousAnalysis, analysis);
|
|
3627
3629
|
comparisonReport = comparator.compare();
|
|
3628
|
-
|
|
3630
|
+
spinner10.stop("\u2713 Comparison complete");
|
|
3629
3631
|
console.log("");
|
|
3630
3632
|
displayComparisonSummary(comparisonReport);
|
|
3631
3633
|
} catch (error) {
|
|
3632
|
-
|
|
3634
|
+
spinner10.stop("\u26A0 Comparison failed");
|
|
3633
3635
|
console.warn(chalk11.yellow(`Could not compare reports: ${error}`));
|
|
3634
3636
|
}
|
|
3635
3637
|
} else {
|
|
@@ -3648,7 +3650,7 @@ async function advisoryCommand(options) {
|
|
|
3648
3650
|
}
|
|
3649
3651
|
const fullOutputDir = join6(cwd, outputDir);
|
|
3650
3652
|
await mkdir4(fullOutputDir, { recursive: true });
|
|
3651
|
-
|
|
3653
|
+
spinner10.start("Generating reports...");
|
|
3652
3654
|
try {
|
|
3653
3655
|
const timestamp = options.timestamp ? (/* @__PURE__ */ new Date()).toISOString().split("T")[0] : "";
|
|
3654
3656
|
if (options.format === "json") {
|
|
@@ -3662,9 +3664,9 @@ async function advisoryCommand(options) {
|
|
|
3662
3664
|
timestamp
|
|
3663
3665
|
);
|
|
3664
3666
|
}
|
|
3665
|
-
|
|
3667
|
+
spinner10.stop("\u2713 Reports generated");
|
|
3666
3668
|
} catch (error) {
|
|
3667
|
-
|
|
3669
|
+
spinner10.stop("\u2717 Failed to write reports");
|
|
3668
3670
|
console.error(chalk11.red(`Error: ${error}`));
|
|
3669
3671
|
process.exit(1);
|
|
3670
3672
|
}
|
|
@@ -4462,8 +4464,8 @@ async function generateInstructionsCommand(options) {
|
|
|
4462
4464
|
process.exit(0);
|
|
4463
4465
|
}
|
|
4464
4466
|
}
|
|
4465
|
-
const
|
|
4466
|
-
|
|
4467
|
+
const spinner10 = p8.spinner();
|
|
4468
|
+
spinner10.start("Generating AI agent instructions from guidelines...");
|
|
4467
4469
|
try {
|
|
4468
4470
|
const result = generateCopilotInstructions(cwd, {
|
|
4469
4471
|
force: true,
|
|
@@ -4471,7 +4473,7 @@ async function generateInstructionsCommand(options) {
|
|
|
4471
4473
|
});
|
|
4472
4474
|
if (result.success) {
|
|
4473
4475
|
const status = result.isNew ? "Generated" : "Regenerated";
|
|
4474
|
-
|
|
4476
|
+
spinner10.stop(
|
|
4475
4477
|
chalk12.green(
|
|
4476
4478
|
`\u2713 ${status} .github/copilot-instructions.md from ${result.guidelinesCount} guidelines`
|
|
4477
4479
|
)
|
|
@@ -4487,12 +4489,12 @@ async function generateInstructionsCommand(options) {
|
|
|
4487
4489
|
)
|
|
4488
4490
|
);
|
|
4489
4491
|
} else {
|
|
4490
|
-
|
|
4492
|
+
spinner10.stop(chalk12.red("\u2717 Failed to generate instructions"));
|
|
4491
4493
|
console.log(chalk12.yellow(`
|
|
4492
4494
|
Reason: ${result.error}`));
|
|
4493
4495
|
}
|
|
4494
4496
|
} catch (error) {
|
|
4495
|
-
|
|
4497
|
+
spinner10.stop(chalk12.red("\u2717 Error generating instructions"));
|
|
4496
4498
|
console.log(
|
|
4497
4499
|
chalk12.yellow(
|
|
4498
4500
|
`
|
|
@@ -4575,8 +4577,8 @@ async function updateTemplatesCommand(options) {
|
|
|
4575
4577
|
process.exit(0);
|
|
4576
4578
|
}
|
|
4577
4579
|
}
|
|
4578
|
-
const
|
|
4579
|
-
|
|
4580
|
+
const spinner10 = p9.spinner();
|
|
4581
|
+
spinner10.start("Updating templates...");
|
|
4580
4582
|
let result;
|
|
4581
4583
|
try {
|
|
4582
4584
|
result = updateTemplates(cwd, templatesDir, {
|
|
@@ -4584,7 +4586,7 @@ async function updateTemplatesCommand(options) {
|
|
|
4584
4586
|
silent: true
|
|
4585
4587
|
});
|
|
4586
4588
|
} catch (error) {
|
|
4587
|
-
|
|
4589
|
+
spinner10.stop("\u274C Failed to update templates");
|
|
4588
4590
|
console.log(
|
|
4589
4591
|
chalk13.red(
|
|
4590
4592
|
`
|
|
@@ -4595,7 +4597,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
4595
4597
|
}
|
|
4596
4598
|
const totalChanges = result.installed.length + result.updated.length;
|
|
4597
4599
|
if (totalChanges === 0 && result.skipped.length > 0) {
|
|
4598
|
-
|
|
4600
|
+
spinner10.stop("No changes needed");
|
|
4599
4601
|
console.log(
|
|
4600
4602
|
chalk13.dim(
|
|
4601
4603
|
`
|
|
@@ -4603,7 +4605,7 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
4603
4605
|
)
|
|
4604
4606
|
);
|
|
4605
4607
|
} else {
|
|
4606
|
-
|
|
4608
|
+
spinner10.stop(`\u2713 Template update complete`);
|
|
4607
4609
|
if (result.installed.length > 0) {
|
|
4608
4610
|
console.log(chalk13.green(`
|
|
4609
4611
|
New templates installed:`));
|
|
@@ -4649,9 +4651,176 @@ Error: ${error instanceof Error ? error.message : String(error)}`
|
|
|
4649
4651
|
p9.outro(chalk13.green("Done!"));
|
|
4650
4652
|
}
|
|
4651
4653
|
|
|
4652
|
-
// src/cli/commands/
|
|
4653
|
-
import chalk14 from "chalk";
|
|
4654
|
+
// src/cli/commands/docs-validate.ts
|
|
4654
4655
|
import * as p10 from "@clack/prompts";
|
|
4656
|
+
import chalk14 from "chalk";
|
|
4657
|
+
import { relative } from "path";
|
|
4658
|
+
async function docsValidateCommand(options) {
|
|
4659
|
+
const { fix = false, patterns, ignore } = options;
|
|
4660
|
+
p10.intro(chalk14.bgBlue(" workflow-agent docs:validate "));
|
|
4661
|
+
const cwd = process.cwd();
|
|
4662
|
+
const spinner10 = p10.spinner();
|
|
4663
|
+
spinner10.start("Scanning markdown files for broken references...");
|
|
4664
|
+
try {
|
|
4665
|
+
const result = await validateDocumentReferences(cwd, {
|
|
4666
|
+
patterns,
|
|
4667
|
+
ignore
|
|
4668
|
+
});
|
|
4669
|
+
spinner10.stop("Scan complete");
|
|
4670
|
+
console.log("");
|
|
4671
|
+
console.log(
|
|
4672
|
+
chalk14.cyan(
|
|
4673
|
+
`\u{1F4C4} Scanned ${result.scannedFiles} file(s), found ${result.totalReferences} reference(s)`
|
|
4674
|
+
)
|
|
4675
|
+
);
|
|
4676
|
+
if (result.errors.length > 0) {
|
|
4677
|
+
console.log("");
|
|
4678
|
+
console.log(chalk14.red("\u274C Errors during validation:"));
|
|
4679
|
+
for (const error of result.errors) {
|
|
4680
|
+
console.log(chalk14.red(` ${error}`));
|
|
4681
|
+
}
|
|
4682
|
+
p10.outro(chalk14.red("Validation failed"));
|
|
4683
|
+
process.exit(1);
|
|
4684
|
+
}
|
|
4685
|
+
if (result.valid) {
|
|
4686
|
+
console.log("");
|
|
4687
|
+
console.log(chalk14.green("\u2705 All document references are valid!"));
|
|
4688
|
+
p10.outro(chalk14.green("No broken links found"));
|
|
4689
|
+
return;
|
|
4690
|
+
}
|
|
4691
|
+
console.log("");
|
|
4692
|
+
console.log(
|
|
4693
|
+
chalk14.yellow(
|
|
4694
|
+
`\u26A0\uFE0F Found ${result.brokenReferences.length} broken reference(s):`
|
|
4695
|
+
)
|
|
4696
|
+
);
|
|
4697
|
+
console.log("");
|
|
4698
|
+
for (const broken of result.brokenReferences) {
|
|
4699
|
+
const relativePath = relative(cwd, broken.file);
|
|
4700
|
+
console.log(
|
|
4701
|
+
chalk14.red(
|
|
4702
|
+
` ${relativePath}:${broken.line}:${broken.column} - ${broken.type}`
|
|
4703
|
+
)
|
|
4704
|
+
);
|
|
4705
|
+
console.log(chalk14.dim(` ${broken.rawLink}`));
|
|
4706
|
+
console.log(chalk14.dim(` Target: ${broken.targetPath}`));
|
|
4707
|
+
if (broken.suggestions.length > 0) {
|
|
4708
|
+
console.log(chalk14.dim(` Suggestions: ${broken.suggestions.slice(0, 3).join(", ")}`));
|
|
4709
|
+
}
|
|
4710
|
+
console.log("");
|
|
4711
|
+
}
|
|
4712
|
+
if (!fix) {
|
|
4713
|
+
console.log(
|
|
4714
|
+
chalk14.yellow("\u{1F4A1} Run with --fix flag to interactively fix broken references")
|
|
4715
|
+
);
|
|
4716
|
+
p10.outro(chalk14.red("Validation failed"));
|
|
4717
|
+
process.exit(1);
|
|
4718
|
+
}
|
|
4719
|
+
console.log(chalk14.cyan("\u{1F527} Interactive fix mode\n"));
|
|
4720
|
+
let fixedCount = 0;
|
|
4721
|
+
let skippedCount = 0;
|
|
4722
|
+
for (const broken of result.brokenReferences) {
|
|
4723
|
+
const relativePath = relative(cwd, broken.file);
|
|
4724
|
+
console.log(chalk14.bold(`
|
|
4725
|
+
${relativePath}:${broken.line}`));
|
|
4726
|
+
console.log(chalk14.dim(` ${broken.rawLink}`));
|
|
4727
|
+
console.log(chalk14.yellow(` \u274C Broken: ${broken.targetPath}
|
|
4728
|
+
`));
|
|
4729
|
+
const options2 = [];
|
|
4730
|
+
if (broken.suggestions.length > 0) {
|
|
4731
|
+
options2.push(
|
|
4732
|
+
...broken.suggestions.slice(0, 8).map((suggestion) => ({
|
|
4733
|
+
value: suggestion,
|
|
4734
|
+
label: `\u{1F4C4} ${suggestion}`
|
|
4735
|
+
}))
|
|
4736
|
+
);
|
|
4737
|
+
}
|
|
4738
|
+
options2.push({
|
|
4739
|
+
value: "__custom__",
|
|
4740
|
+
label: "\u270F\uFE0F Enter custom path"
|
|
4741
|
+
});
|
|
4742
|
+
options2.push({
|
|
4743
|
+
value: "__skip__",
|
|
4744
|
+
label: "\u23ED\uFE0F Skip this reference"
|
|
4745
|
+
});
|
|
4746
|
+
const choice = await p10.select({
|
|
4747
|
+
message: "Choose correct path:",
|
|
4748
|
+
options: options2
|
|
4749
|
+
});
|
|
4750
|
+
if (p10.isCancel(choice)) {
|
|
4751
|
+
console.log("");
|
|
4752
|
+
p10.cancel("Fix operation cancelled");
|
|
4753
|
+
console.log(
|
|
4754
|
+
chalk14.dim(`
|
|
4755
|
+
Fixed: ${fixedCount}, Skipped: ${skippedCount}`)
|
|
4756
|
+
);
|
|
4757
|
+
process.exit(0);
|
|
4758
|
+
}
|
|
4759
|
+
if (choice === "__skip__") {
|
|
4760
|
+
skippedCount++;
|
|
4761
|
+
continue;
|
|
4762
|
+
}
|
|
4763
|
+
let newPath;
|
|
4764
|
+
if (choice === "__custom__") {
|
|
4765
|
+
const customPath = await p10.text({
|
|
4766
|
+
message: "Enter the correct path:",
|
|
4767
|
+
placeholder: broken.targetPath,
|
|
4768
|
+
validate: (value) => {
|
|
4769
|
+
if (!value || value.trim().length === 0) {
|
|
4770
|
+
return "Path cannot be empty";
|
|
4771
|
+
}
|
|
4772
|
+
}
|
|
4773
|
+
});
|
|
4774
|
+
if (p10.isCancel(customPath)) {
|
|
4775
|
+
console.log("");
|
|
4776
|
+
p10.cancel("Fix operation cancelled");
|
|
4777
|
+
console.log(
|
|
4778
|
+
chalk14.dim(`
|
|
4779
|
+
Fixed: ${fixedCount}, Skipped: ${skippedCount}`)
|
|
4780
|
+
);
|
|
4781
|
+
process.exit(0);
|
|
4782
|
+
}
|
|
4783
|
+
newPath = customPath;
|
|
4784
|
+
} else {
|
|
4785
|
+
newPath = choice;
|
|
4786
|
+
}
|
|
4787
|
+
try {
|
|
4788
|
+
await applyReferenceFix(broken.file, broken.rawLink, newPath);
|
|
4789
|
+
console.log(chalk14.green(` \u2705 Fixed: ${broken.targetPath} \u2192 ${newPath}`));
|
|
4790
|
+
fixedCount++;
|
|
4791
|
+
} catch (error) {
|
|
4792
|
+
console.log(
|
|
4793
|
+
chalk14.red(
|
|
4794
|
+
` \u274C Failed to fix: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
4795
|
+
)
|
|
4796
|
+
);
|
|
4797
|
+
skippedCount++;
|
|
4798
|
+
}
|
|
4799
|
+
}
|
|
4800
|
+
console.log("");
|
|
4801
|
+
console.log(chalk14.cyan(`\u{1F4CA} Summary:`));
|
|
4802
|
+
console.log(chalk14.green(` Fixed: ${fixedCount}`));
|
|
4803
|
+
if (skippedCount > 0) {
|
|
4804
|
+
console.log(chalk14.yellow(` Skipped: ${skippedCount}`));
|
|
4805
|
+
}
|
|
4806
|
+
if (fixedCount > 0) {
|
|
4807
|
+
p10.outro(chalk14.green("Document references fixed!"));
|
|
4808
|
+
} else {
|
|
4809
|
+
p10.outro(chalk14.yellow("No references were fixed"));
|
|
4810
|
+
}
|
|
4811
|
+
} catch (error) {
|
|
4812
|
+
spinner10.stop("Scan failed");
|
|
4813
|
+
console.log("");
|
|
4814
|
+
p10.cancel(
|
|
4815
|
+
`Validation error: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
4816
|
+
);
|
|
4817
|
+
process.exit(1);
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
|
|
4821
|
+
// src/cli/commands/learn.ts
|
|
4822
|
+
import chalk15 from "chalk";
|
|
4823
|
+
import * as p11 from "@clack/prompts";
|
|
4655
4824
|
import {
|
|
4656
4825
|
PatternStore as PatternStore2,
|
|
4657
4826
|
ContributorManager as ContributorManager2,
|
|
@@ -4674,10 +4843,10 @@ function formatTags(tags) {
|
|
|
4674
4843
|
async function learnRecordCommand(options) {
|
|
4675
4844
|
const cwd = getWorkspacePath();
|
|
4676
4845
|
const store = new PatternStore2(cwd);
|
|
4677
|
-
console.log(
|
|
4846
|
+
console.log(chalk15.cyan("\n\u{1F4DA} Record a Learning Pattern\n"));
|
|
4678
4847
|
let patternType = options.type;
|
|
4679
4848
|
if (!patternType) {
|
|
4680
|
-
const typeChoice = await
|
|
4849
|
+
const typeChoice = await p11.select({
|
|
4681
4850
|
message: "What type of pattern are you recording?",
|
|
4682
4851
|
options: [
|
|
4683
4852
|
{
|
|
@@ -4690,15 +4859,15 @@ async function learnRecordCommand(options) {
|
|
|
4690
4859
|
}
|
|
4691
4860
|
]
|
|
4692
4861
|
});
|
|
4693
|
-
if (
|
|
4694
|
-
|
|
4862
|
+
if (p11.isCancel(typeChoice)) {
|
|
4863
|
+
p11.cancel("Recording cancelled");
|
|
4695
4864
|
process.exit(0);
|
|
4696
4865
|
}
|
|
4697
4866
|
patternType = typeChoice;
|
|
4698
4867
|
}
|
|
4699
4868
|
let name = options.name;
|
|
4700
4869
|
if (!name) {
|
|
4701
|
-
const nameInput = await
|
|
4870
|
+
const nameInput = await p11.text({
|
|
4702
4871
|
message: "Pattern name:",
|
|
4703
4872
|
placeholder: "e.g., Next.js App Router Migration",
|
|
4704
4873
|
validate: (value) => {
|
|
@@ -4708,15 +4877,15 @@ async function learnRecordCommand(options) {
|
|
|
4708
4877
|
return void 0;
|
|
4709
4878
|
}
|
|
4710
4879
|
});
|
|
4711
|
-
if (
|
|
4712
|
-
|
|
4880
|
+
if (p11.isCancel(nameInput)) {
|
|
4881
|
+
p11.cancel("Recording cancelled");
|
|
4713
4882
|
process.exit(0);
|
|
4714
4883
|
}
|
|
4715
4884
|
name = nameInput;
|
|
4716
4885
|
}
|
|
4717
4886
|
let description = options.description;
|
|
4718
4887
|
if (!description) {
|
|
4719
|
-
const descInput = await
|
|
4888
|
+
const descInput = await p11.text({
|
|
4720
4889
|
message: "Description:",
|
|
4721
4890
|
placeholder: "What does this pattern solve?",
|
|
4722
4891
|
validate: (value) => {
|
|
@@ -4727,40 +4896,40 @@ async function learnRecordCommand(options) {
|
|
|
4727
4896
|
return void 0;
|
|
4728
4897
|
}
|
|
4729
4898
|
});
|
|
4730
|
-
if (
|
|
4731
|
-
|
|
4899
|
+
if (p11.isCancel(descInput)) {
|
|
4900
|
+
p11.cancel("Recording cancelled");
|
|
4732
4901
|
process.exit(0);
|
|
4733
4902
|
}
|
|
4734
4903
|
description = descInput;
|
|
4735
4904
|
}
|
|
4736
4905
|
let framework = options.framework;
|
|
4737
4906
|
if (!framework) {
|
|
4738
|
-
const fwInput = await
|
|
4907
|
+
const fwInput = await p11.text({
|
|
4739
4908
|
message: "Framework:",
|
|
4740
4909
|
placeholder: "e.g., next, react, vue, express"
|
|
4741
4910
|
});
|
|
4742
|
-
if (
|
|
4743
|
-
|
|
4911
|
+
if (p11.isCancel(fwInput)) {
|
|
4912
|
+
p11.cancel("Recording cancelled");
|
|
4744
4913
|
process.exit(0);
|
|
4745
4914
|
}
|
|
4746
4915
|
framework = fwInput;
|
|
4747
4916
|
}
|
|
4748
4917
|
let version = options.version;
|
|
4749
4918
|
if (!version) {
|
|
4750
|
-
const versionInput = await
|
|
4919
|
+
const versionInput = await p11.text({
|
|
4751
4920
|
message: "Framework version (semver range):",
|
|
4752
4921
|
placeholder: "e.g., >=14.0.0, ^18.0.0",
|
|
4753
4922
|
initialValue: ">=1.0.0"
|
|
4754
4923
|
});
|
|
4755
|
-
if (
|
|
4756
|
-
|
|
4924
|
+
if (p11.isCancel(versionInput)) {
|
|
4925
|
+
p11.cancel("Recording cancelled");
|
|
4757
4926
|
process.exit(0);
|
|
4758
4927
|
}
|
|
4759
4928
|
version = versionInput;
|
|
4760
4929
|
}
|
|
4761
4930
|
let category = options.category;
|
|
4762
4931
|
if (patternType === "fix" && !category) {
|
|
4763
|
-
const catChoice = await
|
|
4932
|
+
const catChoice = await p11.select({
|
|
4764
4933
|
message: "Category:",
|
|
4765
4934
|
options: [
|
|
4766
4935
|
{ value: "migration", label: "\u{1F504} Migration" },
|
|
@@ -4775,8 +4944,8 @@ async function learnRecordCommand(options) {
|
|
|
4775
4944
|
{ value: "other", label: "\u{1F4E6} Other" }
|
|
4776
4945
|
]
|
|
4777
4946
|
});
|
|
4778
|
-
if (
|
|
4779
|
-
|
|
4947
|
+
if (p11.isCancel(catChoice)) {
|
|
4948
|
+
p11.cancel("Recording cancelled");
|
|
4780
4949
|
process.exit(0);
|
|
4781
4950
|
}
|
|
4782
4951
|
category = catChoice;
|
|
@@ -4839,14 +5008,14 @@ async function learnRecordCommand(options) {
|
|
|
4839
5008
|
};
|
|
4840
5009
|
const result = await store.saveFixPattern(fixPattern);
|
|
4841
5010
|
if (result.success) {
|
|
4842
|
-
console.log(
|
|
4843
|
-
console.log(
|
|
4844
|
-
console.log(
|
|
4845
|
-
console.log(
|
|
4846
|
-
console.log(
|
|
5011
|
+
console.log(chalk15.green("\n\u2705 Fix pattern recorded successfully!\n"));
|
|
5012
|
+
console.log(chalk15.dim(` ID: ${fixPattern.id}`));
|
|
5013
|
+
console.log(chalk15.dim(` Name: ${name}`));
|
|
5014
|
+
console.log(chalk15.dim(` Category: ${category}`));
|
|
5015
|
+
console.log(chalk15.dim(` Framework: ${framework} ${version}`));
|
|
4847
5016
|
} else {
|
|
4848
|
-
console.log(
|
|
4849
|
-
console.log(
|
|
5017
|
+
console.log(chalk15.red("\n\u274C Failed to record pattern"));
|
|
5018
|
+
console.log(chalk15.dim(` Error: ${result.error}`));
|
|
4850
5019
|
process.exit(1);
|
|
4851
5020
|
}
|
|
4852
5021
|
} else {
|
|
@@ -4893,13 +5062,13 @@ async function learnRecordCommand(options) {
|
|
|
4893
5062
|
};
|
|
4894
5063
|
const result = await store.saveBlueprint(blueprint);
|
|
4895
5064
|
if (result.success) {
|
|
4896
|
-
console.log(
|
|
4897
|
-
console.log(
|
|
4898
|
-
console.log(
|
|
4899
|
-
console.log(
|
|
5065
|
+
console.log(chalk15.green("\n\u2705 Blueprint recorded successfully!\n"));
|
|
5066
|
+
console.log(chalk15.dim(` ID: ${blueprint.id}`));
|
|
5067
|
+
console.log(chalk15.dim(` Name: ${name}`));
|
|
5068
|
+
console.log(chalk15.dim(` Framework: ${framework} ${version}`));
|
|
4900
5069
|
} else {
|
|
4901
|
-
console.log(
|
|
4902
|
-
console.log(
|
|
5070
|
+
console.log(chalk15.red("\n\u274C Failed to record blueprint"));
|
|
5071
|
+
console.log(chalk15.dim(` Error: ${result.error}`));
|
|
4903
5072
|
process.exit(1);
|
|
4904
5073
|
}
|
|
4905
5074
|
}
|
|
@@ -4909,7 +5078,7 @@ async function learnListCommand(options) {
|
|
|
4909
5078
|
const store = new PatternStore2(cwd);
|
|
4910
5079
|
const patternType = options.type ?? "all";
|
|
4911
5080
|
const showDeprecated = options.deprecated ?? false;
|
|
4912
|
-
console.log(
|
|
5081
|
+
console.log(chalk15.cyan("\n\u{1F4DA} Recorded Learning Patterns\n"));
|
|
4913
5082
|
if (patternType === "all" || patternType === "fix") {
|
|
4914
5083
|
const fixResult = await store.listFixPatterns({
|
|
4915
5084
|
tags: options.tag ? [{ category: "framework", name: options.tag }] : void 0,
|
|
@@ -4917,29 +5086,29 @@ async function learnListCommand(options) {
|
|
|
4917
5086
|
includeDeprecated: showDeprecated
|
|
4918
5087
|
});
|
|
4919
5088
|
if (fixResult.success && fixResult.data && fixResult.data.length > 0) {
|
|
4920
|
-
console.log(
|
|
5089
|
+
console.log(chalk15.bold.yellow("\u{1F527} Fix Patterns:\n"));
|
|
4921
5090
|
for (const pattern of fixResult.data) {
|
|
4922
5091
|
const isDeprecated = pattern.deprecatedAt !== void 0;
|
|
4923
5092
|
const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
|
|
4924
|
-
const nameColor = isDeprecated ?
|
|
5093
|
+
const nameColor = isDeprecated ? chalk15.dim : chalk15.white;
|
|
4925
5094
|
console.log(` ${statusIcon} ${nameColor(pattern.name)}`);
|
|
4926
|
-
console.log(
|
|
4927
|
-
console.log(
|
|
5095
|
+
console.log(chalk15.dim(` ID: ${pattern.id}`));
|
|
5096
|
+
console.log(chalk15.dim(` Category: ${pattern.category}`));
|
|
4928
5097
|
console.log(
|
|
4929
|
-
|
|
5098
|
+
chalk15.dim(` Created: ${formatDate(pattern.createdAt)}`)
|
|
4930
5099
|
);
|
|
4931
5100
|
console.log(
|
|
4932
|
-
|
|
5101
|
+
chalk15.dim(
|
|
4933
5102
|
` Success Rate: ${(pattern.metrics.successRate * 100).toFixed(0)}% (${pattern.metrics.successes}/${pattern.metrics.applications})`
|
|
4934
5103
|
)
|
|
4935
5104
|
);
|
|
4936
5105
|
if (pattern.tags.length > 0) {
|
|
4937
|
-
console.log(
|
|
5106
|
+
console.log(chalk15.dim(` Tags: ${formatTags(pattern.tags)}`));
|
|
4938
5107
|
}
|
|
4939
5108
|
console.log("");
|
|
4940
5109
|
}
|
|
4941
5110
|
} else if (patternType === "fix") {
|
|
4942
|
-
console.log(
|
|
5111
|
+
console.log(chalk15.dim(" No fix patterns found.\n"));
|
|
4943
5112
|
}
|
|
4944
5113
|
}
|
|
4945
5114
|
if (patternType === "all" || patternType === "blueprint") {
|
|
@@ -4949,46 +5118,46 @@ async function learnListCommand(options) {
|
|
|
4949
5118
|
includeDeprecated: showDeprecated
|
|
4950
5119
|
});
|
|
4951
5120
|
if (bpResult.success && bpResult.data && bpResult.data.length > 0) {
|
|
4952
|
-
console.log(
|
|
5121
|
+
console.log(chalk15.bold.blue("\u{1F4D0} Blueprints:\n"));
|
|
4953
5122
|
for (const blueprint of bpResult.data) {
|
|
4954
5123
|
const isDeprecated = blueprint.deprecatedAt !== void 0;
|
|
4955
5124
|
const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
|
|
4956
|
-
const nameColor = isDeprecated ?
|
|
5125
|
+
const nameColor = isDeprecated ? chalk15.dim : chalk15.white;
|
|
4957
5126
|
console.log(` ${statusIcon} ${nameColor(blueprint.name)}`);
|
|
4958
|
-
console.log(
|
|
4959
|
-
console.log(
|
|
5127
|
+
console.log(chalk15.dim(` ID: ${blueprint.id}`));
|
|
5128
|
+
console.log(chalk15.dim(` Language: ${blueprint.stack.language}`));
|
|
4960
5129
|
console.log(
|
|
4961
|
-
|
|
5130
|
+
chalk15.dim(` Created: ${formatDate(blueprint.createdAt)}`)
|
|
4962
5131
|
);
|
|
4963
5132
|
console.log(
|
|
4964
|
-
|
|
5133
|
+
chalk15.dim(
|
|
4965
5134
|
` Success Rate: ${(blueprint.metrics.successRate * 100).toFixed(0)}% (${blueprint.metrics.successes}/${blueprint.metrics.applications})`
|
|
4966
5135
|
)
|
|
4967
5136
|
);
|
|
4968
5137
|
if (blueprint.tags.length > 0) {
|
|
4969
|
-
console.log(
|
|
5138
|
+
console.log(chalk15.dim(` Tags: ${formatTags(blueprint.tags)}`));
|
|
4970
5139
|
}
|
|
4971
5140
|
console.log("");
|
|
4972
5141
|
}
|
|
4973
5142
|
} else if (patternType === "blueprint") {
|
|
4974
|
-
console.log(
|
|
5143
|
+
console.log(chalk15.dim(" No blueprints found.\n"));
|
|
4975
5144
|
}
|
|
4976
5145
|
}
|
|
4977
5146
|
const stats = await store.getStats();
|
|
4978
5147
|
const totalPatterns = stats.totalFixes + stats.totalBlueprints;
|
|
4979
5148
|
const totalDeprecated = stats.deprecatedFixes + stats.deprecatedBlueprints;
|
|
4980
|
-
console.log(
|
|
4981
|
-
console.log(
|
|
4982
|
-
console.log(
|
|
4983
|
-
console.log(
|
|
4984
|
-
console.log(
|
|
5149
|
+
console.log(chalk15.dim("\u2501".repeat(40)));
|
|
5150
|
+
console.log(chalk15.dim(`Total: ${totalPatterns} patterns`));
|
|
5151
|
+
console.log(chalk15.dim(` Fix Patterns: ${stats.totalFixes}`));
|
|
5152
|
+
console.log(chalk15.dim(` Blueprints: ${stats.totalBlueprints}`));
|
|
5153
|
+
console.log(chalk15.dim(` Deprecated: ${totalDeprecated}`));
|
|
4985
5154
|
console.log("");
|
|
4986
5155
|
}
|
|
4987
5156
|
async function learnApplyCommand(patternId, options) {
|
|
4988
5157
|
const cwd = getWorkspacePath();
|
|
4989
5158
|
const store = new PatternStore2(cwd);
|
|
4990
5159
|
const telemetry = new TelemetryCollector2(cwd);
|
|
4991
|
-
console.log(
|
|
5160
|
+
console.log(chalk15.cyan("\n\u{1F527} Apply Learning Pattern\n"));
|
|
4992
5161
|
let pattern = await store.getFixPattern(patternId);
|
|
4993
5162
|
let patternType = "fix";
|
|
4994
5163
|
if (!pattern.success || !pattern.data) {
|
|
@@ -4997,21 +5166,21 @@ async function learnApplyCommand(patternId, options) {
|
|
|
4997
5166
|
pattern = bpResult;
|
|
4998
5167
|
patternType = "blueprint";
|
|
4999
5168
|
} else {
|
|
5000
|
-
console.log(
|
|
5169
|
+
console.log(chalk15.red(`
|
|
5001
5170
|
\u274C Pattern not found: ${patternId}`));
|
|
5002
5171
|
console.log(
|
|
5003
|
-
|
|
5172
|
+
chalk15.dim(" Use 'workflow learn:list' to see available patterns")
|
|
5004
5173
|
);
|
|
5005
5174
|
process.exit(1);
|
|
5006
5175
|
}
|
|
5007
5176
|
}
|
|
5008
5177
|
const patternData = pattern.data;
|
|
5009
|
-
console.log(
|
|
5010
|
-
console.log(
|
|
5011
|
-
console.log(
|
|
5178
|
+
console.log(chalk15.white(` Pattern: ${patternData.name}`));
|
|
5179
|
+
console.log(chalk15.dim(` Type: ${patternType}`));
|
|
5180
|
+
console.log(chalk15.dim(` Description: ${patternData.description}`));
|
|
5012
5181
|
if (options.dryRun) {
|
|
5013
5182
|
console.log(
|
|
5014
|
-
|
|
5183
|
+
chalk15.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n")
|
|
5015
5184
|
);
|
|
5016
5185
|
}
|
|
5017
5186
|
const framework = options.framework ?? patternData.compatibility.frameworks[0]?.name ?? "unknown";
|
|
@@ -5019,44 +5188,44 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5019
5188
|
await telemetry.recordApplication(patternId, patternType, framework, version);
|
|
5020
5189
|
if (patternType === "fix") {
|
|
5021
5190
|
const fixPattern = patternData;
|
|
5022
|
-
console.log(
|
|
5191
|
+
console.log(chalk15.cyan("\n\u{1F4CB} Solution Steps:\n"));
|
|
5023
5192
|
if (fixPattern.solution.steps) {
|
|
5024
5193
|
for (let i = 0; i < fixPattern.solution.steps.length; i++) {
|
|
5025
5194
|
const step = fixPattern.solution.steps[i];
|
|
5026
5195
|
console.log(
|
|
5027
|
-
|
|
5196
|
+
chalk15.white(` ${i + 1}. [${step.action}] ${step.description}`)
|
|
5028
5197
|
);
|
|
5029
5198
|
if (step.file) {
|
|
5030
|
-
console.log(
|
|
5199
|
+
console.log(chalk15.dim(` File: ${step.file}`));
|
|
5031
5200
|
}
|
|
5032
5201
|
}
|
|
5033
5202
|
}
|
|
5034
5203
|
} else {
|
|
5035
5204
|
const blueprint = patternData;
|
|
5036
|
-
console.log(
|
|
5205
|
+
console.log(chalk15.cyan("\n\u{1F4CB} Setup Steps:\n"));
|
|
5037
5206
|
if (blueprint.setup.steps) {
|
|
5038
5207
|
for (let i = 0; i < blueprint.setup.steps.length; i++) {
|
|
5039
5208
|
const step = blueprint.setup.steps[i];
|
|
5040
|
-
console.log(
|
|
5209
|
+
console.log(chalk15.white(` ${i + 1}. ${step.description}`));
|
|
5041
5210
|
if (step.command) {
|
|
5042
|
-
console.log(
|
|
5211
|
+
console.log(chalk15.dim(` Command: ${step.command}`));
|
|
5043
5212
|
}
|
|
5044
5213
|
}
|
|
5045
5214
|
}
|
|
5046
5215
|
}
|
|
5047
5216
|
if (!options.dryRun) {
|
|
5048
|
-
const confirmed = await
|
|
5217
|
+
const confirmed = await p11.confirm({
|
|
5049
5218
|
message: "Mark this pattern as successfully applied?",
|
|
5050
5219
|
initialValue: true
|
|
5051
5220
|
});
|
|
5052
|
-
if (
|
|
5053
|
-
|
|
5221
|
+
if (p11.isCancel(confirmed)) {
|
|
5222
|
+
p11.cancel("Application cancelled");
|
|
5054
5223
|
process.exit(0);
|
|
5055
5224
|
}
|
|
5056
5225
|
if (confirmed) {
|
|
5057
5226
|
await store.updatePatternMetrics(patternId, patternType, true);
|
|
5058
5227
|
await telemetry.recordSuccess(patternId, patternType, framework, version);
|
|
5059
|
-
console.log(
|
|
5228
|
+
console.log(chalk15.green("\n\u2705 Pattern marked as successfully applied!"));
|
|
5060
5229
|
} else {
|
|
5061
5230
|
await store.updatePatternMetrics(patternId, patternType, false);
|
|
5062
5231
|
await telemetry.recordFailure(
|
|
@@ -5067,7 +5236,7 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5067
5236
|
"unknown"
|
|
5068
5237
|
);
|
|
5069
5238
|
console.log(
|
|
5070
|
-
|
|
5239
|
+
chalk15.yellow("\n\u26A0\uFE0F Pattern application marked as unsuccessful.")
|
|
5071
5240
|
);
|
|
5072
5241
|
}
|
|
5073
5242
|
}
|
|
@@ -5075,32 +5244,32 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5075
5244
|
async function learnSyncCommand(options) {
|
|
5076
5245
|
const cwd = getWorkspacePath();
|
|
5077
5246
|
const contributorManager = new ContributorManager2(cwd);
|
|
5078
|
-
console.log(
|
|
5247
|
+
console.log(chalk15.cyan("\n\u{1F504} Sync Learning Patterns\n"));
|
|
5079
5248
|
const config = await contributorManager.getConfig();
|
|
5080
5249
|
if (!config.success || !config.data?.syncOptIn) {
|
|
5081
|
-
console.log(
|
|
5082
|
-
console.log(
|
|
5083
|
-
console.log(
|
|
5250
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Sync is not enabled.\n"));
|
|
5251
|
+
console.log(chalk15.dim(" To enable sync, run:"));
|
|
5252
|
+
console.log(chalk15.dim(" workflow learn:config --enable-sync\n"));
|
|
5084
5253
|
console.log(
|
|
5085
|
-
|
|
5254
|
+
chalk15.dim(
|
|
5086
5255
|
" This allows you to share anonymized patterns with the community."
|
|
5087
5256
|
)
|
|
5088
5257
|
);
|
|
5089
5258
|
process.exit(0);
|
|
5090
5259
|
}
|
|
5091
5260
|
if (options.dryRun) {
|
|
5092
|
-
console.log(
|
|
5261
|
+
console.log(chalk15.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be synced\n"));
|
|
5093
5262
|
}
|
|
5094
5263
|
const store = new PatternStore2(cwd);
|
|
5095
5264
|
const anonymizer = new PatternAnonymizer();
|
|
5096
5265
|
const { fixes, blueprints } = await store.getPatternsForSync();
|
|
5097
5266
|
console.log(
|
|
5098
|
-
|
|
5267
|
+
chalk15.dim(
|
|
5099
5268
|
` Patterns ready to sync: ${fixes.length} fixes, ${blueprints.length} blueprints`
|
|
5100
5269
|
)
|
|
5101
5270
|
);
|
|
5102
5271
|
if (options.push) {
|
|
5103
|
-
console.log(
|
|
5272
|
+
console.log(chalk15.cyan("\n\u{1F4E4} Pushing patterns...\n"));
|
|
5104
5273
|
let anonymizedFixes = 0;
|
|
5105
5274
|
let anonymizedBlueprints = 0;
|
|
5106
5275
|
for (const fix of fixes) {
|
|
@@ -5108,7 +5277,7 @@ async function learnSyncCommand(options) {
|
|
|
5108
5277
|
if (result.success) {
|
|
5109
5278
|
anonymizedFixes++;
|
|
5110
5279
|
if (!options.dryRun) {
|
|
5111
|
-
console.log(
|
|
5280
|
+
console.log(chalk15.dim(` \u2713 Anonymized: ${fix.name}`));
|
|
5112
5281
|
}
|
|
5113
5282
|
}
|
|
5114
5283
|
}
|
|
@@ -5117,117 +5286,117 @@ async function learnSyncCommand(options) {
|
|
|
5117
5286
|
if (result.success) {
|
|
5118
5287
|
anonymizedBlueprints++;
|
|
5119
5288
|
if (!options.dryRun) {
|
|
5120
|
-
console.log(
|
|
5289
|
+
console.log(chalk15.dim(` \u2713 Anonymized: ${bp.name}`));
|
|
5121
5290
|
}
|
|
5122
5291
|
}
|
|
5123
5292
|
}
|
|
5124
5293
|
console.log(
|
|
5125
|
-
|
|
5294
|
+
chalk15.green(
|
|
5126
5295
|
`
|
|
5127
5296
|
\u2705 Ready to push ${anonymizedFixes} fixes and ${anonymizedBlueprints} blueprints`
|
|
5128
5297
|
)
|
|
5129
5298
|
);
|
|
5130
|
-
console.log(
|
|
5299
|
+
console.log(chalk15.dim(" (Registry push not yet implemented)"));
|
|
5131
5300
|
}
|
|
5132
5301
|
if (options.pull) {
|
|
5133
|
-
console.log(
|
|
5134
|
-
console.log(
|
|
5302
|
+
console.log(chalk15.cyan("\n\u{1F4E5} Pulling patterns from registry...\n"));
|
|
5303
|
+
console.log(chalk15.dim(" (Registry pull not yet implemented)"));
|
|
5135
5304
|
}
|
|
5136
5305
|
if (!options.push && !options.pull) {
|
|
5137
5306
|
console.log(
|
|
5138
|
-
|
|
5307
|
+
chalk15.dim(" Specify --push to upload or --pull to download patterns.\n")
|
|
5139
5308
|
);
|
|
5140
5309
|
}
|
|
5141
5310
|
}
|
|
5142
5311
|
async function learnConfigCommand(options) {
|
|
5143
5312
|
const cwd = getWorkspacePath();
|
|
5144
5313
|
const contributorManager = new ContributorManager2(cwd);
|
|
5145
|
-
console.log(
|
|
5314
|
+
console.log(chalk15.cyan("\n\u2699\uFE0F Learning Configuration\n"));
|
|
5146
5315
|
if (options.enableSync) {
|
|
5147
5316
|
const result = await contributorManager.enableSync();
|
|
5148
5317
|
if (result.success) {
|
|
5149
|
-
console.log(
|
|
5318
|
+
console.log(chalk15.green("\u2705 Sync enabled"));
|
|
5150
5319
|
console.log(
|
|
5151
|
-
|
|
5320
|
+
chalk15.dim(" Your patterns will be anonymized before sharing.")
|
|
5152
5321
|
);
|
|
5153
5322
|
} else {
|
|
5154
|
-
console.log(
|
|
5323
|
+
console.log(chalk15.red(`\u274C Failed: ${result.error}`));
|
|
5155
5324
|
}
|
|
5156
5325
|
return;
|
|
5157
5326
|
}
|
|
5158
5327
|
if (options.disableSync) {
|
|
5159
5328
|
const result = await contributorManager.disableSync();
|
|
5160
5329
|
if (result.success) {
|
|
5161
|
-
console.log(
|
|
5330
|
+
console.log(chalk15.green("\u2705 Sync disabled"));
|
|
5162
5331
|
} else {
|
|
5163
|
-
console.log(
|
|
5332
|
+
console.log(chalk15.red(`\u274C Failed: ${result.error}`));
|
|
5164
5333
|
}
|
|
5165
5334
|
return;
|
|
5166
5335
|
}
|
|
5167
5336
|
if (options.enableTelemetry) {
|
|
5168
5337
|
const result = await contributorManager.enableTelemetry();
|
|
5169
5338
|
if (result.success) {
|
|
5170
|
-
console.log(
|
|
5339
|
+
console.log(chalk15.green("\u2705 Telemetry enabled"));
|
|
5171
5340
|
console.log(
|
|
5172
|
-
|
|
5341
|
+
chalk15.dim(
|
|
5173
5342
|
" Anonymous usage data helps improve pattern recommendations."
|
|
5174
5343
|
)
|
|
5175
5344
|
);
|
|
5176
5345
|
} else {
|
|
5177
|
-
console.log(
|
|
5346
|
+
console.log(chalk15.red(`\u274C Failed: ${result.error}`));
|
|
5178
5347
|
}
|
|
5179
5348
|
return;
|
|
5180
5349
|
}
|
|
5181
5350
|
if (options.disableTelemetry) {
|
|
5182
5351
|
const result = await contributorManager.disableTelemetry();
|
|
5183
5352
|
if (result.success) {
|
|
5184
|
-
console.log(
|
|
5353
|
+
console.log(chalk15.green("\u2705 Telemetry disabled"));
|
|
5185
5354
|
} else {
|
|
5186
|
-
console.log(
|
|
5355
|
+
console.log(chalk15.red(`\u274C Failed: ${result.error}`));
|
|
5187
5356
|
}
|
|
5188
5357
|
return;
|
|
5189
5358
|
}
|
|
5190
5359
|
if (options.resetId) {
|
|
5191
|
-
const confirmed = await
|
|
5360
|
+
const confirmed = await p11.confirm({
|
|
5192
5361
|
message: "Are you sure you want to reset your contributor ID? This cannot be undone.",
|
|
5193
5362
|
initialValue: false
|
|
5194
5363
|
});
|
|
5195
|
-
if (
|
|
5196
|
-
|
|
5364
|
+
if (p11.isCancel(confirmed) || !confirmed) {
|
|
5365
|
+
p11.cancel("Reset cancelled");
|
|
5197
5366
|
return;
|
|
5198
5367
|
}
|
|
5199
5368
|
const result = await contributorManager.resetId();
|
|
5200
5369
|
if (result.success) {
|
|
5201
|
-
console.log(
|
|
5202
|
-
console.log(
|
|
5370
|
+
console.log(chalk15.green("\u2705 Contributor ID reset"));
|
|
5371
|
+
console.log(chalk15.dim(` New ID: ${result.data?.id}`));
|
|
5203
5372
|
} else {
|
|
5204
|
-
console.log(
|
|
5373
|
+
console.log(chalk15.red(`\u274C Failed: ${result.error}`));
|
|
5205
5374
|
}
|
|
5206
5375
|
return;
|
|
5207
5376
|
}
|
|
5208
5377
|
const config = await contributorManager.getConfig();
|
|
5209
5378
|
if (config.success && config.data) {
|
|
5210
|
-
console.log(
|
|
5211
|
-
console.log(
|
|
5212
|
-
console.log(
|
|
5379
|
+
console.log(chalk15.white(" Current Settings:\n"));
|
|
5380
|
+
console.log(chalk15.dim(` Contributor ID: ${config.data.id}`));
|
|
5381
|
+
console.log(chalk15.dim(` Created: ${formatDate(config.data.createdAt)}`));
|
|
5213
5382
|
console.log(
|
|
5214
|
-
|
|
5383
|
+
chalk15.dim(` Sync Enabled: ${config.data.syncOptIn ? "Yes" : "No"}`)
|
|
5215
5384
|
);
|
|
5216
5385
|
console.log(
|
|
5217
|
-
|
|
5386
|
+
chalk15.dim(
|
|
5218
5387
|
` Telemetry Enabled: ${config.data.telemetryEnabled ? "Yes" : "No"}`
|
|
5219
5388
|
)
|
|
5220
5389
|
);
|
|
5221
5390
|
if (config.data.syncEnabledAt) {
|
|
5222
5391
|
console.log(
|
|
5223
|
-
|
|
5392
|
+
chalk15.dim(
|
|
5224
5393
|
` Sync Enabled At: ${formatDate(config.data.syncEnabledAt)}`
|
|
5225
5394
|
)
|
|
5226
5395
|
);
|
|
5227
5396
|
}
|
|
5228
5397
|
} else {
|
|
5229
5398
|
console.log(
|
|
5230
|
-
|
|
5399
|
+
chalk15.dim(
|
|
5231
5400
|
" No configuration found. Settings will be created on first use.\n"
|
|
5232
5401
|
)
|
|
5233
5402
|
);
|
|
@@ -5236,7 +5405,7 @@ async function learnConfigCommand(options) {
|
|
|
5236
5405
|
async function learnDeprecateCommand(patternId, reason) {
|
|
5237
5406
|
const cwd = getWorkspacePath();
|
|
5238
5407
|
const store = new PatternStore2(cwd);
|
|
5239
|
-
console.log(
|
|
5408
|
+
console.log(chalk15.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
|
|
5240
5409
|
let patternType = "fix";
|
|
5241
5410
|
let pattern = await store.getFixPattern(patternId);
|
|
5242
5411
|
if (!pattern.success || !pattern.data) {
|
|
@@ -5245,26 +5414,26 @@ async function learnDeprecateCommand(patternId, reason) {
|
|
|
5245
5414
|
pattern = bpResult;
|
|
5246
5415
|
patternType = "blueprint";
|
|
5247
5416
|
} else {
|
|
5248
|
-
console.log(
|
|
5417
|
+
console.log(chalk15.red(`
|
|
5249
5418
|
\u274C Pattern not found: ${patternId}`));
|
|
5250
5419
|
process.exit(1);
|
|
5251
5420
|
}
|
|
5252
5421
|
}
|
|
5253
|
-
console.log(
|
|
5254
|
-
console.log(
|
|
5255
|
-
const confirmed = await
|
|
5422
|
+
console.log(chalk15.white(` Pattern: ${pattern.data.name}`));
|
|
5423
|
+
console.log(chalk15.dim(` Reason: ${reason}`));
|
|
5424
|
+
const confirmed = await p11.confirm({
|
|
5256
5425
|
message: "Are you sure you want to deprecate this pattern?",
|
|
5257
5426
|
initialValue: false
|
|
5258
5427
|
});
|
|
5259
|
-
if (
|
|
5260
|
-
|
|
5428
|
+
if (p11.isCancel(confirmed) || !confirmed) {
|
|
5429
|
+
p11.cancel("Deprecation cancelled");
|
|
5261
5430
|
return;
|
|
5262
5431
|
}
|
|
5263
5432
|
const result = await store.deprecatePattern(patternId, patternType, reason);
|
|
5264
5433
|
if (result.success) {
|
|
5265
|
-
console.log(
|
|
5434
|
+
console.log(chalk15.green("\n\u2705 Pattern deprecated successfully"));
|
|
5266
5435
|
} else {
|
|
5267
|
-
console.log(
|
|
5436
|
+
console.log(chalk15.red(`
|
|
5268
5437
|
\u274C Failed: ${result.error}`));
|
|
5269
5438
|
process.exit(1);
|
|
5270
5439
|
}
|
|
@@ -5273,32 +5442,32 @@ async function learnStatsCommand() {
|
|
|
5273
5442
|
const cwd = getWorkspacePath();
|
|
5274
5443
|
const store = new PatternStore2(cwd);
|
|
5275
5444
|
const telemetry = new TelemetryCollector2(cwd);
|
|
5276
|
-
console.log(
|
|
5445
|
+
console.log(chalk15.cyan("\n\u{1F4CA} Learning Statistics\n"));
|
|
5277
5446
|
const storeStats = await store.getStats();
|
|
5278
5447
|
const totalPatterns = storeStats.totalFixes + storeStats.totalBlueprints;
|
|
5279
5448
|
const totalDeprecated = storeStats.deprecatedFixes + storeStats.deprecatedBlueprints;
|
|
5280
|
-
console.log(
|
|
5281
|
-
console.log(
|
|
5282
|
-
console.log(
|
|
5283
|
-
console.log(
|
|
5284
|
-
console.log(
|
|
5449
|
+
console.log(chalk15.bold.white(" Patterns:\n"));
|
|
5450
|
+
console.log(chalk15.dim(` Total: ${totalPatterns}`));
|
|
5451
|
+
console.log(chalk15.dim(` Fix Patterns: ${storeStats.totalFixes}`));
|
|
5452
|
+
console.log(chalk15.dim(` Blueprints: ${storeStats.totalBlueprints}`));
|
|
5453
|
+
console.log(chalk15.dim(` Deprecated: ${totalDeprecated}`));
|
|
5285
5454
|
const telemetryStats = await telemetry.getStats();
|
|
5286
|
-
console.log(
|
|
5287
|
-
console.log(
|
|
5455
|
+
console.log(chalk15.bold.white("\n Telemetry:\n"));
|
|
5456
|
+
console.log(chalk15.dim(` Pending Events: ${telemetryStats.pendingEvents}`));
|
|
5288
5457
|
console.log(
|
|
5289
|
-
|
|
5458
|
+
chalk15.dim(` Total Events Sent: ${telemetryStats.totalEventsSent}`)
|
|
5290
5459
|
);
|
|
5291
5460
|
if (telemetryStats.lastFlushAt) {
|
|
5292
5461
|
console.log(
|
|
5293
|
-
|
|
5462
|
+
chalk15.dim(` Last Flush: ${formatDate(telemetryStats.lastFlushAt)}`)
|
|
5294
5463
|
);
|
|
5295
5464
|
}
|
|
5296
5465
|
console.log("");
|
|
5297
5466
|
}
|
|
5298
5467
|
|
|
5299
5468
|
// src/cli/commands/solution.ts
|
|
5300
|
-
import
|
|
5301
|
-
import * as
|
|
5469
|
+
import chalk16 from "chalk";
|
|
5470
|
+
import * as p12 from "@clack/prompts";
|
|
5302
5471
|
import * as path2 from "path";
|
|
5303
5472
|
import {
|
|
5304
5473
|
PatternStore as PatternStore3,
|
|
@@ -5340,10 +5509,10 @@ function truncate(str, maxLen) {
|
|
|
5340
5509
|
async function solutionCaptureCommand(options) {
|
|
5341
5510
|
const cwd = getWorkspacePath2();
|
|
5342
5511
|
const store = new PatternStore3(cwd);
|
|
5343
|
-
console.log(
|
|
5512
|
+
console.log(chalk16.cyan("\n\u{1F4E6} Capture Solution Pattern\n"));
|
|
5344
5513
|
let targetPath = options.path;
|
|
5345
5514
|
if (!targetPath) {
|
|
5346
|
-
const pathInput = await
|
|
5515
|
+
const pathInput = await p12.text({
|
|
5347
5516
|
message: "Path to the solution directory:",
|
|
5348
5517
|
placeholder: "./src/auth",
|
|
5349
5518
|
validate: (val) => {
|
|
@@ -5351,8 +5520,8 @@ async function solutionCaptureCommand(options) {
|
|
|
5351
5520
|
return void 0;
|
|
5352
5521
|
}
|
|
5353
5522
|
});
|
|
5354
|
-
if (
|
|
5355
|
-
|
|
5523
|
+
if (p12.isCancel(pathInput)) {
|
|
5524
|
+
p12.cancel("Operation cancelled");
|
|
5356
5525
|
process.exit(0);
|
|
5357
5526
|
}
|
|
5358
5527
|
targetPath = pathInput;
|
|
@@ -5360,7 +5529,7 @@ async function solutionCaptureCommand(options) {
|
|
|
5360
5529
|
const absolutePath = path2.isAbsolute(targetPath) ? targetPath : path2.resolve(cwd, targetPath);
|
|
5361
5530
|
let name = options.name;
|
|
5362
5531
|
if (!name) {
|
|
5363
|
-
const nameInput = await
|
|
5532
|
+
const nameInput = await p12.text({
|
|
5364
5533
|
message: "Solution name:",
|
|
5365
5534
|
placeholder: "JWT Authentication",
|
|
5366
5535
|
validate: (val) => {
|
|
@@ -5368,15 +5537,15 @@ async function solutionCaptureCommand(options) {
|
|
|
5368
5537
|
return void 0;
|
|
5369
5538
|
}
|
|
5370
5539
|
});
|
|
5371
|
-
if (
|
|
5372
|
-
|
|
5540
|
+
if (p12.isCancel(nameInput)) {
|
|
5541
|
+
p12.cancel("Operation cancelled");
|
|
5373
5542
|
process.exit(0);
|
|
5374
5543
|
}
|
|
5375
5544
|
name = nameInput;
|
|
5376
5545
|
}
|
|
5377
5546
|
let description = options.description;
|
|
5378
5547
|
if (!description) {
|
|
5379
|
-
const descInput = await
|
|
5548
|
+
const descInput = await p12.text({
|
|
5380
5549
|
message: "Solution description:",
|
|
5381
5550
|
placeholder: "Complete JWT-based authentication with refresh tokens",
|
|
5382
5551
|
validate: (val) => {
|
|
@@ -5385,15 +5554,15 @@ async function solutionCaptureCommand(options) {
|
|
|
5385
5554
|
return void 0;
|
|
5386
5555
|
}
|
|
5387
5556
|
});
|
|
5388
|
-
if (
|
|
5389
|
-
|
|
5557
|
+
if (p12.isCancel(descInput)) {
|
|
5558
|
+
p12.cancel("Operation cancelled");
|
|
5390
5559
|
process.exit(0);
|
|
5391
5560
|
}
|
|
5392
5561
|
description = descInput;
|
|
5393
5562
|
}
|
|
5394
5563
|
let category = options.category;
|
|
5395
5564
|
if (!category) {
|
|
5396
|
-
const categoryChoice = await
|
|
5565
|
+
const categoryChoice = await p12.select({
|
|
5397
5566
|
message: "Solution category:",
|
|
5398
5567
|
options: [
|
|
5399
5568
|
{ value: "auth", label: "\u{1F510} Authentication" },
|
|
@@ -5412,8 +5581,8 @@ async function solutionCaptureCommand(options) {
|
|
|
5412
5581
|
{ value: "other", label: "\u{1F4E6} Other" }
|
|
5413
5582
|
]
|
|
5414
5583
|
});
|
|
5415
|
-
if (
|
|
5416
|
-
|
|
5584
|
+
if (p12.isCancel(categoryChoice)) {
|
|
5585
|
+
p12.cancel("Operation cancelled");
|
|
5417
5586
|
process.exit(0);
|
|
5418
5587
|
}
|
|
5419
5588
|
category = categoryChoice;
|
|
@@ -5422,20 +5591,20 @@ async function solutionCaptureCommand(options) {
|
|
|
5422
5591
|
if (options.keywords) {
|
|
5423
5592
|
keywords = options.keywords.split(",").map((k) => k.trim());
|
|
5424
5593
|
} else {
|
|
5425
|
-
const keywordsInput = await
|
|
5594
|
+
const keywordsInput = await p12.text({
|
|
5426
5595
|
message: "Keywords (comma-separated):",
|
|
5427
5596
|
placeholder: "jwt, authentication, login, refresh-token"
|
|
5428
5597
|
});
|
|
5429
|
-
if (
|
|
5430
|
-
|
|
5598
|
+
if (p12.isCancel(keywordsInput)) {
|
|
5599
|
+
p12.cancel("Operation cancelled");
|
|
5431
5600
|
process.exit(0);
|
|
5432
5601
|
}
|
|
5433
5602
|
if (keywordsInput) {
|
|
5434
5603
|
keywords = keywordsInput.split(",").map((k) => k.trim());
|
|
5435
5604
|
}
|
|
5436
5605
|
}
|
|
5437
|
-
const
|
|
5438
|
-
|
|
5606
|
+
const spinner10 = p12.spinner();
|
|
5607
|
+
spinner10.start("Analyzing solution...");
|
|
5439
5608
|
const analyzer = new CodeAnalyzer({
|
|
5440
5609
|
anonymize: options.anonymize ?? false
|
|
5441
5610
|
});
|
|
@@ -5447,38 +5616,38 @@ async function solutionCaptureCommand(options) {
|
|
|
5447
5616
|
category,
|
|
5448
5617
|
keywords
|
|
5449
5618
|
);
|
|
5450
|
-
|
|
5451
|
-
console.log(
|
|
5452
|
-
console.log(
|
|
5453
|
-
console.log(`${
|
|
5619
|
+
spinner10.stop("Solution analyzed");
|
|
5620
|
+
console.log(chalk16.green("\n\u2713 Solution captured successfully!\n"));
|
|
5621
|
+
console.log(chalk16.dim("\u2500".repeat(50)));
|
|
5622
|
+
console.log(`${chalk16.bold("Name:")} ${pattern.name}`);
|
|
5454
5623
|
console.log(
|
|
5455
|
-
`${
|
|
5624
|
+
`${chalk16.bold("Category:")} ${formatCategory(pattern.category)}`
|
|
5456
5625
|
);
|
|
5457
5626
|
console.log(
|
|
5458
|
-
`${
|
|
5627
|
+
`${chalk16.bold("Files:")} ${pattern.implementation.files.length}`
|
|
5459
5628
|
);
|
|
5460
5629
|
console.log(
|
|
5461
|
-
`${
|
|
5630
|
+
`${chalk16.bold("Dependencies:")} ${pattern.implementation.dependencies.length}`
|
|
5462
5631
|
);
|
|
5463
5632
|
console.log(
|
|
5464
|
-
`${
|
|
5633
|
+
`${chalk16.bold("Framework:")} ${pattern.compatibility.framework || "generic"}`
|
|
5465
5634
|
);
|
|
5466
|
-
console.log(
|
|
5467
|
-
const confirm10 = await
|
|
5635
|
+
console.log(chalk16.dim("\u2500".repeat(50)));
|
|
5636
|
+
const confirm10 = await p12.confirm({
|
|
5468
5637
|
message: "Save this solution pattern?",
|
|
5469
5638
|
initialValue: true
|
|
5470
5639
|
});
|
|
5471
|
-
if (
|
|
5472
|
-
|
|
5640
|
+
if (p12.isCancel(confirm10) || !confirm10) {
|
|
5641
|
+
p12.cancel("Solution not saved");
|
|
5473
5642
|
process.exit(0);
|
|
5474
5643
|
}
|
|
5475
5644
|
await store.saveSolution(pattern);
|
|
5476
|
-
console.log(
|
|
5645
|
+
console.log(chalk16.green(`
|
|
5477
5646
|
\u2713 Solution saved with ID: ${pattern.id}
|
|
5478
5647
|
`));
|
|
5479
5648
|
} catch (error) {
|
|
5480
|
-
|
|
5481
|
-
console.error(
|
|
5649
|
+
spinner10.stop("Analysis failed");
|
|
5650
|
+
console.error(chalk16.red(`
|
|
5482
5651
|
\u2717 Error: ${error.message}
|
|
5483
5652
|
`));
|
|
5484
5653
|
process.exit(1);
|
|
@@ -5487,7 +5656,7 @@ async function solutionCaptureCommand(options) {
|
|
|
5487
5656
|
async function solutionSearchCommand(query, options) {
|
|
5488
5657
|
const cwd = getWorkspacePath2();
|
|
5489
5658
|
const store = new PatternStore3(cwd);
|
|
5490
|
-
console.log(
|
|
5659
|
+
console.log(chalk16.cyan("\n\u{1F50D} Search Solution Patterns\n"));
|
|
5491
5660
|
const keywords = query.split(/\s+/).filter((k) => k.length > 0);
|
|
5492
5661
|
const result = await store.searchSolutions(keywords, {
|
|
5493
5662
|
category: options.category,
|
|
@@ -5495,39 +5664,39 @@ async function solutionSearchCommand(query, options) {
|
|
|
5495
5664
|
limit: options.limit ?? 10
|
|
5496
5665
|
});
|
|
5497
5666
|
if (!result.success || !result.data) {
|
|
5498
|
-
console.error(
|
|
5667
|
+
console.error(chalk16.red(`
|
|
5499
5668
|
\u2717 Search failed: ${result.error}
|
|
5500
5669
|
`));
|
|
5501
5670
|
return;
|
|
5502
5671
|
}
|
|
5503
5672
|
const solutions = result.data;
|
|
5504
5673
|
if (solutions.length === 0) {
|
|
5505
|
-
console.log(
|
|
5506
|
-
console.log(
|
|
5674
|
+
console.log(chalk16.yellow("No solutions found matching your query.\n"));
|
|
5675
|
+
console.log(chalk16.dim("Try different keywords or fewer filters."));
|
|
5507
5676
|
return;
|
|
5508
5677
|
}
|
|
5509
|
-
console.log(
|
|
5678
|
+
console.log(chalk16.green(`Found ${solutions.length} solution(s):
|
|
5510
5679
|
`));
|
|
5511
|
-
console.log(
|
|
5680
|
+
console.log(chalk16.dim("\u2500".repeat(70)));
|
|
5512
5681
|
for (const solution of solutions) {
|
|
5513
5682
|
console.log(
|
|
5514
|
-
`${
|
|
5683
|
+
`${chalk16.bold(solution.name)} ${chalk16.dim(`(${solution.id.slice(0, 8)})`)}`
|
|
5515
5684
|
);
|
|
5516
5685
|
console.log(` ${formatCategory(solution.category)}`);
|
|
5517
|
-
console.log(` ${
|
|
5686
|
+
console.log(` ${chalk16.dim(truncate(solution.description, 60))}`);
|
|
5518
5687
|
console.log(
|
|
5519
5688
|
` Files: ${solution.implementation.files.length} | Framework: ${solution.compatibility.framework || "generic"} | Uses: ${solution.metrics.applications}`
|
|
5520
5689
|
);
|
|
5521
|
-
console.log(
|
|
5690
|
+
console.log(chalk16.dim("\u2500".repeat(70)));
|
|
5522
5691
|
}
|
|
5523
5692
|
console.log(
|
|
5524
|
-
|
|
5693
|
+
chalk16.dim("\nUse 'workflow solution:apply <id>' to apply a solution.")
|
|
5525
5694
|
);
|
|
5526
5695
|
}
|
|
5527
5696
|
async function solutionListCommand(options) {
|
|
5528
5697
|
const cwd = getWorkspacePath2();
|
|
5529
5698
|
const store = new PatternStore3(cwd);
|
|
5530
|
-
console.log(
|
|
5699
|
+
console.log(chalk16.cyan("\n\u{1F4CB} Solution Patterns\n"));
|
|
5531
5700
|
const result = await store.listSolutions({
|
|
5532
5701
|
category: options.category,
|
|
5533
5702
|
framework: options.framework,
|
|
@@ -5535,20 +5704,20 @@ async function solutionListCommand(options) {
|
|
|
5535
5704
|
limit: options.limit ?? 20
|
|
5536
5705
|
});
|
|
5537
5706
|
if (!result.success || !result.data) {
|
|
5538
|
-
console.error(
|
|
5707
|
+
console.error(chalk16.red(`
|
|
5539
5708
|
\u2717 List failed: ${result.error}
|
|
5540
5709
|
`));
|
|
5541
5710
|
return;
|
|
5542
5711
|
}
|
|
5543
5712
|
const solutions = result.data;
|
|
5544
5713
|
if (solutions.length === 0) {
|
|
5545
|
-
console.log(
|
|
5714
|
+
console.log(chalk16.yellow("No solutions found.\n"));
|
|
5546
5715
|
console.log(
|
|
5547
|
-
|
|
5716
|
+
chalk16.dim("Use 'workflow solution:capture' to capture a solution.")
|
|
5548
5717
|
);
|
|
5549
5718
|
return;
|
|
5550
5719
|
}
|
|
5551
|
-
console.log(
|
|
5720
|
+
console.log(chalk16.green(`${solutions.length} solution(s):
|
|
5552
5721
|
`));
|
|
5553
5722
|
const byCategory = /* @__PURE__ */ new Map();
|
|
5554
5723
|
for (const solution of solutions) {
|
|
@@ -5557,24 +5726,24 @@ async function solutionListCommand(options) {
|
|
|
5557
5726
|
byCategory.set(solution.category, list);
|
|
5558
5727
|
}
|
|
5559
5728
|
for (const [category, items] of byCategory) {
|
|
5560
|
-
console.log(
|
|
5729
|
+
console.log(chalk16.bold(`
|
|
5561
5730
|
${formatCategory(category)}`));
|
|
5562
|
-
console.log(
|
|
5731
|
+
console.log(chalk16.dim("\u2500".repeat(50)));
|
|
5563
5732
|
for (const solution of items) {
|
|
5564
|
-
const deprecated = solution.deprecatedAt ?
|
|
5733
|
+
const deprecated = solution.deprecatedAt ? chalk16.red(" [DEPRECATED]") : "";
|
|
5565
5734
|
console.log(
|
|
5566
|
-
` ${
|
|
5735
|
+
` ${chalk16.cyan(solution.id.slice(0, 8))} ${solution.name}${deprecated}`
|
|
5567
5736
|
);
|
|
5568
|
-
console.log(` ${
|
|
5737
|
+
console.log(` ${chalk16.dim(truncate(solution.description, 50))}`);
|
|
5569
5738
|
console.log(
|
|
5570
|
-
|
|
5739
|
+
chalk16.dim(
|
|
5571
5740
|
` Created: ${formatDate2(solution.createdAt)} | Files: ${solution.implementation.files.length}`
|
|
5572
5741
|
)
|
|
5573
5742
|
);
|
|
5574
5743
|
}
|
|
5575
5744
|
}
|
|
5576
5745
|
console.log(
|
|
5577
|
-
|
|
5746
|
+
chalk16.dim(
|
|
5578
5747
|
"\nUse 'workflow solution:search <query>' to find specific solutions."
|
|
5579
5748
|
)
|
|
5580
5749
|
);
|
|
@@ -5582,10 +5751,10 @@ ${formatCategory(category)}`));
|
|
|
5582
5751
|
async function solutionApplyCommand(solutionId, options) {
|
|
5583
5752
|
const cwd = getWorkspacePath2();
|
|
5584
5753
|
const store = new PatternStore3(cwd);
|
|
5585
|
-
console.log(
|
|
5754
|
+
console.log(chalk16.cyan("\n\u{1F680} Apply Solution Pattern\n"));
|
|
5586
5755
|
const result = await store.getSolution(solutionId);
|
|
5587
5756
|
if (!result.success || !result.data) {
|
|
5588
|
-
console.error(
|
|
5757
|
+
console.error(chalk16.red(`
|
|
5589
5758
|
\u2717 Solution not found: ${solutionId}
|
|
5590
5759
|
`));
|
|
5591
5760
|
process.exit(1);
|
|
@@ -5593,60 +5762,60 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5593
5762
|
const solution = result.data;
|
|
5594
5763
|
if (solution.deprecatedAt) {
|
|
5595
5764
|
console.log(
|
|
5596
|
-
|
|
5765
|
+
chalk16.yellow(
|
|
5597
5766
|
`\u26A0\uFE0F This solution is deprecated: ${solution.deprecationReason || "No reason provided"}
|
|
5598
5767
|
`
|
|
5599
5768
|
)
|
|
5600
5769
|
);
|
|
5601
|
-
const proceed = await
|
|
5770
|
+
const proceed = await p12.confirm({
|
|
5602
5771
|
message: "Do you want to continue?",
|
|
5603
5772
|
initialValue: false
|
|
5604
5773
|
});
|
|
5605
|
-
if (
|
|
5606
|
-
|
|
5774
|
+
if (p12.isCancel(proceed) || !proceed) {
|
|
5775
|
+
p12.cancel("Operation cancelled");
|
|
5607
5776
|
process.exit(0);
|
|
5608
5777
|
}
|
|
5609
5778
|
}
|
|
5610
|
-
console.log(
|
|
5611
|
-
console.log(
|
|
5779
|
+
console.log(chalk16.bold(`Solution: ${solution.name}`));
|
|
5780
|
+
console.log(chalk16.dim(solution.description));
|
|
5612
5781
|
console.log();
|
|
5613
|
-
console.log(
|
|
5782
|
+
console.log(chalk16.bold("Files to create:"));
|
|
5614
5783
|
const filesToApply = options.includeTests ? solution.implementation.files : solution.implementation.files.filter(
|
|
5615
5784
|
(f) => f.role !== "test"
|
|
5616
5785
|
);
|
|
5617
5786
|
for (const file of filesToApply) {
|
|
5618
|
-
console.log(
|
|
5787
|
+
console.log(chalk16.dim(` \u2022 ${file.path} (${file.role})`));
|
|
5619
5788
|
}
|
|
5620
5789
|
console.log();
|
|
5621
5790
|
if (solution.implementation.dependencies.length > 0) {
|
|
5622
|
-
console.log(
|
|
5791
|
+
console.log(chalk16.bold("Dependencies to install:"));
|
|
5623
5792
|
for (const dep of solution.implementation.dependencies) {
|
|
5624
|
-
console.log(
|
|
5793
|
+
console.log(chalk16.dim(` \u2022 ${dep.name}@${dep.version}`));
|
|
5625
5794
|
}
|
|
5626
5795
|
console.log();
|
|
5627
5796
|
}
|
|
5628
5797
|
if (solution.implementation.envVars.length > 0) {
|
|
5629
|
-
console.log(
|
|
5798
|
+
console.log(chalk16.bold("Environment variables needed:"));
|
|
5630
5799
|
for (const env of solution.implementation.envVars) {
|
|
5631
|
-
const required = env.required ?
|
|
5632
|
-
console.log(
|
|
5800
|
+
const required = env.required ? chalk16.red("*") : "";
|
|
5801
|
+
console.log(chalk16.dim(` \u2022 ${env.name}${required}`));
|
|
5633
5802
|
}
|
|
5634
5803
|
console.log();
|
|
5635
5804
|
}
|
|
5636
5805
|
if (options.dryRun) {
|
|
5637
|
-
console.log(
|
|
5806
|
+
console.log(chalk16.yellow("Dry run mode - no files were created.\n"));
|
|
5638
5807
|
return;
|
|
5639
5808
|
}
|
|
5640
|
-
const confirm10 = await
|
|
5809
|
+
const confirm10 = await p12.confirm({
|
|
5641
5810
|
message: "Apply this solution?",
|
|
5642
5811
|
initialValue: true
|
|
5643
5812
|
});
|
|
5644
|
-
if (
|
|
5645
|
-
|
|
5813
|
+
if (p12.isCancel(confirm10) || !confirm10) {
|
|
5814
|
+
p12.cancel("Operation cancelled");
|
|
5646
5815
|
process.exit(0);
|
|
5647
5816
|
}
|
|
5648
|
-
const
|
|
5649
|
-
|
|
5817
|
+
const spinner10 = p12.spinner();
|
|
5818
|
+
spinner10.start("Applying solution...");
|
|
5650
5819
|
try {
|
|
5651
5820
|
const outputDir = options.output || cwd;
|
|
5652
5821
|
const fs2 = await import("fs");
|
|
@@ -5658,20 +5827,20 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5658
5827
|
await fs2.promises.writeFile(filePath, file.content);
|
|
5659
5828
|
}
|
|
5660
5829
|
await store.updateSolutionMetrics(solution.id, true);
|
|
5661
|
-
|
|
5662
|
-
console.log(
|
|
5830
|
+
spinner10.stop("Solution applied");
|
|
5831
|
+
console.log(chalk16.green(`
|
|
5663
5832
|
\u2713 Solution applied successfully!
|
|
5664
5833
|
`));
|
|
5665
|
-
console.log(
|
|
5834
|
+
console.log(chalk16.dim(`Created ${filesToApply.length} file(s).`));
|
|
5666
5835
|
if (solution.implementation.dependencies.length > 0) {
|
|
5667
|
-
console.log(
|
|
5836
|
+
console.log(chalk16.cyan("\nNext step: Install dependencies with:"));
|
|
5668
5837
|
const deps = solution.implementation.dependencies.map((d) => `${d.name}@${d.version}`).join(" ");
|
|
5669
|
-
console.log(
|
|
5838
|
+
console.log(chalk16.dim(` npm install ${deps}`));
|
|
5670
5839
|
}
|
|
5671
5840
|
} catch (error) {
|
|
5672
|
-
|
|
5841
|
+
spinner10.stop("Application failed");
|
|
5673
5842
|
await store.updateSolutionMetrics(solution.id, false);
|
|
5674
|
-
console.error(
|
|
5843
|
+
console.error(chalk16.red(`
|
|
5675
5844
|
\u2717 Error: ${error.message}
|
|
5676
5845
|
`));
|
|
5677
5846
|
process.exit(1);
|
|
@@ -5680,48 +5849,48 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5680
5849
|
async function solutionDeprecateCommand(solutionId, reason) {
|
|
5681
5850
|
const cwd = getWorkspacePath2();
|
|
5682
5851
|
const store = new PatternStore3(cwd);
|
|
5683
|
-
console.log(
|
|
5852
|
+
console.log(chalk16.cyan("\n\u26A0\uFE0F Deprecate Solution Pattern\n"));
|
|
5684
5853
|
const result = await store.getSolution(solutionId);
|
|
5685
5854
|
if (!result.success || !result.data) {
|
|
5686
|
-
console.error(
|
|
5855
|
+
console.error(chalk16.red(`
|
|
5687
5856
|
\u2717 Solution not found: ${solutionId}
|
|
5688
5857
|
`));
|
|
5689
5858
|
process.exit(1);
|
|
5690
5859
|
}
|
|
5691
5860
|
const solution = result.data;
|
|
5692
|
-
console.log(`Solution: ${
|
|
5861
|
+
console.log(`Solution: ${chalk16.bold(solution.name)}`);
|
|
5693
5862
|
console.log(`Reason: ${reason}
|
|
5694
5863
|
`);
|
|
5695
|
-
const confirm10 = await
|
|
5864
|
+
const confirm10 = await p12.confirm({
|
|
5696
5865
|
message: "Deprecate this solution?",
|
|
5697
5866
|
initialValue: false
|
|
5698
5867
|
});
|
|
5699
|
-
if (
|
|
5700
|
-
|
|
5868
|
+
if (p12.isCancel(confirm10) || !confirm10) {
|
|
5869
|
+
p12.cancel("Operation cancelled");
|
|
5701
5870
|
process.exit(0);
|
|
5702
5871
|
}
|
|
5703
5872
|
await store.deprecateSolution(solutionId, reason);
|
|
5704
|
-
console.log(
|
|
5873
|
+
console.log(chalk16.green(`
|
|
5705
5874
|
\u2713 Solution deprecated.
|
|
5706
5875
|
`));
|
|
5707
5876
|
}
|
|
5708
5877
|
async function solutionStatsCommand() {
|
|
5709
5878
|
const cwd = getWorkspacePath2();
|
|
5710
5879
|
const store = new PatternStore3(cwd);
|
|
5711
|
-
console.log(
|
|
5880
|
+
console.log(chalk16.cyan("\n\u{1F4CA} Solution Pattern Statistics\n"));
|
|
5712
5881
|
const stats = await store.getStats();
|
|
5713
|
-
console.log(
|
|
5714
|
-
console.log(`${
|
|
5882
|
+
console.log(chalk16.dim("\u2500".repeat(40)));
|
|
5883
|
+
console.log(`${chalk16.bold("Solutions:")} ${stats.totalSolutions}`);
|
|
5715
5884
|
console.log(` Active: ${stats.totalSolutions - stats.deprecatedSolutions}`);
|
|
5716
5885
|
console.log(` Deprecated: ${stats.deprecatedSolutions}`);
|
|
5717
5886
|
console.log(` Private: ${stats.privateSolutions}`);
|
|
5718
5887
|
console.log(` Synced: ${stats.syncedSolutions}`);
|
|
5719
|
-
console.log(
|
|
5720
|
-
console.log(`${
|
|
5721
|
-
console.log(`${
|
|
5722
|
-
console.log(
|
|
5888
|
+
console.log(chalk16.dim("\u2500".repeat(40)));
|
|
5889
|
+
console.log(`${chalk16.bold("Fixes:")} ${stats.totalFixes}`);
|
|
5890
|
+
console.log(`${chalk16.bold("Blueprints:")} ${stats.totalBlueprints}`);
|
|
5891
|
+
console.log(chalk16.dim("\u2500".repeat(40)));
|
|
5723
5892
|
console.log(`
|
|
5724
|
-
${
|
|
5893
|
+
${chalk16.bold("By Category:")}`);
|
|
5725
5894
|
const listResult = await store.listSolutions({ limit: 1e3 });
|
|
5726
5895
|
if (listResult.success && listResult.data) {
|
|
5727
5896
|
const categories = /* @__PURE__ */ new Map();
|
|
@@ -5774,6 +5943,15 @@ program.command("advisory").description("Generate advisory board analysis and do
|
|
|
5774
5943
|
).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);
|
|
5775
5944
|
program.command("generate-instructions").description("Generate .github/copilot-instructions.md from guidelines").option("--force", "Regenerate without confirmation").action(generateInstructionsCommand);
|
|
5776
5945
|
program.command("update-templates").description("Update guideline templates from the latest package version").option("--force", "Overwrite existing template files").option("--skip", "Skip the update (useful in CI)").action(updateTemplatesCommand);
|
|
5946
|
+
program.command("docs:validate").description("Validate document references in markdown files").option("--fix", "Interactively fix broken references").option("--patterns <patterns>", "Glob patterns to scan (comma-separated, default: **/*.md)").option("--ignore <patterns>", "Glob patterns to ignore (comma-separated)").action((options) => {
|
|
5947
|
+
const patterns = options.patterns ? options.patterns.split(",").map((p13) => p13.trim()) : void 0;
|
|
5948
|
+
const ignore = options.ignore ? options.ignore.split(",").map((p13) => p13.trim()) : void 0;
|
|
5949
|
+
return docsValidateCommand({
|
|
5950
|
+
fix: options.fix,
|
|
5951
|
+
patterns,
|
|
5952
|
+
ignore
|
|
5953
|
+
});
|
|
5954
|
+
});
|
|
5777
5955
|
program.command("learn:record").description("Record a new pattern from a successful implementation").option("--name <name>", "Pattern name").option("--description <desc>", "Pattern description").option(
|
|
5778
5956
|
"--category <cat>",
|
|
5779
5957
|
"Category (migration, security, performance, etc.)"
|