workflow-agent-cli 2.6.0 → 2.8.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 +695 -0
- package/dist/chunk-2WUPMAH3.js.map +1 -0
- package/dist/cli/index.js +537 -272
- package/dist/cli/index.js.map +1 -1
- package/dist/scripts/postinstall.js +37 -3
- package/dist/scripts/postinstall.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-LN5OAWEQ.js +0 -92
- package/dist/chunk-LN5OAWEQ.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -22,8 +22,14 @@ import {
|
|
|
22
22
|
import {
|
|
23
23
|
SCRIPT_CATEGORIES,
|
|
24
24
|
TOTAL_SCRIPTS,
|
|
25
|
-
WORKFLOW_SCRIPTS
|
|
26
|
-
|
|
25
|
+
WORKFLOW_SCRIPTS,
|
|
26
|
+
findTemplatesDirectory,
|
|
27
|
+
generateCopilotInstructions,
|
|
28
|
+
getMandatoryTemplateFilenames,
|
|
29
|
+
installMandatoryTemplates,
|
|
30
|
+
templateMetadata,
|
|
31
|
+
updateTemplates
|
|
32
|
+
} from "../chunk-2WUPMAH3.js";
|
|
27
33
|
|
|
28
34
|
// src/cli/index.ts
|
|
29
35
|
import { Command } from "commander";
|
|
@@ -310,10 +316,10 @@ async function initCommand(options) {
|
|
|
310
316
|
try {
|
|
311
317
|
const presetModule = await import(`@workflow/scopes-${preset}`);
|
|
312
318
|
scopes = presetModule.scopes || presetModule.default.scopes;
|
|
313
|
-
const
|
|
314
|
-
|
|
319
|
+
const spinner9 = p.spinner();
|
|
320
|
+
spinner9.start(`Loading ${presetModule.default?.name || preset} preset`);
|
|
315
321
|
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
316
|
-
|
|
322
|
+
spinner9.stop(`\u2713 Loaded ${scopes.length} scopes from preset`);
|
|
317
323
|
} catch (error) {
|
|
318
324
|
console.log(
|
|
319
325
|
chalk.yellow(
|
|
@@ -360,8 +366,8 @@ async function initCommand(options) {
|
|
|
360
366
|
process.exit(0);
|
|
361
367
|
}
|
|
362
368
|
if (shouldGenerateGuidelines) {
|
|
363
|
-
const
|
|
364
|
-
|
|
369
|
+
const spinner9 = p.spinner();
|
|
370
|
+
spinner9.start("Generating guidelines...");
|
|
365
371
|
try {
|
|
366
372
|
const templatesDir = join(__dirname, "../../templates");
|
|
367
373
|
await validateTemplateDirectory(templatesDir);
|
|
@@ -373,9 +379,17 @@ async function initCommand(options) {
|
|
|
373
379
|
guidelinesDir,
|
|
374
380
|
context
|
|
375
381
|
);
|
|
376
|
-
|
|
382
|
+
spinner9.stop(`\u2713 Generated ${renderedFiles.length} guideline documents`);
|
|
383
|
+
const instructionsSpinner = p.spinner();
|
|
384
|
+
instructionsSpinner.start("Generating AI agent instructions...");
|
|
385
|
+
const result = generateCopilotInstructions(cwd, { silent: true });
|
|
386
|
+
if (result.success) {
|
|
387
|
+
instructionsSpinner.stop(`\u2713 Generated .github/copilot-instructions.md`);
|
|
388
|
+
} else {
|
|
389
|
+
instructionsSpinner.stop("\u26A0\uFE0F Could not generate copilot instructions");
|
|
390
|
+
}
|
|
377
391
|
} catch (error) {
|
|
378
|
-
|
|
392
|
+
spinner9.stop("\u26A0\uFE0F Could not generate guidelines");
|
|
379
393
|
console.log(
|
|
380
394
|
chalk.yellow(
|
|
381
395
|
`
|
|
@@ -597,7 +611,10 @@ async function doctorCommand() {
|
|
|
597
611
|
import * as p3 from "@clack/prompts";
|
|
598
612
|
import chalk6 from "chalk";
|
|
599
613
|
import { readFileSync, writeFileSync, existsSync as existsSync2 } from "fs";
|
|
600
|
-
import { join as join2 } from "path";
|
|
614
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
615
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
616
|
+
var __filename2 = fileURLToPath2(import.meta.url);
|
|
617
|
+
var __dirname2 = dirname2(__filename2);
|
|
601
618
|
async function setupCommand() {
|
|
602
619
|
p3.intro(chalk6.bgBlue(" workflow-agent setup "));
|
|
603
620
|
const cwd = process.cwd();
|
|
@@ -667,6 +684,39 @@ async function setupCommand() {
|
|
|
667
684
|
console.log(chalk6.dim("\nRun them with:"));
|
|
668
685
|
console.log(chalk6.dim(" pnpm run workflow:init"));
|
|
669
686
|
console.log(chalk6.dim(" npm run workflow:init\n"));
|
|
687
|
+
const guidelinesDir = join2(cwd, "guidelines");
|
|
688
|
+
if (!existsSync2(guidelinesDir)) {
|
|
689
|
+
const templatesDir = findTemplatesDirectory(__dirname2);
|
|
690
|
+
if (templatesDir) {
|
|
691
|
+
const templateResult = installMandatoryTemplates(cwd, templatesDir, {
|
|
692
|
+
silent: false,
|
|
693
|
+
skipIfExists: true,
|
|
694
|
+
mandatoryOnly: true
|
|
695
|
+
});
|
|
696
|
+
if (templateResult.installed.length > 0) {
|
|
697
|
+
console.log(
|
|
698
|
+
chalk6.green(
|
|
699
|
+
`
|
|
700
|
+
\u2713 Installed ${templateResult.installed.length} mandatory guideline templates`
|
|
701
|
+
)
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
if (existsSync2(guidelinesDir)) {
|
|
707
|
+
const result = generateCopilotInstructions(cwd, { silent: false });
|
|
708
|
+
if (result.success) {
|
|
709
|
+
const status = result.isNew ? "Generated" : "Updated";
|
|
710
|
+
console.log(
|
|
711
|
+
chalk6.green(
|
|
712
|
+
`\u2713 ${status} .github/copilot-instructions.md from ${result.guidelinesCount} guidelines`
|
|
713
|
+
)
|
|
714
|
+
);
|
|
715
|
+
if (result.preservedCustomContent) {
|
|
716
|
+
console.log(chalk6.dim(" (Custom content preserved)"));
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
670
720
|
}
|
|
671
721
|
|
|
672
722
|
// src/cli/commands/scope-create.ts
|
|
@@ -848,8 +898,8 @@ async function scopeCreateCommand(options) {
|
|
|
848
898
|
process.exit(0);
|
|
849
899
|
}
|
|
850
900
|
}
|
|
851
|
-
const
|
|
852
|
-
|
|
901
|
+
const spinner9 = p4.spinner();
|
|
902
|
+
spinner9.start("Creating package structure...");
|
|
853
903
|
try {
|
|
854
904
|
await mkdir2(join3(outputDir, "src"), { recursive: true });
|
|
855
905
|
const packageJson = {
|
|
@@ -980,7 +1030,7 @@ describe('${presetName} Scope Preset', () => {
|
|
|
980
1030
|
"utf-8"
|
|
981
1031
|
);
|
|
982
1032
|
}
|
|
983
|
-
|
|
1033
|
+
spinner9.stop("\u2713 Package structure created");
|
|
984
1034
|
if (isMonorepo2) {
|
|
985
1035
|
const workspaceFile = join3(cwd, "pnpm-workspace.yaml");
|
|
986
1036
|
const workspaceContent = await readFile(workspaceFile, "utf-8");
|
|
@@ -1032,7 +1082,7 @@ describe('${presetName} Scope Preset', () => {
|
|
|
1032
1082
|
);
|
|
1033
1083
|
}
|
|
1034
1084
|
} catch (error) {
|
|
1035
|
-
|
|
1085
|
+
spinner9.stop("\u2717 Failed to create package");
|
|
1036
1086
|
console.error(chalk7.red("\nError:"), error);
|
|
1037
1087
|
process.exit(1);
|
|
1038
1088
|
}
|
|
@@ -1160,8 +1210,8 @@ async function scopeMigrateCommand(options) {
|
|
|
1160
1210
|
process.exit(0);
|
|
1161
1211
|
}
|
|
1162
1212
|
}
|
|
1163
|
-
const
|
|
1164
|
-
|
|
1213
|
+
const spinner9 = p5.spinner();
|
|
1214
|
+
spinner9.start("Migrating scopes to package...");
|
|
1165
1215
|
try {
|
|
1166
1216
|
await mkdir3(join4(outputDir, "src"), { recursive: true });
|
|
1167
1217
|
const packageJson = {
|
|
@@ -1289,7 +1339,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1289
1339
|
});
|
|
1290
1340
|
`;
|
|
1291
1341
|
await writeFile3(join4(outputDir, "src", "index.test.ts"), testFile, "utf-8");
|
|
1292
|
-
|
|
1342
|
+
spinner9.stop("\u2713 Package created from migrated scopes");
|
|
1293
1343
|
if (isMonorepo2) {
|
|
1294
1344
|
const workspaceFile = join4(cwd, "pnpm-workspace.yaml");
|
|
1295
1345
|
const workspaceContent = await readFile2(workspaceFile, "utf-8");
|
|
@@ -1361,7 +1411,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1361
1411
|
)
|
|
1362
1412
|
);
|
|
1363
1413
|
} catch (error) {
|
|
1364
|
-
|
|
1414
|
+
spinner9.stop("\u2717 Migration failed");
|
|
1365
1415
|
console.error(chalk8.red("\nError:"), error);
|
|
1366
1416
|
process.exit(1);
|
|
1367
1417
|
}
|
|
@@ -1601,14 +1651,14 @@ import chalk10 from "chalk";
|
|
|
1601
1651
|
async function autoSetupCommand(options) {
|
|
1602
1652
|
console.log(chalk10.bold.cyan("\n\u{1F527} Workflow Agent Auto-Setup\n"));
|
|
1603
1653
|
const cwd = process.cwd();
|
|
1604
|
-
const
|
|
1605
|
-
|
|
1654
|
+
const spinner9 = p6.spinner();
|
|
1655
|
+
spinner9.start("Analyzing project...");
|
|
1606
1656
|
let report;
|
|
1607
1657
|
try {
|
|
1608
1658
|
report = await generateAuditReport(cwd);
|
|
1609
|
-
|
|
1659
|
+
spinner9.stop("\u2713 Project analysis complete");
|
|
1610
1660
|
} catch (error) {
|
|
1611
|
-
|
|
1661
|
+
spinner9.stop("\u2717 Failed to analyze project");
|
|
1612
1662
|
console.error(
|
|
1613
1663
|
chalk10.red(
|
|
1614
1664
|
`Error: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -2784,7 +2834,7 @@ var QuestionGenerator = class {
|
|
|
2784
2834
|
category: "Platform Strategy",
|
|
2785
2835
|
question: `Are our platform choices (${technology.platforms.join(", ")}) aligned with target market and growth plans?`,
|
|
2786
2836
|
context: `Currently deployed on ${technology.platforms.join(" + ")}`,
|
|
2787
|
-
findings: technology.platforms.map((
|
|
2837
|
+
findings: technology.platforms.map((p12) => `Supports ${p12} platform`),
|
|
2788
2838
|
recommendations: [
|
|
2789
2839
|
"Validate platform coverage matches user demographics",
|
|
2790
2840
|
"Assess cross-platform development efficiency",
|
|
@@ -2846,7 +2896,7 @@ var QuestionGenerator = class {
|
|
|
2846
2896
|
category: "Business Alignment",
|
|
2847
2897
|
question: `How is our authentication solution (${authCat.packages.join(", ")}) supporting user onboarding and security requirements?`,
|
|
2848
2898
|
context: `Using ${authCat.packages.join(" + ")} for authentication`,
|
|
2849
|
-
findings: authCat.packages.map((
|
|
2899
|
+
findings: authCat.packages.map((p12) => `Auth provider: ${p12}`),
|
|
2850
2900
|
recommendations: [
|
|
2851
2901
|
"Measure authentication success rates and friction points",
|
|
2852
2902
|
"Ensure compliance with security standards (SOC2, GDPR, etc.)",
|
|
@@ -2898,12 +2948,12 @@ var QuestionGenerator = class {
|
|
|
2898
2948
|
});
|
|
2899
2949
|
}
|
|
2900
2950
|
if (packages.outdated && packages.outdated.length > 10) {
|
|
2901
|
-
const breakingCount = packages.outdated.filter((
|
|
2951
|
+
const breakingCount = packages.outdated.filter((p12) => p12.breaking).length;
|
|
2902
2952
|
questions.push({
|
|
2903
2953
|
category: "Technical Debt",
|
|
2904
2954
|
question: `How should we prioritize updating ${packages.outdated.length} outdated packages${breakingCount > 0 ? ` (${breakingCount} with breaking changes)` : ""}?`,
|
|
2905
2955
|
context: "Dependency audit found outdated packages",
|
|
2906
|
-
findings: packages.outdated.slice(0, 5).map((
|
|
2956
|
+
findings: packages.outdated.slice(0, 5).map((p12) => `${p12.name}: ${p12.current} \u2192 ${p12.latest}`),
|
|
2907
2957
|
recommendations: [
|
|
2908
2958
|
"Create update roadmap starting with non-breaking changes",
|
|
2909
2959
|
"Test breaking changes in feature branches",
|
|
@@ -3213,10 +3263,10 @@ var ReportComparator = class {
|
|
|
3213
3263
|
*/
|
|
3214
3264
|
comparePackages() {
|
|
3215
3265
|
const baselineProduction = new Map(
|
|
3216
|
-
this.baseline.packages.production.map((
|
|
3266
|
+
this.baseline.packages.production.map((p12) => [p12.name, p12])
|
|
3217
3267
|
);
|
|
3218
3268
|
const currentProduction = new Map(
|
|
3219
|
-
this.current.packages.production.map((
|
|
3269
|
+
this.current.packages.production.map((p12) => [p12.name, p12])
|
|
3220
3270
|
);
|
|
3221
3271
|
const added = [];
|
|
3222
3272
|
const removed = [];
|
|
@@ -3248,10 +3298,10 @@ var ReportComparator = class {
|
|
|
3248
3298
|
}
|
|
3249
3299
|
}
|
|
3250
3300
|
const baselineDev = new Map(
|
|
3251
|
-
this.baseline.packages.development.map((
|
|
3301
|
+
this.baseline.packages.development.map((p12) => [p12.name, p12])
|
|
3252
3302
|
);
|
|
3253
3303
|
const currentDev = new Map(
|
|
3254
|
-
this.current.packages.development.map((
|
|
3304
|
+
this.current.packages.development.map((p12) => [p12.name, p12])
|
|
3255
3305
|
);
|
|
3256
3306
|
for (const [name, pkg] of currentDev) {
|
|
3257
3307
|
if (!baselineDev.has(name)) {
|
|
@@ -3539,20 +3589,20 @@ async function advisoryCommand(options) {
|
|
|
3539
3589
|
includeHealth,
|
|
3540
3590
|
excludePatterns: advisoryConfig?.excludePatterns
|
|
3541
3591
|
});
|
|
3542
|
-
const
|
|
3592
|
+
const spinner9 = p7.spinner();
|
|
3543
3593
|
const depthLabels = {
|
|
3544
3594
|
executive: "executive summary",
|
|
3545
3595
|
quick: "quick scan",
|
|
3546
3596
|
standard: "standard analysis",
|
|
3547
3597
|
comprehensive: "comprehensive analysis"
|
|
3548
3598
|
};
|
|
3549
|
-
|
|
3599
|
+
spinner9.start(`Running ${depthLabels[depth]}...`);
|
|
3550
3600
|
let analysis;
|
|
3551
3601
|
try {
|
|
3552
3602
|
analysis = await analyzer.analyze();
|
|
3553
|
-
|
|
3603
|
+
spinner9.stop(`\u2713 Analysis complete`);
|
|
3554
3604
|
} catch (error) {
|
|
3555
|
-
|
|
3605
|
+
spinner9.stop("\u2717 Analysis failed");
|
|
3556
3606
|
console.error(
|
|
3557
3607
|
chalk11.red(
|
|
3558
3608
|
`Error: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -3569,17 +3619,17 @@ async function advisoryCommand(options) {
|
|
|
3569
3619
|
if (options.compare) {
|
|
3570
3620
|
const comparisonPath = options.compare.endsWith(".json") ? join6(cwd, options.compare) : join6(cwd, options.compare, "analysis.json");
|
|
3571
3621
|
if (existsSync6(comparisonPath)) {
|
|
3572
|
-
|
|
3622
|
+
spinner9.start("Comparing with previous report...");
|
|
3573
3623
|
try {
|
|
3574
3624
|
const previousContent = await readFile4(comparisonPath, "utf-8");
|
|
3575
3625
|
const previousAnalysis = JSON.parse(previousContent);
|
|
3576
3626
|
comparator = new ReportComparator(previousAnalysis, analysis);
|
|
3577
3627
|
comparisonReport = comparator.compare();
|
|
3578
|
-
|
|
3628
|
+
spinner9.stop("\u2713 Comparison complete");
|
|
3579
3629
|
console.log("");
|
|
3580
3630
|
displayComparisonSummary(comparisonReport);
|
|
3581
3631
|
} catch (error) {
|
|
3582
|
-
|
|
3632
|
+
spinner9.stop("\u26A0 Comparison failed");
|
|
3583
3633
|
console.warn(chalk11.yellow(`Could not compare reports: ${error}`));
|
|
3584
3634
|
}
|
|
3585
3635
|
} else {
|
|
@@ -3598,7 +3648,7 @@ async function advisoryCommand(options) {
|
|
|
3598
3648
|
}
|
|
3599
3649
|
const fullOutputDir = join6(cwd, outputDir);
|
|
3600
3650
|
await mkdir4(fullOutputDir, { recursive: true });
|
|
3601
|
-
|
|
3651
|
+
spinner9.start("Generating reports...");
|
|
3602
3652
|
try {
|
|
3603
3653
|
const timestamp = options.timestamp ? (/* @__PURE__ */ new Date()).toISOString().split("T")[0] : "";
|
|
3604
3654
|
if (options.format === "json") {
|
|
@@ -3612,9 +3662,9 @@ async function advisoryCommand(options) {
|
|
|
3612
3662
|
timestamp
|
|
3613
3663
|
);
|
|
3614
3664
|
}
|
|
3615
|
-
|
|
3665
|
+
spinner9.stop("\u2713 Reports generated");
|
|
3616
3666
|
} catch (error) {
|
|
3617
|
-
|
|
3667
|
+
spinner9.stop("\u2717 Failed to write reports");
|
|
3618
3668
|
console.error(chalk11.red(`Error: ${error}`));
|
|
3619
3669
|
process.exit(1);
|
|
3620
3670
|
}
|
|
@@ -4386,9 +4436,222 @@ function checkCIThresholds(analysis, config) {
|
|
|
4386
4436
|
return 0;
|
|
4387
4437
|
}
|
|
4388
4438
|
|
|
4389
|
-
// src/cli/commands/
|
|
4390
|
-
import chalk12 from "chalk";
|
|
4439
|
+
// src/cli/commands/generate-instructions.ts
|
|
4391
4440
|
import * as p8 from "@clack/prompts";
|
|
4441
|
+
import chalk12 from "chalk";
|
|
4442
|
+
import { existsSync as existsSync7 } from "fs";
|
|
4443
|
+
import { join as join7 } from "path";
|
|
4444
|
+
async function generateInstructionsCommand(options) {
|
|
4445
|
+
p8.intro(chalk12.bgBlue(" workflow-agent generate-instructions "));
|
|
4446
|
+
const cwd = process.cwd();
|
|
4447
|
+
const guidelinesDir = join7(cwd, "guidelines");
|
|
4448
|
+
const outputPath = join7(cwd, ".github", "copilot-instructions.md");
|
|
4449
|
+
if (!existsSync7(guidelinesDir)) {
|
|
4450
|
+
p8.cancel(
|
|
4451
|
+
"No guidelines directory found. Run 'workflow init' first to generate guidelines."
|
|
4452
|
+
);
|
|
4453
|
+
process.exit(1);
|
|
4454
|
+
}
|
|
4455
|
+
if (existsSync7(outputPath) && !options.force) {
|
|
4456
|
+
const shouldRegenerate = await p8.confirm({
|
|
4457
|
+
message: ".github/copilot-instructions.md already exists. Regenerate? (Custom content will be preserved)",
|
|
4458
|
+
initialValue: true
|
|
4459
|
+
});
|
|
4460
|
+
if (p8.isCancel(shouldRegenerate) || !shouldRegenerate) {
|
|
4461
|
+
p8.cancel("Generation cancelled");
|
|
4462
|
+
process.exit(0);
|
|
4463
|
+
}
|
|
4464
|
+
}
|
|
4465
|
+
const spinner9 = p8.spinner();
|
|
4466
|
+
spinner9.start("Generating AI agent instructions from guidelines...");
|
|
4467
|
+
try {
|
|
4468
|
+
const result = generateCopilotInstructions(cwd, {
|
|
4469
|
+
force: true,
|
|
4470
|
+
silent: false
|
|
4471
|
+
});
|
|
4472
|
+
if (result.success) {
|
|
4473
|
+
const status = result.isNew ? "Generated" : "Regenerated";
|
|
4474
|
+
spinner9.stop(
|
|
4475
|
+
chalk12.green(
|
|
4476
|
+
`\u2713 ${status} .github/copilot-instructions.md from ${result.guidelinesCount} guidelines`
|
|
4477
|
+
)
|
|
4478
|
+
);
|
|
4479
|
+
if (result.preservedCustomContent) {
|
|
4480
|
+
console.log(chalk12.dim(" Custom content between markers was preserved."));
|
|
4481
|
+
}
|
|
4482
|
+
console.log(chalk12.dim(`
|
|
4483
|
+
Output: ${result.filePath}`));
|
|
4484
|
+
console.log(
|
|
4485
|
+
chalk12.dim(
|
|
4486
|
+
"\n \u{1F4A1} Tip: Add project-specific instructions between the CUSTOM markers."
|
|
4487
|
+
)
|
|
4488
|
+
);
|
|
4489
|
+
} else {
|
|
4490
|
+
spinner9.stop(chalk12.red("\u2717 Failed to generate instructions"));
|
|
4491
|
+
console.log(chalk12.yellow(`
|
|
4492
|
+
Reason: ${result.error}`));
|
|
4493
|
+
}
|
|
4494
|
+
} catch (error) {
|
|
4495
|
+
spinner9.stop(chalk12.red("\u2717 Error generating instructions"));
|
|
4496
|
+
console.log(
|
|
4497
|
+
chalk12.yellow(
|
|
4498
|
+
`
|
|
4499
|
+
Reason: ${error instanceof Error ? error.message : String(error)}`
|
|
4500
|
+
)
|
|
4501
|
+
);
|
|
4502
|
+
process.exit(1);
|
|
4503
|
+
}
|
|
4504
|
+
p8.outro(chalk12.green("\u2713 AI agent instructions ready!"));
|
|
4505
|
+
console.log(chalk12.dim("\nThe .github/copilot-instructions.md file:"));
|
|
4506
|
+
console.log(chalk12.dim(" - Is read by GitHub Copilot and other AI agents"));
|
|
4507
|
+
console.log(chalk12.dim(" - Summarizes all guidelines with links to full docs"));
|
|
4508
|
+
console.log(chalk12.dim(" - Includes your project scopes and conventions"));
|
|
4509
|
+
console.log(chalk12.dim(" - Preserves custom instructions you add between markers\n"));
|
|
4510
|
+
}
|
|
4511
|
+
|
|
4512
|
+
// src/cli/commands/update-templates.ts
|
|
4513
|
+
import * as p9 from "@clack/prompts";
|
|
4514
|
+
import chalk13 from "chalk";
|
|
4515
|
+
import { existsSync as existsSync8 } from "fs";
|
|
4516
|
+
import { join as join8, dirname as dirname3 } from "path";
|
|
4517
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4518
|
+
var __filename3 = fileURLToPath3(import.meta.url);
|
|
4519
|
+
var __dirname3 = dirname3(__filename3);
|
|
4520
|
+
async function updateTemplatesCommand(options) {
|
|
4521
|
+
const { force = false, skip = false } = options;
|
|
4522
|
+
p9.intro(chalk13.bgBlue(" workflow-agent update-templates "));
|
|
4523
|
+
const cwd = process.cwd();
|
|
4524
|
+
const guidelinesDir = join8(cwd, "guidelines");
|
|
4525
|
+
const templatesDir = findTemplatesDirectory(__dirname3);
|
|
4526
|
+
if (!templatesDir) {
|
|
4527
|
+
p9.cancel("Could not find templates directory");
|
|
4528
|
+
process.exit(1);
|
|
4529
|
+
}
|
|
4530
|
+
const guidelinesExist = existsSync8(guidelinesDir);
|
|
4531
|
+
if (!guidelinesExist) {
|
|
4532
|
+
console.log(chalk13.yellow("\n\u26A0\uFE0F No guidelines directory found."));
|
|
4533
|
+
console.log(chalk13.dim("Run 'workflow-agent init' to set up guidelines.\n"));
|
|
4534
|
+
p9.outro(chalk13.yellow("No templates to update"));
|
|
4535
|
+
return;
|
|
4536
|
+
}
|
|
4537
|
+
const mandatoryFiles = getMandatoryTemplateFilenames();
|
|
4538
|
+
const allTemplates = Object.keys(templateMetadata).filter(
|
|
4539
|
+
(f) => f !== "_TEMPLATE_EXAMPLE.md"
|
|
4540
|
+
);
|
|
4541
|
+
console.log(chalk13.cyan("\n\u{1F4CB} Available templates:\n"));
|
|
4542
|
+
console.log(chalk13.bold(" Mandatory templates:"));
|
|
4543
|
+
for (const file of mandatoryFiles) {
|
|
4544
|
+
const meta = templateMetadata[file];
|
|
4545
|
+
console.log(chalk13.dim(` - ${file}`));
|
|
4546
|
+
if (meta?.description) {
|
|
4547
|
+
console.log(chalk13.dim(` ${meta.description}`));
|
|
4548
|
+
}
|
|
4549
|
+
}
|
|
4550
|
+
const optionalFiles = allTemplates.filter(
|
|
4551
|
+
(f) => !mandatoryFiles.includes(f)
|
|
4552
|
+
);
|
|
4553
|
+
if (optionalFiles.length > 0) {
|
|
4554
|
+
console.log(chalk13.bold("\n Optional templates:"));
|
|
4555
|
+
for (const file of optionalFiles) {
|
|
4556
|
+
const meta = templateMetadata[file];
|
|
4557
|
+
console.log(chalk13.dim(` - ${file}`));
|
|
4558
|
+
if (meta?.description) {
|
|
4559
|
+
console.log(chalk13.dim(` ${meta.description}`));
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
console.log("");
|
|
4564
|
+
if (skip) {
|
|
4565
|
+
p9.outro(chalk13.yellow("Skipped template update (--skip flag)"));
|
|
4566
|
+
return;
|
|
4567
|
+
}
|
|
4568
|
+
if (!force) {
|
|
4569
|
+
const shouldContinue = await p9.confirm({
|
|
4570
|
+
message: force ? "Force update all templates? (existing files will be overwritten)" : "Update templates? (existing files will be skipped unless --force is used)",
|
|
4571
|
+
initialValue: true
|
|
4572
|
+
});
|
|
4573
|
+
if (p9.isCancel(shouldContinue) || !shouldContinue) {
|
|
4574
|
+
p9.cancel("Template update cancelled");
|
|
4575
|
+
process.exit(0);
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4578
|
+
const spinner9 = p9.spinner();
|
|
4579
|
+
spinner9.start("Updating templates...");
|
|
4580
|
+
let result;
|
|
4581
|
+
try {
|
|
4582
|
+
result = updateTemplates(cwd, templatesDir, {
|
|
4583
|
+
force,
|
|
4584
|
+
silent: true
|
|
4585
|
+
});
|
|
4586
|
+
} catch (error) {
|
|
4587
|
+
spinner9.stop("\u274C Failed to update templates");
|
|
4588
|
+
console.log(
|
|
4589
|
+
chalk13.red(
|
|
4590
|
+
`
|
|
4591
|
+
Error: ${error instanceof Error ? error.message : String(error)}`
|
|
4592
|
+
)
|
|
4593
|
+
);
|
|
4594
|
+
process.exit(1);
|
|
4595
|
+
}
|
|
4596
|
+
const totalChanges = result.installed.length + result.updated.length;
|
|
4597
|
+
if (totalChanges === 0 && result.skipped.length > 0) {
|
|
4598
|
+
spinner9.stop("No changes needed");
|
|
4599
|
+
console.log(
|
|
4600
|
+
chalk13.dim(
|
|
4601
|
+
`
|
|
4602
|
+
${result.skipped.length} files already up to date (use --force to overwrite)`
|
|
4603
|
+
)
|
|
4604
|
+
);
|
|
4605
|
+
} else {
|
|
4606
|
+
spinner9.stop(`\u2713 Template update complete`);
|
|
4607
|
+
if (result.installed.length > 0) {
|
|
4608
|
+
console.log(chalk13.green(`
|
|
4609
|
+
New templates installed:`));
|
|
4610
|
+
for (const file of result.installed) {
|
|
4611
|
+
console.log(chalk13.dim(` + ${file}`));
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4614
|
+
if (result.updated.length > 0) {
|
|
4615
|
+
console.log(chalk13.yellow(`
|
|
4616
|
+
Templates updated:`));
|
|
4617
|
+
for (const file of result.updated) {
|
|
4618
|
+
console.log(chalk13.dim(` ~ ${file}`));
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
if (result.skipped.length > 0) {
|
|
4622
|
+
console.log(chalk13.dim(`
|
|
4623
|
+
Skipped (already exists):`));
|
|
4624
|
+
for (const file of result.skipped) {
|
|
4625
|
+
console.log(chalk13.dim(` - ${file}`));
|
|
4626
|
+
}
|
|
4627
|
+
}
|
|
4628
|
+
}
|
|
4629
|
+
if (result.errors.length > 0) {
|
|
4630
|
+
console.log(chalk13.red(`
|
|
4631
|
+
Errors:`));
|
|
4632
|
+
for (const error of result.errors) {
|
|
4633
|
+
console.log(chalk13.red(` ! ${error}`));
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
if (totalChanges > 0) {
|
|
4637
|
+
console.log("");
|
|
4638
|
+
const instructionsResult = generateCopilotInstructions(cwd, {
|
|
4639
|
+
silent: true
|
|
4640
|
+
});
|
|
4641
|
+
if (instructionsResult.success) {
|
|
4642
|
+
console.log(
|
|
4643
|
+
chalk13.green(
|
|
4644
|
+
`\u2713 Regenerated .github/copilot-instructions.md from ${instructionsResult.guidelinesCount} guidelines`
|
|
4645
|
+
)
|
|
4646
|
+
);
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
p9.outro(chalk13.green("Done!"));
|
|
4650
|
+
}
|
|
4651
|
+
|
|
4652
|
+
// src/cli/commands/learn.ts
|
|
4653
|
+
import chalk14 from "chalk";
|
|
4654
|
+
import * as p10 from "@clack/prompts";
|
|
4392
4655
|
import {
|
|
4393
4656
|
PatternStore as PatternStore2,
|
|
4394
4657
|
ContributorManager as ContributorManager2,
|
|
@@ -4411,10 +4674,10 @@ function formatTags(tags) {
|
|
|
4411
4674
|
async function learnRecordCommand(options) {
|
|
4412
4675
|
const cwd = getWorkspacePath();
|
|
4413
4676
|
const store = new PatternStore2(cwd);
|
|
4414
|
-
console.log(
|
|
4677
|
+
console.log(chalk14.cyan("\n\u{1F4DA} Record a Learning Pattern\n"));
|
|
4415
4678
|
let patternType = options.type;
|
|
4416
4679
|
if (!patternType) {
|
|
4417
|
-
const typeChoice = await
|
|
4680
|
+
const typeChoice = await p10.select({
|
|
4418
4681
|
message: "What type of pattern are you recording?",
|
|
4419
4682
|
options: [
|
|
4420
4683
|
{
|
|
@@ -4427,15 +4690,15 @@ async function learnRecordCommand(options) {
|
|
|
4427
4690
|
}
|
|
4428
4691
|
]
|
|
4429
4692
|
});
|
|
4430
|
-
if (
|
|
4431
|
-
|
|
4693
|
+
if (p10.isCancel(typeChoice)) {
|
|
4694
|
+
p10.cancel("Recording cancelled");
|
|
4432
4695
|
process.exit(0);
|
|
4433
4696
|
}
|
|
4434
4697
|
patternType = typeChoice;
|
|
4435
4698
|
}
|
|
4436
4699
|
let name = options.name;
|
|
4437
4700
|
if (!name) {
|
|
4438
|
-
const nameInput = await
|
|
4701
|
+
const nameInput = await p10.text({
|
|
4439
4702
|
message: "Pattern name:",
|
|
4440
4703
|
placeholder: "e.g., Next.js App Router Migration",
|
|
4441
4704
|
validate: (value) => {
|
|
@@ -4445,15 +4708,15 @@ async function learnRecordCommand(options) {
|
|
|
4445
4708
|
return void 0;
|
|
4446
4709
|
}
|
|
4447
4710
|
});
|
|
4448
|
-
if (
|
|
4449
|
-
|
|
4711
|
+
if (p10.isCancel(nameInput)) {
|
|
4712
|
+
p10.cancel("Recording cancelled");
|
|
4450
4713
|
process.exit(0);
|
|
4451
4714
|
}
|
|
4452
4715
|
name = nameInput;
|
|
4453
4716
|
}
|
|
4454
4717
|
let description = options.description;
|
|
4455
4718
|
if (!description) {
|
|
4456
|
-
const descInput = await
|
|
4719
|
+
const descInput = await p10.text({
|
|
4457
4720
|
message: "Description:",
|
|
4458
4721
|
placeholder: "What does this pattern solve?",
|
|
4459
4722
|
validate: (value) => {
|
|
@@ -4464,40 +4727,40 @@ async function learnRecordCommand(options) {
|
|
|
4464
4727
|
return void 0;
|
|
4465
4728
|
}
|
|
4466
4729
|
});
|
|
4467
|
-
if (
|
|
4468
|
-
|
|
4730
|
+
if (p10.isCancel(descInput)) {
|
|
4731
|
+
p10.cancel("Recording cancelled");
|
|
4469
4732
|
process.exit(0);
|
|
4470
4733
|
}
|
|
4471
4734
|
description = descInput;
|
|
4472
4735
|
}
|
|
4473
4736
|
let framework = options.framework;
|
|
4474
4737
|
if (!framework) {
|
|
4475
|
-
const fwInput = await
|
|
4738
|
+
const fwInput = await p10.text({
|
|
4476
4739
|
message: "Framework:",
|
|
4477
4740
|
placeholder: "e.g., next, react, vue, express"
|
|
4478
4741
|
});
|
|
4479
|
-
if (
|
|
4480
|
-
|
|
4742
|
+
if (p10.isCancel(fwInput)) {
|
|
4743
|
+
p10.cancel("Recording cancelled");
|
|
4481
4744
|
process.exit(0);
|
|
4482
4745
|
}
|
|
4483
4746
|
framework = fwInput;
|
|
4484
4747
|
}
|
|
4485
4748
|
let version = options.version;
|
|
4486
4749
|
if (!version) {
|
|
4487
|
-
const versionInput = await
|
|
4750
|
+
const versionInput = await p10.text({
|
|
4488
4751
|
message: "Framework version (semver range):",
|
|
4489
4752
|
placeholder: "e.g., >=14.0.0, ^18.0.0",
|
|
4490
4753
|
initialValue: ">=1.0.0"
|
|
4491
4754
|
});
|
|
4492
|
-
if (
|
|
4493
|
-
|
|
4755
|
+
if (p10.isCancel(versionInput)) {
|
|
4756
|
+
p10.cancel("Recording cancelled");
|
|
4494
4757
|
process.exit(0);
|
|
4495
4758
|
}
|
|
4496
4759
|
version = versionInput;
|
|
4497
4760
|
}
|
|
4498
4761
|
let category = options.category;
|
|
4499
4762
|
if (patternType === "fix" && !category) {
|
|
4500
|
-
const catChoice = await
|
|
4763
|
+
const catChoice = await p10.select({
|
|
4501
4764
|
message: "Category:",
|
|
4502
4765
|
options: [
|
|
4503
4766
|
{ value: "migration", label: "\u{1F504} Migration" },
|
|
@@ -4512,8 +4775,8 @@ async function learnRecordCommand(options) {
|
|
|
4512
4775
|
{ value: "other", label: "\u{1F4E6} Other" }
|
|
4513
4776
|
]
|
|
4514
4777
|
});
|
|
4515
|
-
if (
|
|
4516
|
-
|
|
4778
|
+
if (p10.isCancel(catChoice)) {
|
|
4779
|
+
p10.cancel("Recording cancelled");
|
|
4517
4780
|
process.exit(0);
|
|
4518
4781
|
}
|
|
4519
4782
|
category = catChoice;
|
|
@@ -4576,14 +4839,14 @@ async function learnRecordCommand(options) {
|
|
|
4576
4839
|
};
|
|
4577
4840
|
const result = await store.saveFixPattern(fixPattern);
|
|
4578
4841
|
if (result.success) {
|
|
4579
|
-
console.log(
|
|
4580
|
-
console.log(
|
|
4581
|
-
console.log(
|
|
4582
|
-
console.log(
|
|
4583
|
-
console.log(
|
|
4842
|
+
console.log(chalk14.green("\n\u2705 Fix pattern recorded successfully!\n"));
|
|
4843
|
+
console.log(chalk14.dim(` ID: ${fixPattern.id}`));
|
|
4844
|
+
console.log(chalk14.dim(` Name: ${name}`));
|
|
4845
|
+
console.log(chalk14.dim(` Category: ${category}`));
|
|
4846
|
+
console.log(chalk14.dim(` Framework: ${framework} ${version}`));
|
|
4584
4847
|
} else {
|
|
4585
|
-
console.log(
|
|
4586
|
-
console.log(
|
|
4848
|
+
console.log(chalk14.red("\n\u274C Failed to record pattern"));
|
|
4849
|
+
console.log(chalk14.dim(` Error: ${result.error}`));
|
|
4587
4850
|
process.exit(1);
|
|
4588
4851
|
}
|
|
4589
4852
|
} else {
|
|
@@ -4630,13 +4893,13 @@ async function learnRecordCommand(options) {
|
|
|
4630
4893
|
};
|
|
4631
4894
|
const result = await store.saveBlueprint(blueprint);
|
|
4632
4895
|
if (result.success) {
|
|
4633
|
-
console.log(
|
|
4634
|
-
console.log(
|
|
4635
|
-
console.log(
|
|
4636
|
-
console.log(
|
|
4896
|
+
console.log(chalk14.green("\n\u2705 Blueprint recorded successfully!\n"));
|
|
4897
|
+
console.log(chalk14.dim(` ID: ${blueprint.id}`));
|
|
4898
|
+
console.log(chalk14.dim(` Name: ${name}`));
|
|
4899
|
+
console.log(chalk14.dim(` Framework: ${framework} ${version}`));
|
|
4637
4900
|
} else {
|
|
4638
|
-
console.log(
|
|
4639
|
-
console.log(
|
|
4901
|
+
console.log(chalk14.red("\n\u274C Failed to record blueprint"));
|
|
4902
|
+
console.log(chalk14.dim(` Error: ${result.error}`));
|
|
4640
4903
|
process.exit(1);
|
|
4641
4904
|
}
|
|
4642
4905
|
}
|
|
@@ -4646,7 +4909,7 @@ async function learnListCommand(options) {
|
|
|
4646
4909
|
const store = new PatternStore2(cwd);
|
|
4647
4910
|
const patternType = options.type ?? "all";
|
|
4648
4911
|
const showDeprecated = options.deprecated ?? false;
|
|
4649
|
-
console.log(
|
|
4912
|
+
console.log(chalk14.cyan("\n\u{1F4DA} Recorded Learning Patterns\n"));
|
|
4650
4913
|
if (patternType === "all" || patternType === "fix") {
|
|
4651
4914
|
const fixResult = await store.listFixPatterns({
|
|
4652
4915
|
tags: options.tag ? [{ category: "framework", name: options.tag }] : void 0,
|
|
@@ -4654,29 +4917,29 @@ async function learnListCommand(options) {
|
|
|
4654
4917
|
includeDeprecated: showDeprecated
|
|
4655
4918
|
});
|
|
4656
4919
|
if (fixResult.success && fixResult.data && fixResult.data.length > 0) {
|
|
4657
|
-
console.log(
|
|
4920
|
+
console.log(chalk14.bold.yellow("\u{1F527} Fix Patterns:\n"));
|
|
4658
4921
|
for (const pattern of fixResult.data) {
|
|
4659
4922
|
const isDeprecated = pattern.deprecatedAt !== void 0;
|
|
4660
4923
|
const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
|
|
4661
|
-
const nameColor = isDeprecated ?
|
|
4924
|
+
const nameColor = isDeprecated ? chalk14.dim : chalk14.white;
|
|
4662
4925
|
console.log(` ${statusIcon} ${nameColor(pattern.name)}`);
|
|
4663
|
-
console.log(
|
|
4664
|
-
console.log(
|
|
4926
|
+
console.log(chalk14.dim(` ID: ${pattern.id}`));
|
|
4927
|
+
console.log(chalk14.dim(` Category: ${pattern.category}`));
|
|
4665
4928
|
console.log(
|
|
4666
|
-
|
|
4929
|
+
chalk14.dim(` Created: ${formatDate(pattern.createdAt)}`)
|
|
4667
4930
|
);
|
|
4668
4931
|
console.log(
|
|
4669
|
-
|
|
4932
|
+
chalk14.dim(
|
|
4670
4933
|
` Success Rate: ${(pattern.metrics.successRate * 100).toFixed(0)}% (${pattern.metrics.successes}/${pattern.metrics.applications})`
|
|
4671
4934
|
)
|
|
4672
4935
|
);
|
|
4673
4936
|
if (pattern.tags.length > 0) {
|
|
4674
|
-
console.log(
|
|
4937
|
+
console.log(chalk14.dim(` Tags: ${formatTags(pattern.tags)}`));
|
|
4675
4938
|
}
|
|
4676
4939
|
console.log("");
|
|
4677
4940
|
}
|
|
4678
4941
|
} else if (patternType === "fix") {
|
|
4679
|
-
console.log(
|
|
4942
|
+
console.log(chalk14.dim(" No fix patterns found.\n"));
|
|
4680
4943
|
}
|
|
4681
4944
|
}
|
|
4682
4945
|
if (patternType === "all" || patternType === "blueprint") {
|
|
@@ -4686,46 +4949,46 @@ async function learnListCommand(options) {
|
|
|
4686
4949
|
includeDeprecated: showDeprecated
|
|
4687
4950
|
});
|
|
4688
4951
|
if (bpResult.success && bpResult.data && bpResult.data.length > 0) {
|
|
4689
|
-
console.log(
|
|
4952
|
+
console.log(chalk14.bold.blue("\u{1F4D0} Blueprints:\n"));
|
|
4690
4953
|
for (const blueprint of bpResult.data) {
|
|
4691
4954
|
const isDeprecated = blueprint.deprecatedAt !== void 0;
|
|
4692
4955
|
const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
|
|
4693
|
-
const nameColor = isDeprecated ?
|
|
4956
|
+
const nameColor = isDeprecated ? chalk14.dim : chalk14.white;
|
|
4694
4957
|
console.log(` ${statusIcon} ${nameColor(blueprint.name)}`);
|
|
4695
|
-
console.log(
|
|
4696
|
-
console.log(
|
|
4958
|
+
console.log(chalk14.dim(` ID: ${blueprint.id}`));
|
|
4959
|
+
console.log(chalk14.dim(` Language: ${blueprint.stack.language}`));
|
|
4697
4960
|
console.log(
|
|
4698
|
-
|
|
4961
|
+
chalk14.dim(` Created: ${formatDate(blueprint.createdAt)}`)
|
|
4699
4962
|
);
|
|
4700
4963
|
console.log(
|
|
4701
|
-
|
|
4964
|
+
chalk14.dim(
|
|
4702
4965
|
` Success Rate: ${(blueprint.metrics.successRate * 100).toFixed(0)}% (${blueprint.metrics.successes}/${blueprint.metrics.applications})`
|
|
4703
4966
|
)
|
|
4704
4967
|
);
|
|
4705
4968
|
if (blueprint.tags.length > 0) {
|
|
4706
|
-
console.log(
|
|
4969
|
+
console.log(chalk14.dim(` Tags: ${formatTags(blueprint.tags)}`));
|
|
4707
4970
|
}
|
|
4708
4971
|
console.log("");
|
|
4709
4972
|
}
|
|
4710
4973
|
} else if (patternType === "blueprint") {
|
|
4711
|
-
console.log(
|
|
4974
|
+
console.log(chalk14.dim(" No blueprints found.\n"));
|
|
4712
4975
|
}
|
|
4713
4976
|
}
|
|
4714
4977
|
const stats = await store.getStats();
|
|
4715
4978
|
const totalPatterns = stats.totalFixes + stats.totalBlueprints;
|
|
4716
4979
|
const totalDeprecated = stats.deprecatedFixes + stats.deprecatedBlueprints;
|
|
4717
|
-
console.log(
|
|
4718
|
-
console.log(
|
|
4719
|
-
console.log(
|
|
4720
|
-
console.log(
|
|
4721
|
-
console.log(
|
|
4980
|
+
console.log(chalk14.dim("\u2501".repeat(40)));
|
|
4981
|
+
console.log(chalk14.dim(`Total: ${totalPatterns} patterns`));
|
|
4982
|
+
console.log(chalk14.dim(` Fix Patterns: ${stats.totalFixes}`));
|
|
4983
|
+
console.log(chalk14.dim(` Blueprints: ${stats.totalBlueprints}`));
|
|
4984
|
+
console.log(chalk14.dim(` Deprecated: ${totalDeprecated}`));
|
|
4722
4985
|
console.log("");
|
|
4723
4986
|
}
|
|
4724
4987
|
async function learnApplyCommand(patternId, options) {
|
|
4725
4988
|
const cwd = getWorkspacePath();
|
|
4726
4989
|
const store = new PatternStore2(cwd);
|
|
4727
4990
|
const telemetry = new TelemetryCollector2(cwd);
|
|
4728
|
-
console.log(
|
|
4991
|
+
console.log(chalk14.cyan("\n\u{1F527} Apply Learning Pattern\n"));
|
|
4729
4992
|
let pattern = await store.getFixPattern(patternId);
|
|
4730
4993
|
let patternType = "fix";
|
|
4731
4994
|
if (!pattern.success || !pattern.data) {
|
|
@@ -4734,21 +4997,21 @@ async function learnApplyCommand(patternId, options) {
|
|
|
4734
4997
|
pattern = bpResult;
|
|
4735
4998
|
patternType = "blueprint";
|
|
4736
4999
|
} else {
|
|
4737
|
-
console.log(
|
|
5000
|
+
console.log(chalk14.red(`
|
|
4738
5001
|
\u274C Pattern not found: ${patternId}`));
|
|
4739
5002
|
console.log(
|
|
4740
|
-
|
|
5003
|
+
chalk14.dim(" Use 'workflow learn:list' to see available patterns")
|
|
4741
5004
|
);
|
|
4742
5005
|
process.exit(1);
|
|
4743
5006
|
}
|
|
4744
5007
|
}
|
|
4745
5008
|
const patternData = pattern.data;
|
|
4746
|
-
console.log(
|
|
4747
|
-
console.log(
|
|
4748
|
-
console.log(
|
|
5009
|
+
console.log(chalk14.white(` Pattern: ${patternData.name}`));
|
|
5010
|
+
console.log(chalk14.dim(` Type: ${patternType}`));
|
|
5011
|
+
console.log(chalk14.dim(` Description: ${patternData.description}`));
|
|
4749
5012
|
if (options.dryRun) {
|
|
4750
5013
|
console.log(
|
|
4751
|
-
|
|
5014
|
+
chalk14.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n")
|
|
4752
5015
|
);
|
|
4753
5016
|
}
|
|
4754
5017
|
const framework = options.framework ?? patternData.compatibility.frameworks[0]?.name ?? "unknown";
|
|
@@ -4756,44 +5019,44 @@ async function learnApplyCommand(patternId, options) {
|
|
|
4756
5019
|
await telemetry.recordApplication(patternId, patternType, framework, version);
|
|
4757
5020
|
if (patternType === "fix") {
|
|
4758
5021
|
const fixPattern = patternData;
|
|
4759
|
-
console.log(
|
|
5022
|
+
console.log(chalk14.cyan("\n\u{1F4CB} Solution Steps:\n"));
|
|
4760
5023
|
if (fixPattern.solution.steps) {
|
|
4761
5024
|
for (let i = 0; i < fixPattern.solution.steps.length; i++) {
|
|
4762
5025
|
const step = fixPattern.solution.steps[i];
|
|
4763
5026
|
console.log(
|
|
4764
|
-
|
|
5027
|
+
chalk14.white(` ${i + 1}. [${step.action}] ${step.description}`)
|
|
4765
5028
|
);
|
|
4766
5029
|
if (step.file) {
|
|
4767
|
-
console.log(
|
|
5030
|
+
console.log(chalk14.dim(` File: ${step.file}`));
|
|
4768
5031
|
}
|
|
4769
5032
|
}
|
|
4770
5033
|
}
|
|
4771
5034
|
} else {
|
|
4772
5035
|
const blueprint = patternData;
|
|
4773
|
-
console.log(
|
|
5036
|
+
console.log(chalk14.cyan("\n\u{1F4CB} Setup Steps:\n"));
|
|
4774
5037
|
if (blueprint.setup.steps) {
|
|
4775
5038
|
for (let i = 0; i < blueprint.setup.steps.length; i++) {
|
|
4776
5039
|
const step = blueprint.setup.steps[i];
|
|
4777
|
-
console.log(
|
|
5040
|
+
console.log(chalk14.white(` ${i + 1}. ${step.description}`));
|
|
4778
5041
|
if (step.command) {
|
|
4779
|
-
console.log(
|
|
5042
|
+
console.log(chalk14.dim(` Command: ${step.command}`));
|
|
4780
5043
|
}
|
|
4781
5044
|
}
|
|
4782
5045
|
}
|
|
4783
5046
|
}
|
|
4784
5047
|
if (!options.dryRun) {
|
|
4785
|
-
const confirmed = await
|
|
5048
|
+
const confirmed = await p10.confirm({
|
|
4786
5049
|
message: "Mark this pattern as successfully applied?",
|
|
4787
5050
|
initialValue: true
|
|
4788
5051
|
});
|
|
4789
|
-
if (
|
|
4790
|
-
|
|
5052
|
+
if (p10.isCancel(confirmed)) {
|
|
5053
|
+
p10.cancel("Application cancelled");
|
|
4791
5054
|
process.exit(0);
|
|
4792
5055
|
}
|
|
4793
5056
|
if (confirmed) {
|
|
4794
5057
|
await store.updatePatternMetrics(patternId, patternType, true);
|
|
4795
5058
|
await telemetry.recordSuccess(patternId, patternType, framework, version);
|
|
4796
|
-
console.log(
|
|
5059
|
+
console.log(chalk14.green("\n\u2705 Pattern marked as successfully applied!"));
|
|
4797
5060
|
} else {
|
|
4798
5061
|
await store.updatePatternMetrics(patternId, patternType, false);
|
|
4799
5062
|
await telemetry.recordFailure(
|
|
@@ -4804,7 +5067,7 @@ async function learnApplyCommand(patternId, options) {
|
|
|
4804
5067
|
"unknown"
|
|
4805
5068
|
);
|
|
4806
5069
|
console.log(
|
|
4807
|
-
|
|
5070
|
+
chalk14.yellow("\n\u26A0\uFE0F Pattern application marked as unsuccessful.")
|
|
4808
5071
|
);
|
|
4809
5072
|
}
|
|
4810
5073
|
}
|
|
@@ -4812,32 +5075,32 @@ async function learnApplyCommand(patternId, options) {
|
|
|
4812
5075
|
async function learnSyncCommand(options) {
|
|
4813
5076
|
const cwd = getWorkspacePath();
|
|
4814
5077
|
const contributorManager = new ContributorManager2(cwd);
|
|
4815
|
-
console.log(
|
|
5078
|
+
console.log(chalk14.cyan("\n\u{1F504} Sync Learning Patterns\n"));
|
|
4816
5079
|
const config = await contributorManager.getConfig();
|
|
4817
5080
|
if (!config.success || !config.data?.syncOptIn) {
|
|
4818
|
-
console.log(
|
|
4819
|
-
console.log(
|
|
4820
|
-
console.log(
|
|
5081
|
+
console.log(chalk14.yellow("\u26A0\uFE0F Sync is not enabled.\n"));
|
|
5082
|
+
console.log(chalk14.dim(" To enable sync, run:"));
|
|
5083
|
+
console.log(chalk14.dim(" workflow learn:config --enable-sync\n"));
|
|
4821
5084
|
console.log(
|
|
4822
|
-
|
|
5085
|
+
chalk14.dim(
|
|
4823
5086
|
" This allows you to share anonymized patterns with the community."
|
|
4824
5087
|
)
|
|
4825
5088
|
);
|
|
4826
5089
|
process.exit(0);
|
|
4827
5090
|
}
|
|
4828
5091
|
if (options.dryRun) {
|
|
4829
|
-
console.log(
|
|
5092
|
+
console.log(chalk14.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be synced\n"));
|
|
4830
5093
|
}
|
|
4831
5094
|
const store = new PatternStore2(cwd);
|
|
4832
5095
|
const anonymizer = new PatternAnonymizer();
|
|
4833
5096
|
const { fixes, blueprints } = await store.getPatternsForSync();
|
|
4834
5097
|
console.log(
|
|
4835
|
-
|
|
5098
|
+
chalk14.dim(
|
|
4836
5099
|
` Patterns ready to sync: ${fixes.length} fixes, ${blueprints.length} blueprints`
|
|
4837
5100
|
)
|
|
4838
5101
|
);
|
|
4839
5102
|
if (options.push) {
|
|
4840
|
-
console.log(
|
|
5103
|
+
console.log(chalk14.cyan("\n\u{1F4E4} Pushing patterns...\n"));
|
|
4841
5104
|
let anonymizedFixes = 0;
|
|
4842
5105
|
let anonymizedBlueprints = 0;
|
|
4843
5106
|
for (const fix of fixes) {
|
|
@@ -4845,7 +5108,7 @@ async function learnSyncCommand(options) {
|
|
|
4845
5108
|
if (result.success) {
|
|
4846
5109
|
anonymizedFixes++;
|
|
4847
5110
|
if (!options.dryRun) {
|
|
4848
|
-
console.log(
|
|
5111
|
+
console.log(chalk14.dim(` \u2713 Anonymized: ${fix.name}`));
|
|
4849
5112
|
}
|
|
4850
5113
|
}
|
|
4851
5114
|
}
|
|
@@ -4854,117 +5117,117 @@ async function learnSyncCommand(options) {
|
|
|
4854
5117
|
if (result.success) {
|
|
4855
5118
|
anonymizedBlueprints++;
|
|
4856
5119
|
if (!options.dryRun) {
|
|
4857
|
-
console.log(
|
|
5120
|
+
console.log(chalk14.dim(` \u2713 Anonymized: ${bp.name}`));
|
|
4858
5121
|
}
|
|
4859
5122
|
}
|
|
4860
5123
|
}
|
|
4861
5124
|
console.log(
|
|
4862
|
-
|
|
5125
|
+
chalk14.green(
|
|
4863
5126
|
`
|
|
4864
5127
|
\u2705 Ready to push ${anonymizedFixes} fixes and ${anonymizedBlueprints} blueprints`
|
|
4865
5128
|
)
|
|
4866
5129
|
);
|
|
4867
|
-
console.log(
|
|
5130
|
+
console.log(chalk14.dim(" (Registry push not yet implemented)"));
|
|
4868
5131
|
}
|
|
4869
5132
|
if (options.pull) {
|
|
4870
|
-
console.log(
|
|
4871
|
-
console.log(
|
|
5133
|
+
console.log(chalk14.cyan("\n\u{1F4E5} Pulling patterns from registry...\n"));
|
|
5134
|
+
console.log(chalk14.dim(" (Registry pull not yet implemented)"));
|
|
4872
5135
|
}
|
|
4873
5136
|
if (!options.push && !options.pull) {
|
|
4874
5137
|
console.log(
|
|
4875
|
-
|
|
5138
|
+
chalk14.dim(" Specify --push to upload or --pull to download patterns.\n")
|
|
4876
5139
|
);
|
|
4877
5140
|
}
|
|
4878
5141
|
}
|
|
4879
5142
|
async function learnConfigCommand(options) {
|
|
4880
5143
|
const cwd = getWorkspacePath();
|
|
4881
5144
|
const contributorManager = new ContributorManager2(cwd);
|
|
4882
|
-
console.log(
|
|
5145
|
+
console.log(chalk14.cyan("\n\u2699\uFE0F Learning Configuration\n"));
|
|
4883
5146
|
if (options.enableSync) {
|
|
4884
5147
|
const result = await contributorManager.enableSync();
|
|
4885
5148
|
if (result.success) {
|
|
4886
|
-
console.log(
|
|
5149
|
+
console.log(chalk14.green("\u2705 Sync enabled"));
|
|
4887
5150
|
console.log(
|
|
4888
|
-
|
|
5151
|
+
chalk14.dim(" Your patterns will be anonymized before sharing.")
|
|
4889
5152
|
);
|
|
4890
5153
|
} else {
|
|
4891
|
-
console.log(
|
|
5154
|
+
console.log(chalk14.red(`\u274C Failed: ${result.error}`));
|
|
4892
5155
|
}
|
|
4893
5156
|
return;
|
|
4894
5157
|
}
|
|
4895
5158
|
if (options.disableSync) {
|
|
4896
5159
|
const result = await contributorManager.disableSync();
|
|
4897
5160
|
if (result.success) {
|
|
4898
|
-
console.log(
|
|
5161
|
+
console.log(chalk14.green("\u2705 Sync disabled"));
|
|
4899
5162
|
} else {
|
|
4900
|
-
console.log(
|
|
5163
|
+
console.log(chalk14.red(`\u274C Failed: ${result.error}`));
|
|
4901
5164
|
}
|
|
4902
5165
|
return;
|
|
4903
5166
|
}
|
|
4904
5167
|
if (options.enableTelemetry) {
|
|
4905
5168
|
const result = await contributorManager.enableTelemetry();
|
|
4906
5169
|
if (result.success) {
|
|
4907
|
-
console.log(
|
|
5170
|
+
console.log(chalk14.green("\u2705 Telemetry enabled"));
|
|
4908
5171
|
console.log(
|
|
4909
|
-
|
|
5172
|
+
chalk14.dim(
|
|
4910
5173
|
" Anonymous usage data helps improve pattern recommendations."
|
|
4911
5174
|
)
|
|
4912
5175
|
);
|
|
4913
5176
|
} else {
|
|
4914
|
-
console.log(
|
|
5177
|
+
console.log(chalk14.red(`\u274C Failed: ${result.error}`));
|
|
4915
5178
|
}
|
|
4916
5179
|
return;
|
|
4917
5180
|
}
|
|
4918
5181
|
if (options.disableTelemetry) {
|
|
4919
5182
|
const result = await contributorManager.disableTelemetry();
|
|
4920
5183
|
if (result.success) {
|
|
4921
|
-
console.log(
|
|
5184
|
+
console.log(chalk14.green("\u2705 Telemetry disabled"));
|
|
4922
5185
|
} else {
|
|
4923
|
-
console.log(
|
|
5186
|
+
console.log(chalk14.red(`\u274C Failed: ${result.error}`));
|
|
4924
5187
|
}
|
|
4925
5188
|
return;
|
|
4926
5189
|
}
|
|
4927
5190
|
if (options.resetId) {
|
|
4928
|
-
const confirmed = await
|
|
5191
|
+
const confirmed = await p10.confirm({
|
|
4929
5192
|
message: "Are you sure you want to reset your contributor ID? This cannot be undone.",
|
|
4930
5193
|
initialValue: false
|
|
4931
5194
|
});
|
|
4932
|
-
if (
|
|
4933
|
-
|
|
5195
|
+
if (p10.isCancel(confirmed) || !confirmed) {
|
|
5196
|
+
p10.cancel("Reset cancelled");
|
|
4934
5197
|
return;
|
|
4935
5198
|
}
|
|
4936
5199
|
const result = await contributorManager.resetId();
|
|
4937
5200
|
if (result.success) {
|
|
4938
|
-
console.log(
|
|
4939
|
-
console.log(
|
|
5201
|
+
console.log(chalk14.green("\u2705 Contributor ID reset"));
|
|
5202
|
+
console.log(chalk14.dim(` New ID: ${result.data?.id}`));
|
|
4940
5203
|
} else {
|
|
4941
|
-
console.log(
|
|
5204
|
+
console.log(chalk14.red(`\u274C Failed: ${result.error}`));
|
|
4942
5205
|
}
|
|
4943
5206
|
return;
|
|
4944
5207
|
}
|
|
4945
5208
|
const config = await contributorManager.getConfig();
|
|
4946
5209
|
if (config.success && config.data) {
|
|
4947
|
-
console.log(
|
|
4948
|
-
console.log(
|
|
4949
|
-
console.log(
|
|
5210
|
+
console.log(chalk14.white(" Current Settings:\n"));
|
|
5211
|
+
console.log(chalk14.dim(` Contributor ID: ${config.data.id}`));
|
|
5212
|
+
console.log(chalk14.dim(` Created: ${formatDate(config.data.createdAt)}`));
|
|
4950
5213
|
console.log(
|
|
4951
|
-
|
|
5214
|
+
chalk14.dim(` Sync Enabled: ${config.data.syncOptIn ? "Yes" : "No"}`)
|
|
4952
5215
|
);
|
|
4953
5216
|
console.log(
|
|
4954
|
-
|
|
5217
|
+
chalk14.dim(
|
|
4955
5218
|
` Telemetry Enabled: ${config.data.telemetryEnabled ? "Yes" : "No"}`
|
|
4956
5219
|
)
|
|
4957
5220
|
);
|
|
4958
5221
|
if (config.data.syncEnabledAt) {
|
|
4959
5222
|
console.log(
|
|
4960
|
-
|
|
5223
|
+
chalk14.dim(
|
|
4961
5224
|
` Sync Enabled At: ${formatDate(config.data.syncEnabledAt)}`
|
|
4962
5225
|
)
|
|
4963
5226
|
);
|
|
4964
5227
|
}
|
|
4965
5228
|
} else {
|
|
4966
5229
|
console.log(
|
|
4967
|
-
|
|
5230
|
+
chalk14.dim(
|
|
4968
5231
|
" No configuration found. Settings will be created on first use.\n"
|
|
4969
5232
|
)
|
|
4970
5233
|
);
|
|
@@ -4973,7 +5236,7 @@ async function learnConfigCommand(options) {
|
|
|
4973
5236
|
async function learnDeprecateCommand(patternId, reason) {
|
|
4974
5237
|
const cwd = getWorkspacePath();
|
|
4975
5238
|
const store = new PatternStore2(cwd);
|
|
4976
|
-
console.log(
|
|
5239
|
+
console.log(chalk14.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
|
|
4977
5240
|
let patternType = "fix";
|
|
4978
5241
|
let pattern = await store.getFixPattern(patternId);
|
|
4979
5242
|
if (!pattern.success || !pattern.data) {
|
|
@@ -4982,26 +5245,26 @@ async function learnDeprecateCommand(patternId, reason) {
|
|
|
4982
5245
|
pattern = bpResult;
|
|
4983
5246
|
patternType = "blueprint";
|
|
4984
5247
|
} else {
|
|
4985
|
-
console.log(
|
|
5248
|
+
console.log(chalk14.red(`
|
|
4986
5249
|
\u274C Pattern not found: ${patternId}`));
|
|
4987
5250
|
process.exit(1);
|
|
4988
5251
|
}
|
|
4989
5252
|
}
|
|
4990
|
-
console.log(
|
|
4991
|
-
console.log(
|
|
4992
|
-
const confirmed = await
|
|
5253
|
+
console.log(chalk14.white(` Pattern: ${pattern.data.name}`));
|
|
5254
|
+
console.log(chalk14.dim(` Reason: ${reason}`));
|
|
5255
|
+
const confirmed = await p10.confirm({
|
|
4993
5256
|
message: "Are you sure you want to deprecate this pattern?",
|
|
4994
5257
|
initialValue: false
|
|
4995
5258
|
});
|
|
4996
|
-
if (
|
|
4997
|
-
|
|
5259
|
+
if (p10.isCancel(confirmed) || !confirmed) {
|
|
5260
|
+
p10.cancel("Deprecation cancelled");
|
|
4998
5261
|
return;
|
|
4999
5262
|
}
|
|
5000
5263
|
const result = await store.deprecatePattern(patternId, patternType, reason);
|
|
5001
5264
|
if (result.success) {
|
|
5002
|
-
console.log(
|
|
5265
|
+
console.log(chalk14.green("\n\u2705 Pattern deprecated successfully"));
|
|
5003
5266
|
} else {
|
|
5004
|
-
console.log(
|
|
5267
|
+
console.log(chalk14.red(`
|
|
5005
5268
|
\u274C Failed: ${result.error}`));
|
|
5006
5269
|
process.exit(1);
|
|
5007
5270
|
}
|
|
@@ -5010,32 +5273,32 @@ async function learnStatsCommand() {
|
|
|
5010
5273
|
const cwd = getWorkspacePath();
|
|
5011
5274
|
const store = new PatternStore2(cwd);
|
|
5012
5275
|
const telemetry = new TelemetryCollector2(cwd);
|
|
5013
|
-
console.log(
|
|
5276
|
+
console.log(chalk14.cyan("\n\u{1F4CA} Learning Statistics\n"));
|
|
5014
5277
|
const storeStats = await store.getStats();
|
|
5015
5278
|
const totalPatterns = storeStats.totalFixes + storeStats.totalBlueprints;
|
|
5016
5279
|
const totalDeprecated = storeStats.deprecatedFixes + storeStats.deprecatedBlueprints;
|
|
5017
|
-
console.log(
|
|
5018
|
-
console.log(
|
|
5019
|
-
console.log(
|
|
5020
|
-
console.log(
|
|
5021
|
-
console.log(
|
|
5280
|
+
console.log(chalk14.bold.white(" Patterns:\n"));
|
|
5281
|
+
console.log(chalk14.dim(` Total: ${totalPatterns}`));
|
|
5282
|
+
console.log(chalk14.dim(` Fix Patterns: ${storeStats.totalFixes}`));
|
|
5283
|
+
console.log(chalk14.dim(` Blueprints: ${storeStats.totalBlueprints}`));
|
|
5284
|
+
console.log(chalk14.dim(` Deprecated: ${totalDeprecated}`));
|
|
5022
5285
|
const telemetryStats = await telemetry.getStats();
|
|
5023
|
-
console.log(
|
|
5024
|
-
console.log(
|
|
5286
|
+
console.log(chalk14.bold.white("\n Telemetry:\n"));
|
|
5287
|
+
console.log(chalk14.dim(` Pending Events: ${telemetryStats.pendingEvents}`));
|
|
5025
5288
|
console.log(
|
|
5026
|
-
|
|
5289
|
+
chalk14.dim(` Total Events Sent: ${telemetryStats.totalEventsSent}`)
|
|
5027
5290
|
);
|
|
5028
5291
|
if (telemetryStats.lastFlushAt) {
|
|
5029
5292
|
console.log(
|
|
5030
|
-
|
|
5293
|
+
chalk14.dim(` Last Flush: ${formatDate(telemetryStats.lastFlushAt)}`)
|
|
5031
5294
|
);
|
|
5032
5295
|
}
|
|
5033
5296
|
console.log("");
|
|
5034
5297
|
}
|
|
5035
5298
|
|
|
5036
5299
|
// src/cli/commands/solution.ts
|
|
5037
|
-
import
|
|
5038
|
-
import * as
|
|
5300
|
+
import chalk15 from "chalk";
|
|
5301
|
+
import * as p11 from "@clack/prompts";
|
|
5039
5302
|
import * as path2 from "path";
|
|
5040
5303
|
import {
|
|
5041
5304
|
PatternStore as PatternStore3,
|
|
@@ -5077,10 +5340,10 @@ function truncate(str, maxLen) {
|
|
|
5077
5340
|
async function solutionCaptureCommand(options) {
|
|
5078
5341
|
const cwd = getWorkspacePath2();
|
|
5079
5342
|
const store = new PatternStore3(cwd);
|
|
5080
|
-
console.log(
|
|
5343
|
+
console.log(chalk15.cyan("\n\u{1F4E6} Capture Solution Pattern\n"));
|
|
5081
5344
|
let targetPath = options.path;
|
|
5082
5345
|
if (!targetPath) {
|
|
5083
|
-
const pathInput = await
|
|
5346
|
+
const pathInput = await p11.text({
|
|
5084
5347
|
message: "Path to the solution directory:",
|
|
5085
5348
|
placeholder: "./src/auth",
|
|
5086
5349
|
validate: (val) => {
|
|
@@ -5088,8 +5351,8 @@ async function solutionCaptureCommand(options) {
|
|
|
5088
5351
|
return void 0;
|
|
5089
5352
|
}
|
|
5090
5353
|
});
|
|
5091
|
-
if (
|
|
5092
|
-
|
|
5354
|
+
if (p11.isCancel(pathInput)) {
|
|
5355
|
+
p11.cancel("Operation cancelled");
|
|
5093
5356
|
process.exit(0);
|
|
5094
5357
|
}
|
|
5095
5358
|
targetPath = pathInput;
|
|
@@ -5097,7 +5360,7 @@ async function solutionCaptureCommand(options) {
|
|
|
5097
5360
|
const absolutePath = path2.isAbsolute(targetPath) ? targetPath : path2.resolve(cwd, targetPath);
|
|
5098
5361
|
let name = options.name;
|
|
5099
5362
|
if (!name) {
|
|
5100
|
-
const nameInput = await
|
|
5363
|
+
const nameInput = await p11.text({
|
|
5101
5364
|
message: "Solution name:",
|
|
5102
5365
|
placeholder: "JWT Authentication",
|
|
5103
5366
|
validate: (val) => {
|
|
@@ -5105,15 +5368,15 @@ async function solutionCaptureCommand(options) {
|
|
|
5105
5368
|
return void 0;
|
|
5106
5369
|
}
|
|
5107
5370
|
});
|
|
5108
|
-
if (
|
|
5109
|
-
|
|
5371
|
+
if (p11.isCancel(nameInput)) {
|
|
5372
|
+
p11.cancel("Operation cancelled");
|
|
5110
5373
|
process.exit(0);
|
|
5111
5374
|
}
|
|
5112
5375
|
name = nameInput;
|
|
5113
5376
|
}
|
|
5114
5377
|
let description = options.description;
|
|
5115
5378
|
if (!description) {
|
|
5116
|
-
const descInput = await
|
|
5379
|
+
const descInput = await p11.text({
|
|
5117
5380
|
message: "Solution description:",
|
|
5118
5381
|
placeholder: "Complete JWT-based authentication with refresh tokens",
|
|
5119
5382
|
validate: (val) => {
|
|
@@ -5122,15 +5385,15 @@ async function solutionCaptureCommand(options) {
|
|
|
5122
5385
|
return void 0;
|
|
5123
5386
|
}
|
|
5124
5387
|
});
|
|
5125
|
-
if (
|
|
5126
|
-
|
|
5388
|
+
if (p11.isCancel(descInput)) {
|
|
5389
|
+
p11.cancel("Operation cancelled");
|
|
5127
5390
|
process.exit(0);
|
|
5128
5391
|
}
|
|
5129
5392
|
description = descInput;
|
|
5130
5393
|
}
|
|
5131
5394
|
let category = options.category;
|
|
5132
5395
|
if (!category) {
|
|
5133
|
-
const categoryChoice = await
|
|
5396
|
+
const categoryChoice = await p11.select({
|
|
5134
5397
|
message: "Solution category:",
|
|
5135
5398
|
options: [
|
|
5136
5399
|
{ value: "auth", label: "\u{1F510} Authentication" },
|
|
@@ -5149,8 +5412,8 @@ async function solutionCaptureCommand(options) {
|
|
|
5149
5412
|
{ value: "other", label: "\u{1F4E6} Other" }
|
|
5150
5413
|
]
|
|
5151
5414
|
});
|
|
5152
|
-
if (
|
|
5153
|
-
|
|
5415
|
+
if (p11.isCancel(categoryChoice)) {
|
|
5416
|
+
p11.cancel("Operation cancelled");
|
|
5154
5417
|
process.exit(0);
|
|
5155
5418
|
}
|
|
5156
5419
|
category = categoryChoice;
|
|
@@ -5159,20 +5422,20 @@ async function solutionCaptureCommand(options) {
|
|
|
5159
5422
|
if (options.keywords) {
|
|
5160
5423
|
keywords = options.keywords.split(",").map((k) => k.trim());
|
|
5161
5424
|
} else {
|
|
5162
|
-
const keywordsInput = await
|
|
5425
|
+
const keywordsInput = await p11.text({
|
|
5163
5426
|
message: "Keywords (comma-separated):",
|
|
5164
5427
|
placeholder: "jwt, authentication, login, refresh-token"
|
|
5165
5428
|
});
|
|
5166
|
-
if (
|
|
5167
|
-
|
|
5429
|
+
if (p11.isCancel(keywordsInput)) {
|
|
5430
|
+
p11.cancel("Operation cancelled");
|
|
5168
5431
|
process.exit(0);
|
|
5169
5432
|
}
|
|
5170
5433
|
if (keywordsInput) {
|
|
5171
5434
|
keywords = keywordsInput.split(",").map((k) => k.trim());
|
|
5172
5435
|
}
|
|
5173
5436
|
}
|
|
5174
|
-
const
|
|
5175
|
-
|
|
5437
|
+
const spinner9 = p11.spinner();
|
|
5438
|
+
spinner9.start("Analyzing solution...");
|
|
5176
5439
|
const analyzer = new CodeAnalyzer({
|
|
5177
5440
|
anonymize: options.anonymize ?? false
|
|
5178
5441
|
});
|
|
@@ -5184,38 +5447,38 @@ async function solutionCaptureCommand(options) {
|
|
|
5184
5447
|
category,
|
|
5185
5448
|
keywords
|
|
5186
5449
|
);
|
|
5187
|
-
|
|
5188
|
-
console.log(
|
|
5189
|
-
console.log(
|
|
5190
|
-
console.log(`${
|
|
5450
|
+
spinner9.stop("Solution analyzed");
|
|
5451
|
+
console.log(chalk15.green("\n\u2713 Solution captured successfully!\n"));
|
|
5452
|
+
console.log(chalk15.dim("\u2500".repeat(50)));
|
|
5453
|
+
console.log(`${chalk15.bold("Name:")} ${pattern.name}`);
|
|
5191
5454
|
console.log(
|
|
5192
|
-
`${
|
|
5455
|
+
`${chalk15.bold("Category:")} ${formatCategory(pattern.category)}`
|
|
5193
5456
|
);
|
|
5194
5457
|
console.log(
|
|
5195
|
-
`${
|
|
5458
|
+
`${chalk15.bold("Files:")} ${pattern.implementation.files.length}`
|
|
5196
5459
|
);
|
|
5197
5460
|
console.log(
|
|
5198
|
-
`${
|
|
5461
|
+
`${chalk15.bold("Dependencies:")} ${pattern.implementation.dependencies.length}`
|
|
5199
5462
|
);
|
|
5200
5463
|
console.log(
|
|
5201
|
-
`${
|
|
5464
|
+
`${chalk15.bold("Framework:")} ${pattern.compatibility.framework || "generic"}`
|
|
5202
5465
|
);
|
|
5203
|
-
console.log(
|
|
5204
|
-
const
|
|
5466
|
+
console.log(chalk15.dim("\u2500".repeat(50)));
|
|
5467
|
+
const confirm10 = await p11.confirm({
|
|
5205
5468
|
message: "Save this solution pattern?",
|
|
5206
5469
|
initialValue: true
|
|
5207
5470
|
});
|
|
5208
|
-
if (
|
|
5209
|
-
|
|
5471
|
+
if (p11.isCancel(confirm10) || !confirm10) {
|
|
5472
|
+
p11.cancel("Solution not saved");
|
|
5210
5473
|
process.exit(0);
|
|
5211
5474
|
}
|
|
5212
5475
|
await store.saveSolution(pattern);
|
|
5213
|
-
console.log(
|
|
5476
|
+
console.log(chalk15.green(`
|
|
5214
5477
|
\u2713 Solution saved with ID: ${pattern.id}
|
|
5215
5478
|
`));
|
|
5216
5479
|
} catch (error) {
|
|
5217
|
-
|
|
5218
|
-
console.error(
|
|
5480
|
+
spinner9.stop("Analysis failed");
|
|
5481
|
+
console.error(chalk15.red(`
|
|
5219
5482
|
\u2717 Error: ${error.message}
|
|
5220
5483
|
`));
|
|
5221
5484
|
process.exit(1);
|
|
@@ -5224,7 +5487,7 @@ async function solutionCaptureCommand(options) {
|
|
|
5224
5487
|
async function solutionSearchCommand(query, options) {
|
|
5225
5488
|
const cwd = getWorkspacePath2();
|
|
5226
5489
|
const store = new PatternStore3(cwd);
|
|
5227
|
-
console.log(
|
|
5490
|
+
console.log(chalk15.cyan("\n\u{1F50D} Search Solution Patterns\n"));
|
|
5228
5491
|
const keywords = query.split(/\s+/).filter((k) => k.length > 0);
|
|
5229
5492
|
const result = await store.searchSolutions(keywords, {
|
|
5230
5493
|
category: options.category,
|
|
@@ -5232,39 +5495,39 @@ async function solutionSearchCommand(query, options) {
|
|
|
5232
5495
|
limit: options.limit ?? 10
|
|
5233
5496
|
});
|
|
5234
5497
|
if (!result.success || !result.data) {
|
|
5235
|
-
console.error(
|
|
5498
|
+
console.error(chalk15.red(`
|
|
5236
5499
|
\u2717 Search failed: ${result.error}
|
|
5237
5500
|
`));
|
|
5238
5501
|
return;
|
|
5239
5502
|
}
|
|
5240
5503
|
const solutions = result.data;
|
|
5241
5504
|
if (solutions.length === 0) {
|
|
5242
|
-
console.log(
|
|
5243
|
-
console.log(
|
|
5505
|
+
console.log(chalk15.yellow("No solutions found matching your query.\n"));
|
|
5506
|
+
console.log(chalk15.dim("Try different keywords or fewer filters."));
|
|
5244
5507
|
return;
|
|
5245
5508
|
}
|
|
5246
|
-
console.log(
|
|
5509
|
+
console.log(chalk15.green(`Found ${solutions.length} solution(s):
|
|
5247
5510
|
`));
|
|
5248
|
-
console.log(
|
|
5511
|
+
console.log(chalk15.dim("\u2500".repeat(70)));
|
|
5249
5512
|
for (const solution of solutions) {
|
|
5250
5513
|
console.log(
|
|
5251
|
-
`${
|
|
5514
|
+
`${chalk15.bold(solution.name)} ${chalk15.dim(`(${solution.id.slice(0, 8)})`)}`
|
|
5252
5515
|
);
|
|
5253
5516
|
console.log(` ${formatCategory(solution.category)}`);
|
|
5254
|
-
console.log(` ${
|
|
5517
|
+
console.log(` ${chalk15.dim(truncate(solution.description, 60))}`);
|
|
5255
5518
|
console.log(
|
|
5256
5519
|
` Files: ${solution.implementation.files.length} | Framework: ${solution.compatibility.framework || "generic"} | Uses: ${solution.metrics.applications}`
|
|
5257
5520
|
);
|
|
5258
|
-
console.log(
|
|
5521
|
+
console.log(chalk15.dim("\u2500".repeat(70)));
|
|
5259
5522
|
}
|
|
5260
5523
|
console.log(
|
|
5261
|
-
|
|
5524
|
+
chalk15.dim("\nUse 'workflow solution:apply <id>' to apply a solution.")
|
|
5262
5525
|
);
|
|
5263
5526
|
}
|
|
5264
5527
|
async function solutionListCommand(options) {
|
|
5265
5528
|
const cwd = getWorkspacePath2();
|
|
5266
5529
|
const store = new PatternStore3(cwd);
|
|
5267
|
-
console.log(
|
|
5530
|
+
console.log(chalk15.cyan("\n\u{1F4CB} Solution Patterns\n"));
|
|
5268
5531
|
const result = await store.listSolutions({
|
|
5269
5532
|
category: options.category,
|
|
5270
5533
|
framework: options.framework,
|
|
@@ -5272,20 +5535,20 @@ async function solutionListCommand(options) {
|
|
|
5272
5535
|
limit: options.limit ?? 20
|
|
5273
5536
|
});
|
|
5274
5537
|
if (!result.success || !result.data) {
|
|
5275
|
-
console.error(
|
|
5538
|
+
console.error(chalk15.red(`
|
|
5276
5539
|
\u2717 List failed: ${result.error}
|
|
5277
5540
|
`));
|
|
5278
5541
|
return;
|
|
5279
5542
|
}
|
|
5280
5543
|
const solutions = result.data;
|
|
5281
5544
|
if (solutions.length === 0) {
|
|
5282
|
-
console.log(
|
|
5545
|
+
console.log(chalk15.yellow("No solutions found.\n"));
|
|
5283
5546
|
console.log(
|
|
5284
|
-
|
|
5547
|
+
chalk15.dim("Use 'workflow solution:capture' to capture a solution.")
|
|
5285
5548
|
);
|
|
5286
5549
|
return;
|
|
5287
5550
|
}
|
|
5288
|
-
console.log(
|
|
5551
|
+
console.log(chalk15.green(`${solutions.length} solution(s):
|
|
5289
5552
|
`));
|
|
5290
5553
|
const byCategory = /* @__PURE__ */ new Map();
|
|
5291
5554
|
for (const solution of solutions) {
|
|
@@ -5294,24 +5557,24 @@ async function solutionListCommand(options) {
|
|
|
5294
5557
|
byCategory.set(solution.category, list);
|
|
5295
5558
|
}
|
|
5296
5559
|
for (const [category, items] of byCategory) {
|
|
5297
|
-
console.log(
|
|
5560
|
+
console.log(chalk15.bold(`
|
|
5298
5561
|
${formatCategory(category)}`));
|
|
5299
|
-
console.log(
|
|
5562
|
+
console.log(chalk15.dim("\u2500".repeat(50)));
|
|
5300
5563
|
for (const solution of items) {
|
|
5301
|
-
const deprecated = solution.deprecatedAt ?
|
|
5564
|
+
const deprecated = solution.deprecatedAt ? chalk15.red(" [DEPRECATED]") : "";
|
|
5302
5565
|
console.log(
|
|
5303
|
-
` ${
|
|
5566
|
+
` ${chalk15.cyan(solution.id.slice(0, 8))} ${solution.name}${deprecated}`
|
|
5304
5567
|
);
|
|
5305
|
-
console.log(` ${
|
|
5568
|
+
console.log(` ${chalk15.dim(truncate(solution.description, 50))}`);
|
|
5306
5569
|
console.log(
|
|
5307
|
-
|
|
5570
|
+
chalk15.dim(
|
|
5308
5571
|
` Created: ${formatDate2(solution.createdAt)} | Files: ${solution.implementation.files.length}`
|
|
5309
5572
|
)
|
|
5310
5573
|
);
|
|
5311
5574
|
}
|
|
5312
5575
|
}
|
|
5313
5576
|
console.log(
|
|
5314
|
-
|
|
5577
|
+
chalk15.dim(
|
|
5315
5578
|
"\nUse 'workflow solution:search <query>' to find specific solutions."
|
|
5316
5579
|
)
|
|
5317
5580
|
);
|
|
@@ -5319,10 +5582,10 @@ ${formatCategory(category)}`));
|
|
|
5319
5582
|
async function solutionApplyCommand(solutionId, options) {
|
|
5320
5583
|
const cwd = getWorkspacePath2();
|
|
5321
5584
|
const store = new PatternStore3(cwd);
|
|
5322
|
-
console.log(
|
|
5585
|
+
console.log(chalk15.cyan("\n\u{1F680} Apply Solution Pattern\n"));
|
|
5323
5586
|
const result = await store.getSolution(solutionId);
|
|
5324
5587
|
if (!result.success || !result.data) {
|
|
5325
|
-
console.error(
|
|
5588
|
+
console.error(chalk15.red(`
|
|
5326
5589
|
\u2717 Solution not found: ${solutionId}
|
|
5327
5590
|
`));
|
|
5328
5591
|
process.exit(1);
|
|
@@ -5330,60 +5593,60 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5330
5593
|
const solution = result.data;
|
|
5331
5594
|
if (solution.deprecatedAt) {
|
|
5332
5595
|
console.log(
|
|
5333
|
-
|
|
5596
|
+
chalk15.yellow(
|
|
5334
5597
|
`\u26A0\uFE0F This solution is deprecated: ${solution.deprecationReason || "No reason provided"}
|
|
5335
5598
|
`
|
|
5336
5599
|
)
|
|
5337
5600
|
);
|
|
5338
|
-
const proceed = await
|
|
5601
|
+
const proceed = await p11.confirm({
|
|
5339
5602
|
message: "Do you want to continue?",
|
|
5340
5603
|
initialValue: false
|
|
5341
5604
|
});
|
|
5342
|
-
if (
|
|
5343
|
-
|
|
5605
|
+
if (p11.isCancel(proceed) || !proceed) {
|
|
5606
|
+
p11.cancel("Operation cancelled");
|
|
5344
5607
|
process.exit(0);
|
|
5345
5608
|
}
|
|
5346
5609
|
}
|
|
5347
|
-
console.log(
|
|
5348
|
-
console.log(
|
|
5610
|
+
console.log(chalk15.bold(`Solution: ${solution.name}`));
|
|
5611
|
+
console.log(chalk15.dim(solution.description));
|
|
5349
5612
|
console.log();
|
|
5350
|
-
console.log(
|
|
5613
|
+
console.log(chalk15.bold("Files to create:"));
|
|
5351
5614
|
const filesToApply = options.includeTests ? solution.implementation.files : solution.implementation.files.filter(
|
|
5352
5615
|
(f) => f.role !== "test"
|
|
5353
5616
|
);
|
|
5354
5617
|
for (const file of filesToApply) {
|
|
5355
|
-
console.log(
|
|
5618
|
+
console.log(chalk15.dim(` \u2022 ${file.path} (${file.role})`));
|
|
5356
5619
|
}
|
|
5357
5620
|
console.log();
|
|
5358
5621
|
if (solution.implementation.dependencies.length > 0) {
|
|
5359
|
-
console.log(
|
|
5622
|
+
console.log(chalk15.bold("Dependencies to install:"));
|
|
5360
5623
|
for (const dep of solution.implementation.dependencies) {
|
|
5361
|
-
console.log(
|
|
5624
|
+
console.log(chalk15.dim(` \u2022 ${dep.name}@${dep.version}`));
|
|
5362
5625
|
}
|
|
5363
5626
|
console.log();
|
|
5364
5627
|
}
|
|
5365
5628
|
if (solution.implementation.envVars.length > 0) {
|
|
5366
|
-
console.log(
|
|
5629
|
+
console.log(chalk15.bold("Environment variables needed:"));
|
|
5367
5630
|
for (const env of solution.implementation.envVars) {
|
|
5368
|
-
const required = env.required ?
|
|
5369
|
-
console.log(
|
|
5631
|
+
const required = env.required ? chalk15.red("*") : "";
|
|
5632
|
+
console.log(chalk15.dim(` \u2022 ${env.name}${required}`));
|
|
5370
5633
|
}
|
|
5371
5634
|
console.log();
|
|
5372
5635
|
}
|
|
5373
5636
|
if (options.dryRun) {
|
|
5374
|
-
console.log(
|
|
5637
|
+
console.log(chalk15.yellow("Dry run mode - no files were created.\n"));
|
|
5375
5638
|
return;
|
|
5376
5639
|
}
|
|
5377
|
-
const
|
|
5640
|
+
const confirm10 = await p11.confirm({
|
|
5378
5641
|
message: "Apply this solution?",
|
|
5379
5642
|
initialValue: true
|
|
5380
5643
|
});
|
|
5381
|
-
if (
|
|
5382
|
-
|
|
5644
|
+
if (p11.isCancel(confirm10) || !confirm10) {
|
|
5645
|
+
p11.cancel("Operation cancelled");
|
|
5383
5646
|
process.exit(0);
|
|
5384
5647
|
}
|
|
5385
|
-
const
|
|
5386
|
-
|
|
5648
|
+
const spinner9 = p11.spinner();
|
|
5649
|
+
spinner9.start("Applying solution...");
|
|
5387
5650
|
try {
|
|
5388
5651
|
const outputDir = options.output || cwd;
|
|
5389
5652
|
const fs2 = await import("fs");
|
|
@@ -5395,20 +5658,20 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5395
5658
|
await fs2.promises.writeFile(filePath, file.content);
|
|
5396
5659
|
}
|
|
5397
5660
|
await store.updateSolutionMetrics(solution.id, true);
|
|
5398
|
-
|
|
5399
|
-
console.log(
|
|
5661
|
+
spinner9.stop("Solution applied");
|
|
5662
|
+
console.log(chalk15.green(`
|
|
5400
5663
|
\u2713 Solution applied successfully!
|
|
5401
5664
|
`));
|
|
5402
|
-
console.log(
|
|
5665
|
+
console.log(chalk15.dim(`Created ${filesToApply.length} file(s).`));
|
|
5403
5666
|
if (solution.implementation.dependencies.length > 0) {
|
|
5404
|
-
console.log(
|
|
5667
|
+
console.log(chalk15.cyan("\nNext step: Install dependencies with:"));
|
|
5405
5668
|
const deps = solution.implementation.dependencies.map((d) => `${d.name}@${d.version}`).join(" ");
|
|
5406
|
-
console.log(
|
|
5669
|
+
console.log(chalk15.dim(` npm install ${deps}`));
|
|
5407
5670
|
}
|
|
5408
5671
|
} catch (error) {
|
|
5409
|
-
|
|
5672
|
+
spinner9.stop("Application failed");
|
|
5410
5673
|
await store.updateSolutionMetrics(solution.id, false);
|
|
5411
|
-
console.error(
|
|
5674
|
+
console.error(chalk15.red(`
|
|
5412
5675
|
\u2717 Error: ${error.message}
|
|
5413
5676
|
`));
|
|
5414
5677
|
process.exit(1);
|
|
@@ -5417,48 +5680,48 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5417
5680
|
async function solutionDeprecateCommand(solutionId, reason) {
|
|
5418
5681
|
const cwd = getWorkspacePath2();
|
|
5419
5682
|
const store = new PatternStore3(cwd);
|
|
5420
|
-
console.log(
|
|
5683
|
+
console.log(chalk15.cyan("\n\u26A0\uFE0F Deprecate Solution Pattern\n"));
|
|
5421
5684
|
const result = await store.getSolution(solutionId);
|
|
5422
5685
|
if (!result.success || !result.data) {
|
|
5423
|
-
console.error(
|
|
5686
|
+
console.error(chalk15.red(`
|
|
5424
5687
|
\u2717 Solution not found: ${solutionId}
|
|
5425
5688
|
`));
|
|
5426
5689
|
process.exit(1);
|
|
5427
5690
|
}
|
|
5428
5691
|
const solution = result.data;
|
|
5429
|
-
console.log(`Solution: ${
|
|
5692
|
+
console.log(`Solution: ${chalk15.bold(solution.name)}`);
|
|
5430
5693
|
console.log(`Reason: ${reason}
|
|
5431
5694
|
`);
|
|
5432
|
-
const
|
|
5695
|
+
const confirm10 = await p11.confirm({
|
|
5433
5696
|
message: "Deprecate this solution?",
|
|
5434
5697
|
initialValue: false
|
|
5435
5698
|
});
|
|
5436
|
-
if (
|
|
5437
|
-
|
|
5699
|
+
if (p11.isCancel(confirm10) || !confirm10) {
|
|
5700
|
+
p11.cancel("Operation cancelled");
|
|
5438
5701
|
process.exit(0);
|
|
5439
5702
|
}
|
|
5440
5703
|
await store.deprecateSolution(solutionId, reason);
|
|
5441
|
-
console.log(
|
|
5704
|
+
console.log(chalk15.green(`
|
|
5442
5705
|
\u2713 Solution deprecated.
|
|
5443
5706
|
`));
|
|
5444
5707
|
}
|
|
5445
5708
|
async function solutionStatsCommand() {
|
|
5446
5709
|
const cwd = getWorkspacePath2();
|
|
5447
5710
|
const store = new PatternStore3(cwd);
|
|
5448
|
-
console.log(
|
|
5711
|
+
console.log(chalk15.cyan("\n\u{1F4CA} Solution Pattern Statistics\n"));
|
|
5449
5712
|
const stats = await store.getStats();
|
|
5450
|
-
console.log(
|
|
5451
|
-
console.log(`${
|
|
5713
|
+
console.log(chalk15.dim("\u2500".repeat(40)));
|
|
5714
|
+
console.log(`${chalk15.bold("Solutions:")} ${stats.totalSolutions}`);
|
|
5452
5715
|
console.log(` Active: ${stats.totalSolutions - stats.deprecatedSolutions}`);
|
|
5453
5716
|
console.log(` Deprecated: ${stats.deprecatedSolutions}`);
|
|
5454
5717
|
console.log(` Private: ${stats.privateSolutions}`);
|
|
5455
5718
|
console.log(` Synced: ${stats.syncedSolutions}`);
|
|
5456
|
-
console.log(
|
|
5457
|
-
console.log(`${
|
|
5458
|
-
console.log(`${
|
|
5459
|
-
console.log(
|
|
5719
|
+
console.log(chalk15.dim("\u2500".repeat(40)));
|
|
5720
|
+
console.log(`${chalk15.bold("Fixes:")} ${stats.totalFixes}`);
|
|
5721
|
+
console.log(`${chalk15.bold("Blueprints:")} ${stats.totalBlueprints}`);
|
|
5722
|
+
console.log(chalk15.dim("\u2500".repeat(40)));
|
|
5460
5723
|
console.log(`
|
|
5461
|
-
${
|
|
5724
|
+
${chalk15.bold("By Category:")}`);
|
|
5462
5725
|
const listResult = await store.listSolutions({ limit: 1e3 });
|
|
5463
5726
|
if (listResult.success && listResult.data) {
|
|
5464
5727
|
const categories = /* @__PURE__ */ new Map();
|
|
@@ -5509,6 +5772,8 @@ program.command("advisory").description("Generate advisory board analysis and do
|
|
|
5509
5772
|
"--format <type>",
|
|
5510
5773
|
"Output format: markdown, json (default: markdown)"
|
|
5511
5774
|
).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
|
+
program.command("generate-instructions").description("Generate .github/copilot-instructions.md from guidelines").option("--force", "Regenerate without confirmation").action(generateInstructionsCommand);
|
|
5776
|
+
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);
|
|
5512
5777
|
program.command("learn:record").description("Record a new pattern from a successful implementation").option("--name <name>", "Pattern name").option("--description <desc>", "Pattern description").option(
|
|
5513
5778
|
"--category <cat>",
|
|
5514
5779
|
"Category (migration, security, performance, etc.)"
|