workflow-agent-cli 2.23.0 → 2.23.2
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/README.md +15 -15
- package/dist/{auto-fix-7WAESKYO.js → auto-fix-WGRYEFLJ.js} +2 -2
- package/dist/{chunk-IWFUJ2DS.js → chunk-DWHIY7R4.js} +20 -9
- package/dist/chunk-DWHIY7R4.js.map +1 -0
- package/dist/{chunk-D36IFZUZ.js → chunk-EHRI6BI6.js} +15 -4
- package/dist/chunk-EHRI6BI6.js.map +1 -0
- package/dist/{chunk-M6RHIUSM.js → chunk-K42R54II.js} +147 -54
- package/dist/chunk-K42R54II.js.map +1 -0
- package/dist/{chunk-XGS2VFBP.js → chunk-MBRMT5ZG.js} +865 -18
- package/dist/chunk-MBRMT5ZG.js.map +1 -0
- package/dist/{chunk-YELUGXOM.js → chunk-NPJJZHJG.js} +1 -1
- package/dist/chunk-NPJJZHJG.js.map +1 -0
- package/dist/{chunk-UWJ2ZGEI.js → chunk-OH6TK27N.js} +3 -3
- package/dist/{chunk-ZLDJ2OGO.js → chunk-WK7D2AVV.js} +11 -3
- package/dist/{chunk-ZLDJ2OGO.js.map → chunk-WK7D2AVV.js.map} +1 -1
- package/dist/cli/index.js +771 -285
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.js +2 -2
- package/dist/index.d.ts +87 -56
- package/dist/index.js +26 -10
- package/dist/scripts/postinstall.js +1 -1
- package/dist/scripts/postinstall.js.map +1 -1
- package/dist/sync-HHQM3GKR.js +7 -0
- package/dist/validators/index.js +1 -1
- package/dist/verify-PA7R6FBJ.js +8 -0
- package/package.json +2 -2
- package/dist/chunk-3ADL5QDN.js +0 -396
- package/dist/chunk-3ADL5QDN.js.map +0 -1
- package/dist/chunk-D36IFZUZ.js.map +0 -1
- package/dist/chunk-IWFUJ2DS.js.map +0 -1
- package/dist/chunk-M6RHIUSM.js.map +0 -1
- package/dist/chunk-XGS2VFBP.js.map +0 -1
- package/dist/chunk-YELUGXOM.js.map +0 -1
- package/dist/sync-6T5TD4QS.js +0 -7
- package/dist/verify-TX6LFMI6.js +0 -8
- /package/dist/{auto-fix-7WAESKYO.js.map → auto-fix-WGRYEFLJ.js.map} +0 -0
- /package/dist/{chunk-UWJ2ZGEI.js.map → chunk-OH6TK27N.js.map} +0 -0
- /package/dist/{sync-6T5TD4QS.js.map → sync-HHQM3GKR.js.map} +0 -0
- /package/dist/{verify-TX6LFMI6.js.map → verify-PA7R6FBJ.js.map} +0 -0
package/dist/cli/index.js
CHANGED
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
analyzeProject,
|
|
4
|
-
detectPackageManager,
|
|
5
|
-
generateAuditReport,
|
|
6
|
-
isMonorepo,
|
|
7
|
-
runAllSetups
|
|
8
|
-
} from "../chunk-XGS2VFBP.js";
|
|
9
2
|
import {
|
|
10
3
|
applyReferenceFix,
|
|
11
4
|
validateBranchName,
|
|
12
5
|
validateCommitMessage,
|
|
13
6
|
validateDocumentReferences,
|
|
14
7
|
validatePRTitle
|
|
15
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-WK7D2AVV.js";
|
|
16
9
|
import {
|
|
17
10
|
hasConfig,
|
|
18
11
|
loadConfig,
|
|
19
12
|
loadConfigSafe
|
|
20
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-OH6TK27N.js";
|
|
21
14
|
import {
|
|
22
15
|
DEPRECATED_SCRIPTS,
|
|
23
16
|
WORKFLOW_SCRIPTS,
|
|
@@ -29,25 +22,31 @@ import {
|
|
|
29
22
|
templateMetadata,
|
|
30
23
|
updateTemplates,
|
|
31
24
|
validateAllScripts
|
|
32
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-DWHIY7R4.js";
|
|
33
26
|
import {
|
|
34
27
|
autoFixConfigFile,
|
|
35
28
|
validateScopeDefinitions
|
|
36
|
-
} from "../chunk-
|
|
29
|
+
} from "../chunk-NPJJZHJG.js";
|
|
37
30
|
import {
|
|
38
31
|
verifyCommand
|
|
39
|
-
} from "../chunk-
|
|
40
|
-
import
|
|
32
|
+
} from "../chunk-EHRI6BI6.js";
|
|
33
|
+
import {
|
|
34
|
+
analyzeProject,
|
|
35
|
+
detectPackageManager,
|
|
36
|
+
generateAuditReport,
|
|
37
|
+
isMonorepo,
|
|
38
|
+
runAllSetups
|
|
39
|
+
} from "../chunk-MBRMT5ZG.js";
|
|
41
40
|
import {
|
|
42
41
|
syncCommand
|
|
43
|
-
} from "../chunk-
|
|
42
|
+
} from "../chunk-K42R54II.js";
|
|
44
43
|
|
|
45
44
|
// src/cli/index.ts
|
|
46
45
|
import { Command as Command7 } from "commander";
|
|
47
46
|
import chalk24 from "chalk";
|
|
48
47
|
import { readFileSync as readFileSync3 } from "fs";
|
|
49
48
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
50
|
-
import { dirname as dirname5, join as
|
|
49
|
+
import { dirname as dirname5, join as join13 } from "path";
|
|
51
50
|
|
|
52
51
|
// src/cli/commands/init.ts
|
|
53
52
|
import * as p from "@clack/prompts";
|
|
@@ -813,11 +812,19 @@ async function doctorCommand(options) {
|
|
|
813
812
|
for (const issue of result.issues) {
|
|
814
813
|
console.log(chalk5.red(` \u2717 ${issue.path}: ${issue.message}`));
|
|
815
814
|
if (issue.currentValue !== void 0) {
|
|
816
|
-
console.log(
|
|
815
|
+
console.log(
|
|
816
|
+
chalk5.dim(` Current value: ${JSON.stringify(issue.currentValue)}`)
|
|
817
|
+
);
|
|
817
818
|
}
|
|
818
819
|
if (issue.suggestedFix) {
|
|
819
|
-
console.log(
|
|
820
|
-
|
|
820
|
+
console.log(
|
|
821
|
+
chalk5.green(` Suggested fix: ${issue.suggestedFix.description}`)
|
|
822
|
+
);
|
|
823
|
+
console.log(
|
|
824
|
+
chalk5.dim(
|
|
825
|
+
` New value: ${JSON.stringify(issue.suggestedFix.newValue)}`
|
|
826
|
+
)
|
|
827
|
+
);
|
|
821
828
|
}
|
|
822
829
|
}
|
|
823
830
|
const hasAutoFixes = result.issues.some((i) => i.suggestedFix);
|
|
@@ -830,7 +837,9 @@ async function doctorCommand(options) {
|
|
|
830
837
|
for (const change of fixResult.changes) {
|
|
831
838
|
console.log(chalk5.dim(` \u2022 ${change}`));
|
|
832
839
|
}
|
|
833
|
-
console.log(
|
|
840
|
+
console.log(
|
|
841
|
+
chalk5.cyan("\n Run 'workflow doctor' again to verify.\n")
|
|
842
|
+
);
|
|
834
843
|
process.exit(0);
|
|
835
844
|
} else {
|
|
836
845
|
console.log(chalk5.red(`\u2717 Auto-fix failed: ${fixResult.error}`));
|
|
@@ -865,15 +874,15 @@ async function doctorCommand(options) {
|
|
|
865
874
|
}
|
|
866
875
|
if (missingFiles.length === 0) {
|
|
867
876
|
console.log(
|
|
868
|
-
chalk5.green(
|
|
869
|
-
|
|
877
|
+
chalk5.green(
|
|
878
|
+
`
|
|
879
|
+
\u2713 All ${mandatoryFiles.length} mandatory guidelines present`
|
|
880
|
+
)
|
|
870
881
|
);
|
|
871
882
|
} else {
|
|
872
883
|
console.log(
|
|
873
|
-
chalk5.red(
|
|
874
|
-
|
|
875
|
-
\u2717 Missing ${missingFiles.length} mandatory guideline(s)`
|
|
876
|
-
)
|
|
884
|
+
chalk5.red(`
|
|
885
|
+
\u2717 Missing ${missingFiles.length} mandatory guideline(s)`)
|
|
877
886
|
);
|
|
878
887
|
}
|
|
879
888
|
if (options?.checkGuidelinesOnly) {
|
|
@@ -899,7 +908,11 @@ async function doctorCommand(options) {
|
|
|
899
908
|
}
|
|
900
909
|
} catch (error) {
|
|
901
910
|
console.log(chalk5.yellow("\u26A0 Could not check hooks status"));
|
|
902
|
-
console.log(
|
|
911
|
+
console.log(
|
|
912
|
+
chalk5.dim(
|
|
913
|
+
` ${error instanceof Error ? error.message : "Unknown error"}`
|
|
914
|
+
)
|
|
915
|
+
);
|
|
903
916
|
}
|
|
904
917
|
}
|
|
905
918
|
if (missingFiles.length > 0) {
|
|
@@ -960,9 +973,7 @@ async function setupCommand() {
|
|
|
960
973
|
}
|
|
961
974
|
const hasChanges = scriptAdded || scriptUpdated || removedScripts.length > 0;
|
|
962
975
|
if (!hasChanges) {
|
|
963
|
-
p3.outro(
|
|
964
|
-
chalk6.green(`\u2713 Workflow script is already configured!`)
|
|
965
|
-
);
|
|
976
|
+
p3.outro(chalk6.green(`\u2713 Workflow script is already configured!`));
|
|
966
977
|
return;
|
|
967
978
|
}
|
|
968
979
|
writeFileSync(
|
|
@@ -983,8 +994,10 @@ async function setupCommand() {
|
|
|
983
994
|
}
|
|
984
995
|
if (removedScripts.length > 0) {
|
|
985
996
|
console.log(
|
|
986
|
-
chalk6.yellow(
|
|
987
|
-
|
|
997
|
+
chalk6.yellow(
|
|
998
|
+
`
|
|
999
|
+
\u26A0\uFE0F Removed ${removedScripts.length} deprecated scripts`
|
|
1000
|
+
)
|
|
988
1001
|
);
|
|
989
1002
|
console.log(
|
|
990
1003
|
chalk6.dim(
|
|
@@ -1186,7 +1199,9 @@ function formatAuditReportColored(report) {
|
|
|
1186
1199
|
|
|
1187
1200
|
// src/cli/commands/setup/index.ts
|
|
1188
1201
|
function createSetupCommand() {
|
|
1189
|
-
const setupCmd = new Command("setup").description(
|
|
1202
|
+
const setupCmd = new Command("setup").description(
|
|
1203
|
+
"Setup and configuration commands"
|
|
1204
|
+
);
|
|
1190
1205
|
setupCmd.action(setupCommand);
|
|
1191
1206
|
setupCmd.command("scripts").description("Add workflow scripts to package.json").action(setupCommand);
|
|
1192
1207
|
setupCmd.command("auto").description("Automatically configure linting, formatting, testing, and CI").option("-y, --yes", "Auto-approve all prompts").option("--audit", "Show audit report without applying changes").action(autoSetupCommand);
|
|
@@ -1973,13 +1988,19 @@ async function docsValidateCommand(options) {
|
|
|
1973
1988
|
console.log(chalk11.dim(` ${broken.rawLink}`));
|
|
1974
1989
|
console.log(chalk11.dim(` Target: ${broken.targetPath}`));
|
|
1975
1990
|
if (broken.suggestions.length > 0) {
|
|
1976
|
-
console.log(
|
|
1991
|
+
console.log(
|
|
1992
|
+
chalk11.dim(
|
|
1993
|
+
` Suggestions: ${broken.suggestions.slice(0, 3).join(", ")}`
|
|
1994
|
+
)
|
|
1995
|
+
);
|
|
1977
1996
|
}
|
|
1978
1997
|
console.log("");
|
|
1979
1998
|
}
|
|
1980
1999
|
if (!fix) {
|
|
1981
2000
|
console.log(
|
|
1982
|
-
chalk11.yellow(
|
|
2001
|
+
chalk11.yellow(
|
|
2002
|
+
"\u{1F4A1} Run with --fix flag to interactively fix broken references"
|
|
2003
|
+
)
|
|
1983
2004
|
);
|
|
1984
2005
|
p7.outro(chalk11.red("Validation failed"));
|
|
1985
2006
|
process.exit(1);
|
|
@@ -2055,7 +2076,9 @@ Fixed: ${fixedCount}, Skipped: ${skippedCount}`)
|
|
|
2055
2076
|
}
|
|
2056
2077
|
try {
|
|
2057
2078
|
await applyReferenceFix(broken.file, broken.rawLink, newPath);
|
|
2058
|
-
console.log(
|
|
2079
|
+
console.log(
|
|
2080
|
+
chalk11.green(` \u2705 Fixed: ${broken.targetPath} \u2192 ${newPath}`)
|
|
2081
|
+
);
|
|
2059
2082
|
fixedCount++;
|
|
2060
2083
|
} catch (error) {
|
|
2061
2084
|
console.log(
|
|
@@ -2128,7 +2151,9 @@ async function docsGenerateCommand(options) {
|
|
|
2128
2151
|
)
|
|
2129
2152
|
);
|
|
2130
2153
|
if (result.preservedCustomContent) {
|
|
2131
|
-
console.log(
|
|
2154
|
+
console.log(
|
|
2155
|
+
chalk12.dim(" Custom content between markers was preserved.")
|
|
2156
|
+
);
|
|
2132
2157
|
}
|
|
2133
2158
|
console.log(chalk12.dim(`
|
|
2134
2159
|
Output: ${result.filePath}`));
|
|
@@ -2155,9 +2180,13 @@ Reason: ${error instanceof Error ? error.message : String(error)}`
|
|
|
2155
2180
|
p8.outro(chalk12.green("\u2713 AI agent instructions ready!"));
|
|
2156
2181
|
console.log(chalk12.dim("\nThe .github/copilot-instructions.md file:"));
|
|
2157
2182
|
console.log(chalk12.dim(" - Is read by GitHub Copilot and other AI agents"));
|
|
2158
|
-
console.log(
|
|
2183
|
+
console.log(
|
|
2184
|
+
chalk12.dim(" - Summarizes all guidelines with links to full docs")
|
|
2185
|
+
);
|
|
2159
2186
|
console.log(chalk12.dim(" - Includes your project scopes and conventions"));
|
|
2160
|
-
console.log(
|
|
2187
|
+
console.log(
|
|
2188
|
+
chalk12.dim(" - Preserves custom instructions you add between markers\n")
|
|
2189
|
+
);
|
|
2161
2190
|
}
|
|
2162
2191
|
|
|
2163
2192
|
// src/cli/commands/docs/update.ts
|
|
@@ -2198,9 +2227,7 @@ async function docsUpdateCommand(options) {
|
|
|
2198
2227
|
console.log(chalk13.dim(` ${meta.description}`));
|
|
2199
2228
|
}
|
|
2200
2229
|
}
|
|
2201
|
-
const optionalFiles = allTemplates.filter(
|
|
2202
|
-
(f) => !mandatoryFiles.includes(f)
|
|
2203
|
-
);
|
|
2230
|
+
const optionalFiles = allTemplates.filter((f) => !mandatoryFiles.includes(f));
|
|
2204
2231
|
if (optionalFiles.length > 0) {
|
|
2205
2232
|
console.log(chalk13.bold("\n Optional templates:"));
|
|
2206
2233
|
for (const file of optionalFiles) {
|
|
@@ -4094,7 +4121,7 @@ async function advisoryCommand(options) {
|
|
|
4094
4121
|
const analyzer = new AdvisoryAnalyzer({
|
|
4095
4122
|
depth,
|
|
4096
4123
|
cwd,
|
|
4097
|
-
config,
|
|
4124
|
+
config: config ?? void 0,
|
|
4098
4125
|
includeHealth,
|
|
4099
4126
|
excludePatterns: advisoryConfig?.excludePatterns
|
|
4100
4127
|
});
|
|
@@ -5004,7 +5031,13 @@ ${chalk15.bold("Examples:")}
|
|
|
5004
5031
|
docsCmd.command("advisory").description("Generate advisory board analysis and documentation").option(
|
|
5005
5032
|
"--depth <level>",
|
|
5006
5033
|
"Analysis depth: executive, quick, standard, comprehensive"
|
|
5007
|
-
).option("--output <path>", "Output directory (default: docs/advisory)").option("--interactive", "Enable interactive mode").option("--dry-run", "Preview analysis without writing files").option(
|
|
5034
|
+
).option("--output <path>", "Output directory (default: docs/advisory)").option("--interactive", "Enable interactive mode").option("--dry-run", "Preview analysis without writing files").option(
|
|
5035
|
+
"--format <type>",
|
|
5036
|
+
"Output format: markdown, json (default: markdown)"
|
|
5037
|
+
).option("--timestamp", "Append timestamp to filenames").option(
|
|
5038
|
+
"--include-health",
|
|
5039
|
+
"Include code health metrics from verify/doctor"
|
|
5040
|
+
).option("--ci", "CI mode with exit codes on high-risk findings").option("--compare <path>", "Compare with previous report").addHelpText(
|
|
5008
5041
|
"after",
|
|
5009
5042
|
`
|
|
5010
5043
|
${chalk15.bold("Examples:")}
|
|
@@ -5152,10 +5185,10 @@ async function statusAction() {
|
|
|
5152
5185
|
async function testAction(options) {
|
|
5153
5186
|
console.log(chalk17.bold.cyan("\n\u{1F9EA} Testing Git Hooks\n"));
|
|
5154
5187
|
const fs3 = await import("fs");
|
|
5155
|
-
const
|
|
5188
|
+
const path5 = await import("path");
|
|
5156
5189
|
const cwd = process.cwd();
|
|
5157
|
-
const gitDir =
|
|
5158
|
-
const hooksDir =
|
|
5190
|
+
const gitDir = path5.join(cwd, ".git");
|
|
5191
|
+
const hooksDir = path5.join(gitDir, "hooks");
|
|
5159
5192
|
if (!fs3.existsSync(gitDir)) {
|
|
5160
5193
|
console.log(chalk17.red("\u2717 Not a git repository"));
|
|
5161
5194
|
process.exit(1);
|
|
@@ -5168,14 +5201,18 @@ async function testAction(options) {
|
|
|
5168
5201
|
const hookTypes = ["pre-commit", "commit-msg"];
|
|
5169
5202
|
let allInstalled = true;
|
|
5170
5203
|
for (const hookType of hookTypes) {
|
|
5171
|
-
const hookPath =
|
|
5204
|
+
const hookPath = path5.join(hooksDir, hookType);
|
|
5172
5205
|
const exists = fs3.existsSync(hookPath);
|
|
5173
5206
|
const isExecutable = exists && (fs3.statSync(hookPath).mode & 73) !== 0;
|
|
5174
5207
|
const isWorkflowHook2 = exists && fs3.readFileSync(hookPath, "utf-8").toLowerCase().includes("workflow");
|
|
5175
5208
|
if (exists && isExecutable && isWorkflowHook2) {
|
|
5176
5209
|
console.log(chalk17.green(` \u2713 ${hookType} - installed and executable`));
|
|
5177
5210
|
} else if (exists && !isWorkflowHook2) {
|
|
5178
|
-
console.log(
|
|
5211
|
+
console.log(
|
|
5212
|
+
chalk17.yellow(
|
|
5213
|
+
` \u26A0 ${hookType} - exists but not managed by workflow-agent`
|
|
5214
|
+
)
|
|
5215
|
+
);
|
|
5179
5216
|
allInstalled = false;
|
|
5180
5217
|
} else if (exists && !isExecutable) {
|
|
5181
5218
|
console.log(chalk17.red(` \u2717 ${hookType} - exists but not executable`));
|
|
@@ -5188,7 +5225,7 @@ async function testAction(options) {
|
|
|
5188
5225
|
if (options.dryRun) {
|
|
5189
5226
|
console.log(chalk17.bold.cyan("\n Dry-run hook simulation:\n"));
|
|
5190
5227
|
console.log(chalk17.dim(" Simulating pre-commit hook..."));
|
|
5191
|
-
const { verifyCommand: verifyCommand2 } = await import("../verify-
|
|
5228
|
+
const { verifyCommand: verifyCommand2 } = await import("../verify-PA7R6FBJ.js");
|
|
5192
5229
|
try {
|
|
5193
5230
|
await verifyCommand2({ fix: false, dryRun: true, maxRetries: "1" });
|
|
5194
5231
|
} catch {
|
|
@@ -5446,14 +5483,20 @@ async function solutionCaptureCommand(options) {
|
|
|
5446
5483
|
}
|
|
5447
5484
|
const saveResult = await store.saveSolution(pattern);
|
|
5448
5485
|
if (!saveResult.success) {
|
|
5449
|
-
console.error(
|
|
5486
|
+
console.error(
|
|
5487
|
+
chalk18.red(`
|
|
5450
5488
|
\u2717 Failed to save solution: ${saveResult.error}
|
|
5451
|
-
`)
|
|
5489
|
+
`)
|
|
5490
|
+
);
|
|
5452
5491
|
process.exit(1);
|
|
5453
5492
|
}
|
|
5454
|
-
console.log(
|
|
5493
|
+
console.log(
|
|
5494
|
+
chalk18.green(
|
|
5495
|
+
`
|
|
5455
5496
|
\u2713 Solution saved: .workflow/patterns/solutions/${pattern.id}.json
|
|
5456
|
-
`
|
|
5497
|
+
`
|
|
5498
|
+
)
|
|
5499
|
+
);
|
|
5457
5500
|
} catch (error) {
|
|
5458
5501
|
spinner10.stop("Analysis failed");
|
|
5459
5502
|
console.error(chalk18.red(`
|
|
@@ -5801,12 +5844,13 @@ async function solutionCreateCommand(options) {
|
|
|
5801
5844
|
name,
|
|
5802
5845
|
description,
|
|
5803
5846
|
category,
|
|
5804
|
-
tags: keywords.map((k) => ({
|
|
5847
|
+
tags: keywords.map((k) => ({
|
|
5848
|
+
name: k,
|
|
5849
|
+
category: "custom"
|
|
5850
|
+
})),
|
|
5805
5851
|
problem: {
|
|
5806
5852
|
description,
|
|
5807
5853
|
keywords,
|
|
5808
|
-
symptoms: [],
|
|
5809
|
-
impact: "To be documented",
|
|
5810
5854
|
errorPatterns: []
|
|
5811
5855
|
},
|
|
5812
5856
|
implementation: {
|
|
@@ -5851,17 +5895,23 @@ async function solutionCreateCommand(options) {
|
|
|
5851
5895
|
};
|
|
5852
5896
|
const saveResult = await store.saveSolution(solution);
|
|
5853
5897
|
if (!saveResult.success) {
|
|
5854
|
-
console.error(
|
|
5898
|
+
console.error(
|
|
5899
|
+
chalk18.red(`
|
|
5855
5900
|
\u2717 Failed to save solution: ${saveResult.error}
|
|
5856
|
-
`)
|
|
5901
|
+
`)
|
|
5902
|
+
);
|
|
5857
5903
|
process.exit(1);
|
|
5858
5904
|
}
|
|
5859
5905
|
console.log(chalk18.green("\n\u2713 Solution pattern created!\n"));
|
|
5860
|
-
console.log(
|
|
5906
|
+
console.log(
|
|
5907
|
+
chalk18.dim(` Path: .workflow/patterns/solutions/${solution.id}.json`)
|
|
5908
|
+
);
|
|
5861
5909
|
console.log(chalk18.dim(` Name: ${name}`));
|
|
5862
5910
|
console.log(chalk18.dim(` Category: ${category}`));
|
|
5863
|
-
console.log(
|
|
5864
|
-
|
|
5911
|
+
console.log(
|
|
5912
|
+
chalk18.dim(`
|
|
5913
|
+
Add files using 'workflow solution capture --path <dir>'`)
|
|
5914
|
+
);
|
|
5865
5915
|
}
|
|
5866
5916
|
async function solutionShowCommand(solutionId) {
|
|
5867
5917
|
const cwd = getWorkspacePath();
|
|
@@ -5885,20 +5935,26 @@ async function solutionShowCommand(solutionId) {
|
|
|
5885
5935
|
console.log(chalk18.bold("\nCompatibility:"));
|
|
5886
5936
|
console.log(` Framework: ${solution.compatibility.framework || "generic"}`);
|
|
5887
5937
|
console.log(` Version: ${solution.compatibility.frameworkVersion}`);
|
|
5888
|
-
console.log(
|
|
5938
|
+
console.log(
|
|
5939
|
+
` Runtime: ${solution.compatibility.runtime} ${solution.compatibility.runtimeVersion}`
|
|
5940
|
+
);
|
|
5889
5941
|
console.log(chalk18.bold("\nImplementation:"));
|
|
5890
5942
|
console.log(` Files: ${solution.implementation.files.length}`);
|
|
5891
5943
|
for (const file of solution.implementation.files) {
|
|
5892
5944
|
console.log(chalk18.dim(` \u2022 ${file.path} (${file.role})`));
|
|
5893
5945
|
}
|
|
5894
5946
|
if (solution.implementation.dependencies.length > 0) {
|
|
5895
|
-
console.log(
|
|
5947
|
+
console.log(
|
|
5948
|
+
` Dependencies: ${solution.implementation.dependencies.length}`
|
|
5949
|
+
);
|
|
5896
5950
|
for (const dep of solution.implementation.dependencies) {
|
|
5897
5951
|
console.log(chalk18.dim(` \u2022 ${dep.name}@${dep.version}`));
|
|
5898
5952
|
}
|
|
5899
5953
|
}
|
|
5900
5954
|
if (solution.implementation.envVars.length > 0) {
|
|
5901
|
-
console.log(
|
|
5955
|
+
console.log(
|
|
5956
|
+
` Environment Variables: ${solution.implementation.envVars.length}`
|
|
5957
|
+
);
|
|
5902
5958
|
for (const env of solution.implementation.envVars) {
|
|
5903
5959
|
const required = env.required ? chalk18.red("*") : "";
|
|
5904
5960
|
console.log(chalk18.dim(` \u2022 ${env.name}${required}`));
|
|
@@ -5906,14 +5962,22 @@ async function solutionShowCommand(solutionId) {
|
|
|
5906
5962
|
}
|
|
5907
5963
|
console.log(chalk18.bold("\nMetrics:"));
|
|
5908
5964
|
console.log(` Applications: ${solution.metrics.applications}`);
|
|
5909
|
-
console.log(
|
|
5965
|
+
console.log(
|
|
5966
|
+
` Success Rate: ${(solution.metrics.successRate * 100).toFixed(1)}%`
|
|
5967
|
+
);
|
|
5910
5968
|
console.log(chalk18.bold("\nMetadata:"));
|
|
5911
5969
|
console.log(` Created: ${formatDate(solution.createdAt)}`);
|
|
5912
5970
|
console.log(` Updated: ${formatDate(solution.updatedAt)}`);
|
|
5913
5971
|
console.log(` Private: ${solution.isPrivate ? "Yes" : "No"}`);
|
|
5914
5972
|
if (solution.deprecatedAt) {
|
|
5915
|
-
console.log(
|
|
5916
|
-
|
|
5973
|
+
console.log(
|
|
5974
|
+
chalk18.red(` Deprecated: ${formatDate(solution.deprecatedAt)}`)
|
|
5975
|
+
);
|
|
5976
|
+
console.log(
|
|
5977
|
+
chalk18.dim(
|
|
5978
|
+
` Reason: ${solution.deprecationReason || "No reason provided"}`
|
|
5979
|
+
)
|
|
5980
|
+
);
|
|
5917
5981
|
}
|
|
5918
5982
|
console.log();
|
|
5919
5983
|
}
|
|
@@ -5995,7 +6059,9 @@ async function solutionImportCommand(file, options) {
|
|
|
5995
6059
|
let importData;
|
|
5996
6060
|
try {
|
|
5997
6061
|
if (file.endsWith(".yaml") || file.endsWith(".yml")) {
|
|
5998
|
-
console.log(
|
|
6062
|
+
console.log(
|
|
6063
|
+
chalk18.yellow(" YAML import not fully supported, treating as JSON")
|
|
6064
|
+
);
|
|
5999
6065
|
}
|
|
6000
6066
|
importData = JSON.parse(content);
|
|
6001
6067
|
} catch {
|
|
@@ -6012,7 +6078,9 @@ async function solutionImportCommand(file, options) {
|
|
|
6012
6078
|
if (dryRun) {
|
|
6013
6079
|
console.log(chalk18.yellow(" \u{1F50D} Dry run - no changes will be made\n"));
|
|
6014
6080
|
for (const solution of solutions) {
|
|
6015
|
-
console.log(
|
|
6081
|
+
console.log(
|
|
6082
|
+
chalk18.dim(` Would import: ${solution.name} (${solution.id})`)
|
|
6083
|
+
);
|
|
6016
6084
|
}
|
|
6017
6085
|
return;
|
|
6018
6086
|
}
|
|
@@ -6027,7 +6095,11 @@ async function solutionImportCommand(file, options) {
|
|
|
6027
6095
|
}
|
|
6028
6096
|
const saveResult = await store.saveSolution(solution);
|
|
6029
6097
|
if (!saveResult.success) {
|
|
6030
|
-
console.log(
|
|
6098
|
+
console.log(
|
|
6099
|
+
chalk18.red(
|
|
6100
|
+
` \u2717 Failed to import: ${solution.name} - ${saveResult.error}`
|
|
6101
|
+
)
|
|
6102
|
+
);
|
|
6031
6103
|
continue;
|
|
6032
6104
|
}
|
|
6033
6105
|
console.log(chalk18.green(` \u2713 Imported: ${solution.name}`));
|
|
@@ -6046,21 +6118,83 @@ async function solutionAnalyzeCommand() {
|
|
|
6046
6118
|
const pathModule = await import("path");
|
|
6047
6119
|
console.log(chalk18.cyan("\n\u{1F50D} Analyzing Codebase for Solution Patterns\n"));
|
|
6048
6120
|
const existingResult = await store.listSolutions({ limit: 1e3 });
|
|
6049
|
-
const existingNames = (existingResult.data || []).map(
|
|
6121
|
+
const existingNames = (existingResult.data || []).map(
|
|
6122
|
+
(s) => s.name.toLowerCase()
|
|
6123
|
+
);
|
|
6050
6124
|
const opportunities = [];
|
|
6051
6125
|
const patterns = [
|
|
6052
|
-
{
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
{
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6126
|
+
{
|
|
6127
|
+
path: "src/auth",
|
|
6128
|
+
name: "Authentication Module",
|
|
6129
|
+
category: "auth",
|
|
6130
|
+
desc: "Authentication implementation"
|
|
6131
|
+
},
|
|
6132
|
+
{
|
|
6133
|
+
path: "src/lib/auth",
|
|
6134
|
+
name: "Auth Library",
|
|
6135
|
+
category: "auth",
|
|
6136
|
+
desc: "Authentication utilities"
|
|
6137
|
+
},
|
|
6138
|
+
{
|
|
6139
|
+
path: "src/api",
|
|
6140
|
+
name: "API Layer",
|
|
6141
|
+
category: "api",
|
|
6142
|
+
desc: "API routing structure"
|
|
6143
|
+
},
|
|
6144
|
+
{
|
|
6145
|
+
path: "app/api",
|
|
6146
|
+
name: "Next.js API Routes",
|
|
6147
|
+
category: "api",
|
|
6148
|
+
desc: "Next.js API implementation"
|
|
6149
|
+
},
|
|
6150
|
+
{
|
|
6151
|
+
path: "src/db",
|
|
6152
|
+
name: "Database Layer",
|
|
6153
|
+
category: "database",
|
|
6154
|
+
desc: "Database connection and queries"
|
|
6155
|
+
},
|
|
6156
|
+
{
|
|
6157
|
+
path: "src/lib/db",
|
|
6158
|
+
name: "Database Utilities",
|
|
6159
|
+
category: "database",
|
|
6160
|
+
desc: "Database helper functions"
|
|
6161
|
+
},
|
|
6162
|
+
{
|
|
6163
|
+
path: "src/components/ui",
|
|
6164
|
+
name: "UI Components",
|
|
6165
|
+
category: "ui",
|
|
6166
|
+
desc: "Reusable UI components"
|
|
6167
|
+
},
|
|
6168
|
+
{
|
|
6169
|
+
path: "src/hooks",
|
|
6170
|
+
name: "Custom Hooks",
|
|
6171
|
+
category: "ui",
|
|
6172
|
+
desc: "React custom hooks"
|
|
6173
|
+
},
|
|
6174
|
+
{
|
|
6175
|
+
path: "__tests__",
|
|
6176
|
+
name: "Testing Setup",
|
|
6177
|
+
category: "testing",
|
|
6178
|
+
desc: "Test configuration and utilities"
|
|
6179
|
+
},
|
|
6180
|
+
{
|
|
6181
|
+
path: ".github/workflows",
|
|
6182
|
+
name: "CI/CD Pipeline",
|
|
6183
|
+
category: "deployment",
|
|
6184
|
+
desc: "GitHub Actions workflows"
|
|
6185
|
+
},
|
|
6186
|
+
{
|
|
6187
|
+
path: "src/integrations",
|
|
6188
|
+
name: "Integrations",
|
|
6189
|
+
category: "integrations",
|
|
6190
|
+
desc: "Third-party integrations"
|
|
6191
|
+
},
|
|
6192
|
+
{
|
|
6193
|
+
path: "src/middleware",
|
|
6194
|
+
name: "Middleware",
|
|
6195
|
+
category: "security",
|
|
6196
|
+
desc: "Request middleware and guards"
|
|
6197
|
+
}
|
|
6064
6198
|
];
|
|
6065
6199
|
for (const pattern of patterns) {
|
|
6066
6200
|
const fullPath = pathModule.default.join(cwd, pattern.path);
|
|
@@ -6078,8 +6212,10 @@ async function solutionAnalyzeCommand() {
|
|
|
6078
6212
|
console.log(chalk18.dim("\n Your solutions seem well-captured!"));
|
|
6079
6213
|
return;
|
|
6080
6214
|
}
|
|
6081
|
-
console.log(
|
|
6082
|
-
`
|
|
6215
|
+
console.log(
|
|
6216
|
+
chalk18.bold(` Found ${opportunities.length} potential solutions:
|
|
6217
|
+
`)
|
|
6218
|
+
);
|
|
6083
6219
|
for (const opp of opportunities) {
|
|
6084
6220
|
console.log(` ${formatCategory(opp.category)}`);
|
|
6085
6221
|
console.log(chalk18.bold(` ${opp.name}`));
|
|
@@ -6088,7 +6224,9 @@ async function solutionAnalyzeCommand() {
|
|
|
6088
6224
|
`));
|
|
6089
6225
|
}
|
|
6090
6226
|
console.log(chalk18.dim(" To capture a solution:"));
|
|
6091
|
-
console.log(
|
|
6227
|
+
console.log(
|
|
6228
|
+
chalk18.cyan(" workflow solution capture --path <path> --name <name>")
|
|
6229
|
+
);
|
|
6092
6230
|
}
|
|
6093
6231
|
async function solutionMigrateCommand(options) {
|
|
6094
6232
|
const cwd = getWorkspacePath();
|
|
@@ -6098,8 +6236,16 @@ async function solutionMigrateCommand(options) {
|
|
|
6098
6236
|
if (!options.public && !options.private) {
|
|
6099
6237
|
console.log(chalk18.yellow(" Please specify --public or --private"));
|
|
6100
6238
|
console.log(chalk18.dim("\n Examples:"));
|
|
6101
|
-
console.log(
|
|
6102
|
-
|
|
6239
|
+
console.log(
|
|
6240
|
+
chalk18.dim(
|
|
6241
|
+
" workflow solution migrate --public # Make all solutions public"
|
|
6242
|
+
)
|
|
6243
|
+
);
|
|
6244
|
+
console.log(
|
|
6245
|
+
chalk18.dim(
|
|
6246
|
+
" workflow solution migrate --private # Make all solutions private"
|
|
6247
|
+
)
|
|
6248
|
+
);
|
|
6103
6249
|
return;
|
|
6104
6250
|
}
|
|
6105
6251
|
const targetPrivate = options.private ?? false;
|
|
@@ -6112,17 +6258,31 @@ async function solutionMigrateCommand(options) {
|
|
|
6112
6258
|
const solutions = result.data;
|
|
6113
6259
|
const toMigrate = solutions.filter((s) => s.isPrivate !== targetPrivate);
|
|
6114
6260
|
if (toMigrate.length === 0) {
|
|
6115
|
-
console.log(
|
|
6261
|
+
console.log(
|
|
6262
|
+
chalk18.green(
|
|
6263
|
+
` \u2713 All ${solutions.length} solutions are already ${targetLabel}`
|
|
6264
|
+
)
|
|
6265
|
+
);
|
|
6116
6266
|
return;
|
|
6117
6267
|
}
|
|
6118
|
-
console.log(
|
|
6119
|
-
|
|
6268
|
+
console.log(
|
|
6269
|
+
chalk18.dim(
|
|
6270
|
+
` Found ${toMigrate.length} solutions to make ${targetLabel}:
|
|
6271
|
+
`
|
|
6272
|
+
)
|
|
6273
|
+
);
|
|
6120
6274
|
for (const solution of toMigrate) {
|
|
6121
|
-
console.log(
|
|
6275
|
+
console.log(
|
|
6276
|
+
chalk18.dim(` \u2022 ${solution.name} (${solution.id.slice(0, 8)})`)
|
|
6277
|
+
);
|
|
6122
6278
|
}
|
|
6123
6279
|
if (options.dryRun) {
|
|
6124
|
-
console.log(
|
|
6125
|
-
|
|
6280
|
+
console.log(
|
|
6281
|
+
chalk18.yellow(
|
|
6282
|
+
`
|
|
6283
|
+
[DRY-RUN] Would migrate ${toMigrate.length} solutions to ${targetLabel}`
|
|
6284
|
+
)
|
|
6285
|
+
);
|
|
6126
6286
|
return;
|
|
6127
6287
|
}
|
|
6128
6288
|
const confirm10 = await p11.confirm({
|
|
@@ -6145,10 +6305,16 @@ async function solutionMigrateCommand(options) {
|
|
|
6145
6305
|
migrated++;
|
|
6146
6306
|
}
|
|
6147
6307
|
}
|
|
6148
|
-
console.log(
|
|
6149
|
-
|
|
6308
|
+
console.log(
|
|
6309
|
+
chalk18.green(`
|
|
6310
|
+
\u2713 Migrated ${migrated} solutions to ${targetLabel}`)
|
|
6311
|
+
);
|
|
6150
6312
|
if (!targetPrivate) {
|
|
6151
|
-
console.log(
|
|
6313
|
+
console.log(
|
|
6314
|
+
chalk18.dim(
|
|
6315
|
+
" These solutions can now be synced with 'workflow sync --solutions --push'"
|
|
6316
|
+
)
|
|
6317
|
+
);
|
|
6152
6318
|
}
|
|
6153
6319
|
}
|
|
6154
6320
|
async function solutionEditCommand(solutionId, options) {
|
|
@@ -6195,7 +6361,9 @@ async function solutionEditCommand(solutionId, options) {
|
|
|
6195
6361
|
console.log(chalk18.dim(" --private Make private"));
|
|
6196
6362
|
return;
|
|
6197
6363
|
}
|
|
6198
|
-
console.log(
|
|
6364
|
+
console.log(
|
|
6365
|
+
chalk18.dim(` Solution: ${solution.name} (${solution.id.slice(0, 8)})`)
|
|
6366
|
+
);
|
|
6199
6367
|
console.log(chalk18.dim(" Changes:"));
|
|
6200
6368
|
for (const change of changes) {
|
|
6201
6369
|
console.log(chalk18.dim(` \u2022 ${change}`));
|
|
@@ -6205,7 +6373,11 @@ async function solutionEditCommand(solutionId, options) {
|
|
|
6205
6373
|
if (saveResult.success) {
|
|
6206
6374
|
console.log(chalk18.green("\n \u2713 Solution updated"));
|
|
6207
6375
|
if (options.public) {
|
|
6208
|
-
console.log(
|
|
6376
|
+
console.log(
|
|
6377
|
+
chalk18.dim(
|
|
6378
|
+
" This solution can now be synced with 'workflow sync --solutions --push'"
|
|
6379
|
+
)
|
|
6380
|
+
);
|
|
6209
6381
|
}
|
|
6210
6382
|
} else {
|
|
6211
6383
|
console.log(chalk18.red(`
|
|
@@ -6377,7 +6549,8 @@ import {
|
|
|
6377
6549
|
TelemetryCollector,
|
|
6378
6550
|
FixPatternSchema,
|
|
6379
6551
|
BlueprintSchema,
|
|
6380
|
-
SolutionPatternSchema
|
|
6552
|
+
SolutionPatternSchema,
|
|
6553
|
+
createDefaultMetrics
|
|
6381
6554
|
} from "@hawkinside_out/workflow-improvement-tracker";
|
|
6382
6555
|
function getWorkspacePath2() {
|
|
6383
6556
|
return process.cwd();
|
|
@@ -6621,7 +6794,9 @@ async function learnRecordCommand(options) {
|
|
|
6621
6794
|
console.log(chalk20.dim(` ID: ${blueprint.id}`));
|
|
6622
6795
|
console.log(chalk20.dim(` Name: ${name}`));
|
|
6623
6796
|
console.log(chalk20.dim(` Framework: ${framework} ${version}`));
|
|
6624
|
-
console.log(
|
|
6797
|
+
console.log(
|
|
6798
|
+
chalk20.dim(` Path: .workflow/patterns/blueprints/${blueprint.id}.json`)
|
|
6799
|
+
);
|
|
6625
6800
|
} else {
|
|
6626
6801
|
console.log(chalk20.red("\n\u274C Failed to record blueprint"));
|
|
6627
6802
|
console.log(chalk20.dim(` Error: ${result.error}`));
|
|
@@ -6716,15 +6891,11 @@ async function learnListCommand(options) {
|
|
|
6716
6891
|
\u26A0\uFE0F ${totalInvalid} pattern(s) failed schema validation and were skipped:`
|
|
6717
6892
|
)
|
|
6718
6893
|
);
|
|
6719
|
-
console.log(
|
|
6720
|
-
chalk20.dim(` Fix patterns: ${stats.invalidFixes} invalid`)
|
|
6721
|
-
);
|
|
6894
|
+
console.log(chalk20.dim(` Fix patterns: ${stats.invalidFixes} invalid`));
|
|
6722
6895
|
console.log(
|
|
6723
6896
|
chalk20.dim(` Blueprints: ${stats.invalidBlueprints} invalid`)
|
|
6724
6897
|
);
|
|
6725
|
-
console.log(
|
|
6726
|
-
chalk20.dim(` Solutions: ${stats.invalidSolutions} invalid`)
|
|
6727
|
-
);
|
|
6898
|
+
console.log(chalk20.dim(` Solutions: ${stats.invalidSolutions} invalid`));
|
|
6728
6899
|
const validationErrors = store.getValidationErrors();
|
|
6729
6900
|
if (validationErrors.length > 0) {
|
|
6730
6901
|
console.log(chalk20.yellow("\n Validation errors:"));
|
|
@@ -6743,9 +6914,7 @@ async function learnListCommand(options) {
|
|
|
6743
6914
|
}
|
|
6744
6915
|
if (validationErrors.length > 5) {
|
|
6745
6916
|
console.log(
|
|
6746
|
-
chalk20.dim(
|
|
6747
|
-
` ... and ${validationErrors.length - 5} more errors`
|
|
6748
|
-
)
|
|
6917
|
+
chalk20.dim(` ... and ${validationErrors.length - 5} more errors`)
|
|
6749
6918
|
);
|
|
6750
6919
|
}
|
|
6751
6920
|
}
|
|
@@ -6768,12 +6937,17 @@ async function learnApplyCommand(patternId, options) {
|
|
|
6768
6937
|
await store.initialize();
|
|
6769
6938
|
const telemetry = new TelemetryCollector(cwd);
|
|
6770
6939
|
console.log(chalk20.cyan("\n\u{1F527} Apply Learning Pattern\n"));
|
|
6771
|
-
let
|
|
6940
|
+
let fixPattern;
|
|
6941
|
+
let blueprintPattern;
|
|
6772
6942
|
let patternType = "fix";
|
|
6773
|
-
|
|
6943
|
+
const fixResult = await store.getFixPattern(patternId);
|
|
6944
|
+
if (fixResult.success && fixResult.data) {
|
|
6945
|
+
fixPattern = fixResult.data;
|
|
6946
|
+
patternType = "fix";
|
|
6947
|
+
} else {
|
|
6774
6948
|
const bpResult = await store.getBlueprint(patternId);
|
|
6775
6949
|
if (bpResult.success && bpResult.data) {
|
|
6776
|
-
|
|
6950
|
+
blueprintPattern = bpResult.data;
|
|
6777
6951
|
patternType = "blueprint";
|
|
6778
6952
|
} else {
|
|
6779
6953
|
console.log(chalk20.red(`
|
|
@@ -6784,7 +6958,7 @@ async function learnApplyCommand(patternId, options) {
|
|
|
6784
6958
|
process.exit(1);
|
|
6785
6959
|
}
|
|
6786
6960
|
}
|
|
6787
|
-
const patternData =
|
|
6961
|
+
const patternData = fixPattern ?? blueprintPattern;
|
|
6788
6962
|
console.log(chalk20.white(` Pattern: ${patternData.name}`));
|
|
6789
6963
|
console.log(chalk20.dim(` Type: ${patternType}`));
|
|
6790
6964
|
console.log(chalk20.dim(` Description: ${patternData.description}`));
|
|
@@ -6793,11 +6967,10 @@ async function learnApplyCommand(patternId, options) {
|
|
|
6793
6967
|
chalk20.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n")
|
|
6794
6968
|
);
|
|
6795
6969
|
}
|
|
6796
|
-
const framework = options.framework ?? patternData.compatibility?.
|
|
6797
|
-
const version = options.version ?? patternData.compatibility?.
|
|
6970
|
+
const framework = options.framework ?? patternData.compatibility?.framework ?? "unknown";
|
|
6971
|
+
const version = options.version ?? patternData.compatibility?.frameworkVersion ?? "0.0.0";
|
|
6798
6972
|
await telemetry.recordApplication(patternId, patternType, framework, version);
|
|
6799
|
-
if (patternType === "fix") {
|
|
6800
|
-
const fixPattern = patternData;
|
|
6973
|
+
if (patternType === "fix" && fixPattern) {
|
|
6801
6974
|
console.log(chalk20.cyan("\n\u{1F4CB} Solution Steps:\n"));
|
|
6802
6975
|
if (fixPattern.solution.steps) {
|
|
6803
6976
|
for (let i = 0; i < fixPattern.solution.steps.length; i++) {
|
|
@@ -6805,17 +6978,16 @@ async function learnApplyCommand(patternId, options) {
|
|
|
6805
6978
|
console.log(
|
|
6806
6979
|
chalk20.white(` ${i + 1}. [${step.action}] ${step.description}`)
|
|
6807
6980
|
);
|
|
6808
|
-
if (step.
|
|
6809
|
-
console.log(chalk20.dim(`
|
|
6981
|
+
if (step.target) {
|
|
6982
|
+
console.log(chalk20.dim(` Target: ${step.target}`));
|
|
6810
6983
|
}
|
|
6811
6984
|
}
|
|
6812
6985
|
}
|
|
6813
|
-
} else {
|
|
6814
|
-
const blueprint = patternData;
|
|
6986
|
+
} else if (blueprintPattern) {
|
|
6815
6987
|
console.log(chalk20.cyan("\n\u{1F4CB} Setup Steps:\n"));
|
|
6816
|
-
if (
|
|
6817
|
-
for (let i = 0; i <
|
|
6818
|
-
const step =
|
|
6988
|
+
if (blueprintPattern.setup.steps) {
|
|
6989
|
+
for (let i = 0; i < blueprintPattern.setup.steps.length; i++) {
|
|
6990
|
+
const step = blueprintPattern.setup.steps[i];
|
|
6819
6991
|
console.log(chalk20.white(` ${i + 1}. ${step.description}`));
|
|
6820
6992
|
if (step.command) {
|
|
6821
6993
|
console.log(chalk20.dim(` Command: ${step.command}`));
|
|
@@ -6967,7 +7139,9 @@ ${emoji} Mark Pattern(s) ${actionWord}
|
|
|
6967
7139
|
const totalToUpdate = fixesToUpdate.length + blueprintsToUpdate.length;
|
|
6968
7140
|
if (totalToUpdate === 0) {
|
|
6969
7141
|
console.log(
|
|
6970
|
-
chalk20.yellow(
|
|
7142
|
+
chalk20.yellow(
|
|
7143
|
+
` All patterns are already ${actionWord}. Nothing to do.`
|
|
7144
|
+
)
|
|
6971
7145
|
);
|
|
6972
7146
|
return;
|
|
6973
7147
|
}
|
|
@@ -6990,9 +7164,9 @@ ${emoji} Mark Pattern(s) ${actionWord}
|
|
|
6990
7164
|
}
|
|
6991
7165
|
let successCount = 0;
|
|
6992
7166
|
let failCount = 0;
|
|
6993
|
-
for (const
|
|
7167
|
+
for (const pattern of fixesToUpdate) {
|
|
6994
7168
|
const result2 = await store.saveFixPattern({
|
|
6995
|
-
...
|
|
7169
|
+
...pattern,
|
|
6996
7170
|
isPrivate: makePrivate,
|
|
6997
7171
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6998
7172
|
});
|
|
@@ -7028,17 +7202,20 @@ ${emoji} Mark Pattern(s) ${actionWord}
|
|
|
7028
7202
|
console.log(
|
|
7029
7203
|
chalk20.dim(" Usage: workflow learn:publish <patternId> [--private]")
|
|
7030
7204
|
);
|
|
7031
|
-
console.log(
|
|
7032
|
-
chalk20.dim(" workflow learn:publish --all [--private]")
|
|
7033
|
-
);
|
|
7205
|
+
console.log(chalk20.dim(" workflow learn:publish --all [--private]"));
|
|
7034
7206
|
process.exit(1);
|
|
7035
7207
|
}
|
|
7036
7208
|
let patternType = "fix";
|
|
7037
|
-
let
|
|
7038
|
-
|
|
7209
|
+
let fixPatternData;
|
|
7210
|
+
let blueprintData;
|
|
7211
|
+
const fixResult = await store.getFixPattern(patternId);
|
|
7212
|
+
if (fixResult.success && fixResult.data) {
|
|
7213
|
+
fixPatternData = fixResult.data;
|
|
7214
|
+
patternType = "fix";
|
|
7215
|
+
} else {
|
|
7039
7216
|
const bpResult = await store.getBlueprint(patternId);
|
|
7040
7217
|
if (bpResult.success && bpResult.data) {
|
|
7041
|
-
|
|
7218
|
+
blueprintData = bpResult.data;
|
|
7042
7219
|
patternType = "blueprint";
|
|
7043
7220
|
} else {
|
|
7044
7221
|
console.log(chalk20.red(`
|
|
@@ -7049,15 +7226,16 @@ ${emoji} Mark Pattern(s) ${actionWord}
|
|
|
7049
7226
|
process.exit(1);
|
|
7050
7227
|
}
|
|
7051
7228
|
}
|
|
7052
|
-
const
|
|
7053
|
-
|
|
7229
|
+
const patternInfo = fixPatternData ?? blueprintData;
|
|
7230
|
+
const currentStatus = patternInfo.isPrivate ? "private" : "public";
|
|
7231
|
+
if (patternInfo.isPrivate === makePrivate) {
|
|
7054
7232
|
console.log(
|
|
7055
7233
|
chalk20.yellow(` Pattern is already ${actionWord}. Nothing to do.`)
|
|
7056
7234
|
);
|
|
7057
|
-
console.log(chalk20.dim(` Name: ${
|
|
7235
|
+
console.log(chalk20.dim(` Name: ${patternInfo.name}`));
|
|
7058
7236
|
return;
|
|
7059
7237
|
}
|
|
7060
|
-
console.log(chalk20.white(` Pattern: ${
|
|
7238
|
+
console.log(chalk20.white(` Pattern: ${patternInfo.name}`));
|
|
7061
7239
|
console.log(chalk20.dim(` Type: ${patternType}`));
|
|
7062
7240
|
console.log(chalk20.dim(` Current: ${currentStatus} \u2192 ${actionWord}`));
|
|
7063
7241
|
if (!options.yes) {
|
|
@@ -7070,16 +7248,24 @@ ${emoji} Mark Pattern(s) ${actionWord}
|
|
|
7070
7248
|
return;
|
|
7071
7249
|
}
|
|
7072
7250
|
}
|
|
7073
|
-
const updatedPattern = {
|
|
7074
|
-
...pattern.data,
|
|
7075
|
-
isPrivate: makePrivate,
|
|
7076
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7077
|
-
};
|
|
7078
7251
|
let result;
|
|
7079
|
-
if (patternType === "fix") {
|
|
7080
|
-
|
|
7252
|
+
if (patternType === "fix" && fixPatternData) {
|
|
7253
|
+
const updatedFix = {
|
|
7254
|
+
...fixPatternData,
|
|
7255
|
+
isPrivate: makePrivate,
|
|
7256
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7257
|
+
};
|
|
7258
|
+
result = await store.saveFixPattern(updatedFix);
|
|
7259
|
+
} else if (blueprintData) {
|
|
7260
|
+
const updatedBlueprint = {
|
|
7261
|
+
...blueprintData,
|
|
7262
|
+
isPrivate: makePrivate,
|
|
7263
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7264
|
+
};
|
|
7265
|
+
result = await store.saveBlueprint(updatedBlueprint);
|
|
7081
7266
|
} else {
|
|
7082
|
-
|
|
7267
|
+
console.log(chalk20.red("\n\u274C Unexpected error: pattern data not found"));
|
|
7268
|
+
process.exit(1);
|
|
7083
7269
|
}
|
|
7084
7270
|
if (result.success) {
|
|
7085
7271
|
console.log(chalk20.green(`
|
|
@@ -7101,19 +7287,23 @@ async function learnDeprecateCommand(patternId, reason) {
|
|
|
7101
7287
|
await store.initialize();
|
|
7102
7288
|
console.log(chalk20.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
|
|
7103
7289
|
let patternType = "fix";
|
|
7104
|
-
let
|
|
7105
|
-
|
|
7290
|
+
let patternName;
|
|
7291
|
+
const fixResult = await store.getFixPattern(patternId);
|
|
7292
|
+
if (fixResult.success && fixResult.data) {
|
|
7293
|
+
patternType = "fix";
|
|
7294
|
+
patternName = fixResult.data.name;
|
|
7295
|
+
} else {
|
|
7106
7296
|
const bpResult = await store.getBlueprint(patternId);
|
|
7107
7297
|
if (bpResult.success && bpResult.data) {
|
|
7108
|
-
pattern = bpResult;
|
|
7109
7298
|
patternType = "blueprint";
|
|
7299
|
+
patternName = bpResult.data.name;
|
|
7110
7300
|
} else {
|
|
7111
7301
|
console.log(chalk20.red(`
|
|
7112
7302
|
\u274C Pattern not found: ${patternId}`));
|
|
7113
7303
|
process.exit(1);
|
|
7114
7304
|
}
|
|
7115
7305
|
}
|
|
7116
|
-
console.log(chalk20.white(` Pattern: ${
|
|
7306
|
+
console.log(chalk20.white(` Pattern: ${patternName}`));
|
|
7117
7307
|
console.log(chalk20.dim(` Reason: ${reason}`));
|
|
7118
7308
|
const confirmed = await p12.confirm({
|
|
7119
7309
|
message: "Are you sure you want to deprecate this pattern?",
|
|
@@ -7288,7 +7478,13 @@ async function validatePatternDirectory(dirPath, type, schema, verbose) {
|
|
|
7288
7478
|
for (const file of files) {
|
|
7289
7479
|
if (!file.endsWith(".json")) continue;
|
|
7290
7480
|
const filePath = path3.join(dirPath, file);
|
|
7291
|
-
const result = await validatePatternFile(
|
|
7481
|
+
const result = await validatePatternFile(
|
|
7482
|
+
filePath,
|
|
7483
|
+
file,
|
|
7484
|
+
type,
|
|
7485
|
+
schema,
|
|
7486
|
+
verbose
|
|
7487
|
+
);
|
|
7292
7488
|
results.push(result);
|
|
7293
7489
|
if (verbose) {
|
|
7294
7490
|
if (result.valid) {
|
|
@@ -7344,7 +7540,7 @@ async function validateSingleFile(filePath, verbose) {
|
|
|
7344
7540
|
}
|
|
7345
7541
|
return validatePatternFile(filePath, fileName, type, schema, verbose);
|
|
7346
7542
|
}
|
|
7347
|
-
async function validatePatternFile(filePath, fileName, type, schema,
|
|
7543
|
+
async function validatePatternFile(filePath, fileName, type, schema, _verbose) {
|
|
7348
7544
|
try {
|
|
7349
7545
|
const content = await fs2.promises.readFile(filePath, "utf-8");
|
|
7350
7546
|
const data = JSON.parse(content);
|
|
@@ -7361,7 +7557,11 @@ async function validatePatternFile(filePath, fileName, type, schema, verbose) {
|
|
|
7361
7557
|
const errors = validation.error.issues.map(
|
|
7362
7558
|
(i) => `${i.path.join(".")}: ${i.message}`
|
|
7363
7559
|
);
|
|
7364
|
-
const { fixable, fixedData } = tryAutoFix(
|
|
7560
|
+
const { fixable, fixedData } = tryAutoFix(
|
|
7561
|
+
data,
|
|
7562
|
+
type,
|
|
7563
|
+
validation.error.issues
|
|
7564
|
+
);
|
|
7365
7565
|
return {
|
|
7366
7566
|
file: fileName,
|
|
7367
7567
|
type,
|
|
@@ -7375,9 +7575,7 @@ async function validatePatternFile(filePath, fileName, type, schema, verbose) {
|
|
|
7375
7575
|
file: fileName,
|
|
7376
7576
|
type,
|
|
7377
7577
|
valid: false,
|
|
7378
|
-
errors: [
|
|
7379
|
-
error instanceof Error ? error.message : "Failed to parse JSON"
|
|
7380
|
-
],
|
|
7578
|
+
errors: [error instanceof Error ? error.message : "Failed to parse JSON"],
|
|
7381
7579
|
fixable: false
|
|
7382
7580
|
};
|
|
7383
7581
|
}
|
|
@@ -7444,53 +7642,125 @@ function tryAutoFix(data, type, issues) {
|
|
|
7444
7642
|
}
|
|
7445
7643
|
var LIBRARY_TAG_MAP = {
|
|
7446
7644
|
// Frontend Frameworks
|
|
7447
|
-
|
|
7645
|
+
react: [{ category: "framework", name: "react" }],
|
|
7448
7646
|
"react-dom": [{ category: "framework", name: "react" }],
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7647
|
+
next: [{ category: "framework", name: "next" }],
|
|
7648
|
+
vue: [{ category: "framework", name: "vue" }],
|
|
7649
|
+
nuxt: [{ category: "framework", name: "nuxt" }],
|
|
7650
|
+
svelte: [{ category: "framework", name: "svelte" }],
|
|
7453
7651
|
"@sveltejs/kit": [{ category: "framework", name: "sveltekit" }],
|
|
7454
7652
|
"solid-js": [{ category: "framework", name: "solid" }],
|
|
7455
7653
|
"@angular/core": [{ category: "framework", name: "angular" }],
|
|
7456
|
-
|
|
7457
|
-
|
|
7654
|
+
astro: [{ category: "framework", name: "astro" }],
|
|
7655
|
+
remix: [{ category: "framework", name: "remix" }],
|
|
7458
7656
|
// Backend Frameworks
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7657
|
+
express: [{ category: "framework", name: "express" }],
|
|
7658
|
+
fastify: [{ category: "framework", name: "fastify" }],
|
|
7659
|
+
hono: [{ category: "framework", name: "hono" }],
|
|
7660
|
+
koa: [{ category: "framework", name: "koa" }],
|
|
7463
7661
|
"@nestjs/core": [{ category: "framework", name: "nestjs" }],
|
|
7464
|
-
|
|
7662
|
+
hapi: [{ category: "framework", name: "hapi" }],
|
|
7465
7663
|
// Testing
|
|
7466
|
-
|
|
7467
|
-
|
|
7664
|
+
vitest: [
|
|
7665
|
+
{ category: "tool", name: "vitest" },
|
|
7666
|
+
{ category: "testing", name: "testing" }
|
|
7667
|
+
],
|
|
7668
|
+
jest: [
|
|
7669
|
+
{ category: "tool", name: "jest" },
|
|
7670
|
+
{ category: "testing", name: "testing" }
|
|
7671
|
+
],
|
|
7468
7672
|
"@testing-library/react": [{ category: "tool", name: "testing-library" }],
|
|
7469
|
-
|
|
7470
|
-
|
|
7673
|
+
playwright: [
|
|
7674
|
+
{ category: "tool", name: "playwright" },
|
|
7675
|
+
{ category: "testing", name: "e2e" }
|
|
7676
|
+
],
|
|
7677
|
+
cypress: [
|
|
7678
|
+
{ category: "tool", name: "cypress" },
|
|
7679
|
+
{ category: "testing", name: "e2e" }
|
|
7680
|
+
],
|
|
7471
7681
|
// State Management
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7682
|
+
zustand: [
|
|
7683
|
+
{ category: "tool", name: "zustand" },
|
|
7684
|
+
{ category: "state", name: "state" }
|
|
7685
|
+
],
|
|
7686
|
+
redux: [
|
|
7687
|
+
{ category: "tool", name: "redux" },
|
|
7688
|
+
{ category: "state", name: "state" }
|
|
7689
|
+
],
|
|
7690
|
+
"@reduxjs/toolkit": [
|
|
7691
|
+
{ category: "tool", name: "redux-toolkit" },
|
|
7692
|
+
{ category: "state", name: "state" }
|
|
7693
|
+
],
|
|
7694
|
+
jotai: [
|
|
7695
|
+
{ category: "tool", name: "jotai" },
|
|
7696
|
+
{ category: "state", name: "state" }
|
|
7697
|
+
],
|
|
7698
|
+
recoil: [
|
|
7699
|
+
{ category: "tool", name: "recoil" },
|
|
7700
|
+
{ category: "state", name: "state" }
|
|
7701
|
+
],
|
|
7702
|
+
mobx: [
|
|
7703
|
+
{ category: "tool", name: "mobx" },
|
|
7704
|
+
{ category: "state", name: "state" }
|
|
7705
|
+
],
|
|
7706
|
+
pinia: [
|
|
7707
|
+
{ category: "tool", name: "pinia" },
|
|
7708
|
+
{ category: "state", name: "state" }
|
|
7709
|
+
],
|
|
7710
|
+
xstate: [
|
|
7711
|
+
{ category: "tool", name: "xstate" },
|
|
7712
|
+
{ category: "state", name: "state-machine" }
|
|
7713
|
+
],
|
|
7480
7714
|
// Database & ORM
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
"
|
|
7486
|
-
|
|
7487
|
-
|
|
7715
|
+
prisma: [
|
|
7716
|
+
{ category: "tool", name: "prisma" },
|
|
7717
|
+
{ category: "database", name: "database" }
|
|
7718
|
+
],
|
|
7719
|
+
"@prisma/client": [
|
|
7720
|
+
{ category: "tool", name: "prisma" },
|
|
7721
|
+
{ category: "database", name: "database" }
|
|
7722
|
+
],
|
|
7723
|
+
"drizzle-orm": [
|
|
7724
|
+
{ category: "tool", name: "drizzle" },
|
|
7725
|
+
{ category: "database", name: "database" }
|
|
7726
|
+
],
|
|
7727
|
+
typeorm: [
|
|
7728
|
+
{ category: "tool", name: "typeorm" },
|
|
7729
|
+
{ category: "database", name: "database" }
|
|
7730
|
+
],
|
|
7731
|
+
mongoose: [
|
|
7732
|
+
{ category: "tool", name: "mongoose" },
|
|
7733
|
+
{ category: "database", name: "mongodb" }
|
|
7734
|
+
],
|
|
7735
|
+
knex: [
|
|
7736
|
+
{ category: "tool", name: "knex" },
|
|
7737
|
+
{ category: "database", name: "database" }
|
|
7738
|
+
],
|
|
7739
|
+
sequelize: [
|
|
7740
|
+
{ category: "tool", name: "sequelize" },
|
|
7741
|
+
{ category: "database", name: "database" }
|
|
7742
|
+
],
|
|
7488
7743
|
// Authentication
|
|
7489
|
-
"next-auth": [
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
"@
|
|
7744
|
+
"next-auth": [
|
|
7745
|
+
{ category: "tool", name: "next-auth" },
|
|
7746
|
+
{ category: "auth", name: "auth" }
|
|
7747
|
+
],
|
|
7748
|
+
"@auth/core": [
|
|
7749
|
+
{ category: "tool", name: "authjs" },
|
|
7750
|
+
{ category: "auth", name: "auth" }
|
|
7751
|
+
],
|
|
7752
|
+
passport: [
|
|
7753
|
+
{ category: "tool", name: "passport" },
|
|
7754
|
+
{ category: "auth", name: "auth" }
|
|
7755
|
+
],
|
|
7756
|
+
lucia: [
|
|
7757
|
+
{ category: "tool", name: "lucia" },
|
|
7758
|
+
{ category: "auth", name: "auth" }
|
|
7759
|
+
],
|
|
7760
|
+
"@clerk/nextjs": [
|
|
7761
|
+
{ category: "tool", name: "clerk" },
|
|
7762
|
+
{ category: "auth", name: "auth" }
|
|
7763
|
+
],
|
|
7494
7764
|
// UI Libraries
|
|
7495
7765
|
"@radix-ui/react-dialog": [{ category: "tool", name: "radix-ui" }],
|
|
7496
7766
|
"@radix-ui/react-dropdown-menu": [{ category: "tool", name: "radix-ui" }],
|
|
@@ -7498,49 +7768,97 @@ var LIBRARY_TAG_MAP = {
|
|
|
7498
7768
|
"@chakra-ui/react": [{ category: "tool", name: "chakra-ui" }],
|
|
7499
7769
|
"@mantine/core": [{ category: "tool", name: "mantine" }],
|
|
7500
7770
|
"@headlessui/react": [{ category: "tool", name: "headlessui" }],
|
|
7501
|
-
|
|
7771
|
+
antd: [{ category: "tool", name: "antd" }],
|
|
7502
7772
|
"@mui/material": [{ category: "tool", name: "material-ui" }],
|
|
7503
7773
|
// Styling
|
|
7504
|
-
|
|
7774
|
+
tailwindcss: [{ category: "tool", name: "tailwind" }],
|
|
7505
7775
|
"styled-components": [{ category: "tool", name: "styled-components" }],
|
|
7506
7776
|
"@emotion/react": [{ category: "tool", name: "emotion" }],
|
|
7507
|
-
|
|
7777
|
+
sass: [{ category: "tool", name: "sass" }],
|
|
7508
7778
|
// API & Data Fetching
|
|
7509
|
-
"@tanstack/react-query": [
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7779
|
+
"@tanstack/react-query": [
|
|
7780
|
+
{ category: "tool", name: "tanstack-query" },
|
|
7781
|
+
{ category: "api", name: "data-fetching" }
|
|
7782
|
+
],
|
|
7783
|
+
swr: [
|
|
7784
|
+
{ category: "tool", name: "swr" },
|
|
7785
|
+
{ category: "api", name: "data-fetching" }
|
|
7786
|
+
],
|
|
7787
|
+
"@trpc/server": [
|
|
7788
|
+
{ category: "tool", name: "trpc" },
|
|
7789
|
+
{ category: "api", name: "api" }
|
|
7790
|
+
],
|
|
7791
|
+
"@trpc/client": [
|
|
7792
|
+
{ category: "tool", name: "trpc" },
|
|
7793
|
+
{ category: "api", name: "api" }
|
|
7794
|
+
],
|
|
7795
|
+
graphql: [
|
|
7796
|
+
{ category: "tool", name: "graphql" },
|
|
7797
|
+
{ category: "api", name: "api" }
|
|
7798
|
+
],
|
|
7799
|
+
"@apollo/client": [
|
|
7800
|
+
{ category: "tool", name: "apollo" },
|
|
7801
|
+
{ category: "api", name: "graphql" }
|
|
7802
|
+
],
|
|
7803
|
+
axios: [{ category: "tool", name: "axios" }],
|
|
7516
7804
|
// Form Libraries
|
|
7517
|
-
"react-hook-form": [
|
|
7518
|
-
|
|
7519
|
-
|
|
7805
|
+
"react-hook-form": [
|
|
7806
|
+
{ category: "tool", name: "react-hook-form" },
|
|
7807
|
+
{ category: "feature", name: "forms" }
|
|
7808
|
+
],
|
|
7809
|
+
formik: [
|
|
7810
|
+
{ category: "tool", name: "formik" },
|
|
7811
|
+
{ category: "feature", name: "forms" }
|
|
7812
|
+
],
|
|
7813
|
+
"@tanstack/react-form": [
|
|
7814
|
+
{ category: "tool", name: "tanstack-form" },
|
|
7815
|
+
{ category: "feature", name: "forms" }
|
|
7816
|
+
],
|
|
7520
7817
|
// Validation
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7818
|
+
zod: [
|
|
7819
|
+
{ category: "tool", name: "zod" },
|
|
7820
|
+
{ category: "feature", name: "validation" }
|
|
7821
|
+
],
|
|
7822
|
+
yup: [
|
|
7823
|
+
{ category: "tool", name: "yup" },
|
|
7824
|
+
{ category: "feature", name: "validation" }
|
|
7825
|
+
],
|
|
7826
|
+
valibot: [
|
|
7827
|
+
{ category: "tool", name: "valibot" },
|
|
7828
|
+
{ category: "feature", name: "validation" }
|
|
7829
|
+
],
|
|
7524
7830
|
// Build Tools
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7831
|
+
vite: [{ category: "tool", name: "vite" }],
|
|
7832
|
+
esbuild: [{ category: "tool", name: "esbuild" }],
|
|
7833
|
+
tsup: [{ category: "tool", name: "tsup" }],
|
|
7834
|
+
webpack: [{ category: "tool", name: "webpack" }],
|
|
7835
|
+
turbo: [{ category: "tool", name: "turborepo" }],
|
|
7530
7836
|
// Utilities
|
|
7531
|
-
|
|
7837
|
+
lodash: [{ category: "tool", name: "lodash" }],
|
|
7532
7838
|
"date-fns": [{ category: "tool", name: "date-fns" }],
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7839
|
+
dayjs: [{ category: "tool", name: "dayjs" }],
|
|
7840
|
+
uuid: [{ category: "tool", name: "uuid" }],
|
|
7841
|
+
nanoid: [{ category: "tool", name: "nanoid" }],
|
|
7536
7842
|
// CLI & Developer Tools
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7843
|
+
commander: [
|
|
7844
|
+
{ category: "tool", name: "commander" },
|
|
7845
|
+
{ category: "feature", name: "cli" }
|
|
7846
|
+
],
|
|
7847
|
+
yargs: [
|
|
7848
|
+
{ category: "tool", name: "yargs" },
|
|
7849
|
+
{ category: "feature", name: "cli" }
|
|
7850
|
+
],
|
|
7851
|
+
"@clack/prompts": [
|
|
7852
|
+
{ category: "tool", name: "clack" },
|
|
7853
|
+
{ category: "feature", name: "cli" }
|
|
7854
|
+
],
|
|
7855
|
+
inquirer: [
|
|
7856
|
+
{ category: "tool", name: "inquirer" },
|
|
7857
|
+
{ category: "feature", name: "cli" }
|
|
7858
|
+
],
|
|
7859
|
+
chalk: [{ category: "tool", name: "chalk" }],
|
|
7542
7860
|
// Runtime & Languages
|
|
7543
|
-
|
|
7861
|
+
typescript: [{ category: "language", name: "typescript" }]
|
|
7544
7862
|
};
|
|
7545
7863
|
function inferPatternName(filePaths) {
|
|
7546
7864
|
if (filePaths.length === 1) {
|
|
@@ -7554,7 +7872,9 @@ function inferPatternName(filePaths) {
|
|
|
7554
7872
|
const dirName = path3.basename(uniqueDirs[0]);
|
|
7555
7873
|
return dirName.replace(/[-_]/g, " ").replace(/([A-Z])/g, " $1").trim().split(/\s+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ") + " Pattern";
|
|
7556
7874
|
}
|
|
7557
|
-
const fileNames = filePaths.map(
|
|
7875
|
+
const fileNames = filePaths.map(
|
|
7876
|
+
(p13) => path3.basename(p13).replace(/\.[^.]+$/, "")
|
|
7877
|
+
);
|
|
7558
7878
|
if (fileNames.length > 0) {
|
|
7559
7879
|
let commonPrefix = fileNames[0];
|
|
7560
7880
|
for (const name of fileNames.slice(1)) {
|
|
@@ -7722,7 +8042,8 @@ async function learnCaptureCommand(paths, options) {
|
|
|
7722
8042
|
placeholder: inferredName,
|
|
7723
8043
|
initialValue: inferredName,
|
|
7724
8044
|
validate: (value) => {
|
|
7725
|
-
if (!value || value.length < 3)
|
|
8045
|
+
if (!value || value.length < 3)
|
|
8046
|
+
return "Name must be at least 3 characters";
|
|
7726
8047
|
if (value.length > 100) return "Name must be less than 100 characters";
|
|
7727
8048
|
return void 0;
|
|
7728
8049
|
}
|
|
@@ -7739,8 +8060,10 @@ async function learnCaptureCommand(paths, options) {
|
|
|
7739
8060
|
message: "Description:",
|
|
7740
8061
|
placeholder: "What does this pattern provide?",
|
|
7741
8062
|
validate: (value) => {
|
|
7742
|
-
if (!value || value.length < 10)
|
|
7743
|
-
|
|
8063
|
+
if (!value || value.length < 10)
|
|
8064
|
+
return "Description must be at least 10 characters";
|
|
8065
|
+
if (value.length > 500)
|
|
8066
|
+
return "Description must be less than 500 characters";
|
|
7744
8067
|
return void 0;
|
|
7745
8068
|
}
|
|
7746
8069
|
});
|
|
@@ -7798,7 +8121,18 @@ async function learnCaptureCommand(paths, options) {
|
|
|
7798
8121
|
for (const file of files) {
|
|
7799
8122
|
languageCounts[file.language] = (languageCounts[file.language] || 0) + 1;
|
|
7800
8123
|
}
|
|
7801
|
-
const
|
|
8124
|
+
const detectedLanguage = Object.entries(languageCounts).sort((a, b) => b[1] - a[1])[0]?.[0] || "typescript";
|
|
8125
|
+
const validLanguages = [
|
|
8126
|
+
"typescript",
|
|
8127
|
+
"javascript",
|
|
8128
|
+
"python",
|
|
8129
|
+
"go",
|
|
8130
|
+
"rust",
|
|
8131
|
+
"other"
|
|
8132
|
+
];
|
|
8133
|
+
const primaryLanguage = validLanguages.includes(
|
|
8134
|
+
detectedLanguage
|
|
8135
|
+
) ? detectedLanguage : "other";
|
|
7802
8136
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7803
8137
|
const contributorManager = new ContributorManager2(cwd);
|
|
7804
8138
|
const contributorResult = await contributorManager.getOrCreateId();
|
|
@@ -7808,6 +8142,13 @@ async function learnCaptureCommand(paths, options) {
|
|
|
7808
8142
|
purpose: `${f.language} file`,
|
|
7809
8143
|
content: f.content
|
|
7810
8144
|
}));
|
|
8145
|
+
const uniqueDirs = [
|
|
8146
|
+
...new Set(files.map((f) => path3.dirname(f.path)).filter((d) => d !== "."))
|
|
8147
|
+
];
|
|
8148
|
+
const directories = uniqueDirs.map((dir) => ({
|
|
8149
|
+
path: dir,
|
|
8150
|
+
purpose: `Directory for ${path3.basename(dir)} files`
|
|
8151
|
+
}));
|
|
7811
8152
|
const blueprint = {
|
|
7812
8153
|
id: crypto.randomUUID(),
|
|
7813
8154
|
name,
|
|
@@ -7822,7 +8163,7 @@ async function learnCaptureCommand(paths, options) {
|
|
|
7822
8163
|
devDependencies: []
|
|
7823
8164
|
},
|
|
7824
8165
|
structure: {
|
|
7825
|
-
directories
|
|
8166
|
+
directories,
|
|
7826
8167
|
keyFiles
|
|
7827
8168
|
},
|
|
7828
8169
|
setup: {
|
|
@@ -7871,7 +8212,9 @@ async function learnCaptureCommand(paths, options) {
|
|
|
7871
8212
|
console.log(chalk20.dim(`Name: ${name}`));
|
|
7872
8213
|
console.log(chalk20.dim(`Files: ${files.length}`));
|
|
7873
8214
|
console.log(chalk20.dim(`Tags: ${formatTags(uniqueTags)}`));
|
|
7874
|
-
console.log(
|
|
8215
|
+
console.log(
|
|
8216
|
+
chalk20.dim(`Path: .workflow/patterns/blueprints/${blueprint.id}.json`)
|
|
8217
|
+
);
|
|
7875
8218
|
console.log(chalk20.dim(`
|
|
7876
8219
|
To apply this pattern:`));
|
|
7877
8220
|
console.log(chalk20.cyan(` pnpm workflow:learn:apply ${blueprint.id}`));
|
|
@@ -7900,7 +8243,9 @@ async function learnAnalyzeCommand(options) {
|
|
|
7900
8243
|
const store = new PatternStore2(cwd);
|
|
7901
8244
|
await store.initialize();
|
|
7902
8245
|
const verbose = options.verbose ?? false;
|
|
7903
|
-
console.log(
|
|
8246
|
+
console.log(
|
|
8247
|
+
chalk20.cyan("\n\u{1F50D} Analyzing Codebase for Learning Opportunities\n")
|
|
8248
|
+
);
|
|
7904
8249
|
const fixResult = await store.listFixPatterns({});
|
|
7905
8250
|
const bpResult = await store.listBlueprints({});
|
|
7906
8251
|
const existingPatterns = [
|
|
@@ -7965,8 +8310,12 @@ async function learnAnalyzeCommand(options) {
|
|
|
7965
8310
|
console.log(chalk20.dim("\n Your patterns seem well-captured!"));
|
|
7966
8311
|
return;
|
|
7967
8312
|
}
|
|
7968
|
-
console.log(
|
|
7969
|
-
|
|
8313
|
+
console.log(
|
|
8314
|
+
chalk20.bold(
|
|
8315
|
+
` Found ${opportunities.length} potential learning opportunities:
|
|
8316
|
+
`
|
|
8317
|
+
)
|
|
8318
|
+
);
|
|
7970
8319
|
for (const opp of opportunities) {
|
|
7971
8320
|
const icon = opp.type === "blueprint" ? "\u{1F4D0}" : "\u{1F527}";
|
|
7972
8321
|
console.log(` ${icon} ${chalk20.green(opp.name)}`);
|
|
@@ -8074,7 +8423,9 @@ async function learnImportCommand(file, options) {
|
|
|
8074
8423
|
let importData;
|
|
8075
8424
|
try {
|
|
8076
8425
|
if (file.endsWith(".yaml") || file.endsWith(".yml")) {
|
|
8077
|
-
console.log(
|
|
8426
|
+
console.log(
|
|
8427
|
+
chalk20.yellow(" YAML import not fully supported, treating as JSON")
|
|
8428
|
+
);
|
|
8078
8429
|
}
|
|
8079
8430
|
importData = JSON.parse(content);
|
|
8080
8431
|
} catch {
|
|
@@ -8097,7 +8448,9 @@ async function learnImportCommand(file, options) {
|
|
|
8097
8448
|
console.log(chalk20.dim(` Would import fix: ${fix.name} (${fix.id})`));
|
|
8098
8449
|
}
|
|
8099
8450
|
for (const bp of blueprints) {
|
|
8100
|
-
console.log(
|
|
8451
|
+
console.log(
|
|
8452
|
+
chalk20.dim(` Would import blueprint: ${bp.name} (${bp.id})`)
|
|
8453
|
+
);
|
|
8101
8454
|
}
|
|
8102
8455
|
return;
|
|
8103
8456
|
}
|
|
@@ -8150,8 +8503,12 @@ async function learnCleanCommand(options) {
|
|
|
8150
8503
|
if (!cleanDeprecated && !cleanStale && !cleanAll) {
|
|
8151
8504
|
console.log(chalk20.yellow(" Specify what to clean:"));
|
|
8152
8505
|
console.log(chalk20.dim(" --deprecated Remove deprecated patterns"));
|
|
8153
|
-
console.log(
|
|
8154
|
-
|
|
8506
|
+
console.log(
|
|
8507
|
+
chalk20.dim(" --stale Remove patterns not used in 90+ days")
|
|
8508
|
+
);
|
|
8509
|
+
console.log(
|
|
8510
|
+
chalk20.dim(" --all Remove all patterns (use with caution!)")
|
|
8511
|
+
);
|
|
8155
8512
|
return;
|
|
8156
8513
|
}
|
|
8157
8514
|
const toRemove = [];
|
|
@@ -8166,23 +8523,48 @@ async function learnCleanCommand(options) {
|
|
|
8166
8523
|
if (cleanAll) {
|
|
8167
8524
|
toRemove.push({ id: fix.id, name: fix.name, type: "fix", reason: "all" });
|
|
8168
8525
|
} else if (cleanDeprecated && fix.deprecatedAt) {
|
|
8169
|
-
toRemove.push({
|
|
8526
|
+
toRemove.push({
|
|
8527
|
+
id: fix.id,
|
|
8528
|
+
name: fix.name,
|
|
8529
|
+
type: "fix",
|
|
8530
|
+
reason: "deprecated"
|
|
8531
|
+
});
|
|
8170
8532
|
} else if (cleanStale) {
|
|
8171
8533
|
const lastUsed = new Date(fix.updatedAt).getTime();
|
|
8172
8534
|
if (lastUsed < staleThreshold) {
|
|
8173
|
-
toRemove.push({
|
|
8535
|
+
toRemove.push({
|
|
8536
|
+
id: fix.id,
|
|
8537
|
+
name: fix.name,
|
|
8538
|
+
type: "fix",
|
|
8539
|
+
reason: "stale"
|
|
8540
|
+
});
|
|
8174
8541
|
}
|
|
8175
8542
|
}
|
|
8176
8543
|
}
|
|
8177
8544
|
for (const bp of blueprints) {
|
|
8178
8545
|
if (cleanAll) {
|
|
8179
|
-
toRemove.push({
|
|
8546
|
+
toRemove.push({
|
|
8547
|
+
id: bp.id,
|
|
8548
|
+
name: bp.name,
|
|
8549
|
+
type: "blueprint",
|
|
8550
|
+
reason: "all"
|
|
8551
|
+
});
|
|
8180
8552
|
} else if (cleanDeprecated && bp.deprecatedAt) {
|
|
8181
|
-
toRemove.push({
|
|
8553
|
+
toRemove.push({
|
|
8554
|
+
id: bp.id,
|
|
8555
|
+
name: bp.name,
|
|
8556
|
+
type: "blueprint",
|
|
8557
|
+
reason: "deprecated"
|
|
8558
|
+
});
|
|
8182
8559
|
} else if (cleanStale) {
|
|
8183
8560
|
const lastUsed = new Date(bp.updatedAt).getTime();
|
|
8184
8561
|
if (lastUsed < staleThreshold) {
|
|
8185
|
-
toRemove.push({
|
|
8562
|
+
toRemove.push({
|
|
8563
|
+
id: bp.id,
|
|
8564
|
+
name: bp.name,
|
|
8565
|
+
type: "blueprint",
|
|
8566
|
+
reason: "stale"
|
|
8567
|
+
});
|
|
8186
8568
|
}
|
|
8187
8569
|
}
|
|
8188
8570
|
}
|
|
@@ -8248,7 +8630,10 @@ ${chalk21.bold("Examples:")}
|
|
|
8248
8630
|
).action(() => {
|
|
8249
8631
|
learnCmd.help();
|
|
8250
8632
|
});
|
|
8251
|
-
learnCmd.command("record").description("Record a new pattern from a successful implementation").option("--name <name>", "Pattern name").option("--description <desc>", "Pattern description").option(
|
|
8633
|
+
learnCmd.command("record").description("Record a new pattern from a successful implementation").option("--name <name>", "Pattern name").option("--description <desc>", "Pattern description").option(
|
|
8634
|
+
"--category <cat>",
|
|
8635
|
+
"Category (migration, security, performance, etc.)"
|
|
8636
|
+
).option("--framework <fw>", "Framework (next, react, vue, etc.)").option("--version <ver>", "Framework version range").option("--tags <tags>", "Comma-separated tags (category:value)").option("--type <type>", "Pattern type (fix, blueprint)").addHelpText(
|
|
8252
8637
|
"after",
|
|
8253
8638
|
`
|
|
8254
8639
|
${chalk21.bold("Examples:")}
|
|
@@ -8278,7 +8663,9 @@ ${chalk21.bold("Examples:")}
|
|
|
8278
8663
|
$ workflow learn apply abc123 --framework react ${chalk21.dim("# Override framework")}
|
|
8279
8664
|
`
|
|
8280
8665
|
).action(learnApplyCommand);
|
|
8281
|
-
learnCmd.command("capture <paths...>").description(
|
|
8666
|
+
learnCmd.command("capture <paths...>").description(
|
|
8667
|
+
"Capture files as a blueprint pattern with auto-inferred metadata"
|
|
8668
|
+
).option("--name <name>", "Pattern name (inferred from paths if omitted)").option("--description <desc>", "Pattern description").option("--framework <fw>", "Override inferred framework").option("--tags <tags>", "Additional tags (comma-separated)").option("--dry-run", "Preview what would be captured without saving").addHelpText(
|
|
8282
8669
|
"after",
|
|
8283
8670
|
`
|
|
8284
8671
|
${chalk21.bold("Examples:")}
|
|
@@ -8288,7 +8675,9 @@ ${chalk21.bold("Examples:")}
|
|
|
8288
8675
|
$ workflow learn capture ./hooks --tags "react,hooks" ${chalk21.dim("# With tags")}
|
|
8289
8676
|
`
|
|
8290
8677
|
).action(learnCaptureCommand);
|
|
8291
|
-
learnCmd.command("sync").description(
|
|
8678
|
+
learnCmd.command("sync").description(
|
|
8679
|
+
"Sync patterns with remote registry (alias for: workflow sync --learn)"
|
|
8680
|
+
).option("--push", "Push local patterns to registry").option("--pull", "Pull patterns from registry").option("--dry-run", "Preview without syncing").addHelpText(
|
|
8292
8681
|
"after",
|
|
8293
8682
|
`
|
|
8294
8683
|
${chalk21.bold("Examples:")}
|
|
@@ -8302,7 +8691,7 @@ ${chalk21.bold("Pro Tip:")}
|
|
|
8302
8691
|
$ workflow sync --all ${chalk21.dim("# Sync everything")}
|
|
8303
8692
|
`
|
|
8304
8693
|
).action(async (options) => {
|
|
8305
|
-
const { syncCommand: syncCommand2 } = await import("../sync-
|
|
8694
|
+
const { syncCommand: syncCommand2 } = await import("../sync-HHQM3GKR.js");
|
|
8306
8695
|
return syncCommand2({ ...options, learn: true });
|
|
8307
8696
|
});
|
|
8308
8697
|
learnCmd.command("config").description("Configure learning settings").option("--enable-sync", "Enable pattern sync").option("--disable-sync", "Disable pattern sync").option("--enable-telemetry", "Enable anonymous telemetry").option("--disable-telemetry", "Disable telemetry").option("--reset-id", "Reset contributor ID").option("--show", "Show current configuration").addHelpText(
|
|
@@ -8348,7 +8737,11 @@ ${chalk21.bold("Examples:")}
|
|
|
8348
8737
|
$ workflow learn analyze --verbose ${chalk21.dim("# Show paths and details")}
|
|
8349
8738
|
`
|
|
8350
8739
|
).action(learnAnalyzeCommand);
|
|
8351
|
-
learnCmd.command("export").description("Export learning patterns to a file").option("-o, --output <path>", "Output file path", "patterns-export.json").option("-f, --format <format>", "Output format (json, yaml)", "json").option(
|
|
8740
|
+
learnCmd.command("export").description("Export learning patterns to a file").option("-o, --output <path>", "Output file path", "patterns-export.json").option("-f, --format <format>", "Output format (json, yaml)", "json").option(
|
|
8741
|
+
"-t, --type <type>",
|
|
8742
|
+
"Pattern type to export (fix, blueprint, all)",
|
|
8743
|
+
"all"
|
|
8744
|
+
).addHelpText(
|
|
8352
8745
|
"after",
|
|
8353
8746
|
`
|
|
8354
8747
|
${chalk21.bold("Examples:")}
|
|
@@ -8376,7 +8769,11 @@ ${chalk21.bold("Examples:")}
|
|
|
8376
8769
|
$ workflow learn clean --all --dry-run ${chalk21.dim("# Preview full clean")}
|
|
8377
8770
|
`
|
|
8378
8771
|
).action(learnCleanCommand);
|
|
8379
|
-
learnCmd.command("validate").description("Validate pattern files and optionally auto-fix common issues").option(
|
|
8772
|
+
learnCmd.command("validate").description("Validate pattern files and optionally auto-fix common issues").option(
|
|
8773
|
+
"-t, --type <type>",
|
|
8774
|
+
"Pattern type to validate (fix, blueprint, solution, all)",
|
|
8775
|
+
"all"
|
|
8776
|
+
).option("-f, --file <path>", "Validate a specific file by path").option("--fix", "Automatically fix common issues").option("-v, --verbose", "Show detailed validation output").addHelpText(
|
|
8380
8777
|
"after",
|
|
8381
8778
|
`
|
|
8382
8779
|
${chalk21.bold("Examples:")}
|
|
@@ -8410,10 +8807,14 @@ async function scopeListCommand() {
|
|
|
8410
8807
|
byCategory[cat].push(scope);
|
|
8411
8808
|
}
|
|
8412
8809
|
for (const [category, categoryScopes] of Object.entries(byCategory)) {
|
|
8413
|
-
console.log(
|
|
8810
|
+
console.log(
|
|
8811
|
+
chalk22.bold(` ${category.charAt(0).toUpperCase() + category.slice(1)}:`)
|
|
8812
|
+
);
|
|
8414
8813
|
for (const scope of categoryScopes) {
|
|
8415
8814
|
const emoji = scope.emoji || "\u{1F4E6}";
|
|
8416
|
-
console.log(
|
|
8815
|
+
console.log(
|
|
8816
|
+
` ${emoji} ${chalk22.green(scope.name)} - ${scope.description || "No description"}`
|
|
8817
|
+
);
|
|
8417
8818
|
}
|
|
8418
8819
|
console.log("");
|
|
8419
8820
|
}
|
|
@@ -8424,12 +8825,16 @@ async function scopeAddCommand(name, options) {
|
|
|
8424
8825
|
\u2795 Adding Scope: ${name}
|
|
8425
8826
|
`));
|
|
8426
8827
|
const fs3 = await import("fs");
|
|
8427
|
-
const
|
|
8828
|
+
const path5 = await import("path");
|
|
8428
8829
|
const cwd = process.cwd();
|
|
8429
|
-
const configFiles = [
|
|
8830
|
+
const configFiles = [
|
|
8831
|
+
"workflow.config.json",
|
|
8832
|
+
"workflow.config.js",
|
|
8833
|
+
".workflowrc.json"
|
|
8834
|
+
];
|
|
8430
8835
|
let configPath = null;
|
|
8431
8836
|
for (const file of configFiles) {
|
|
8432
|
-
const fullPath =
|
|
8837
|
+
const fullPath = path5.join(cwd, file);
|
|
8433
8838
|
if (fs3.existsSync(fullPath)) {
|
|
8434
8839
|
configPath = fullPath;
|
|
8435
8840
|
break;
|
|
@@ -8467,12 +8872,16 @@ async function scopeRemoveCommand(name) {
|
|
|
8467
8872
|
\u2796 Removing Scope: ${name}
|
|
8468
8873
|
`));
|
|
8469
8874
|
const fs3 = await import("fs");
|
|
8470
|
-
const
|
|
8875
|
+
const path5 = await import("path");
|
|
8471
8876
|
const cwd = process.cwd();
|
|
8472
|
-
const configFiles = [
|
|
8877
|
+
const configFiles = [
|
|
8878
|
+
"workflow.config.json",
|
|
8879
|
+
"workflow.config.js",
|
|
8880
|
+
".workflowrc.json"
|
|
8881
|
+
];
|
|
8473
8882
|
let configPath = null;
|
|
8474
8883
|
for (const file of configFiles) {
|
|
8475
|
-
const fullPath =
|
|
8884
|
+
const fullPath = path5.join(cwd, file);
|
|
8476
8885
|
if (fs3.existsSync(fullPath)) {
|
|
8477
8886
|
configPath = fullPath;
|
|
8478
8887
|
break;
|
|
@@ -8488,7 +8897,9 @@ async function scopeRemoveCommand(name) {
|
|
|
8488
8897
|
console.log(chalk22.yellow(" No scopes configured"));
|
|
8489
8898
|
process.exit(1);
|
|
8490
8899
|
}
|
|
8491
|
-
const index = config.scopes.findIndex(
|
|
8900
|
+
const index = config.scopes.findIndex(
|
|
8901
|
+
(s) => s.name === name
|
|
8902
|
+
);
|
|
8492
8903
|
if (index === -1) {
|
|
8493
8904
|
console.log(chalk22.yellow(` Scope "${name}" not found`));
|
|
8494
8905
|
process.exit(1);
|
|
@@ -8499,7 +8910,7 @@ async function scopeRemoveCommand(name) {
|
|
|
8499
8910
|
}
|
|
8500
8911
|
async function scopeSyncCommand(options) {
|
|
8501
8912
|
console.log(chalk22.bold.cyan("\n\u{1F504} Syncing Scopes\n"));
|
|
8502
|
-
const { syncCommand: syncCommand2 } = await import("../sync-
|
|
8913
|
+
const { syncCommand: syncCommand2 } = await import("../sync-HHQM3GKR.js");
|
|
8503
8914
|
await syncCommand2({
|
|
8504
8915
|
...options,
|
|
8505
8916
|
scopes: true,
|
|
@@ -8512,7 +8923,11 @@ async function scopeAnalyzeCommand() {
|
|
|
8512
8923
|
const { execa: execa2 } = await import("execa");
|
|
8513
8924
|
const cwd = process.cwd();
|
|
8514
8925
|
try {
|
|
8515
|
-
const { stdout } = await execa2(
|
|
8926
|
+
const { stdout } = await execa2(
|
|
8927
|
+
"git",
|
|
8928
|
+
["log", "--oneline", "-50", "--format=%s"],
|
|
8929
|
+
{ cwd }
|
|
8930
|
+
);
|
|
8516
8931
|
const commits = stdout.split("\n").filter(Boolean);
|
|
8517
8932
|
const config = await loadConfig();
|
|
8518
8933
|
const scopes = config?.scopes || [];
|
|
@@ -8539,13 +8954,19 @@ async function scopeAnalyzeCommand() {
|
|
|
8539
8954
|
console.log("");
|
|
8540
8955
|
const sortedUsage = Object.entries(usage).sort((a, b) => b[1] - a[1]);
|
|
8541
8956
|
for (const [scope, count] of sortedUsage) {
|
|
8542
|
-
const scopeConfig = scopes.find(
|
|
8957
|
+
const scopeConfig = scopes.find(
|
|
8958
|
+
(s) => s.name === scope
|
|
8959
|
+
);
|
|
8543
8960
|
const emoji = scopeConfig?.emoji || "\u{1F4E6}";
|
|
8544
8961
|
const bar = "\u2588".repeat(Math.min(count, 20));
|
|
8545
|
-
console.log(
|
|
8962
|
+
console.log(
|
|
8963
|
+
` ${emoji} ${chalk22.green(scope.padEnd(15))} ${bar} ${count}`
|
|
8964
|
+
);
|
|
8546
8965
|
}
|
|
8547
8966
|
if (unscoped > 0) {
|
|
8548
|
-
console.log(
|
|
8967
|
+
console.log(
|
|
8968
|
+
` ${chalk22.yellow("(unscoped)".padEnd(17))} ${"\u2591".repeat(Math.min(unscoped, 20))} ${unscoped}`
|
|
8969
|
+
);
|
|
8549
8970
|
}
|
|
8550
8971
|
const unusedScopes = scopeNames.filter((name) => !usage[name]);
|
|
8551
8972
|
if (unusedScopes.length > 0) {
|
|
@@ -8563,7 +8984,9 @@ async function scopeAnalyzeCommand() {
|
|
|
8563
8984
|
console.log("");
|
|
8564
8985
|
} catch {
|
|
8565
8986
|
console.log(chalk22.yellow(" Unable to analyze git history"));
|
|
8566
|
-
console.log(
|
|
8987
|
+
console.log(
|
|
8988
|
+
chalk22.dim(" Make sure you're in a git repository with commit history")
|
|
8989
|
+
);
|
|
8567
8990
|
}
|
|
8568
8991
|
}
|
|
8569
8992
|
function createScopeCommand() {
|
|
@@ -8645,14 +9068,20 @@ ${chalk22.bold("Details:")}
|
|
|
8645
9068
|
|
|
8646
9069
|
// src/cli/commands/migrate.ts
|
|
8647
9070
|
import chalk23 from "chalk";
|
|
8648
|
-
import
|
|
9071
|
+
import * as path4 from "path";
|
|
9072
|
+
import {
|
|
9073
|
+
PatternStore as PatternStore3,
|
|
9074
|
+
PATTERNS_DIR
|
|
9075
|
+
} from "@hawkinside_out/workflow-improvement-tracker";
|
|
8649
9076
|
async function migrateCommand(subcommand, options) {
|
|
8650
9077
|
if (subcommand === "filenames") {
|
|
8651
9078
|
await migrateFilenames(options);
|
|
8652
9079
|
} else {
|
|
8653
9080
|
console.error(chalk23.red(`Unknown migrate subcommand: ${subcommand}`));
|
|
8654
9081
|
console.log(chalk23.dim("\nAvailable subcommands:"));
|
|
8655
|
-
console.log(
|
|
9082
|
+
console.log(
|
|
9083
|
+
chalk23.dim(" filenames Migrate pattern files to slugified names")
|
|
9084
|
+
);
|
|
8656
9085
|
process.exit(1);
|
|
8657
9086
|
}
|
|
8658
9087
|
}
|
|
@@ -8663,8 +9092,23 @@ async function migrateFilenames(options) {
|
|
|
8663
9092
|
if (isDryRun) {
|
|
8664
9093
|
console.log(chalk23.yellow("\u{1F50D} DRY RUN MODE - No files will be modified\n"));
|
|
8665
9094
|
}
|
|
8666
|
-
const store = new PatternStore3();
|
|
8667
9095
|
const cwd = process.cwd();
|
|
9096
|
+
const store = new PatternStore3(cwd);
|
|
9097
|
+
await store.initialize();
|
|
9098
|
+
const fixesPath = path4.join(cwd, PATTERNS_DIR, "fixes");
|
|
9099
|
+
const blueprintsPath = path4.join(cwd, PATTERNS_DIR, "blueprints");
|
|
9100
|
+
const solutionsPath = path4.join(cwd, PATTERNS_DIR, "solutions");
|
|
9101
|
+
function slugify(text8) {
|
|
9102
|
+
const slug = text8.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
|
|
9103
|
+
return slug.substring(0, 50);
|
|
9104
|
+
}
|
|
9105
|
+
function getFilePath(basePath, id, name) {
|
|
9106
|
+
if (name) {
|
|
9107
|
+
const slug = slugify(name);
|
|
9108
|
+
return path4.join(basePath, `${slug}-${id}.json`);
|
|
9109
|
+
}
|
|
9110
|
+
return path4.join(basePath, `${id}.json`);
|
|
9111
|
+
}
|
|
8668
9112
|
let totalProcessed = 0;
|
|
8669
9113
|
let totalMigrated = 0;
|
|
8670
9114
|
let totalFailed = 0;
|
|
@@ -8672,13 +9116,15 @@ async function migrateFilenames(options) {
|
|
|
8672
9116
|
const results = [];
|
|
8673
9117
|
if (targetType === "fix" || targetType === "all") {
|
|
8674
9118
|
console.log(chalk23.bold("Fixes:"));
|
|
8675
|
-
const fixesResult = await store.
|
|
9119
|
+
const fixesResult = await store.listFixPatterns({
|
|
9120
|
+
includeDeprecated: true
|
|
9121
|
+
});
|
|
8676
9122
|
if (fixesResult.success && fixesResult.data) {
|
|
8677
9123
|
for (const fix of fixesResult.data) {
|
|
8678
9124
|
totalProcessed++;
|
|
8679
9125
|
try {
|
|
8680
|
-
const oldPath =
|
|
8681
|
-
const newPath =
|
|
9126
|
+
const oldPath = getFilePath(fixesPath, fix.id);
|
|
9127
|
+
const newPath = getFilePath(fixesPath, fix.id, fix.name);
|
|
8682
9128
|
if (oldPath === newPath) {
|
|
8683
9129
|
console.log(chalk23.dim(` \u2298 ${fix.name} - already migrated`));
|
|
8684
9130
|
results.push({
|
|
@@ -8722,13 +9168,19 @@ async function migrateFilenames(options) {
|
|
|
8722
9168
|
}
|
|
8723
9169
|
if (targetType === "blueprint" || targetType === "all") {
|
|
8724
9170
|
console.log(chalk23.bold("Blueprints:"));
|
|
8725
|
-
const blueprintsResult = await store.
|
|
9171
|
+
const blueprintsResult = await store.listBlueprints({
|
|
9172
|
+
includeDeprecated: true
|
|
9173
|
+
});
|
|
8726
9174
|
if (blueprintsResult.success && blueprintsResult.data) {
|
|
8727
9175
|
for (const blueprint of blueprintsResult.data) {
|
|
8728
9176
|
totalProcessed++;
|
|
8729
9177
|
try {
|
|
8730
|
-
const oldPath =
|
|
8731
|
-
const newPath =
|
|
9178
|
+
const oldPath = getFilePath(blueprintsPath, blueprint.id);
|
|
9179
|
+
const newPath = getFilePath(
|
|
9180
|
+
blueprintsPath,
|
|
9181
|
+
blueprint.id,
|
|
9182
|
+
blueprint.name
|
|
9183
|
+
);
|
|
8732
9184
|
if (oldPath === newPath) {
|
|
8733
9185
|
console.log(chalk23.dim(` \u2298 ${blueprint.name} - already migrated`));
|
|
8734
9186
|
results.push({
|
|
@@ -8772,13 +9224,19 @@ async function migrateFilenames(options) {
|
|
|
8772
9224
|
}
|
|
8773
9225
|
if (targetType === "solution" || targetType === "all") {
|
|
8774
9226
|
console.log(chalk23.bold("Solutions:"));
|
|
8775
|
-
const solutionsResult = await store.
|
|
9227
|
+
const solutionsResult = await store.listSolutions({
|
|
9228
|
+
includeDeprecated: true
|
|
9229
|
+
});
|
|
8776
9230
|
if (solutionsResult.success && solutionsResult.data) {
|
|
8777
9231
|
for (const solution of solutionsResult.data) {
|
|
8778
9232
|
totalProcessed++;
|
|
8779
9233
|
try {
|
|
8780
|
-
const oldPath =
|
|
8781
|
-
const newPath =
|
|
9234
|
+
const oldPath = getFilePath(solutionsPath, solution.id);
|
|
9235
|
+
const newPath = getFilePath(
|
|
9236
|
+
solutionsPath,
|
|
9237
|
+
solution.id,
|
|
9238
|
+
solution.name
|
|
9239
|
+
);
|
|
8782
9240
|
if (oldPath === newPath) {
|
|
8783
9241
|
console.log(chalk23.dim(` \u2298 ${solution.name} - already migrated`));
|
|
8784
9242
|
results.push({
|
|
@@ -8832,14 +9290,22 @@ async function migrateFilenames(options) {
|
|
|
8832
9290
|
console.log(chalk23.red(` \u2717 Failed: ${totalFailed}`));
|
|
8833
9291
|
}
|
|
8834
9292
|
if (isDryRun && totalMigrated > 0) {
|
|
8835
|
-
console.log(
|
|
9293
|
+
console.log(
|
|
9294
|
+
chalk23.yellow(
|
|
9295
|
+
"\n\u26A0\uFE0F This was a dry run. Run without --dry-run to apply changes."
|
|
9296
|
+
)
|
|
9297
|
+
);
|
|
8836
9298
|
} else if (!isDryRun && totalMigrated > 0) {
|
|
8837
9299
|
console.log(chalk23.green("\n\u2713 Migration complete!"));
|
|
8838
9300
|
} else if (totalSkipped === totalProcessed) {
|
|
8839
9301
|
console.log(chalk23.dim("\n\u2713 All patterns already use slugified filenames."));
|
|
8840
9302
|
}
|
|
8841
9303
|
if (totalFailed > 0) {
|
|
8842
|
-
console.log(
|
|
9304
|
+
console.log(
|
|
9305
|
+
chalk23.red(
|
|
9306
|
+
"\n\u26A0\uFE0F Some patterns failed to migrate. Check the errors above."
|
|
9307
|
+
)
|
|
9308
|
+
);
|
|
8843
9309
|
process.exit(1);
|
|
8844
9310
|
}
|
|
8845
9311
|
}
|
|
@@ -8848,10 +9314,12 @@ async function migrateFilenames(options) {
|
|
|
8848
9314
|
var __filename4 = fileURLToPath4(import.meta.url);
|
|
8849
9315
|
var __dirname4 = dirname5(__filename4);
|
|
8850
9316
|
var packageJson = JSON.parse(
|
|
8851
|
-
readFileSync3(
|
|
9317
|
+
readFileSync3(join13(__dirname4, "../../package.json"), "utf-8")
|
|
8852
9318
|
);
|
|
8853
9319
|
function deprecationWarning(oldCmd, newCmd) {
|
|
8854
|
-
console.warn(
|
|
9320
|
+
console.warn(
|
|
9321
|
+
chalk24.yellow(`\u26A0\uFE0F "${oldCmd}" is deprecated and will be removed in v2.0.`)
|
|
9322
|
+
);
|
|
8855
9323
|
console.warn(chalk24.yellow(` Use: ${newCmd}
|
|
8856
9324
|
`));
|
|
8857
9325
|
}
|
|
@@ -8863,7 +9331,11 @@ program.addCommand(createDocsCommand());
|
|
|
8863
9331
|
program.addCommand(createSolutionCommand());
|
|
8864
9332
|
program.addCommand(createLearnCommand());
|
|
8865
9333
|
program.addCommand(createScopeCommand());
|
|
8866
|
-
program.command("migrate <subcommand>").description("Migrate patterns and configurations").option("--dry-run", "Preview without making changes").option(
|
|
9334
|
+
program.command("migrate <subcommand>").description("Migrate patterns and configurations").option("--dry-run", "Preview without making changes").option(
|
|
9335
|
+
"--type <type>",
|
|
9336
|
+
"Pattern type to migrate (fix, blueprint, solution, or all)",
|
|
9337
|
+
"all"
|
|
9338
|
+
).addHelpText(
|
|
8867
9339
|
"after",
|
|
8868
9340
|
`
|
|
8869
9341
|
${chalk24.bold("Subcommands:")}
|
|
@@ -8933,7 +9405,9 @@ program.command("config:fix").description("Automatically fix common configuratio
|
|
|
8933
9405
|
process.exit(0);
|
|
8934
9406
|
} else {
|
|
8935
9407
|
if (result.configPath) {
|
|
8936
|
-
console.log(
|
|
9408
|
+
console.log(
|
|
9409
|
+
chalk25.red(`\u2717 Failed to fix configuration: ${result.error}`)
|
|
9410
|
+
);
|
|
8937
9411
|
} else {
|
|
8938
9412
|
console.log(chalk25.red("\u2717 No workflow configuration file found"));
|
|
8939
9413
|
console.log(chalk25.yellow(" Run: workflow init"));
|
|
@@ -8970,7 +9444,10 @@ program.command("scope:migrate", { hidden: true }).description("[DEPRECATED] Use
|
|
|
8970
9444
|
deprecationWarning("workflow scope:migrate", "workflow scope migrate");
|
|
8971
9445
|
return scopeMigrateCommand(options);
|
|
8972
9446
|
});
|
|
8973
|
-
program.command("verify").description("Run all quality checks with fix-and-revalidate pattern").option("--fix", "Enable auto-fix for lint and format issues").option("--max-retries <n>", "Maximum retry cycles (default: 10)", "10").option("--commit", "Commit changes if all checks pass").option("--dry-run", "Preview fixes without applying them").option("--learn", "Record successful fixes as learning patterns").
|
|
9447
|
+
program.command("verify").description("Run all quality checks with fix-and-revalidate pattern").option("--fix", "Enable auto-fix for lint and format issues").option("--max-retries <n>", "Maximum retry cycles (default: 10)", "10").option("--commit", "Commit changes if all checks pass").option("--dry-run", "Preview fixes without applying them").option("--learn", "Record successful fixes as learning patterns").option(
|
|
9448
|
+
"--no-platform-checks",
|
|
9449
|
+
"Skip platform-specific checks (Shopify, WordPress, etc.)"
|
|
9450
|
+
).action(verifyCommand);
|
|
8974
9451
|
program.command("pre-commit").description("Run pre-commit checks (alias for verify --fix --staged)").option("--dry-run", "Preview fixes without applying them").action(preCommitCommand);
|
|
8975
9452
|
program.command("auto-setup", { hidden: true }).description("[DEPRECATED] Use: workflow setup auto").option("-y, --yes", "Auto-approve all prompts").option("--audit", "Show audit report without applying changes").action(async (options) => {
|
|
8976
9453
|
deprecationWarning("workflow auto-setup", "workflow setup auto");
|
|
@@ -8981,7 +9458,10 @@ program.command("advisory", { hidden: true }).description("[DEPRECATED] Use: wor
|
|
|
8981
9458
|
return advisoryCommand(options);
|
|
8982
9459
|
});
|
|
8983
9460
|
program.command("generate-instructions", { hidden: true }).description("[DEPRECATED] Use: workflow docs generate").option("--force", "Regenerate without confirmation").action(async (options) => {
|
|
8984
|
-
deprecationWarning(
|
|
9461
|
+
deprecationWarning(
|
|
9462
|
+
"workflow generate-instructions",
|
|
9463
|
+
"workflow docs generate"
|
|
9464
|
+
);
|
|
8985
9465
|
return docsGenerateCommand(options);
|
|
8986
9466
|
});
|
|
8987
9467
|
program.command("update-templates", { hidden: true }).description("[DEPRECATED] Use: workflow docs update").option("--force", "Overwrite existing template files").option("--skip", "Skip the update").action(async (options) => {
|
|
@@ -9039,7 +9519,10 @@ program.command("learn:validate", { hidden: true }).description("[DEPRECATED] Us
|
|
|
9039
9519
|
return learnValidateCommand(options);
|
|
9040
9520
|
});
|
|
9041
9521
|
program.command("solution:capture", { hidden: true }).description("[DEPRECATED] Use: workflow solution capture").option("--name <name>", "Solution name").option("--description <desc>", "Solution description").option("--category <cat>", "Category").option("--keywords <kw>", "Comma-separated keywords").option("--path <path>", "Path to the solution directory").option("--anonymize", "Anonymize sensitive data").option("--private", "Keep solution private").action(async (options) => {
|
|
9042
|
-
deprecationWarning(
|
|
9522
|
+
deprecationWarning(
|
|
9523
|
+
"workflow solution:capture",
|
|
9524
|
+
"workflow solution capture"
|
|
9525
|
+
);
|
|
9043
9526
|
return solutionCaptureCommand(options);
|
|
9044
9527
|
});
|
|
9045
9528
|
program.command("solution:search <query>", { hidden: true }).description("[DEPRECATED] Use: workflow solution search").option("--category <cat>", "Filter by category").option("--framework <fw>", "Filter by framework").option("--limit <n>", "Maximum results", "10").action(async (query, options) => {
|
|
@@ -9055,7 +9538,10 @@ program.command("solution:apply <solutionId>", { hidden: true }).description("[D
|
|
|
9055
9538
|
return solutionApplyCommand(solutionId, options);
|
|
9056
9539
|
});
|
|
9057
9540
|
program.command("solution:deprecate <solutionId> <reason>", { hidden: true }).description("[DEPRECATED] Use: workflow solution deprecate").action(async (solutionId, reason) => {
|
|
9058
|
-
deprecationWarning(
|
|
9541
|
+
deprecationWarning(
|
|
9542
|
+
"workflow solution:deprecate",
|
|
9543
|
+
"workflow solution deprecate"
|
|
9544
|
+
);
|
|
9059
9545
|
return solutionDeprecateCommand(solutionId, reason);
|
|
9060
9546
|
});
|
|
9061
9547
|
program.command("solution:stats", { hidden: true }).description("[DEPRECATED] Use: workflow solution stats").action(async () => {
|