workflow-agent-cli 2.9.0 → 2.9.1
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/LICENSE +21 -0
- package/dist/{chunk-Y5N3JJTU.js → chunk-YEOQZ7XC.js} +3 -3
- package/dist/cli/index.js +631 -270
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/scripts/postinstall.js +1 -1
- package/dist/validators/index.d.ts +1 -1
- package/package.json +30 -30
- package/dist/{chunk-Y5N3JJTU.js.map → chunk-YEOQZ7XC.js.map} +0 -0
- package/dist/{schema-BUu8Cefw.d.ts → schema-D0zTM83x.d.ts} +4 -4
package/dist/cli/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
installMandatoryTemplates,
|
|
32
32
|
templateMetadata,
|
|
33
33
|
updateTemplates
|
|
34
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-YEOQZ7XC.js";
|
|
35
35
|
|
|
36
36
|
// src/cli/index.ts
|
|
37
37
|
import { Command } from "commander";
|
|
@@ -359,11 +359,11 @@ async function initCommand(options) {
|
|
|
359
359
|
if (!existsSync(workflowDir)) {
|
|
360
360
|
await mkdir(workflowDir, { recursive: true });
|
|
361
361
|
}
|
|
362
|
-
const shouldGenerateGuidelines = await p.confirm({
|
|
362
|
+
const shouldGenerateGuidelines = options.yes || isNonInteractive ? true : await p.confirm({
|
|
363
363
|
message: "Generate workflow guidelines from templates?",
|
|
364
364
|
initialValue: true
|
|
365
365
|
});
|
|
366
|
-
if (p.isCancel(shouldGenerateGuidelines)) {
|
|
366
|
+
if (!isNonInteractive && p.isCancel(shouldGenerateGuidelines)) {
|
|
367
367
|
p.cancel("Initialization cancelled");
|
|
368
368
|
process.exit(0);
|
|
369
369
|
}
|
|
@@ -403,11 +403,11 @@ Reason: ${error instanceof Error ? error.message : String(error)}`
|
|
|
403
403
|
);
|
|
404
404
|
}
|
|
405
405
|
}
|
|
406
|
-
const shouldAutoSetup = options.yes ? true : await p.confirm({
|
|
406
|
+
const shouldAutoSetup = options.yes || isNonInteractive ? true : await p.confirm({
|
|
407
407
|
message: "Set up linting, formatting, testing, and CI automatically?",
|
|
408
408
|
initialValue: true
|
|
409
409
|
});
|
|
410
|
-
if (p.isCancel(shouldAutoSetup)) {
|
|
410
|
+
if (!isNonInteractive && p.isCancel(shouldAutoSetup)) {
|
|
411
411
|
p.cancel("Initialization cancelled");
|
|
412
412
|
process.exit(0);
|
|
413
413
|
}
|
|
@@ -590,7 +590,204 @@ async function suggestCommand(feedback, options = {}) {
|
|
|
590
590
|
|
|
591
591
|
// src/cli/commands/doctor.ts
|
|
592
592
|
import chalk5 from "chalk";
|
|
593
|
-
|
|
593
|
+
import { existsSync as existsSync3 } from "fs";
|
|
594
|
+
import { join as join3 } from "path";
|
|
595
|
+
|
|
596
|
+
// src/utils/hooks.ts
|
|
597
|
+
import { existsSync as existsSync2 } from "fs";
|
|
598
|
+
import { readFile, writeFile as writeFile2, unlink, chmod, rename, mkdir as mkdir2 } from "fs/promises";
|
|
599
|
+
import { join as join2 } from "path";
|
|
600
|
+
function getGitHooksDir(projectPath = process.cwd()) {
|
|
601
|
+
return join2(projectPath, ".git", "hooks");
|
|
602
|
+
}
|
|
603
|
+
function hasGitRepo(projectPath = process.cwd()) {
|
|
604
|
+
return existsSync2(join2(projectPath, ".git"));
|
|
605
|
+
}
|
|
606
|
+
function generatePreCommitHook(config) {
|
|
607
|
+
const checks = config?.preCommit || ["validate-branch", "check-guidelines"];
|
|
608
|
+
const checkCommands = checks.map((check) => {
|
|
609
|
+
switch (check) {
|
|
610
|
+
case "validate-branch":
|
|
611
|
+
return " workflow validate branch";
|
|
612
|
+
case "validate-commit":
|
|
613
|
+
return " workflow validate commit";
|
|
614
|
+
case "check-guidelines":
|
|
615
|
+
return " workflow doctor --check-guidelines-only 2>/dev/null || true";
|
|
616
|
+
case "validate-scopes":
|
|
617
|
+
return " workflow config validate";
|
|
618
|
+
default:
|
|
619
|
+
return "";
|
|
620
|
+
}
|
|
621
|
+
}).filter(Boolean).join("\n");
|
|
622
|
+
return `#!/bin/sh
|
|
623
|
+
# Workflow Agent pre-commit hook
|
|
624
|
+
# Auto-generated - do not edit manually
|
|
625
|
+
# To reinstall: workflow hooks install
|
|
626
|
+
# To uninstall: workflow hooks uninstall
|
|
627
|
+
|
|
628
|
+
# Skip in CI environment
|
|
629
|
+
if [ -n "\${CI:-}" ] || [ -n "\${GITHUB_ACTIONS:-}" ] || [ -n "\${GITLAB_CI:-}" ]; then
|
|
630
|
+
exit 0
|
|
631
|
+
fi
|
|
632
|
+
|
|
633
|
+
# Run workflow checks
|
|
634
|
+
${checkCommands}
|
|
635
|
+
|
|
636
|
+
# Run original hook if it exists
|
|
637
|
+
if [ -f ".git/hooks/pre-commit.original" ]; then
|
|
638
|
+
.git/hooks/pre-commit.original "$@"
|
|
639
|
+
fi
|
|
640
|
+
`;
|
|
641
|
+
}
|
|
642
|
+
function generateCommitMsgHook(config) {
|
|
643
|
+
const checks = config?.commitMsg || ["validate-commit"];
|
|
644
|
+
const checkCommands = checks.map((check) => {
|
|
645
|
+
switch (check) {
|
|
646
|
+
case "validate-commit":
|
|
647
|
+
return ' workflow validate commit "$(cat "$1")"';
|
|
648
|
+
default:
|
|
649
|
+
return "";
|
|
650
|
+
}
|
|
651
|
+
}).filter(Boolean).join("\n");
|
|
652
|
+
return `#!/bin/sh
|
|
653
|
+
# Workflow Agent commit-msg hook
|
|
654
|
+
# Auto-generated - do not edit manually
|
|
655
|
+
# To reinstall: workflow hooks install
|
|
656
|
+
# To uninstall: workflow hooks uninstall
|
|
657
|
+
|
|
658
|
+
# Skip in CI environment
|
|
659
|
+
if [ -n "\${CI:-}" ] || [ -n "\${GITHUB_ACTIONS:-}" ] || [ -n "\${GITLAB_CI:-}" ]; then
|
|
660
|
+
exit 0
|
|
661
|
+
fi
|
|
662
|
+
|
|
663
|
+
# Run workflow checks
|
|
664
|
+
${checkCommands}
|
|
665
|
+
|
|
666
|
+
# Run original hook if it exists
|
|
667
|
+
if [ -f ".git/hooks/commit-msg.original" ]; then
|
|
668
|
+
.git/hooks/commit-msg.original "$@"
|
|
669
|
+
fi
|
|
670
|
+
`;
|
|
671
|
+
}
|
|
672
|
+
async function isWorkflowHook(hookPath) {
|
|
673
|
+
try {
|
|
674
|
+
const content = await readFile(hookPath, "utf-8");
|
|
675
|
+
return content.includes("Workflow Agent") && content.includes("Auto-generated");
|
|
676
|
+
} catch {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
async function getHookStatus(hookType, projectPath = process.cwd()) {
|
|
681
|
+
const hooksDir = getGitHooksDir(projectPath);
|
|
682
|
+
const hookPath = join2(hooksDir, hookType);
|
|
683
|
+
const originalPath = join2(hooksDir, `${hookType}.original`);
|
|
684
|
+
const status = {
|
|
685
|
+
installed: false,
|
|
686
|
+
hookType,
|
|
687
|
+
hasExistingHook: false,
|
|
688
|
+
wrappedOriginal: false
|
|
689
|
+
};
|
|
690
|
+
if (!existsSync2(hookPath)) {
|
|
691
|
+
return status;
|
|
692
|
+
}
|
|
693
|
+
status.hasExistingHook = true;
|
|
694
|
+
if (await isWorkflowHook(hookPath)) {
|
|
695
|
+
status.installed = true;
|
|
696
|
+
status.wrappedOriginal = existsSync2(originalPath);
|
|
697
|
+
}
|
|
698
|
+
return status;
|
|
699
|
+
}
|
|
700
|
+
async function getAllHooksStatus(projectPath = process.cwd()) {
|
|
701
|
+
return Promise.all([
|
|
702
|
+
getHookStatus("pre-commit", projectPath),
|
|
703
|
+
getHookStatus("commit-msg", projectPath)
|
|
704
|
+
]);
|
|
705
|
+
}
|
|
706
|
+
async function installSingleHook(hookType, config, projectPath = process.cwd()) {
|
|
707
|
+
const hooksDir = getGitHooksDir(projectPath);
|
|
708
|
+
const hookPath = join2(hooksDir, hookType);
|
|
709
|
+
const originalPath = join2(hooksDir, `${hookType}.original`);
|
|
710
|
+
const result = {
|
|
711
|
+
success: false,
|
|
712
|
+
hookType,
|
|
713
|
+
wrappedExisting: false
|
|
714
|
+
};
|
|
715
|
+
try {
|
|
716
|
+
if (!existsSync2(hooksDir)) {
|
|
717
|
+
await mkdir2(hooksDir, { recursive: true });
|
|
718
|
+
}
|
|
719
|
+
if (existsSync2(hookPath)) {
|
|
720
|
+
const isOurs = await isWorkflowHook(hookPath);
|
|
721
|
+
if (!isOurs) {
|
|
722
|
+
await rename(hookPath, originalPath);
|
|
723
|
+
result.wrappedExisting = true;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
const hookContent = hookType === "pre-commit" ? generatePreCommitHook(config) : generateCommitMsgHook(config);
|
|
727
|
+
await writeFile2(hookPath, hookContent, "utf-8");
|
|
728
|
+
await chmod(hookPath, 493);
|
|
729
|
+
result.success = true;
|
|
730
|
+
} catch (error) {
|
|
731
|
+
result.error = error instanceof Error ? error.message : String(error);
|
|
732
|
+
}
|
|
733
|
+
return result;
|
|
734
|
+
}
|
|
735
|
+
async function installHooks(config, projectPath = process.cwd()) {
|
|
736
|
+
if (!hasGitRepo(projectPath)) {
|
|
737
|
+
return [
|
|
738
|
+
{
|
|
739
|
+
success: false,
|
|
740
|
+
hookType: "pre-commit",
|
|
741
|
+
wrappedExisting: false,
|
|
742
|
+
error: "No git repository found. Run git init first."
|
|
743
|
+
}
|
|
744
|
+
];
|
|
745
|
+
}
|
|
746
|
+
const results = await Promise.all([
|
|
747
|
+
installSingleHook("pre-commit", config, projectPath),
|
|
748
|
+
installSingleHook("commit-msg", config, projectPath)
|
|
749
|
+
]);
|
|
750
|
+
return results;
|
|
751
|
+
}
|
|
752
|
+
async function uninstallSingleHook(hookType, projectPath = process.cwd()) {
|
|
753
|
+
const hooksDir = getGitHooksDir(projectPath);
|
|
754
|
+
const hookPath = join2(hooksDir, hookType);
|
|
755
|
+
const originalPath = join2(hooksDir, `${hookType}.original`);
|
|
756
|
+
const result = {
|
|
757
|
+
success: false,
|
|
758
|
+
hookType,
|
|
759
|
+
wrappedExisting: false
|
|
760
|
+
};
|
|
761
|
+
try {
|
|
762
|
+
if (!existsSync2(hookPath)) {
|
|
763
|
+
result.success = true;
|
|
764
|
+
return result;
|
|
765
|
+
}
|
|
766
|
+
const isOurs = await isWorkflowHook(hookPath);
|
|
767
|
+
if (!isOurs) {
|
|
768
|
+
result.error = "Hook is not managed by Workflow Agent";
|
|
769
|
+
return result;
|
|
770
|
+
}
|
|
771
|
+
await unlink(hookPath);
|
|
772
|
+
if (existsSync2(originalPath)) {
|
|
773
|
+
await rename(originalPath, hookPath);
|
|
774
|
+
result.wrappedExisting = true;
|
|
775
|
+
}
|
|
776
|
+
result.success = true;
|
|
777
|
+
} catch (error) {
|
|
778
|
+
result.error = error instanceof Error ? error.message : String(error);
|
|
779
|
+
}
|
|
780
|
+
return result;
|
|
781
|
+
}
|
|
782
|
+
async function uninstallHooks(projectPath = process.cwd()) {
|
|
783
|
+
return Promise.all([
|
|
784
|
+
uninstallSingleHook("pre-commit", projectPath),
|
|
785
|
+
uninstallSingleHook("commit-msg", projectPath)
|
|
786
|
+
]);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// src/cli/commands/doctor.ts
|
|
790
|
+
async function doctorCommand(options) {
|
|
594
791
|
console.log(chalk5.bold.cyan("\n\u{1F3E5} Workflow Agent Health Check\n"));
|
|
595
792
|
const config = await loadConfig();
|
|
596
793
|
if (!config) {
|
|
@@ -603,25 +800,72 @@ async function doctorCommand() {
|
|
|
603
800
|
console.log(chalk5.dim(` Scopes: ${config.scopes.length} configured`));
|
|
604
801
|
console.log(chalk5.dim(` Enforcement: ${config.enforcement}`));
|
|
605
802
|
console.log(chalk5.dim(` Language: ${config.language}`));
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
803
|
+
const cwd = process.cwd();
|
|
804
|
+
const guidelinesDir = join3(cwd, "guidelines");
|
|
805
|
+
const mandatoryFiles = getMandatoryTemplateFilenames();
|
|
806
|
+
const missingFiles = [];
|
|
807
|
+
console.log(chalk5.cyan("\n\u{1F4DA} Guidelines Check:\n"));
|
|
808
|
+
for (const filename of mandatoryFiles) {
|
|
809
|
+
const filePath = join3(guidelinesDir, filename);
|
|
810
|
+
if (existsSync3(filePath)) {
|
|
811
|
+
console.log(chalk5.green(`\u2713 ${filename}`));
|
|
812
|
+
} else {
|
|
813
|
+
console.log(chalk5.red(`\u2717 ${filename} (missing)`));
|
|
814
|
+
missingFiles.push(filename);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
if (missingFiles.length === 0) {
|
|
818
|
+
console.log(
|
|
819
|
+
chalk5.green(`
|
|
820
|
+
\u2713 All ${mandatoryFiles.length} mandatory guidelines present`)
|
|
821
|
+
);
|
|
822
|
+
} else {
|
|
823
|
+
console.log(
|
|
824
|
+
chalk5.red(
|
|
825
|
+
`
|
|
826
|
+
\u2717 Missing ${missingFiles.length} mandatory guideline(s)`
|
|
827
|
+
)
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
if (options?.checkGuidelinesOnly) {
|
|
831
|
+
process.exit(missingFiles.length > 0 ? 1 : 0);
|
|
832
|
+
}
|
|
833
|
+
console.log(chalk5.cyan("\n\u{1F517} Git Hooks Check:\n"));
|
|
834
|
+
if (!hasGitRepo(cwd)) {
|
|
835
|
+
console.log(chalk5.yellow("\u26A0 No git repository found"));
|
|
836
|
+
console.log(chalk5.dim(" Run: git init"));
|
|
837
|
+
} else {
|
|
838
|
+
const hooksStatus = getAllHooksStatus(cwd);
|
|
839
|
+
for (const status of hooksStatus) {
|
|
840
|
+
if (status.installed) {
|
|
841
|
+
console.log(chalk5.green(`\u2713 ${status.hookType}: installed`));
|
|
842
|
+
} else {
|
|
843
|
+
console.log(chalk5.yellow(`\u26A0 ${status.hookType}: not installed`));
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
const allInstalled = hooksStatus.every((s) => s.installed);
|
|
847
|
+
if (!allInstalled) {
|
|
848
|
+
console.log(chalk5.dim("\n Run: workflow hooks install"));
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
if (missingFiles.length > 0) {
|
|
852
|
+
process.exit(1);
|
|
853
|
+
}
|
|
610
854
|
}
|
|
611
855
|
|
|
612
856
|
// src/cli/commands/setup.ts
|
|
613
857
|
import * as p3 from "@clack/prompts";
|
|
614
858
|
import chalk6 from "chalk";
|
|
615
|
-
import { readFileSync, writeFileSync, existsSync as
|
|
616
|
-
import { join as
|
|
859
|
+
import { readFileSync, writeFileSync, existsSync as existsSync4 } from "fs";
|
|
860
|
+
import { join as join4, dirname as dirname2 } from "path";
|
|
617
861
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
618
862
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
619
863
|
var __dirname2 = dirname2(__filename2);
|
|
620
864
|
async function setupCommand() {
|
|
621
865
|
p3.intro(chalk6.bgBlue(" workflow-agent setup "));
|
|
622
866
|
const cwd = process.cwd();
|
|
623
|
-
const packageJsonPath =
|
|
624
|
-
if (!
|
|
867
|
+
const packageJsonPath = join4(cwd, "package.json");
|
|
868
|
+
if (!existsSync4(packageJsonPath)) {
|
|
625
869
|
p3.cancel("No package.json found in current directory");
|
|
626
870
|
process.exit(1);
|
|
627
871
|
}
|
|
@@ -686,8 +930,8 @@ async function setupCommand() {
|
|
|
686
930
|
console.log(chalk6.dim("\nRun them with:"));
|
|
687
931
|
console.log(chalk6.dim(" pnpm run workflow:init"));
|
|
688
932
|
console.log(chalk6.dim(" npm run workflow:init\n"));
|
|
689
|
-
const guidelinesDir =
|
|
690
|
-
if (!
|
|
933
|
+
const guidelinesDir = join4(cwd, "guidelines");
|
|
934
|
+
if (!existsSync4(guidelinesDir)) {
|
|
691
935
|
const templatesDir = findTemplatesDirectory(__dirname2);
|
|
692
936
|
if (templatesDir) {
|
|
693
937
|
const templateResult = installMandatoryTemplates(cwd, templatesDir, {
|
|
@@ -705,7 +949,7 @@ async function setupCommand() {
|
|
|
705
949
|
}
|
|
706
950
|
}
|
|
707
951
|
}
|
|
708
|
-
if (
|
|
952
|
+
if (existsSync4(guidelinesDir)) {
|
|
709
953
|
const result = generateCopilotInstructions(cwd, { silent: false });
|
|
710
954
|
if (result.success) {
|
|
711
955
|
const status = result.isNew ? "Generated" : "Updated";
|
|
@@ -724,14 +968,14 @@ async function setupCommand() {
|
|
|
724
968
|
// src/cli/commands/scope-create.ts
|
|
725
969
|
import * as p4 from "@clack/prompts";
|
|
726
970
|
import chalk7 from "chalk";
|
|
727
|
-
import { existsSync as
|
|
728
|
-
import { writeFile as
|
|
729
|
-
import { join as
|
|
971
|
+
import { existsSync as existsSync5 } from "fs";
|
|
972
|
+
import { writeFile as writeFile3, mkdir as mkdir3, readFile as readFile2 } from "fs/promises";
|
|
973
|
+
import { join as join5 } from "path";
|
|
730
974
|
async function scopeCreateCommand(options) {
|
|
731
975
|
console.log(chalk7.bold.cyan("\n\u{1F3A8} Create Custom Scope Package\n"));
|
|
732
976
|
const cwd = process.cwd();
|
|
733
977
|
const isNonInteractive = !!(options.name && options.scopes && options.presetName);
|
|
734
|
-
const isMonorepo2 =
|
|
978
|
+
const isMonorepo2 = existsSync5(join5(cwd, "pnpm-workspace.yaml"));
|
|
735
979
|
if (isMonorepo2) {
|
|
736
980
|
console.log(chalk7.dim("\u2713 Detected monorepo workspace\n"));
|
|
737
981
|
}
|
|
@@ -877,7 +1121,7 @@ async function scopeCreateCommand(options) {
|
|
|
877
1121
|
if (options.outputDir) {
|
|
878
1122
|
outputDir = options.outputDir;
|
|
879
1123
|
} else if (isMonorepo2) {
|
|
880
|
-
outputDir =
|
|
1124
|
+
outputDir = join5(cwd, "packages", `scopes-${packageName}`);
|
|
881
1125
|
} else {
|
|
882
1126
|
const customDir = await p4.text({
|
|
883
1127
|
message: "Output directory:",
|
|
@@ -888,9 +1132,9 @@ async function scopeCreateCommand(options) {
|
|
|
888
1132
|
p4.cancel("Operation cancelled");
|
|
889
1133
|
process.exit(0);
|
|
890
1134
|
}
|
|
891
|
-
outputDir =
|
|
1135
|
+
outputDir = join5(cwd, customDir);
|
|
892
1136
|
}
|
|
893
|
-
if (
|
|
1137
|
+
if (existsSync5(outputDir)) {
|
|
894
1138
|
const shouldOverwrite = await p4.confirm({
|
|
895
1139
|
message: `Directory ${outputDir} already exists. Overwrite?`,
|
|
896
1140
|
initialValue: false
|
|
@@ -903,7 +1147,7 @@ async function scopeCreateCommand(options) {
|
|
|
903
1147
|
const spinner10 = p4.spinner();
|
|
904
1148
|
spinner10.start("Creating package structure...");
|
|
905
1149
|
try {
|
|
906
|
-
await
|
|
1150
|
+
await mkdir3(join5(outputDir, "src"), { recursive: true });
|
|
907
1151
|
const packageJson = {
|
|
908
1152
|
name: `@workflow/scopes-${packageName}`,
|
|
909
1153
|
version: "1.0.0",
|
|
@@ -943,8 +1187,8 @@ async function scopeCreateCommand(options) {
|
|
|
943
1187
|
access: "public"
|
|
944
1188
|
}
|
|
945
1189
|
};
|
|
946
|
-
await
|
|
947
|
-
|
|
1190
|
+
await writeFile3(
|
|
1191
|
+
join5(outputDir, "package.json"),
|
|
948
1192
|
JSON.stringify(packageJson, null, 2),
|
|
949
1193
|
"utf-8"
|
|
950
1194
|
);
|
|
@@ -956,8 +1200,8 @@ async function scopeCreateCommand(options) {
|
|
|
956
1200
|
},
|
|
957
1201
|
include: ["src/**/*"]
|
|
958
1202
|
};
|
|
959
|
-
await
|
|
960
|
-
|
|
1203
|
+
await writeFile3(
|
|
1204
|
+
join5(outputDir, "tsconfig.json"),
|
|
961
1205
|
JSON.stringify(tsconfig, null, 2),
|
|
962
1206
|
"utf-8"
|
|
963
1207
|
);
|
|
@@ -971,7 +1215,7 @@ export default defineConfig({
|
|
|
971
1215
|
sourcemap: true,
|
|
972
1216
|
});
|
|
973
1217
|
`;
|
|
974
|
-
await
|
|
1218
|
+
await writeFile3(join5(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
|
|
975
1219
|
const indexTs = `import type { Scope } from '@hawkinside_out/workflow-agent/config';
|
|
976
1220
|
|
|
977
1221
|
export const scopes: Scope[] = ${JSON.stringify(scopes, null, 2)};
|
|
@@ -985,7 +1229,7 @@ export const preset = {
|
|
|
985
1229
|
|
|
986
1230
|
export default preset;
|
|
987
1231
|
`;
|
|
988
|
-
await
|
|
1232
|
+
await writeFile3(join5(outputDir, "src", "index.ts"), indexTs, "utf-8");
|
|
989
1233
|
if (!options.noTest) {
|
|
990
1234
|
const testFile = `import { describe, it, expect } from 'vitest';
|
|
991
1235
|
import { scopes, preset } from './index.js';
|
|
@@ -1026,16 +1270,16 @@ describe('${presetName} Scope Preset', () => {
|
|
|
1026
1270
|
});
|
|
1027
1271
|
});
|
|
1028
1272
|
`;
|
|
1029
|
-
await
|
|
1030
|
-
|
|
1273
|
+
await writeFile3(
|
|
1274
|
+
join5(outputDir, "src", "index.test.ts"),
|
|
1031
1275
|
testFile,
|
|
1032
1276
|
"utf-8"
|
|
1033
1277
|
);
|
|
1034
1278
|
}
|
|
1035
1279
|
spinner10.stop("\u2713 Package structure created");
|
|
1036
1280
|
if (isMonorepo2) {
|
|
1037
|
-
const workspaceFile =
|
|
1038
|
-
const workspaceContent = await
|
|
1281
|
+
const workspaceFile = join5(cwd, "pnpm-workspace.yaml");
|
|
1282
|
+
const workspaceContent = await readFile2(workspaceFile, "utf-8");
|
|
1039
1283
|
const packagePath = `packages/scopes-${packageName}`;
|
|
1040
1284
|
if (!workspaceContent.includes(packagePath) && !workspaceContent.includes("packages/*")) {
|
|
1041
1285
|
console.log(
|
|
@@ -1093,9 +1337,9 @@ describe('${presetName} Scope Preset', () => {
|
|
|
1093
1337
|
// src/cli/commands/scope-migrate.ts
|
|
1094
1338
|
import * as p5 from "@clack/prompts";
|
|
1095
1339
|
import chalk8 from "chalk";
|
|
1096
|
-
import { existsSync as
|
|
1097
|
-
import { writeFile as
|
|
1098
|
-
import { join as
|
|
1340
|
+
import { existsSync as existsSync6 } from "fs";
|
|
1341
|
+
import { writeFile as writeFile4, mkdir as mkdir4, readFile as readFile3 } from "fs/promises";
|
|
1342
|
+
import { join as join6 } from "path";
|
|
1099
1343
|
async function scopeMigrateCommand(options) {
|
|
1100
1344
|
console.log(chalk8.bold.cyan("\n\u{1F504} Migrate Scopes to Custom Package\n"));
|
|
1101
1345
|
const cwd = process.cwd();
|
|
@@ -1139,7 +1383,7 @@ async function scopeMigrateCommand(options) {
|
|
|
1139
1383
|
p5.cancel("Migration cancelled");
|
|
1140
1384
|
process.exit(0);
|
|
1141
1385
|
}
|
|
1142
|
-
const isMonorepo2 =
|
|
1386
|
+
const isMonorepo2 = existsSync6(join6(cwd, "pnpm-workspace.yaml"));
|
|
1143
1387
|
if (isMonorepo2) {
|
|
1144
1388
|
console.log(chalk8.dim("\n\u2713 Detected monorepo workspace\n"));
|
|
1145
1389
|
}
|
|
@@ -1189,7 +1433,7 @@ async function scopeMigrateCommand(options) {
|
|
|
1189
1433
|
if (options.outputDir) {
|
|
1190
1434
|
outputDir = options.outputDir;
|
|
1191
1435
|
} else if (isMonorepo2) {
|
|
1192
|
-
outputDir =
|
|
1436
|
+
outputDir = join6(cwd, "packages", `scopes-${packageName}`);
|
|
1193
1437
|
} else {
|
|
1194
1438
|
const customDir = await p5.text({
|
|
1195
1439
|
message: "Output directory:",
|
|
@@ -1200,9 +1444,9 @@ async function scopeMigrateCommand(options) {
|
|
|
1200
1444
|
p5.cancel("Migration cancelled");
|
|
1201
1445
|
process.exit(0);
|
|
1202
1446
|
}
|
|
1203
|
-
outputDir =
|
|
1447
|
+
outputDir = join6(cwd, customDir);
|
|
1204
1448
|
}
|
|
1205
|
-
if (
|
|
1449
|
+
if (existsSync6(outputDir)) {
|
|
1206
1450
|
const shouldOverwrite = await p5.confirm({
|
|
1207
1451
|
message: `Directory ${outputDir} already exists. Overwrite?`,
|
|
1208
1452
|
initialValue: false
|
|
@@ -1215,7 +1459,7 @@ async function scopeMigrateCommand(options) {
|
|
|
1215
1459
|
const spinner10 = p5.spinner();
|
|
1216
1460
|
spinner10.start("Migrating scopes to package...");
|
|
1217
1461
|
try {
|
|
1218
|
-
await
|
|
1462
|
+
await mkdir4(join6(outputDir, "src"), { recursive: true });
|
|
1219
1463
|
const packageJson = {
|
|
1220
1464
|
name: `@workflow/scopes-${packageName}`,
|
|
1221
1465
|
version: "1.0.0",
|
|
@@ -1255,8 +1499,8 @@ async function scopeMigrateCommand(options) {
|
|
|
1255
1499
|
access: "public"
|
|
1256
1500
|
}
|
|
1257
1501
|
};
|
|
1258
|
-
await
|
|
1259
|
-
|
|
1502
|
+
await writeFile4(
|
|
1503
|
+
join6(outputDir, "package.json"),
|
|
1260
1504
|
JSON.stringify(packageJson, null, 2),
|
|
1261
1505
|
"utf-8"
|
|
1262
1506
|
);
|
|
@@ -1268,8 +1512,8 @@ async function scopeMigrateCommand(options) {
|
|
|
1268
1512
|
},
|
|
1269
1513
|
include: ["src/**/*"]
|
|
1270
1514
|
};
|
|
1271
|
-
await
|
|
1272
|
-
|
|
1515
|
+
await writeFile4(
|
|
1516
|
+
join6(outputDir, "tsconfig.json"),
|
|
1273
1517
|
JSON.stringify(tsconfig, null, 2),
|
|
1274
1518
|
"utf-8"
|
|
1275
1519
|
);
|
|
@@ -1283,7 +1527,7 @@ export default defineConfig({
|
|
|
1283
1527
|
sourcemap: true,
|
|
1284
1528
|
});
|
|
1285
1529
|
`;
|
|
1286
|
-
await
|
|
1530
|
+
await writeFile4(join6(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
|
|
1287
1531
|
const indexTs = `import type { Scope } from '@hawkinside_out/workflow-agent/config';
|
|
1288
1532
|
|
|
1289
1533
|
export const scopes: Scope[] = ${JSON.stringify(config.scopes, null, 2)};
|
|
@@ -1297,7 +1541,7 @@ export const preset = {
|
|
|
1297
1541
|
|
|
1298
1542
|
export default preset;
|
|
1299
1543
|
`;
|
|
1300
|
-
await
|
|
1544
|
+
await writeFile4(join6(outputDir, "src", "index.ts"), indexTs, "utf-8");
|
|
1301
1545
|
const testFile = `import { describe, it, expect } from 'vitest';
|
|
1302
1546
|
import { scopes, preset } from './index.js';
|
|
1303
1547
|
import { ScopeSchema } from '@hawkinside_out/workflow-agent/config';
|
|
@@ -1340,11 +1584,11 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1340
1584
|
});
|
|
1341
1585
|
});
|
|
1342
1586
|
`;
|
|
1343
|
-
await
|
|
1587
|
+
await writeFile4(join6(outputDir, "src", "index.test.ts"), testFile, "utf-8");
|
|
1344
1588
|
spinner10.stop("\u2713 Package created from migrated scopes");
|
|
1345
1589
|
if (isMonorepo2) {
|
|
1346
|
-
const workspaceFile =
|
|
1347
|
-
const workspaceContent = await
|
|
1590
|
+
const workspaceFile = join6(cwd, "pnpm-workspace.yaml");
|
|
1591
|
+
const workspaceContent = await readFile3(workspaceFile, "utf-8");
|
|
1348
1592
|
const packagePath = `packages/scopes-${packageName}`;
|
|
1349
1593
|
if (!workspaceContent.includes(packagePath) && !workspaceContent.includes("packages/*")) {
|
|
1350
1594
|
console.log(
|
|
@@ -1360,7 +1604,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1360
1604
|
initialValue: false
|
|
1361
1605
|
});
|
|
1362
1606
|
if (!p5.isCancel(keepConfig) && !keepConfig) {
|
|
1363
|
-
const configPath =
|
|
1607
|
+
const configPath = join6(cwd, "workflow.config.json");
|
|
1364
1608
|
const updatedConfig = {
|
|
1365
1609
|
...config,
|
|
1366
1610
|
scopes: [],
|
|
@@ -1368,7 +1612,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1368
1612
|
preset: `scopes-${packageName}`
|
|
1369
1613
|
// Reference the new package
|
|
1370
1614
|
};
|
|
1371
|
-
await
|
|
1615
|
+
await writeFile4(
|
|
1372
1616
|
configPath,
|
|
1373
1617
|
JSON.stringify(updatedConfig, null, 2),
|
|
1374
1618
|
"utf-8"
|
|
@@ -1796,14 +2040,14 @@ function formatAuditReportColored(report) {
|
|
|
1796
2040
|
// src/cli/commands/advisory.ts
|
|
1797
2041
|
import * as p7 from "@clack/prompts";
|
|
1798
2042
|
import chalk11 from "chalk";
|
|
1799
|
-
import { existsSync as
|
|
1800
|
-
import { readFile as
|
|
1801
|
-
import { join as
|
|
2043
|
+
import { existsSync as existsSync8 } from "fs";
|
|
2044
|
+
import { readFile as readFile5, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
2045
|
+
import { join as join8 } from "path";
|
|
1802
2046
|
|
|
1803
2047
|
// src/utils/advisory-analyzer.ts
|
|
1804
|
-
import { existsSync as
|
|
1805
|
-
import { readFile as
|
|
1806
|
-
import { join as
|
|
2048
|
+
import { existsSync as existsSync7 } from "fs";
|
|
2049
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
2050
|
+
import { join as join7 } from "path";
|
|
1807
2051
|
import fg from "fast-glob";
|
|
1808
2052
|
var AdvisoryAnalyzer = class {
|
|
1809
2053
|
options;
|
|
@@ -2247,11 +2491,11 @@ var AdvisoryAnalyzer = class {
|
|
|
2247
2491
|
// Helper Methods
|
|
2248
2492
|
// ============================================================================
|
|
2249
2493
|
async readPackageJson() {
|
|
2250
|
-
const pkgPath =
|
|
2251
|
-
if (!
|
|
2494
|
+
const pkgPath = join7(this.options.cwd, "package.json");
|
|
2495
|
+
if (!existsSync7(pkgPath)) {
|
|
2252
2496
|
throw new Error("package.json not found");
|
|
2253
2497
|
}
|
|
2254
|
-
const content = await
|
|
2498
|
+
const content = await readFile4(pkgPath, "utf-8");
|
|
2255
2499
|
return JSON.parse(content);
|
|
2256
2500
|
}
|
|
2257
2501
|
async countFiles() {
|
|
@@ -3619,11 +3863,11 @@ async function advisoryCommand(options) {
|
|
|
3619
3863
|
let comparisonReport;
|
|
3620
3864
|
let comparator;
|
|
3621
3865
|
if (options.compare) {
|
|
3622
|
-
const comparisonPath = options.compare.endsWith(".json") ?
|
|
3623
|
-
if (
|
|
3866
|
+
const comparisonPath = options.compare.endsWith(".json") ? join8(cwd, options.compare) : join8(cwd, options.compare, "analysis.json");
|
|
3867
|
+
if (existsSync8(comparisonPath)) {
|
|
3624
3868
|
spinner10.start("Comparing with previous report...");
|
|
3625
3869
|
try {
|
|
3626
|
-
const previousContent = await
|
|
3870
|
+
const previousContent = await readFile5(comparisonPath, "utf-8");
|
|
3627
3871
|
const previousAnalysis = JSON.parse(previousContent);
|
|
3628
3872
|
comparator = new ReportComparator(previousAnalysis, analysis);
|
|
3629
3873
|
comparisonReport = comparator.compare();
|
|
@@ -3648,8 +3892,8 @@ async function advisoryCommand(options) {
|
|
|
3648
3892
|
console.log(chalk11.dim("\n--dry-run mode: No files written.\n"));
|
|
3649
3893
|
return;
|
|
3650
3894
|
}
|
|
3651
|
-
const fullOutputDir =
|
|
3652
|
-
await
|
|
3895
|
+
const fullOutputDir = join8(cwd, outputDir);
|
|
3896
|
+
await mkdir5(fullOutputDir, { recursive: true });
|
|
3653
3897
|
spinner10.start("Generating reports...");
|
|
3654
3898
|
try {
|
|
3655
3899
|
const timestamp = options.timestamp ? (/* @__PURE__ */ new Date()).toISOString().split("T")[0] : "";
|
|
@@ -3674,24 +3918,24 @@ async function advisoryCommand(options) {
|
|
|
3674
3918
|
console.log(chalk11.green("\u{1F4DD} Reports written to:"));
|
|
3675
3919
|
const suffix = options.timestamp ? `-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}` : "";
|
|
3676
3920
|
if (options.format === "json") {
|
|
3677
|
-
console.log(chalk11.dim(` ${
|
|
3678
|
-
console.log(chalk11.dim(` ${
|
|
3921
|
+
console.log(chalk11.dim(` ${join8(outputDir, `analysis${suffix}.json`)}`));
|
|
3922
|
+
console.log(chalk11.dim(` ${join8(outputDir, `questions${suffix}.json`)}`));
|
|
3679
3923
|
} else {
|
|
3680
3924
|
console.log(
|
|
3681
|
-
chalk11.dim(` ${
|
|
3925
|
+
chalk11.dim(` ${join8(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`)}`)
|
|
3682
3926
|
);
|
|
3683
3927
|
console.log(
|
|
3684
|
-
chalk11.dim(` ${
|
|
3928
|
+
chalk11.dim(` ${join8(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`)}`)
|
|
3685
3929
|
);
|
|
3686
3930
|
console.log(
|
|
3687
|
-
chalk11.dim(` ${
|
|
3931
|
+
chalk11.dim(` ${join8(outputDir, `STRATEGIC_ROADMAP${suffix}.md`)}`)
|
|
3688
3932
|
);
|
|
3689
3933
|
console.log(
|
|
3690
|
-
chalk11.dim(` ${
|
|
3934
|
+
chalk11.dim(` ${join8(outputDir, `BOARD_QUESTIONS${suffix}.md`)}`)
|
|
3691
3935
|
);
|
|
3692
3936
|
if (comparisonReport) {
|
|
3693
3937
|
console.log(
|
|
3694
|
-
chalk11.dim(` ${
|
|
3938
|
+
chalk11.dim(` ${join8(outputDir, `DIFF_REPORT${suffix}.md`)}`)
|
|
3695
3939
|
);
|
|
3696
3940
|
}
|
|
3697
3941
|
}
|
|
@@ -3784,47 +4028,47 @@ function displayComparisonSummary(comparison) {
|
|
|
3784
4028
|
}
|
|
3785
4029
|
async function writeAnalysisJson(outputDir, analysis, questions, timestamp) {
|
|
3786
4030
|
const suffix = timestamp ? `-${timestamp}` : "";
|
|
3787
|
-
await
|
|
3788
|
-
|
|
4031
|
+
await writeFile5(
|
|
4032
|
+
join8(outputDir, `analysis${suffix}.json`),
|
|
3789
4033
|
JSON.stringify(analysis, null, 2),
|
|
3790
4034
|
"utf-8"
|
|
3791
4035
|
);
|
|
3792
|
-
await
|
|
3793
|
-
|
|
4036
|
+
await writeFile5(
|
|
4037
|
+
join8(outputDir, `questions${suffix}.json`),
|
|
3794
4038
|
JSON.stringify(questions, null, 2),
|
|
3795
4039
|
"utf-8"
|
|
3796
4040
|
);
|
|
3797
4041
|
}
|
|
3798
4042
|
async function writeMarkdownReports(outputDir, analysis, questions, comparator, timestamp) {
|
|
3799
4043
|
const suffix = timestamp ? `-${timestamp}` : "";
|
|
3800
|
-
await
|
|
3801
|
-
|
|
4044
|
+
await writeFile5(
|
|
4045
|
+
join8(outputDir, `analysis.json`),
|
|
3802
4046
|
JSON.stringify(analysis, null, 2),
|
|
3803
4047
|
"utf-8"
|
|
3804
4048
|
);
|
|
3805
|
-
await
|
|
3806
|
-
|
|
4049
|
+
await writeFile5(
|
|
4050
|
+
join8(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`),
|
|
3807
4051
|
generateExecutiveSummary(analysis, questions),
|
|
3808
4052
|
"utf-8"
|
|
3809
4053
|
);
|
|
3810
|
-
await
|
|
3811
|
-
|
|
4054
|
+
await writeFile5(
|
|
4055
|
+
join8(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`),
|
|
3812
4056
|
generateTechnologyAudit(analysis),
|
|
3813
4057
|
"utf-8"
|
|
3814
4058
|
);
|
|
3815
|
-
await
|
|
3816
|
-
|
|
4059
|
+
await writeFile5(
|
|
4060
|
+
join8(outputDir, `STRATEGIC_ROADMAP${suffix}.md`),
|
|
3817
4061
|
generateStrategicRoadmap(analysis, questions),
|
|
3818
4062
|
"utf-8"
|
|
3819
4063
|
);
|
|
3820
|
-
await
|
|
3821
|
-
|
|
4064
|
+
await writeFile5(
|
|
4065
|
+
join8(outputDir, `BOARD_QUESTIONS${suffix}.md`),
|
|
3822
4066
|
generateBoardQuestions(questions),
|
|
3823
4067
|
"utf-8"
|
|
3824
4068
|
);
|
|
3825
4069
|
if (comparator) {
|
|
3826
|
-
await
|
|
3827
|
-
|
|
4070
|
+
await writeFile5(
|
|
4071
|
+
join8(outputDir, `DIFF_REPORT${suffix}.md`),
|
|
3828
4072
|
comparator.generateMarkdownSummary(),
|
|
3829
4073
|
"utf-8"
|
|
3830
4074
|
);
|
|
@@ -4441,20 +4685,20 @@ function checkCIThresholds(analysis, config) {
|
|
|
4441
4685
|
// src/cli/commands/generate-instructions.ts
|
|
4442
4686
|
import * as p8 from "@clack/prompts";
|
|
4443
4687
|
import chalk12 from "chalk";
|
|
4444
|
-
import { existsSync as
|
|
4445
|
-
import { join as
|
|
4688
|
+
import { existsSync as existsSync9 } from "fs";
|
|
4689
|
+
import { join as join9 } from "path";
|
|
4446
4690
|
async function generateInstructionsCommand(options) {
|
|
4447
4691
|
p8.intro(chalk12.bgBlue(" workflow-agent generate-instructions "));
|
|
4448
4692
|
const cwd = process.cwd();
|
|
4449
|
-
const guidelinesDir =
|
|
4450
|
-
const outputPath =
|
|
4451
|
-
if (!
|
|
4693
|
+
const guidelinesDir = join9(cwd, "guidelines");
|
|
4694
|
+
const outputPath = join9(cwd, ".github", "copilot-instructions.md");
|
|
4695
|
+
if (!existsSync9(guidelinesDir)) {
|
|
4452
4696
|
p8.cancel(
|
|
4453
4697
|
"No guidelines directory found. Run 'workflow init' first to generate guidelines."
|
|
4454
4698
|
);
|
|
4455
4699
|
process.exit(1);
|
|
4456
4700
|
}
|
|
4457
|
-
if (
|
|
4701
|
+
if (existsSync9(outputPath) && !options.force) {
|
|
4458
4702
|
const shouldRegenerate = await p8.confirm({
|
|
4459
4703
|
message: ".github/copilot-instructions.md already exists. Regenerate? (Custom content will be preserved)",
|
|
4460
4704
|
initialValue: true
|
|
@@ -4514,8 +4758,8 @@ Reason: ${error instanceof Error ? error.message : String(error)}`
|
|
|
4514
4758
|
// src/cli/commands/update-templates.ts
|
|
4515
4759
|
import * as p9 from "@clack/prompts";
|
|
4516
4760
|
import chalk13 from "chalk";
|
|
4517
|
-
import { existsSync as
|
|
4518
|
-
import { join as
|
|
4761
|
+
import { existsSync as existsSync10 } from "fs";
|
|
4762
|
+
import { join as join10, dirname as dirname3 } from "path";
|
|
4519
4763
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4520
4764
|
var __filename3 = fileURLToPath3(import.meta.url);
|
|
4521
4765
|
var __dirname3 = dirname3(__filename3);
|
|
@@ -4523,13 +4767,13 @@ async function updateTemplatesCommand(options) {
|
|
|
4523
4767
|
const { force = false, skip = false } = options;
|
|
4524
4768
|
p9.intro(chalk13.bgBlue(" workflow-agent update-templates "));
|
|
4525
4769
|
const cwd = process.cwd();
|
|
4526
|
-
const guidelinesDir =
|
|
4770
|
+
const guidelinesDir = join10(cwd, "guidelines");
|
|
4527
4771
|
const templatesDir = findTemplatesDirectory(__dirname3);
|
|
4528
4772
|
if (!templatesDir) {
|
|
4529
4773
|
p9.cancel("Could not find templates directory");
|
|
4530
4774
|
process.exit(1);
|
|
4531
4775
|
}
|
|
4532
|
-
const guidelinesExist =
|
|
4776
|
+
const guidelinesExist = existsSync10(guidelinesDir);
|
|
4533
4777
|
if (!guidelinesExist) {
|
|
4534
4778
|
console.log(chalk13.yellow("\n\u26A0\uFE0F No guidelines directory found."));
|
|
4535
4779
|
console.log(chalk13.dim("Run 'workflow-agent init' to set up guidelines.\n"));
|
|
@@ -4818,8 +5062,124 @@ Fixed: ${fixedCount}, Skipped: ${skippedCount}`)
|
|
|
4818
5062
|
}
|
|
4819
5063
|
}
|
|
4820
5064
|
|
|
4821
|
-
// src/cli/commands/
|
|
5065
|
+
// src/cli/commands/hooks.ts
|
|
4822
5066
|
import chalk15 from "chalk";
|
|
5067
|
+
async function hooksCommand(action) {
|
|
5068
|
+
const cwd = process.cwd();
|
|
5069
|
+
switch (action) {
|
|
5070
|
+
case "install":
|
|
5071
|
+
await installHooksAction(cwd);
|
|
5072
|
+
break;
|
|
5073
|
+
case "uninstall":
|
|
5074
|
+
await uninstallHooksAction(cwd);
|
|
5075
|
+
break;
|
|
5076
|
+
case "status":
|
|
5077
|
+
await statusHooksAction(cwd);
|
|
5078
|
+
break;
|
|
5079
|
+
default:
|
|
5080
|
+
console.error(chalk15.red(`Unknown action: ${action}`));
|
|
5081
|
+
console.log(chalk15.dim("Available actions: install, uninstall, status"));
|
|
5082
|
+
process.exit(1);
|
|
5083
|
+
}
|
|
5084
|
+
}
|
|
5085
|
+
async function installHooksAction(cwd) {
|
|
5086
|
+
console.log(chalk15.bold.cyan("\n\u{1F517} Installing Workflow Agent Git Hooks\n"));
|
|
5087
|
+
if (!hasGitRepo(cwd)) {
|
|
5088
|
+
console.error(chalk15.red("\u2717 No git repository found"));
|
|
5089
|
+
console.log(chalk15.yellow(" Run: git init"));
|
|
5090
|
+
process.exit(1);
|
|
5091
|
+
}
|
|
5092
|
+
const config = await loadConfig();
|
|
5093
|
+
const hooksConfig = config?.hooks;
|
|
5094
|
+
const results = await installHooks(hooksConfig, cwd);
|
|
5095
|
+
let hasErrors = false;
|
|
5096
|
+
for (const result of results) {
|
|
5097
|
+
if (result.success) {
|
|
5098
|
+
if (result.wrappedExisting) {
|
|
5099
|
+
console.log(
|
|
5100
|
+
chalk15.green(
|
|
5101
|
+
`\u2713 Installed ${result.hookType} hook (wrapped existing hook)`
|
|
5102
|
+
)
|
|
5103
|
+
);
|
|
5104
|
+
} else {
|
|
5105
|
+
console.log(chalk15.green(`\u2713 Installed ${result.hookType} hook`));
|
|
5106
|
+
}
|
|
5107
|
+
} else {
|
|
5108
|
+
console.error(
|
|
5109
|
+
chalk15.red(`\u2717 Failed to install ${result.hookType}: ${result.error}`)
|
|
5110
|
+
);
|
|
5111
|
+
hasErrors = true;
|
|
5112
|
+
}
|
|
5113
|
+
}
|
|
5114
|
+
if (!hasErrors) {
|
|
5115
|
+
console.log(chalk15.green("\n\u2713 Git hooks installed successfully"));
|
|
5116
|
+
console.log(chalk15.dim("\nHooks will run automatically on commit."));
|
|
5117
|
+
console.log(chalk15.dim("They will be skipped in CI environments."));
|
|
5118
|
+
} else {
|
|
5119
|
+
process.exit(1);
|
|
5120
|
+
}
|
|
5121
|
+
}
|
|
5122
|
+
async function uninstallHooksAction(cwd) {
|
|
5123
|
+
console.log(chalk15.bold.cyan("\n\u{1F513} Uninstalling Workflow Agent Git Hooks\n"));
|
|
5124
|
+
if (!hasGitRepo(cwd)) {
|
|
5125
|
+
console.error(chalk15.red("\u2717 No git repository found"));
|
|
5126
|
+
process.exit(1);
|
|
5127
|
+
}
|
|
5128
|
+
const results = await uninstallHooks(cwd);
|
|
5129
|
+
let hasErrors = false;
|
|
5130
|
+
for (const result of results) {
|
|
5131
|
+
if (result.success) {
|
|
5132
|
+
if (result.wrappedExisting) {
|
|
5133
|
+
console.log(
|
|
5134
|
+
chalk15.green(`\u2713 Removed ${result.hookType} hook (restored original)`)
|
|
5135
|
+
);
|
|
5136
|
+
} else {
|
|
5137
|
+
console.log(chalk15.green(`\u2713 Removed ${result.hookType} hook`));
|
|
5138
|
+
}
|
|
5139
|
+
} else if (result.error) {
|
|
5140
|
+
console.error(
|
|
5141
|
+
chalk15.red(`\u2717 Failed to remove ${result.hookType}: ${result.error}`)
|
|
5142
|
+
);
|
|
5143
|
+
hasErrors = true;
|
|
5144
|
+
}
|
|
5145
|
+
}
|
|
5146
|
+
if (!hasErrors) {
|
|
5147
|
+
console.log(chalk15.green("\n\u2713 Git hooks uninstalled successfully"));
|
|
5148
|
+
} else {
|
|
5149
|
+
process.exit(1);
|
|
5150
|
+
}
|
|
5151
|
+
}
|
|
5152
|
+
async function statusHooksAction(cwd) {
|
|
5153
|
+
console.log(chalk15.bold.cyan("\n\u{1F4CA} Workflow Agent Git Hooks Status\n"));
|
|
5154
|
+
if (!hasGitRepo(cwd)) {
|
|
5155
|
+
console.error(chalk15.red("\u2717 No git repository found"));
|
|
5156
|
+
process.exit(1);
|
|
5157
|
+
}
|
|
5158
|
+
const statuses = await getAllHooksStatus(cwd);
|
|
5159
|
+
for (const status of statuses) {
|
|
5160
|
+
const icon = status.installed ? "\u2713" : "\u2717";
|
|
5161
|
+
const color = status.installed ? chalk15.green : chalk15.yellow;
|
|
5162
|
+
let message = `${icon} ${status.hookType}`;
|
|
5163
|
+
if (status.installed) {
|
|
5164
|
+
message += " - installed";
|
|
5165
|
+
if (status.wrappedOriginal) {
|
|
5166
|
+
message += " (wrapping original hook)";
|
|
5167
|
+
}
|
|
5168
|
+
} else if (status.hasExistingHook) {
|
|
5169
|
+
message += " - existing hook (not managed by Workflow Agent)";
|
|
5170
|
+
} else {
|
|
5171
|
+
message += " - not installed";
|
|
5172
|
+
}
|
|
5173
|
+
console.log(color(message));
|
|
5174
|
+
}
|
|
5175
|
+
const allInstalled = statuses.every((s) => s.installed);
|
|
5176
|
+
if (!allInstalled) {
|
|
5177
|
+
console.log(chalk15.dim("\nTo install hooks: workflow hooks install"));
|
|
5178
|
+
}
|
|
5179
|
+
}
|
|
5180
|
+
|
|
5181
|
+
// src/cli/commands/learn.ts
|
|
5182
|
+
import chalk16 from "chalk";
|
|
4823
5183
|
import * as p11 from "@clack/prompts";
|
|
4824
5184
|
import {
|
|
4825
5185
|
PatternStore as PatternStore2,
|
|
@@ -4843,7 +5203,7 @@ function formatTags(tags) {
|
|
|
4843
5203
|
async function learnRecordCommand(options) {
|
|
4844
5204
|
const cwd = getWorkspacePath();
|
|
4845
5205
|
const store = new PatternStore2(cwd);
|
|
4846
|
-
console.log(
|
|
5206
|
+
console.log(chalk16.cyan("\n\u{1F4DA} Record a Learning Pattern\n"));
|
|
4847
5207
|
let patternType = options.type;
|
|
4848
5208
|
if (!patternType) {
|
|
4849
5209
|
const typeChoice = await p11.select({
|
|
@@ -5008,14 +5368,14 @@ async function learnRecordCommand(options) {
|
|
|
5008
5368
|
};
|
|
5009
5369
|
const result = await store.saveFixPattern(fixPattern);
|
|
5010
5370
|
if (result.success) {
|
|
5011
|
-
console.log(
|
|
5012
|
-
console.log(
|
|
5013
|
-
console.log(
|
|
5014
|
-
console.log(
|
|
5015
|
-
console.log(
|
|
5371
|
+
console.log(chalk16.green("\n\u2705 Fix pattern recorded successfully!\n"));
|
|
5372
|
+
console.log(chalk16.dim(` ID: ${fixPattern.id}`));
|
|
5373
|
+
console.log(chalk16.dim(` Name: ${name}`));
|
|
5374
|
+
console.log(chalk16.dim(` Category: ${category}`));
|
|
5375
|
+
console.log(chalk16.dim(` Framework: ${framework} ${version}`));
|
|
5016
5376
|
} else {
|
|
5017
|
-
console.log(
|
|
5018
|
-
console.log(
|
|
5377
|
+
console.log(chalk16.red("\n\u274C Failed to record pattern"));
|
|
5378
|
+
console.log(chalk16.dim(` Error: ${result.error}`));
|
|
5019
5379
|
process.exit(1);
|
|
5020
5380
|
}
|
|
5021
5381
|
} else {
|
|
@@ -5062,13 +5422,13 @@ async function learnRecordCommand(options) {
|
|
|
5062
5422
|
};
|
|
5063
5423
|
const result = await store.saveBlueprint(blueprint);
|
|
5064
5424
|
if (result.success) {
|
|
5065
|
-
console.log(
|
|
5066
|
-
console.log(
|
|
5067
|
-
console.log(
|
|
5068
|
-
console.log(
|
|
5425
|
+
console.log(chalk16.green("\n\u2705 Blueprint recorded successfully!\n"));
|
|
5426
|
+
console.log(chalk16.dim(` ID: ${blueprint.id}`));
|
|
5427
|
+
console.log(chalk16.dim(` Name: ${name}`));
|
|
5428
|
+
console.log(chalk16.dim(` Framework: ${framework} ${version}`));
|
|
5069
5429
|
} else {
|
|
5070
|
-
console.log(
|
|
5071
|
-
console.log(
|
|
5430
|
+
console.log(chalk16.red("\n\u274C Failed to record blueprint"));
|
|
5431
|
+
console.log(chalk16.dim(` Error: ${result.error}`));
|
|
5072
5432
|
process.exit(1);
|
|
5073
5433
|
}
|
|
5074
5434
|
}
|
|
@@ -5078,7 +5438,7 @@ async function learnListCommand(options) {
|
|
|
5078
5438
|
const store = new PatternStore2(cwd);
|
|
5079
5439
|
const patternType = options.type ?? "all";
|
|
5080
5440
|
const showDeprecated = options.deprecated ?? false;
|
|
5081
|
-
console.log(
|
|
5441
|
+
console.log(chalk16.cyan("\n\u{1F4DA} Recorded Learning Patterns\n"));
|
|
5082
5442
|
if (patternType === "all" || patternType === "fix") {
|
|
5083
5443
|
const fixResult = await store.listFixPatterns({
|
|
5084
5444
|
tags: options.tag ? [{ category: "framework", name: options.tag }] : void 0,
|
|
@@ -5086,29 +5446,29 @@ async function learnListCommand(options) {
|
|
|
5086
5446
|
includeDeprecated: showDeprecated
|
|
5087
5447
|
});
|
|
5088
5448
|
if (fixResult.success && fixResult.data && fixResult.data.length > 0) {
|
|
5089
|
-
console.log(
|
|
5449
|
+
console.log(chalk16.bold.yellow("\u{1F527} Fix Patterns:\n"));
|
|
5090
5450
|
for (const pattern of fixResult.data) {
|
|
5091
5451
|
const isDeprecated = pattern.deprecatedAt !== void 0;
|
|
5092
5452
|
const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
|
|
5093
|
-
const nameColor = isDeprecated ?
|
|
5453
|
+
const nameColor = isDeprecated ? chalk16.dim : chalk16.white;
|
|
5094
5454
|
console.log(` ${statusIcon} ${nameColor(pattern.name)}`);
|
|
5095
|
-
console.log(
|
|
5096
|
-
console.log(
|
|
5455
|
+
console.log(chalk16.dim(` ID: ${pattern.id}`));
|
|
5456
|
+
console.log(chalk16.dim(` Category: ${pattern.category}`));
|
|
5097
5457
|
console.log(
|
|
5098
|
-
|
|
5458
|
+
chalk16.dim(` Created: ${formatDate(pattern.createdAt)}`)
|
|
5099
5459
|
);
|
|
5100
5460
|
console.log(
|
|
5101
|
-
|
|
5461
|
+
chalk16.dim(
|
|
5102
5462
|
` Success Rate: ${(pattern.metrics.successRate * 100).toFixed(0)}% (${pattern.metrics.successes}/${pattern.metrics.applications})`
|
|
5103
5463
|
)
|
|
5104
5464
|
);
|
|
5105
5465
|
if (pattern.tags.length > 0) {
|
|
5106
|
-
console.log(
|
|
5466
|
+
console.log(chalk16.dim(` Tags: ${formatTags(pattern.tags)}`));
|
|
5107
5467
|
}
|
|
5108
5468
|
console.log("");
|
|
5109
5469
|
}
|
|
5110
5470
|
} else if (patternType === "fix") {
|
|
5111
|
-
console.log(
|
|
5471
|
+
console.log(chalk16.dim(" No fix patterns found.\n"));
|
|
5112
5472
|
}
|
|
5113
5473
|
}
|
|
5114
5474
|
if (patternType === "all" || patternType === "blueprint") {
|
|
@@ -5118,46 +5478,46 @@ async function learnListCommand(options) {
|
|
|
5118
5478
|
includeDeprecated: showDeprecated
|
|
5119
5479
|
});
|
|
5120
5480
|
if (bpResult.success && bpResult.data && bpResult.data.length > 0) {
|
|
5121
|
-
console.log(
|
|
5481
|
+
console.log(chalk16.bold.blue("\u{1F4D0} Blueprints:\n"));
|
|
5122
5482
|
for (const blueprint of bpResult.data) {
|
|
5123
5483
|
const isDeprecated = blueprint.deprecatedAt !== void 0;
|
|
5124
5484
|
const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
|
|
5125
|
-
const nameColor = isDeprecated ?
|
|
5485
|
+
const nameColor = isDeprecated ? chalk16.dim : chalk16.white;
|
|
5126
5486
|
console.log(` ${statusIcon} ${nameColor(blueprint.name)}`);
|
|
5127
|
-
console.log(
|
|
5128
|
-
console.log(
|
|
5487
|
+
console.log(chalk16.dim(` ID: ${blueprint.id}`));
|
|
5488
|
+
console.log(chalk16.dim(` Language: ${blueprint.stack.language}`));
|
|
5129
5489
|
console.log(
|
|
5130
|
-
|
|
5490
|
+
chalk16.dim(` Created: ${formatDate(blueprint.createdAt)}`)
|
|
5131
5491
|
);
|
|
5132
5492
|
console.log(
|
|
5133
|
-
|
|
5493
|
+
chalk16.dim(
|
|
5134
5494
|
` Success Rate: ${(blueprint.metrics.successRate * 100).toFixed(0)}% (${blueprint.metrics.successes}/${blueprint.metrics.applications})`
|
|
5135
5495
|
)
|
|
5136
5496
|
);
|
|
5137
5497
|
if (blueprint.tags.length > 0) {
|
|
5138
|
-
console.log(
|
|
5498
|
+
console.log(chalk16.dim(` Tags: ${formatTags(blueprint.tags)}`));
|
|
5139
5499
|
}
|
|
5140
5500
|
console.log("");
|
|
5141
5501
|
}
|
|
5142
5502
|
} else if (patternType === "blueprint") {
|
|
5143
|
-
console.log(
|
|
5503
|
+
console.log(chalk16.dim(" No blueprints found.\n"));
|
|
5144
5504
|
}
|
|
5145
5505
|
}
|
|
5146
5506
|
const stats = await store.getStats();
|
|
5147
5507
|
const totalPatterns = stats.totalFixes + stats.totalBlueprints;
|
|
5148
5508
|
const totalDeprecated = stats.deprecatedFixes + stats.deprecatedBlueprints;
|
|
5149
|
-
console.log(
|
|
5150
|
-
console.log(
|
|
5151
|
-
console.log(
|
|
5152
|
-
console.log(
|
|
5153
|
-
console.log(
|
|
5509
|
+
console.log(chalk16.dim("\u2501".repeat(40)));
|
|
5510
|
+
console.log(chalk16.dim(`Total: ${totalPatterns} patterns`));
|
|
5511
|
+
console.log(chalk16.dim(` Fix Patterns: ${stats.totalFixes}`));
|
|
5512
|
+
console.log(chalk16.dim(` Blueprints: ${stats.totalBlueprints}`));
|
|
5513
|
+
console.log(chalk16.dim(` Deprecated: ${totalDeprecated}`));
|
|
5154
5514
|
console.log("");
|
|
5155
5515
|
}
|
|
5156
5516
|
async function learnApplyCommand(patternId, options) {
|
|
5157
5517
|
const cwd = getWorkspacePath();
|
|
5158
5518
|
const store = new PatternStore2(cwd);
|
|
5159
5519
|
const telemetry = new TelemetryCollector2(cwd);
|
|
5160
|
-
console.log(
|
|
5520
|
+
console.log(chalk16.cyan("\n\u{1F527} Apply Learning Pattern\n"));
|
|
5161
5521
|
let pattern = await store.getFixPattern(patternId);
|
|
5162
5522
|
let patternType = "fix";
|
|
5163
5523
|
if (!pattern.success || !pattern.data) {
|
|
@@ -5166,21 +5526,21 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5166
5526
|
pattern = bpResult;
|
|
5167
5527
|
patternType = "blueprint";
|
|
5168
5528
|
} else {
|
|
5169
|
-
console.log(
|
|
5529
|
+
console.log(chalk16.red(`
|
|
5170
5530
|
\u274C Pattern not found: ${patternId}`));
|
|
5171
5531
|
console.log(
|
|
5172
|
-
|
|
5532
|
+
chalk16.dim(" Use 'workflow learn:list' to see available patterns")
|
|
5173
5533
|
);
|
|
5174
5534
|
process.exit(1);
|
|
5175
5535
|
}
|
|
5176
5536
|
}
|
|
5177
5537
|
const patternData = pattern.data;
|
|
5178
|
-
console.log(
|
|
5179
|
-
console.log(
|
|
5180
|
-
console.log(
|
|
5538
|
+
console.log(chalk16.white(` Pattern: ${patternData.name}`));
|
|
5539
|
+
console.log(chalk16.dim(` Type: ${patternType}`));
|
|
5540
|
+
console.log(chalk16.dim(` Description: ${patternData.description}`));
|
|
5181
5541
|
if (options.dryRun) {
|
|
5182
5542
|
console.log(
|
|
5183
|
-
|
|
5543
|
+
chalk16.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n")
|
|
5184
5544
|
);
|
|
5185
5545
|
}
|
|
5186
5546
|
const framework = options.framework ?? patternData.compatibility.frameworks[0]?.name ?? "unknown";
|
|
@@ -5188,27 +5548,27 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5188
5548
|
await telemetry.recordApplication(patternId, patternType, framework, version);
|
|
5189
5549
|
if (patternType === "fix") {
|
|
5190
5550
|
const fixPattern = patternData;
|
|
5191
|
-
console.log(
|
|
5551
|
+
console.log(chalk16.cyan("\n\u{1F4CB} Solution Steps:\n"));
|
|
5192
5552
|
if (fixPattern.solution.steps) {
|
|
5193
5553
|
for (let i = 0; i < fixPattern.solution.steps.length; i++) {
|
|
5194
5554
|
const step = fixPattern.solution.steps[i];
|
|
5195
5555
|
console.log(
|
|
5196
|
-
|
|
5556
|
+
chalk16.white(` ${i + 1}. [${step.action}] ${step.description}`)
|
|
5197
5557
|
);
|
|
5198
5558
|
if (step.file) {
|
|
5199
|
-
console.log(
|
|
5559
|
+
console.log(chalk16.dim(` File: ${step.file}`));
|
|
5200
5560
|
}
|
|
5201
5561
|
}
|
|
5202
5562
|
}
|
|
5203
5563
|
} else {
|
|
5204
5564
|
const blueprint = patternData;
|
|
5205
|
-
console.log(
|
|
5565
|
+
console.log(chalk16.cyan("\n\u{1F4CB} Setup Steps:\n"));
|
|
5206
5566
|
if (blueprint.setup.steps) {
|
|
5207
5567
|
for (let i = 0; i < blueprint.setup.steps.length; i++) {
|
|
5208
5568
|
const step = blueprint.setup.steps[i];
|
|
5209
|
-
console.log(
|
|
5569
|
+
console.log(chalk16.white(` ${i + 1}. ${step.description}`));
|
|
5210
5570
|
if (step.command) {
|
|
5211
|
-
console.log(
|
|
5571
|
+
console.log(chalk16.dim(` Command: ${step.command}`));
|
|
5212
5572
|
}
|
|
5213
5573
|
}
|
|
5214
5574
|
}
|
|
@@ -5225,7 +5585,7 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5225
5585
|
if (confirmed) {
|
|
5226
5586
|
await store.updatePatternMetrics(patternId, patternType, true);
|
|
5227
5587
|
await telemetry.recordSuccess(patternId, patternType, framework, version);
|
|
5228
|
-
console.log(
|
|
5588
|
+
console.log(chalk16.green("\n\u2705 Pattern marked as successfully applied!"));
|
|
5229
5589
|
} else {
|
|
5230
5590
|
await store.updatePatternMetrics(patternId, patternType, false);
|
|
5231
5591
|
await telemetry.recordFailure(
|
|
@@ -5236,7 +5596,7 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5236
5596
|
"unknown"
|
|
5237
5597
|
);
|
|
5238
5598
|
console.log(
|
|
5239
|
-
|
|
5599
|
+
chalk16.yellow("\n\u26A0\uFE0F Pattern application marked as unsuccessful.")
|
|
5240
5600
|
);
|
|
5241
5601
|
}
|
|
5242
5602
|
}
|
|
@@ -5244,32 +5604,32 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5244
5604
|
async function learnSyncCommand(options) {
|
|
5245
5605
|
const cwd = getWorkspacePath();
|
|
5246
5606
|
const contributorManager = new ContributorManager2(cwd);
|
|
5247
|
-
console.log(
|
|
5607
|
+
console.log(chalk16.cyan("\n\u{1F504} Sync Learning Patterns\n"));
|
|
5248
5608
|
const config = await contributorManager.getConfig();
|
|
5249
5609
|
if (!config.success || !config.data?.syncOptIn) {
|
|
5250
|
-
console.log(
|
|
5251
|
-
console.log(
|
|
5252
|
-
console.log(
|
|
5610
|
+
console.log(chalk16.yellow("\u26A0\uFE0F Sync is not enabled.\n"));
|
|
5611
|
+
console.log(chalk16.dim(" To enable sync, run:"));
|
|
5612
|
+
console.log(chalk16.dim(" workflow learn:config --enable-sync\n"));
|
|
5253
5613
|
console.log(
|
|
5254
|
-
|
|
5614
|
+
chalk16.dim(
|
|
5255
5615
|
" This allows you to share anonymized patterns with the community."
|
|
5256
5616
|
)
|
|
5257
5617
|
);
|
|
5258
5618
|
process.exit(0);
|
|
5259
5619
|
}
|
|
5260
5620
|
if (options.dryRun) {
|
|
5261
|
-
console.log(
|
|
5621
|
+
console.log(chalk16.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be synced\n"));
|
|
5262
5622
|
}
|
|
5263
5623
|
const store = new PatternStore2(cwd);
|
|
5264
5624
|
const anonymizer = new PatternAnonymizer();
|
|
5265
5625
|
const { fixes, blueprints } = await store.getPatternsForSync();
|
|
5266
5626
|
console.log(
|
|
5267
|
-
|
|
5627
|
+
chalk16.dim(
|
|
5268
5628
|
` Patterns ready to sync: ${fixes.length} fixes, ${blueprints.length} blueprints`
|
|
5269
5629
|
)
|
|
5270
5630
|
);
|
|
5271
5631
|
if (options.push) {
|
|
5272
|
-
console.log(
|
|
5632
|
+
console.log(chalk16.cyan("\n\u{1F4E4} Pushing patterns...\n"));
|
|
5273
5633
|
let anonymizedFixes = 0;
|
|
5274
5634
|
let anonymizedBlueprints = 0;
|
|
5275
5635
|
for (const fix of fixes) {
|
|
@@ -5277,7 +5637,7 @@ async function learnSyncCommand(options) {
|
|
|
5277
5637
|
if (result.success) {
|
|
5278
5638
|
anonymizedFixes++;
|
|
5279
5639
|
if (!options.dryRun) {
|
|
5280
|
-
console.log(
|
|
5640
|
+
console.log(chalk16.dim(` \u2713 Anonymized: ${fix.name}`));
|
|
5281
5641
|
}
|
|
5282
5642
|
}
|
|
5283
5643
|
}
|
|
@@ -5286,73 +5646,73 @@ async function learnSyncCommand(options) {
|
|
|
5286
5646
|
if (result.success) {
|
|
5287
5647
|
anonymizedBlueprints++;
|
|
5288
5648
|
if (!options.dryRun) {
|
|
5289
|
-
console.log(
|
|
5649
|
+
console.log(chalk16.dim(` \u2713 Anonymized: ${bp.name}`));
|
|
5290
5650
|
}
|
|
5291
5651
|
}
|
|
5292
5652
|
}
|
|
5293
5653
|
console.log(
|
|
5294
|
-
|
|
5654
|
+
chalk16.green(
|
|
5295
5655
|
`
|
|
5296
5656
|
\u2705 Ready to push ${anonymizedFixes} fixes and ${anonymizedBlueprints} blueprints`
|
|
5297
5657
|
)
|
|
5298
5658
|
);
|
|
5299
|
-
console.log(
|
|
5659
|
+
console.log(chalk16.dim(" (Registry push not yet implemented)"));
|
|
5300
5660
|
}
|
|
5301
5661
|
if (options.pull) {
|
|
5302
|
-
console.log(
|
|
5303
|
-
console.log(
|
|
5662
|
+
console.log(chalk16.cyan("\n\u{1F4E5} Pulling patterns from registry...\n"));
|
|
5663
|
+
console.log(chalk16.dim(" (Registry pull not yet implemented)"));
|
|
5304
5664
|
}
|
|
5305
5665
|
if (!options.push && !options.pull) {
|
|
5306
5666
|
console.log(
|
|
5307
|
-
|
|
5667
|
+
chalk16.dim(" Specify --push to upload or --pull to download patterns.\n")
|
|
5308
5668
|
);
|
|
5309
5669
|
}
|
|
5310
5670
|
}
|
|
5311
5671
|
async function learnConfigCommand(options) {
|
|
5312
5672
|
const cwd = getWorkspacePath();
|
|
5313
5673
|
const contributorManager = new ContributorManager2(cwd);
|
|
5314
|
-
console.log(
|
|
5674
|
+
console.log(chalk16.cyan("\n\u2699\uFE0F Learning Configuration\n"));
|
|
5315
5675
|
if (options.enableSync) {
|
|
5316
5676
|
const result = await contributorManager.enableSync();
|
|
5317
5677
|
if (result.success) {
|
|
5318
|
-
console.log(
|
|
5678
|
+
console.log(chalk16.green("\u2705 Sync enabled"));
|
|
5319
5679
|
console.log(
|
|
5320
|
-
|
|
5680
|
+
chalk16.dim(" Your patterns will be anonymized before sharing.")
|
|
5321
5681
|
);
|
|
5322
5682
|
} else {
|
|
5323
|
-
console.log(
|
|
5683
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5324
5684
|
}
|
|
5325
5685
|
return;
|
|
5326
5686
|
}
|
|
5327
5687
|
if (options.disableSync) {
|
|
5328
5688
|
const result = await contributorManager.disableSync();
|
|
5329
5689
|
if (result.success) {
|
|
5330
|
-
console.log(
|
|
5690
|
+
console.log(chalk16.green("\u2705 Sync disabled"));
|
|
5331
5691
|
} else {
|
|
5332
|
-
console.log(
|
|
5692
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5333
5693
|
}
|
|
5334
5694
|
return;
|
|
5335
5695
|
}
|
|
5336
5696
|
if (options.enableTelemetry) {
|
|
5337
5697
|
const result = await contributorManager.enableTelemetry();
|
|
5338
5698
|
if (result.success) {
|
|
5339
|
-
console.log(
|
|
5699
|
+
console.log(chalk16.green("\u2705 Telemetry enabled"));
|
|
5340
5700
|
console.log(
|
|
5341
|
-
|
|
5701
|
+
chalk16.dim(
|
|
5342
5702
|
" Anonymous usage data helps improve pattern recommendations."
|
|
5343
5703
|
)
|
|
5344
5704
|
);
|
|
5345
5705
|
} else {
|
|
5346
|
-
console.log(
|
|
5706
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5347
5707
|
}
|
|
5348
5708
|
return;
|
|
5349
5709
|
}
|
|
5350
5710
|
if (options.disableTelemetry) {
|
|
5351
5711
|
const result = await contributorManager.disableTelemetry();
|
|
5352
5712
|
if (result.success) {
|
|
5353
|
-
console.log(
|
|
5713
|
+
console.log(chalk16.green("\u2705 Telemetry disabled"));
|
|
5354
5714
|
} else {
|
|
5355
|
-
console.log(
|
|
5715
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5356
5716
|
}
|
|
5357
5717
|
return;
|
|
5358
5718
|
}
|
|
@@ -5367,36 +5727,36 @@ async function learnConfigCommand(options) {
|
|
|
5367
5727
|
}
|
|
5368
5728
|
const result = await contributorManager.resetId();
|
|
5369
5729
|
if (result.success) {
|
|
5370
|
-
console.log(
|
|
5371
|
-
console.log(
|
|
5730
|
+
console.log(chalk16.green("\u2705 Contributor ID reset"));
|
|
5731
|
+
console.log(chalk16.dim(` New ID: ${result.data?.id}`));
|
|
5372
5732
|
} else {
|
|
5373
|
-
console.log(
|
|
5733
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5374
5734
|
}
|
|
5375
5735
|
return;
|
|
5376
5736
|
}
|
|
5377
5737
|
const config = await contributorManager.getConfig();
|
|
5378
5738
|
if (config.success && config.data) {
|
|
5379
|
-
console.log(
|
|
5380
|
-
console.log(
|
|
5381
|
-
console.log(
|
|
5739
|
+
console.log(chalk16.white(" Current Settings:\n"));
|
|
5740
|
+
console.log(chalk16.dim(` Contributor ID: ${config.data.id}`));
|
|
5741
|
+
console.log(chalk16.dim(` Created: ${formatDate(config.data.createdAt)}`));
|
|
5382
5742
|
console.log(
|
|
5383
|
-
|
|
5743
|
+
chalk16.dim(` Sync Enabled: ${config.data.syncOptIn ? "Yes" : "No"}`)
|
|
5384
5744
|
);
|
|
5385
5745
|
console.log(
|
|
5386
|
-
|
|
5746
|
+
chalk16.dim(
|
|
5387
5747
|
` Telemetry Enabled: ${config.data.telemetryEnabled ? "Yes" : "No"}`
|
|
5388
5748
|
)
|
|
5389
5749
|
);
|
|
5390
5750
|
if (config.data.syncEnabledAt) {
|
|
5391
5751
|
console.log(
|
|
5392
|
-
|
|
5752
|
+
chalk16.dim(
|
|
5393
5753
|
` Sync Enabled At: ${formatDate(config.data.syncEnabledAt)}`
|
|
5394
5754
|
)
|
|
5395
5755
|
);
|
|
5396
5756
|
}
|
|
5397
5757
|
} else {
|
|
5398
5758
|
console.log(
|
|
5399
|
-
|
|
5759
|
+
chalk16.dim(
|
|
5400
5760
|
" No configuration found. Settings will be created on first use.\n"
|
|
5401
5761
|
)
|
|
5402
5762
|
);
|
|
@@ -5405,7 +5765,7 @@ async function learnConfigCommand(options) {
|
|
|
5405
5765
|
async function learnDeprecateCommand(patternId, reason) {
|
|
5406
5766
|
const cwd = getWorkspacePath();
|
|
5407
5767
|
const store = new PatternStore2(cwd);
|
|
5408
|
-
console.log(
|
|
5768
|
+
console.log(chalk16.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
|
|
5409
5769
|
let patternType = "fix";
|
|
5410
5770
|
let pattern = await store.getFixPattern(patternId);
|
|
5411
5771
|
if (!pattern.success || !pattern.data) {
|
|
@@ -5414,13 +5774,13 @@ async function learnDeprecateCommand(patternId, reason) {
|
|
|
5414
5774
|
pattern = bpResult;
|
|
5415
5775
|
patternType = "blueprint";
|
|
5416
5776
|
} else {
|
|
5417
|
-
console.log(
|
|
5777
|
+
console.log(chalk16.red(`
|
|
5418
5778
|
\u274C Pattern not found: ${patternId}`));
|
|
5419
5779
|
process.exit(1);
|
|
5420
5780
|
}
|
|
5421
5781
|
}
|
|
5422
|
-
console.log(
|
|
5423
|
-
console.log(
|
|
5782
|
+
console.log(chalk16.white(` Pattern: ${pattern.data.name}`));
|
|
5783
|
+
console.log(chalk16.dim(` Reason: ${reason}`));
|
|
5424
5784
|
const confirmed = await p11.confirm({
|
|
5425
5785
|
message: "Are you sure you want to deprecate this pattern?",
|
|
5426
5786
|
initialValue: false
|
|
@@ -5431,9 +5791,9 @@ async function learnDeprecateCommand(patternId, reason) {
|
|
|
5431
5791
|
}
|
|
5432
5792
|
const result = await store.deprecatePattern(patternId, patternType, reason);
|
|
5433
5793
|
if (result.success) {
|
|
5434
|
-
console.log(
|
|
5794
|
+
console.log(chalk16.green("\n\u2705 Pattern deprecated successfully"));
|
|
5435
5795
|
} else {
|
|
5436
|
-
console.log(
|
|
5796
|
+
console.log(chalk16.red(`
|
|
5437
5797
|
\u274C Failed: ${result.error}`));
|
|
5438
5798
|
process.exit(1);
|
|
5439
5799
|
}
|
|
@@ -5442,31 +5802,31 @@ async function learnStatsCommand() {
|
|
|
5442
5802
|
const cwd = getWorkspacePath();
|
|
5443
5803
|
const store = new PatternStore2(cwd);
|
|
5444
5804
|
const telemetry = new TelemetryCollector2(cwd);
|
|
5445
|
-
console.log(
|
|
5805
|
+
console.log(chalk16.cyan("\n\u{1F4CA} Learning Statistics\n"));
|
|
5446
5806
|
const storeStats = await store.getStats();
|
|
5447
5807
|
const totalPatterns = storeStats.totalFixes + storeStats.totalBlueprints;
|
|
5448
5808
|
const totalDeprecated = storeStats.deprecatedFixes + storeStats.deprecatedBlueprints;
|
|
5449
|
-
console.log(
|
|
5450
|
-
console.log(
|
|
5451
|
-
console.log(
|
|
5452
|
-
console.log(
|
|
5453
|
-
console.log(
|
|
5809
|
+
console.log(chalk16.bold.white(" Patterns:\n"));
|
|
5810
|
+
console.log(chalk16.dim(` Total: ${totalPatterns}`));
|
|
5811
|
+
console.log(chalk16.dim(` Fix Patterns: ${storeStats.totalFixes}`));
|
|
5812
|
+
console.log(chalk16.dim(` Blueprints: ${storeStats.totalBlueprints}`));
|
|
5813
|
+
console.log(chalk16.dim(` Deprecated: ${totalDeprecated}`));
|
|
5454
5814
|
const telemetryStats = await telemetry.getStats();
|
|
5455
|
-
console.log(
|
|
5456
|
-
console.log(
|
|
5815
|
+
console.log(chalk16.bold.white("\n Telemetry:\n"));
|
|
5816
|
+
console.log(chalk16.dim(` Pending Events: ${telemetryStats.pendingEvents}`));
|
|
5457
5817
|
console.log(
|
|
5458
|
-
|
|
5818
|
+
chalk16.dim(` Total Events Sent: ${telemetryStats.totalEventsSent}`)
|
|
5459
5819
|
);
|
|
5460
5820
|
if (telemetryStats.lastFlushAt) {
|
|
5461
5821
|
console.log(
|
|
5462
|
-
|
|
5822
|
+
chalk16.dim(` Last Flush: ${formatDate(telemetryStats.lastFlushAt)}`)
|
|
5463
5823
|
);
|
|
5464
5824
|
}
|
|
5465
5825
|
console.log("");
|
|
5466
5826
|
}
|
|
5467
5827
|
|
|
5468
5828
|
// src/cli/commands/solution.ts
|
|
5469
|
-
import
|
|
5829
|
+
import chalk17 from "chalk";
|
|
5470
5830
|
import * as p12 from "@clack/prompts";
|
|
5471
5831
|
import * as path2 from "path";
|
|
5472
5832
|
import {
|
|
@@ -5509,7 +5869,7 @@ function truncate(str, maxLen) {
|
|
|
5509
5869
|
async function solutionCaptureCommand(options) {
|
|
5510
5870
|
const cwd = getWorkspacePath2();
|
|
5511
5871
|
const store = new PatternStore3(cwd);
|
|
5512
|
-
console.log(
|
|
5872
|
+
console.log(chalk17.cyan("\n\u{1F4E6} Capture Solution Pattern\n"));
|
|
5513
5873
|
let targetPath = options.path;
|
|
5514
5874
|
if (!targetPath) {
|
|
5515
5875
|
const pathInput = await p12.text({
|
|
@@ -5617,22 +5977,22 @@ async function solutionCaptureCommand(options) {
|
|
|
5617
5977
|
keywords
|
|
5618
5978
|
);
|
|
5619
5979
|
spinner10.stop("Solution analyzed");
|
|
5620
|
-
console.log(
|
|
5621
|
-
console.log(
|
|
5622
|
-
console.log(`${
|
|
5980
|
+
console.log(chalk17.green("\n\u2713 Solution captured successfully!\n"));
|
|
5981
|
+
console.log(chalk17.dim("\u2500".repeat(50)));
|
|
5982
|
+
console.log(`${chalk17.bold("Name:")} ${pattern.name}`);
|
|
5623
5983
|
console.log(
|
|
5624
|
-
`${
|
|
5984
|
+
`${chalk17.bold("Category:")} ${formatCategory(pattern.category)}`
|
|
5625
5985
|
);
|
|
5626
5986
|
console.log(
|
|
5627
|
-
`${
|
|
5987
|
+
`${chalk17.bold("Files:")} ${pattern.implementation.files.length}`
|
|
5628
5988
|
);
|
|
5629
5989
|
console.log(
|
|
5630
|
-
`${
|
|
5990
|
+
`${chalk17.bold("Dependencies:")} ${pattern.implementation.dependencies.length}`
|
|
5631
5991
|
);
|
|
5632
5992
|
console.log(
|
|
5633
|
-
`${
|
|
5993
|
+
`${chalk17.bold("Framework:")} ${pattern.compatibility.framework || "generic"}`
|
|
5634
5994
|
);
|
|
5635
|
-
console.log(
|
|
5995
|
+
console.log(chalk17.dim("\u2500".repeat(50)));
|
|
5636
5996
|
const confirm10 = await p12.confirm({
|
|
5637
5997
|
message: "Save this solution pattern?",
|
|
5638
5998
|
initialValue: true
|
|
@@ -5642,12 +6002,12 @@ async function solutionCaptureCommand(options) {
|
|
|
5642
6002
|
process.exit(0);
|
|
5643
6003
|
}
|
|
5644
6004
|
await store.saveSolution(pattern);
|
|
5645
|
-
console.log(
|
|
6005
|
+
console.log(chalk17.green(`
|
|
5646
6006
|
\u2713 Solution saved with ID: ${pattern.id}
|
|
5647
6007
|
`));
|
|
5648
6008
|
} catch (error) {
|
|
5649
6009
|
spinner10.stop("Analysis failed");
|
|
5650
|
-
console.error(
|
|
6010
|
+
console.error(chalk17.red(`
|
|
5651
6011
|
\u2717 Error: ${error.message}
|
|
5652
6012
|
`));
|
|
5653
6013
|
process.exit(1);
|
|
@@ -5656,7 +6016,7 @@ async function solutionCaptureCommand(options) {
|
|
|
5656
6016
|
async function solutionSearchCommand(query, options) {
|
|
5657
6017
|
const cwd = getWorkspacePath2();
|
|
5658
6018
|
const store = new PatternStore3(cwd);
|
|
5659
|
-
console.log(
|
|
6019
|
+
console.log(chalk17.cyan("\n\u{1F50D} Search Solution Patterns\n"));
|
|
5660
6020
|
const keywords = query.split(/\s+/).filter((k) => k.length > 0);
|
|
5661
6021
|
const result = await store.searchSolutions(keywords, {
|
|
5662
6022
|
category: options.category,
|
|
@@ -5664,39 +6024,39 @@ async function solutionSearchCommand(query, options) {
|
|
|
5664
6024
|
limit: options.limit ?? 10
|
|
5665
6025
|
});
|
|
5666
6026
|
if (!result.success || !result.data) {
|
|
5667
|
-
console.error(
|
|
6027
|
+
console.error(chalk17.red(`
|
|
5668
6028
|
\u2717 Search failed: ${result.error}
|
|
5669
6029
|
`));
|
|
5670
6030
|
return;
|
|
5671
6031
|
}
|
|
5672
6032
|
const solutions = result.data;
|
|
5673
6033
|
if (solutions.length === 0) {
|
|
5674
|
-
console.log(
|
|
5675
|
-
console.log(
|
|
6034
|
+
console.log(chalk17.yellow("No solutions found matching your query.\n"));
|
|
6035
|
+
console.log(chalk17.dim("Try different keywords or fewer filters."));
|
|
5676
6036
|
return;
|
|
5677
6037
|
}
|
|
5678
|
-
console.log(
|
|
6038
|
+
console.log(chalk17.green(`Found ${solutions.length} solution(s):
|
|
5679
6039
|
`));
|
|
5680
|
-
console.log(
|
|
6040
|
+
console.log(chalk17.dim("\u2500".repeat(70)));
|
|
5681
6041
|
for (const solution of solutions) {
|
|
5682
6042
|
console.log(
|
|
5683
|
-
`${
|
|
6043
|
+
`${chalk17.bold(solution.name)} ${chalk17.dim(`(${solution.id.slice(0, 8)})`)}`
|
|
5684
6044
|
);
|
|
5685
6045
|
console.log(` ${formatCategory(solution.category)}`);
|
|
5686
|
-
console.log(` ${
|
|
6046
|
+
console.log(` ${chalk17.dim(truncate(solution.description, 60))}`);
|
|
5687
6047
|
console.log(
|
|
5688
6048
|
` Files: ${solution.implementation.files.length} | Framework: ${solution.compatibility.framework || "generic"} | Uses: ${solution.metrics.applications}`
|
|
5689
6049
|
);
|
|
5690
|
-
console.log(
|
|
6050
|
+
console.log(chalk17.dim("\u2500".repeat(70)));
|
|
5691
6051
|
}
|
|
5692
6052
|
console.log(
|
|
5693
|
-
|
|
6053
|
+
chalk17.dim("\nUse 'workflow solution:apply <id>' to apply a solution.")
|
|
5694
6054
|
);
|
|
5695
6055
|
}
|
|
5696
6056
|
async function solutionListCommand(options) {
|
|
5697
6057
|
const cwd = getWorkspacePath2();
|
|
5698
6058
|
const store = new PatternStore3(cwd);
|
|
5699
|
-
console.log(
|
|
6059
|
+
console.log(chalk17.cyan("\n\u{1F4CB} Solution Patterns\n"));
|
|
5700
6060
|
const result = await store.listSolutions({
|
|
5701
6061
|
category: options.category,
|
|
5702
6062
|
framework: options.framework,
|
|
@@ -5704,20 +6064,20 @@ async function solutionListCommand(options) {
|
|
|
5704
6064
|
limit: options.limit ?? 20
|
|
5705
6065
|
});
|
|
5706
6066
|
if (!result.success || !result.data) {
|
|
5707
|
-
console.error(
|
|
6067
|
+
console.error(chalk17.red(`
|
|
5708
6068
|
\u2717 List failed: ${result.error}
|
|
5709
6069
|
`));
|
|
5710
6070
|
return;
|
|
5711
6071
|
}
|
|
5712
6072
|
const solutions = result.data;
|
|
5713
6073
|
if (solutions.length === 0) {
|
|
5714
|
-
console.log(
|
|
6074
|
+
console.log(chalk17.yellow("No solutions found.\n"));
|
|
5715
6075
|
console.log(
|
|
5716
|
-
|
|
6076
|
+
chalk17.dim("Use 'workflow solution:capture' to capture a solution.")
|
|
5717
6077
|
);
|
|
5718
6078
|
return;
|
|
5719
6079
|
}
|
|
5720
|
-
console.log(
|
|
6080
|
+
console.log(chalk17.green(`${solutions.length} solution(s):
|
|
5721
6081
|
`));
|
|
5722
6082
|
const byCategory = /* @__PURE__ */ new Map();
|
|
5723
6083
|
for (const solution of solutions) {
|
|
@@ -5726,24 +6086,24 @@ async function solutionListCommand(options) {
|
|
|
5726
6086
|
byCategory.set(solution.category, list);
|
|
5727
6087
|
}
|
|
5728
6088
|
for (const [category, items] of byCategory) {
|
|
5729
|
-
console.log(
|
|
6089
|
+
console.log(chalk17.bold(`
|
|
5730
6090
|
${formatCategory(category)}`));
|
|
5731
|
-
console.log(
|
|
6091
|
+
console.log(chalk17.dim("\u2500".repeat(50)));
|
|
5732
6092
|
for (const solution of items) {
|
|
5733
|
-
const deprecated = solution.deprecatedAt ?
|
|
6093
|
+
const deprecated = solution.deprecatedAt ? chalk17.red(" [DEPRECATED]") : "";
|
|
5734
6094
|
console.log(
|
|
5735
|
-
` ${
|
|
6095
|
+
` ${chalk17.cyan(solution.id.slice(0, 8))} ${solution.name}${deprecated}`
|
|
5736
6096
|
);
|
|
5737
|
-
console.log(` ${
|
|
6097
|
+
console.log(` ${chalk17.dim(truncate(solution.description, 50))}`);
|
|
5738
6098
|
console.log(
|
|
5739
|
-
|
|
6099
|
+
chalk17.dim(
|
|
5740
6100
|
` Created: ${formatDate2(solution.createdAt)} | Files: ${solution.implementation.files.length}`
|
|
5741
6101
|
)
|
|
5742
6102
|
);
|
|
5743
6103
|
}
|
|
5744
6104
|
}
|
|
5745
6105
|
console.log(
|
|
5746
|
-
|
|
6106
|
+
chalk17.dim(
|
|
5747
6107
|
"\nUse 'workflow solution:search <query>' to find specific solutions."
|
|
5748
6108
|
)
|
|
5749
6109
|
);
|
|
@@ -5751,10 +6111,10 @@ ${formatCategory(category)}`));
|
|
|
5751
6111
|
async function solutionApplyCommand(solutionId, options) {
|
|
5752
6112
|
const cwd = getWorkspacePath2();
|
|
5753
6113
|
const store = new PatternStore3(cwd);
|
|
5754
|
-
console.log(
|
|
6114
|
+
console.log(chalk17.cyan("\n\u{1F680} Apply Solution Pattern\n"));
|
|
5755
6115
|
const result = await store.getSolution(solutionId);
|
|
5756
6116
|
if (!result.success || !result.data) {
|
|
5757
|
-
console.error(
|
|
6117
|
+
console.error(chalk17.red(`
|
|
5758
6118
|
\u2717 Solution not found: ${solutionId}
|
|
5759
6119
|
`));
|
|
5760
6120
|
process.exit(1);
|
|
@@ -5762,7 +6122,7 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5762
6122
|
const solution = result.data;
|
|
5763
6123
|
if (solution.deprecatedAt) {
|
|
5764
6124
|
console.log(
|
|
5765
|
-
|
|
6125
|
+
chalk17.yellow(
|
|
5766
6126
|
`\u26A0\uFE0F This solution is deprecated: ${solution.deprecationReason || "No reason provided"}
|
|
5767
6127
|
`
|
|
5768
6128
|
)
|
|
@@ -5776,34 +6136,34 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5776
6136
|
process.exit(0);
|
|
5777
6137
|
}
|
|
5778
6138
|
}
|
|
5779
|
-
console.log(
|
|
5780
|
-
console.log(
|
|
6139
|
+
console.log(chalk17.bold(`Solution: ${solution.name}`));
|
|
6140
|
+
console.log(chalk17.dim(solution.description));
|
|
5781
6141
|
console.log();
|
|
5782
|
-
console.log(
|
|
6142
|
+
console.log(chalk17.bold("Files to create:"));
|
|
5783
6143
|
const filesToApply = options.includeTests ? solution.implementation.files : solution.implementation.files.filter(
|
|
5784
6144
|
(f) => f.role !== "test"
|
|
5785
6145
|
);
|
|
5786
6146
|
for (const file of filesToApply) {
|
|
5787
|
-
console.log(
|
|
6147
|
+
console.log(chalk17.dim(` \u2022 ${file.path} (${file.role})`));
|
|
5788
6148
|
}
|
|
5789
6149
|
console.log();
|
|
5790
6150
|
if (solution.implementation.dependencies.length > 0) {
|
|
5791
|
-
console.log(
|
|
6151
|
+
console.log(chalk17.bold("Dependencies to install:"));
|
|
5792
6152
|
for (const dep of solution.implementation.dependencies) {
|
|
5793
|
-
console.log(
|
|
6153
|
+
console.log(chalk17.dim(` \u2022 ${dep.name}@${dep.version}`));
|
|
5794
6154
|
}
|
|
5795
6155
|
console.log();
|
|
5796
6156
|
}
|
|
5797
6157
|
if (solution.implementation.envVars.length > 0) {
|
|
5798
|
-
console.log(
|
|
6158
|
+
console.log(chalk17.bold("Environment variables needed:"));
|
|
5799
6159
|
for (const env of solution.implementation.envVars) {
|
|
5800
|
-
const required = env.required ?
|
|
5801
|
-
console.log(
|
|
6160
|
+
const required = env.required ? chalk17.red("*") : "";
|
|
6161
|
+
console.log(chalk17.dim(` \u2022 ${env.name}${required}`));
|
|
5802
6162
|
}
|
|
5803
6163
|
console.log();
|
|
5804
6164
|
}
|
|
5805
6165
|
if (options.dryRun) {
|
|
5806
|
-
console.log(
|
|
6166
|
+
console.log(chalk17.yellow("Dry run mode - no files were created.\n"));
|
|
5807
6167
|
return;
|
|
5808
6168
|
}
|
|
5809
6169
|
const confirm10 = await p12.confirm({
|
|
@@ -5828,19 +6188,19 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5828
6188
|
}
|
|
5829
6189
|
await store.updateSolutionMetrics(solution.id, true);
|
|
5830
6190
|
spinner10.stop("Solution applied");
|
|
5831
|
-
console.log(
|
|
6191
|
+
console.log(chalk17.green(`
|
|
5832
6192
|
\u2713 Solution applied successfully!
|
|
5833
6193
|
`));
|
|
5834
|
-
console.log(
|
|
6194
|
+
console.log(chalk17.dim(`Created ${filesToApply.length} file(s).`));
|
|
5835
6195
|
if (solution.implementation.dependencies.length > 0) {
|
|
5836
|
-
console.log(
|
|
6196
|
+
console.log(chalk17.cyan("\nNext step: Install dependencies with:"));
|
|
5837
6197
|
const deps = solution.implementation.dependencies.map((d) => `${d.name}@${d.version}`).join(" ");
|
|
5838
|
-
console.log(
|
|
6198
|
+
console.log(chalk17.dim(` npm install ${deps}`));
|
|
5839
6199
|
}
|
|
5840
6200
|
} catch (error) {
|
|
5841
6201
|
spinner10.stop("Application failed");
|
|
5842
6202
|
await store.updateSolutionMetrics(solution.id, false);
|
|
5843
|
-
console.error(
|
|
6203
|
+
console.error(chalk17.red(`
|
|
5844
6204
|
\u2717 Error: ${error.message}
|
|
5845
6205
|
`));
|
|
5846
6206
|
process.exit(1);
|
|
@@ -5849,16 +6209,16 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5849
6209
|
async function solutionDeprecateCommand(solutionId, reason) {
|
|
5850
6210
|
const cwd = getWorkspacePath2();
|
|
5851
6211
|
const store = new PatternStore3(cwd);
|
|
5852
|
-
console.log(
|
|
6212
|
+
console.log(chalk17.cyan("\n\u26A0\uFE0F Deprecate Solution Pattern\n"));
|
|
5853
6213
|
const result = await store.getSolution(solutionId);
|
|
5854
6214
|
if (!result.success || !result.data) {
|
|
5855
|
-
console.error(
|
|
6215
|
+
console.error(chalk17.red(`
|
|
5856
6216
|
\u2717 Solution not found: ${solutionId}
|
|
5857
6217
|
`));
|
|
5858
6218
|
process.exit(1);
|
|
5859
6219
|
}
|
|
5860
6220
|
const solution = result.data;
|
|
5861
|
-
console.log(`Solution: ${
|
|
6221
|
+
console.log(`Solution: ${chalk17.bold(solution.name)}`);
|
|
5862
6222
|
console.log(`Reason: ${reason}
|
|
5863
6223
|
`);
|
|
5864
6224
|
const confirm10 = await p12.confirm({
|
|
@@ -5870,27 +6230,27 @@ async function solutionDeprecateCommand(solutionId, reason) {
|
|
|
5870
6230
|
process.exit(0);
|
|
5871
6231
|
}
|
|
5872
6232
|
await store.deprecateSolution(solutionId, reason);
|
|
5873
|
-
console.log(
|
|
6233
|
+
console.log(chalk17.green(`
|
|
5874
6234
|
\u2713 Solution deprecated.
|
|
5875
6235
|
`));
|
|
5876
6236
|
}
|
|
5877
6237
|
async function solutionStatsCommand() {
|
|
5878
6238
|
const cwd = getWorkspacePath2();
|
|
5879
6239
|
const store = new PatternStore3(cwd);
|
|
5880
|
-
console.log(
|
|
6240
|
+
console.log(chalk17.cyan("\n\u{1F4CA} Solution Pattern Statistics\n"));
|
|
5881
6241
|
const stats = await store.getStats();
|
|
5882
|
-
console.log(
|
|
5883
|
-
console.log(`${
|
|
6242
|
+
console.log(chalk17.dim("\u2500".repeat(40)));
|
|
6243
|
+
console.log(`${chalk17.bold("Solutions:")} ${stats.totalSolutions}`);
|
|
5884
6244
|
console.log(` Active: ${stats.totalSolutions - stats.deprecatedSolutions}`);
|
|
5885
6245
|
console.log(` Deprecated: ${stats.deprecatedSolutions}`);
|
|
5886
6246
|
console.log(` Private: ${stats.privateSolutions}`);
|
|
5887
6247
|
console.log(` Synced: ${stats.syncedSolutions}`);
|
|
5888
|
-
console.log(
|
|
5889
|
-
console.log(`${
|
|
5890
|
-
console.log(`${
|
|
5891
|
-
console.log(
|
|
6248
|
+
console.log(chalk17.dim("\u2500".repeat(40)));
|
|
6249
|
+
console.log(`${chalk17.bold("Fixes:")} ${stats.totalFixes}`);
|
|
6250
|
+
console.log(`${chalk17.bold("Blueprints:")} ${stats.totalBlueprints}`);
|
|
6251
|
+
console.log(chalk17.dim("\u2500".repeat(40)));
|
|
5892
6252
|
console.log(`
|
|
5893
|
-
${
|
|
6253
|
+
${chalk17.bold("By Category:")}`);
|
|
5894
6254
|
const listResult = await store.listSolutions({ limit: 1e3 });
|
|
5895
6255
|
if (listResult.success && listResult.data) {
|
|
5896
6256
|
const categories = /* @__PURE__ */ new Map();
|
|
@@ -5926,7 +6286,8 @@ program.command("suggest").description("Submit an improvement suggestion").argum
|
|
|
5926
6286
|
"Category: feature, bug, documentation, performance, other"
|
|
5927
6287
|
).action(suggestCommand);
|
|
5928
6288
|
program.command("setup").description("Add workflow scripts to package.json").action(setupCommand);
|
|
5929
|
-
program.command("doctor").description("Run health check and get optimization suggestions").action(doctorCommand);
|
|
6289
|
+
program.command("doctor").description("Run health check and get optimization suggestions").option("--check-guidelines-only", "Only check guidelines presence").action(doctorCommand);
|
|
6290
|
+
program.command("hooks <action>").description("Manage git hooks").action(hooksCommand);
|
|
5930
6291
|
program.command("scope:create").description("Create a custom scope package").option("--name <name>", 'Package name (e.g., "fintech", "gaming")').option(
|
|
5931
6292
|
"--scopes <scopes>",
|
|
5932
6293
|
"Comma-separated scopes (format: name:description:emoji:category)"
|