workflow-agent-cli 2.9.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto-fix-7WAESKYO.js +13 -0
- package/dist/auto-fix-7WAESKYO.js.map +1 -0
- package/dist/chunk-UWJ2ZGEI.js +98 -0
- package/dist/chunk-UWJ2ZGEI.js.map +1 -0
- package/dist/chunk-YELUGXOM.js +335 -0
- package/dist/chunk-YELUGXOM.js.map +1 -0
- package/dist/{chunk-Y5N3JJTU.js → chunk-YEOQZ7XC.js} +3 -3
- package/dist/cli/index.js +702 -274
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +46 -4
- package/dist/config/index.js +16 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +16 -4
- package/dist/scripts/postinstall.js +1 -1
- package/dist/validators/index.d.ts +1 -1
- package/package.json +2 -1
- package/dist/chunk-DEAF7P4L.js +0 -199
- package/dist/chunk-DEAF7P4L.js.map +0 -1
- 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
|
@@ -19,8 +19,8 @@ import {
|
|
|
19
19
|
import {
|
|
20
20
|
hasConfig,
|
|
21
21
|
loadConfig,
|
|
22
|
-
|
|
23
|
-
} from "../chunk-
|
|
22
|
+
loadConfigSafe
|
|
23
|
+
} from "../chunk-UWJ2ZGEI.js";
|
|
24
24
|
import {
|
|
25
25
|
SCRIPT_CATEGORIES,
|
|
26
26
|
TOTAL_SCRIPTS,
|
|
@@ -31,7 +31,11 @@ import {
|
|
|
31
31
|
installMandatoryTemplates,
|
|
32
32
|
templateMetadata,
|
|
33
33
|
updateTemplates
|
|
34
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-YEOQZ7XC.js";
|
|
35
|
+
import {
|
|
36
|
+
autoFixConfigFile,
|
|
37
|
+
validateScopeDefinitions
|
|
38
|
+
} from "../chunk-YELUGXOM.js";
|
|
35
39
|
|
|
36
40
|
// src/cli/index.ts
|
|
37
41
|
import { Command } from "commander";
|
|
@@ -359,11 +363,11 @@ async function initCommand(options) {
|
|
|
359
363
|
if (!existsSync(workflowDir)) {
|
|
360
364
|
await mkdir(workflowDir, { recursive: true });
|
|
361
365
|
}
|
|
362
|
-
const shouldGenerateGuidelines = await p.confirm({
|
|
366
|
+
const shouldGenerateGuidelines = options.yes || isNonInteractive ? true : await p.confirm({
|
|
363
367
|
message: "Generate workflow guidelines from templates?",
|
|
364
368
|
initialValue: true
|
|
365
369
|
});
|
|
366
|
-
if (p.isCancel(shouldGenerateGuidelines)) {
|
|
370
|
+
if (!isNonInteractive && p.isCancel(shouldGenerateGuidelines)) {
|
|
367
371
|
p.cancel("Initialization cancelled");
|
|
368
372
|
process.exit(0);
|
|
369
373
|
}
|
|
@@ -403,11 +407,11 @@ Reason: ${error instanceof Error ? error.message : String(error)}`
|
|
|
403
407
|
);
|
|
404
408
|
}
|
|
405
409
|
}
|
|
406
|
-
const shouldAutoSetup = options.yes ? true : await p.confirm({
|
|
410
|
+
const shouldAutoSetup = options.yes || isNonInteractive ? true : await p.confirm({
|
|
407
411
|
message: "Set up linting, formatting, testing, and CI automatically?",
|
|
408
412
|
initialValue: true
|
|
409
413
|
});
|
|
410
|
-
if (p.isCancel(shouldAutoSetup)) {
|
|
414
|
+
if (!isNonInteractive && p.isCancel(shouldAutoSetup)) {
|
|
411
415
|
p.cancel("Initialization cancelled");
|
|
412
416
|
process.exit(0);
|
|
413
417
|
}
|
|
@@ -590,38 +594,318 @@ async function suggestCommand(feedback, options = {}) {
|
|
|
590
594
|
|
|
591
595
|
// src/cli/commands/doctor.ts
|
|
592
596
|
import chalk5 from "chalk";
|
|
593
|
-
|
|
597
|
+
import { existsSync as existsSync3 } from "fs";
|
|
598
|
+
import { join as join3 } from "path";
|
|
599
|
+
|
|
600
|
+
// src/utils/hooks.ts
|
|
601
|
+
import { existsSync as existsSync2 } from "fs";
|
|
602
|
+
import { readFile, writeFile as writeFile2, unlink, chmod, rename, mkdir as mkdir2 } from "fs/promises";
|
|
603
|
+
import { join as join2 } from "path";
|
|
604
|
+
function getGitHooksDir(projectPath = process.cwd()) {
|
|
605
|
+
return join2(projectPath, ".git", "hooks");
|
|
606
|
+
}
|
|
607
|
+
function hasGitRepo(projectPath = process.cwd()) {
|
|
608
|
+
return existsSync2(join2(projectPath, ".git"));
|
|
609
|
+
}
|
|
610
|
+
function generatePreCommitHook(config) {
|
|
611
|
+
const checks = config?.preCommit || ["validate-branch", "check-guidelines"];
|
|
612
|
+
const checkCommands = checks.map((check) => {
|
|
613
|
+
switch (check) {
|
|
614
|
+
case "validate-branch":
|
|
615
|
+
return " workflow validate branch";
|
|
616
|
+
case "validate-commit":
|
|
617
|
+
return " workflow validate commit";
|
|
618
|
+
case "check-guidelines":
|
|
619
|
+
return " workflow doctor --check-guidelines-only 2>/dev/null || true";
|
|
620
|
+
case "validate-scopes":
|
|
621
|
+
return " workflow config validate";
|
|
622
|
+
default:
|
|
623
|
+
return "";
|
|
624
|
+
}
|
|
625
|
+
}).filter(Boolean).join("\n");
|
|
626
|
+
return `#!/bin/sh
|
|
627
|
+
# Workflow Agent pre-commit hook
|
|
628
|
+
# Auto-generated - do not edit manually
|
|
629
|
+
# To reinstall: workflow hooks install
|
|
630
|
+
# To uninstall: workflow hooks uninstall
|
|
631
|
+
|
|
632
|
+
# Skip in CI environment
|
|
633
|
+
if [ -n "\${CI:-}" ] || [ -n "\${GITHUB_ACTIONS:-}" ] || [ -n "\${GITLAB_CI:-}" ]; then
|
|
634
|
+
exit 0
|
|
635
|
+
fi
|
|
636
|
+
|
|
637
|
+
# Run workflow checks
|
|
638
|
+
${checkCommands}
|
|
639
|
+
|
|
640
|
+
# Run original hook if it exists
|
|
641
|
+
if [ -f ".git/hooks/pre-commit.original" ]; then
|
|
642
|
+
.git/hooks/pre-commit.original "$@"
|
|
643
|
+
fi
|
|
644
|
+
`;
|
|
645
|
+
}
|
|
646
|
+
function generateCommitMsgHook(config) {
|
|
647
|
+
const checks = config?.commitMsg || ["validate-commit"];
|
|
648
|
+
const checkCommands = checks.map((check) => {
|
|
649
|
+
switch (check) {
|
|
650
|
+
case "validate-commit":
|
|
651
|
+
return ' workflow validate commit "$(cat "$1")"';
|
|
652
|
+
default:
|
|
653
|
+
return "";
|
|
654
|
+
}
|
|
655
|
+
}).filter(Boolean).join("\n");
|
|
656
|
+
return `#!/bin/sh
|
|
657
|
+
# Workflow Agent commit-msg hook
|
|
658
|
+
# Auto-generated - do not edit manually
|
|
659
|
+
# To reinstall: workflow hooks install
|
|
660
|
+
# To uninstall: workflow hooks uninstall
|
|
661
|
+
|
|
662
|
+
# Skip in CI environment
|
|
663
|
+
if [ -n "\${CI:-}" ] || [ -n "\${GITHUB_ACTIONS:-}" ] || [ -n "\${GITLAB_CI:-}" ]; then
|
|
664
|
+
exit 0
|
|
665
|
+
fi
|
|
666
|
+
|
|
667
|
+
# Run workflow checks
|
|
668
|
+
${checkCommands}
|
|
669
|
+
|
|
670
|
+
# Run original hook if it exists
|
|
671
|
+
if [ -f ".git/hooks/commit-msg.original" ]; then
|
|
672
|
+
.git/hooks/commit-msg.original "$@"
|
|
673
|
+
fi
|
|
674
|
+
`;
|
|
675
|
+
}
|
|
676
|
+
async function isWorkflowHook(hookPath) {
|
|
677
|
+
try {
|
|
678
|
+
const content = await readFile(hookPath, "utf-8");
|
|
679
|
+
return content.includes("Workflow Agent") && content.includes("Auto-generated");
|
|
680
|
+
} catch {
|
|
681
|
+
return false;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
async function getHookStatus(hookType, projectPath = process.cwd()) {
|
|
685
|
+
const hooksDir = getGitHooksDir(projectPath);
|
|
686
|
+
const hookPath = join2(hooksDir, hookType);
|
|
687
|
+
const originalPath = join2(hooksDir, `${hookType}.original`);
|
|
688
|
+
const status = {
|
|
689
|
+
installed: false,
|
|
690
|
+
hookType,
|
|
691
|
+
hasExistingHook: false,
|
|
692
|
+
wrappedOriginal: false
|
|
693
|
+
};
|
|
694
|
+
if (!existsSync2(hookPath)) {
|
|
695
|
+
return status;
|
|
696
|
+
}
|
|
697
|
+
status.hasExistingHook = true;
|
|
698
|
+
if (await isWorkflowHook(hookPath)) {
|
|
699
|
+
status.installed = true;
|
|
700
|
+
status.wrappedOriginal = existsSync2(originalPath);
|
|
701
|
+
}
|
|
702
|
+
return status;
|
|
703
|
+
}
|
|
704
|
+
async function getAllHooksStatus(projectPath = process.cwd()) {
|
|
705
|
+
return Promise.all([
|
|
706
|
+
getHookStatus("pre-commit", projectPath),
|
|
707
|
+
getHookStatus("commit-msg", projectPath)
|
|
708
|
+
]);
|
|
709
|
+
}
|
|
710
|
+
async function installSingleHook(hookType, config, projectPath = process.cwd()) {
|
|
711
|
+
const hooksDir = getGitHooksDir(projectPath);
|
|
712
|
+
const hookPath = join2(hooksDir, hookType);
|
|
713
|
+
const originalPath = join2(hooksDir, `${hookType}.original`);
|
|
714
|
+
const result = {
|
|
715
|
+
success: false,
|
|
716
|
+
hookType,
|
|
717
|
+
wrappedExisting: false
|
|
718
|
+
};
|
|
719
|
+
try {
|
|
720
|
+
if (!existsSync2(hooksDir)) {
|
|
721
|
+
await mkdir2(hooksDir, { recursive: true });
|
|
722
|
+
}
|
|
723
|
+
if (existsSync2(hookPath)) {
|
|
724
|
+
const isOurs = await isWorkflowHook(hookPath);
|
|
725
|
+
if (!isOurs) {
|
|
726
|
+
await rename(hookPath, originalPath);
|
|
727
|
+
result.wrappedExisting = true;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
const hookContent = hookType === "pre-commit" ? generatePreCommitHook(config) : generateCommitMsgHook(config);
|
|
731
|
+
await writeFile2(hookPath, hookContent, "utf-8");
|
|
732
|
+
await chmod(hookPath, 493);
|
|
733
|
+
result.success = true;
|
|
734
|
+
} catch (error) {
|
|
735
|
+
result.error = error instanceof Error ? error.message : String(error);
|
|
736
|
+
}
|
|
737
|
+
return result;
|
|
738
|
+
}
|
|
739
|
+
async function installHooks(config, projectPath = process.cwd()) {
|
|
740
|
+
if (!hasGitRepo(projectPath)) {
|
|
741
|
+
return [
|
|
742
|
+
{
|
|
743
|
+
success: false,
|
|
744
|
+
hookType: "pre-commit",
|
|
745
|
+
wrappedExisting: false,
|
|
746
|
+
error: "No git repository found. Run git init first."
|
|
747
|
+
}
|
|
748
|
+
];
|
|
749
|
+
}
|
|
750
|
+
const results = await Promise.all([
|
|
751
|
+
installSingleHook("pre-commit", config, projectPath),
|
|
752
|
+
installSingleHook("commit-msg", config, projectPath)
|
|
753
|
+
]);
|
|
754
|
+
return results;
|
|
755
|
+
}
|
|
756
|
+
async function uninstallSingleHook(hookType, projectPath = process.cwd()) {
|
|
757
|
+
const hooksDir = getGitHooksDir(projectPath);
|
|
758
|
+
const hookPath = join2(hooksDir, hookType);
|
|
759
|
+
const originalPath = join2(hooksDir, `${hookType}.original`);
|
|
760
|
+
const result = {
|
|
761
|
+
success: false,
|
|
762
|
+
hookType,
|
|
763
|
+
wrappedExisting: false
|
|
764
|
+
};
|
|
765
|
+
try {
|
|
766
|
+
if (!existsSync2(hookPath)) {
|
|
767
|
+
result.success = true;
|
|
768
|
+
return result;
|
|
769
|
+
}
|
|
770
|
+
const isOurs = await isWorkflowHook(hookPath);
|
|
771
|
+
if (!isOurs) {
|
|
772
|
+
result.error = "Hook is not managed by Workflow Agent";
|
|
773
|
+
return result;
|
|
774
|
+
}
|
|
775
|
+
await unlink(hookPath);
|
|
776
|
+
if (existsSync2(originalPath)) {
|
|
777
|
+
await rename(originalPath, hookPath);
|
|
778
|
+
result.wrappedExisting = true;
|
|
779
|
+
}
|
|
780
|
+
result.success = true;
|
|
781
|
+
} catch (error) {
|
|
782
|
+
result.error = error instanceof Error ? error.message : String(error);
|
|
783
|
+
}
|
|
784
|
+
return result;
|
|
785
|
+
}
|
|
786
|
+
async function uninstallHooks(projectPath = process.cwd()) {
|
|
787
|
+
return Promise.all([
|
|
788
|
+
uninstallSingleHook("pre-commit", projectPath),
|
|
789
|
+
uninstallSingleHook("commit-msg", projectPath)
|
|
790
|
+
]);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// src/cli/commands/doctor.ts
|
|
794
|
+
async function doctorCommand(options) {
|
|
594
795
|
console.log(chalk5.bold.cyan("\n\u{1F3E5} Workflow Agent Health Check\n"));
|
|
595
|
-
const
|
|
596
|
-
if (!
|
|
796
|
+
const result = await loadConfigSafe();
|
|
797
|
+
if (!result.configPath && !result.rawConfig) {
|
|
597
798
|
console.error(chalk5.red("\u2717 No workflow configuration found"));
|
|
598
799
|
console.log(chalk5.yellow(" Run: workflow init"));
|
|
599
800
|
process.exit(1);
|
|
600
801
|
}
|
|
802
|
+
if (!result.valid && result.issues.length > 0) {
|
|
803
|
+
console.log(chalk5.yellow("\u26A0 Configuration has validation issues:\n"));
|
|
804
|
+
for (const issue of result.issues) {
|
|
805
|
+
console.log(chalk5.red(` \u2717 ${issue.path}: ${issue.message}`));
|
|
806
|
+
if (issue.currentValue !== void 0) {
|
|
807
|
+
console.log(chalk5.dim(` Current value: ${JSON.stringify(issue.currentValue)}`));
|
|
808
|
+
}
|
|
809
|
+
if (issue.suggestedFix) {
|
|
810
|
+
console.log(chalk5.green(` Suggested fix: ${issue.suggestedFix.description}`));
|
|
811
|
+
console.log(chalk5.dim(` New value: ${JSON.stringify(issue.suggestedFix.newValue)}`));
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
const hasAutoFixes = result.issues.some((i) => i.suggestedFix);
|
|
815
|
+
if (hasAutoFixes) {
|
|
816
|
+
if (options?.fix) {
|
|
817
|
+
console.log(chalk5.cyan("\n\u{1F527} Attempting to auto-fix issues...\n"));
|
|
818
|
+
const fixResult = await autoFixConfigFile();
|
|
819
|
+
if (fixResult.success) {
|
|
820
|
+
console.log(chalk5.green("\u2713 Configuration fixed successfully!\n"));
|
|
821
|
+
for (const change of fixResult.changes) {
|
|
822
|
+
console.log(chalk5.dim(` \u2022 ${change}`));
|
|
823
|
+
}
|
|
824
|
+
console.log(chalk5.cyan("\n Run 'workflow doctor' again to verify.\n"));
|
|
825
|
+
process.exit(0);
|
|
826
|
+
} else {
|
|
827
|
+
console.log(chalk5.red(`\u2717 Auto-fix failed: ${fixResult.error}`));
|
|
828
|
+
process.exit(1);
|
|
829
|
+
}
|
|
830
|
+
} else {
|
|
831
|
+
console.log(chalk5.cyan("\n\u{1F4A1} Auto-fix available!"));
|
|
832
|
+
console.log(chalk5.dim(" Run: workflow doctor --fix\n"));
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
process.exit(1);
|
|
836
|
+
}
|
|
837
|
+
const config = result.config;
|
|
601
838
|
console.log(chalk5.green("\u2713 Configuration loaded successfully"));
|
|
602
839
|
console.log(chalk5.dim(` Project: ${config.projectName}`));
|
|
603
840
|
console.log(chalk5.dim(` Scopes: ${config.scopes.length} configured`));
|
|
604
841
|
console.log(chalk5.dim(` Enforcement: ${config.enforcement}`));
|
|
605
842
|
console.log(chalk5.dim(` Language: ${config.language}`));
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
843
|
+
const cwd = process.cwd();
|
|
844
|
+
const guidelinesDir = join3(cwd, "guidelines");
|
|
845
|
+
const mandatoryFiles = getMandatoryTemplateFilenames();
|
|
846
|
+
const missingFiles = [];
|
|
847
|
+
console.log(chalk5.cyan("\n\u{1F4DA} Guidelines Check:\n"));
|
|
848
|
+
for (const filename of mandatoryFiles) {
|
|
849
|
+
const filePath = join3(guidelinesDir, filename);
|
|
850
|
+
if (existsSync3(filePath)) {
|
|
851
|
+
console.log(chalk5.green(`\u2713 ${filename}`));
|
|
852
|
+
} else {
|
|
853
|
+
console.log(chalk5.red(`\u2717 ${filename} (missing)`));
|
|
854
|
+
missingFiles.push(filename);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
if (missingFiles.length === 0) {
|
|
858
|
+
console.log(
|
|
859
|
+
chalk5.green(`
|
|
860
|
+
\u2713 All ${mandatoryFiles.length} mandatory guidelines present`)
|
|
861
|
+
);
|
|
862
|
+
} else {
|
|
863
|
+
console.log(
|
|
864
|
+
chalk5.red(
|
|
865
|
+
`
|
|
866
|
+
\u2717 Missing ${missingFiles.length} mandatory guideline(s)`
|
|
867
|
+
)
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
if (options?.checkGuidelinesOnly) {
|
|
871
|
+
process.exit(missingFiles.length > 0 ? 1 : 0);
|
|
872
|
+
}
|
|
873
|
+
console.log(chalk5.cyan("\n\u{1F517} Git Hooks Check:\n"));
|
|
874
|
+
if (!hasGitRepo(cwd)) {
|
|
875
|
+
console.log(chalk5.yellow("\u26A0 No git repository found"));
|
|
876
|
+
console.log(chalk5.dim(" Run: git init"));
|
|
877
|
+
} else {
|
|
878
|
+
const hooksStatus = getAllHooksStatus(cwd);
|
|
879
|
+
for (const status of hooksStatus) {
|
|
880
|
+
if (status.installed) {
|
|
881
|
+
console.log(chalk5.green(`\u2713 ${status.hookType}: installed`));
|
|
882
|
+
} else {
|
|
883
|
+
console.log(chalk5.yellow(`\u26A0 ${status.hookType}: not installed`));
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
const allInstalled = hooksStatus.every((s) => s.installed);
|
|
887
|
+
if (!allInstalled) {
|
|
888
|
+
console.log(chalk5.dim("\n Run: workflow hooks install"));
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
if (missingFiles.length > 0) {
|
|
892
|
+
process.exit(1);
|
|
893
|
+
}
|
|
610
894
|
}
|
|
611
895
|
|
|
612
896
|
// src/cli/commands/setup.ts
|
|
613
897
|
import * as p3 from "@clack/prompts";
|
|
614
898
|
import chalk6 from "chalk";
|
|
615
|
-
import { readFileSync, writeFileSync, existsSync as
|
|
616
|
-
import { join as
|
|
899
|
+
import { readFileSync, writeFileSync, existsSync as existsSync4 } from "fs";
|
|
900
|
+
import { join as join4, dirname as dirname2 } from "path";
|
|
617
901
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
618
902
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
619
903
|
var __dirname2 = dirname2(__filename2);
|
|
620
904
|
async function setupCommand() {
|
|
621
905
|
p3.intro(chalk6.bgBlue(" workflow-agent setup "));
|
|
622
906
|
const cwd = process.cwd();
|
|
623
|
-
const packageJsonPath =
|
|
624
|
-
if (!
|
|
907
|
+
const packageJsonPath = join4(cwd, "package.json");
|
|
908
|
+
if (!existsSync4(packageJsonPath)) {
|
|
625
909
|
p3.cancel("No package.json found in current directory");
|
|
626
910
|
process.exit(1);
|
|
627
911
|
}
|
|
@@ -686,8 +970,8 @@ async function setupCommand() {
|
|
|
686
970
|
console.log(chalk6.dim("\nRun them with:"));
|
|
687
971
|
console.log(chalk6.dim(" pnpm run workflow:init"));
|
|
688
972
|
console.log(chalk6.dim(" npm run workflow:init\n"));
|
|
689
|
-
const guidelinesDir =
|
|
690
|
-
if (!
|
|
973
|
+
const guidelinesDir = join4(cwd, "guidelines");
|
|
974
|
+
if (!existsSync4(guidelinesDir)) {
|
|
691
975
|
const templatesDir = findTemplatesDirectory(__dirname2);
|
|
692
976
|
if (templatesDir) {
|
|
693
977
|
const templateResult = installMandatoryTemplates(cwd, templatesDir, {
|
|
@@ -705,7 +989,7 @@ async function setupCommand() {
|
|
|
705
989
|
}
|
|
706
990
|
}
|
|
707
991
|
}
|
|
708
|
-
if (
|
|
992
|
+
if (existsSync4(guidelinesDir)) {
|
|
709
993
|
const result = generateCopilotInstructions(cwd, { silent: false });
|
|
710
994
|
if (result.success) {
|
|
711
995
|
const status = result.isNew ? "Generated" : "Updated";
|
|
@@ -724,14 +1008,14 @@ async function setupCommand() {
|
|
|
724
1008
|
// src/cli/commands/scope-create.ts
|
|
725
1009
|
import * as p4 from "@clack/prompts";
|
|
726
1010
|
import chalk7 from "chalk";
|
|
727
|
-
import { existsSync as
|
|
728
|
-
import { writeFile as
|
|
729
|
-
import { join as
|
|
1011
|
+
import { existsSync as existsSync5 } from "fs";
|
|
1012
|
+
import { writeFile as writeFile3, mkdir as mkdir3, readFile as readFile2 } from "fs/promises";
|
|
1013
|
+
import { join as join5 } from "path";
|
|
730
1014
|
async function scopeCreateCommand(options) {
|
|
731
1015
|
console.log(chalk7.bold.cyan("\n\u{1F3A8} Create Custom Scope Package\n"));
|
|
732
1016
|
const cwd = process.cwd();
|
|
733
1017
|
const isNonInteractive = !!(options.name && options.scopes && options.presetName);
|
|
734
|
-
const isMonorepo2 =
|
|
1018
|
+
const isMonorepo2 = existsSync5(join5(cwd, "pnpm-workspace.yaml"));
|
|
735
1019
|
if (isMonorepo2) {
|
|
736
1020
|
console.log(chalk7.dim("\u2713 Detected monorepo workspace\n"));
|
|
737
1021
|
}
|
|
@@ -877,7 +1161,7 @@ async function scopeCreateCommand(options) {
|
|
|
877
1161
|
if (options.outputDir) {
|
|
878
1162
|
outputDir = options.outputDir;
|
|
879
1163
|
} else if (isMonorepo2) {
|
|
880
|
-
outputDir =
|
|
1164
|
+
outputDir = join5(cwd, "packages", `scopes-${packageName}`);
|
|
881
1165
|
} else {
|
|
882
1166
|
const customDir = await p4.text({
|
|
883
1167
|
message: "Output directory:",
|
|
@@ -888,9 +1172,9 @@ async function scopeCreateCommand(options) {
|
|
|
888
1172
|
p4.cancel("Operation cancelled");
|
|
889
1173
|
process.exit(0);
|
|
890
1174
|
}
|
|
891
|
-
outputDir =
|
|
1175
|
+
outputDir = join5(cwd, customDir);
|
|
892
1176
|
}
|
|
893
|
-
if (
|
|
1177
|
+
if (existsSync5(outputDir)) {
|
|
894
1178
|
const shouldOverwrite = await p4.confirm({
|
|
895
1179
|
message: `Directory ${outputDir} already exists. Overwrite?`,
|
|
896
1180
|
initialValue: false
|
|
@@ -903,7 +1187,7 @@ async function scopeCreateCommand(options) {
|
|
|
903
1187
|
const spinner10 = p4.spinner();
|
|
904
1188
|
spinner10.start("Creating package structure...");
|
|
905
1189
|
try {
|
|
906
|
-
await
|
|
1190
|
+
await mkdir3(join5(outputDir, "src"), { recursive: true });
|
|
907
1191
|
const packageJson = {
|
|
908
1192
|
name: `@workflow/scopes-${packageName}`,
|
|
909
1193
|
version: "1.0.0",
|
|
@@ -943,8 +1227,8 @@ async function scopeCreateCommand(options) {
|
|
|
943
1227
|
access: "public"
|
|
944
1228
|
}
|
|
945
1229
|
};
|
|
946
|
-
await
|
|
947
|
-
|
|
1230
|
+
await writeFile3(
|
|
1231
|
+
join5(outputDir, "package.json"),
|
|
948
1232
|
JSON.stringify(packageJson, null, 2),
|
|
949
1233
|
"utf-8"
|
|
950
1234
|
);
|
|
@@ -956,8 +1240,8 @@ async function scopeCreateCommand(options) {
|
|
|
956
1240
|
},
|
|
957
1241
|
include: ["src/**/*"]
|
|
958
1242
|
};
|
|
959
|
-
await
|
|
960
|
-
|
|
1243
|
+
await writeFile3(
|
|
1244
|
+
join5(outputDir, "tsconfig.json"),
|
|
961
1245
|
JSON.stringify(tsconfig, null, 2),
|
|
962
1246
|
"utf-8"
|
|
963
1247
|
);
|
|
@@ -971,7 +1255,7 @@ export default defineConfig({
|
|
|
971
1255
|
sourcemap: true,
|
|
972
1256
|
});
|
|
973
1257
|
`;
|
|
974
|
-
await
|
|
1258
|
+
await writeFile3(join5(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
|
|
975
1259
|
const indexTs = `import type { Scope } from '@hawkinside_out/workflow-agent/config';
|
|
976
1260
|
|
|
977
1261
|
export const scopes: Scope[] = ${JSON.stringify(scopes, null, 2)};
|
|
@@ -985,7 +1269,7 @@ export const preset = {
|
|
|
985
1269
|
|
|
986
1270
|
export default preset;
|
|
987
1271
|
`;
|
|
988
|
-
await
|
|
1272
|
+
await writeFile3(join5(outputDir, "src", "index.ts"), indexTs, "utf-8");
|
|
989
1273
|
if (!options.noTest) {
|
|
990
1274
|
const testFile = `import { describe, it, expect } from 'vitest';
|
|
991
1275
|
import { scopes, preset } from './index.js';
|
|
@@ -1026,16 +1310,16 @@ describe('${presetName} Scope Preset', () => {
|
|
|
1026
1310
|
});
|
|
1027
1311
|
});
|
|
1028
1312
|
`;
|
|
1029
|
-
await
|
|
1030
|
-
|
|
1313
|
+
await writeFile3(
|
|
1314
|
+
join5(outputDir, "src", "index.test.ts"),
|
|
1031
1315
|
testFile,
|
|
1032
1316
|
"utf-8"
|
|
1033
1317
|
);
|
|
1034
1318
|
}
|
|
1035
1319
|
spinner10.stop("\u2713 Package structure created");
|
|
1036
1320
|
if (isMonorepo2) {
|
|
1037
|
-
const workspaceFile =
|
|
1038
|
-
const workspaceContent = await
|
|
1321
|
+
const workspaceFile = join5(cwd, "pnpm-workspace.yaml");
|
|
1322
|
+
const workspaceContent = await readFile2(workspaceFile, "utf-8");
|
|
1039
1323
|
const packagePath = `packages/scopes-${packageName}`;
|
|
1040
1324
|
if (!workspaceContent.includes(packagePath) && !workspaceContent.includes("packages/*")) {
|
|
1041
1325
|
console.log(
|
|
@@ -1093,9 +1377,9 @@ describe('${presetName} Scope Preset', () => {
|
|
|
1093
1377
|
// src/cli/commands/scope-migrate.ts
|
|
1094
1378
|
import * as p5 from "@clack/prompts";
|
|
1095
1379
|
import chalk8 from "chalk";
|
|
1096
|
-
import { existsSync as
|
|
1097
|
-
import { writeFile as
|
|
1098
|
-
import { join as
|
|
1380
|
+
import { existsSync as existsSync6 } from "fs";
|
|
1381
|
+
import { writeFile as writeFile4, mkdir as mkdir4, readFile as readFile3 } from "fs/promises";
|
|
1382
|
+
import { join as join6 } from "path";
|
|
1099
1383
|
async function scopeMigrateCommand(options) {
|
|
1100
1384
|
console.log(chalk8.bold.cyan("\n\u{1F504} Migrate Scopes to Custom Package\n"));
|
|
1101
1385
|
const cwd = process.cwd();
|
|
@@ -1139,7 +1423,7 @@ async function scopeMigrateCommand(options) {
|
|
|
1139
1423
|
p5.cancel("Migration cancelled");
|
|
1140
1424
|
process.exit(0);
|
|
1141
1425
|
}
|
|
1142
|
-
const isMonorepo2 =
|
|
1426
|
+
const isMonorepo2 = existsSync6(join6(cwd, "pnpm-workspace.yaml"));
|
|
1143
1427
|
if (isMonorepo2) {
|
|
1144
1428
|
console.log(chalk8.dim("\n\u2713 Detected monorepo workspace\n"));
|
|
1145
1429
|
}
|
|
@@ -1189,7 +1473,7 @@ async function scopeMigrateCommand(options) {
|
|
|
1189
1473
|
if (options.outputDir) {
|
|
1190
1474
|
outputDir = options.outputDir;
|
|
1191
1475
|
} else if (isMonorepo2) {
|
|
1192
|
-
outputDir =
|
|
1476
|
+
outputDir = join6(cwd, "packages", `scopes-${packageName}`);
|
|
1193
1477
|
} else {
|
|
1194
1478
|
const customDir = await p5.text({
|
|
1195
1479
|
message: "Output directory:",
|
|
@@ -1200,9 +1484,9 @@ async function scopeMigrateCommand(options) {
|
|
|
1200
1484
|
p5.cancel("Migration cancelled");
|
|
1201
1485
|
process.exit(0);
|
|
1202
1486
|
}
|
|
1203
|
-
outputDir =
|
|
1487
|
+
outputDir = join6(cwd, customDir);
|
|
1204
1488
|
}
|
|
1205
|
-
if (
|
|
1489
|
+
if (existsSync6(outputDir)) {
|
|
1206
1490
|
const shouldOverwrite = await p5.confirm({
|
|
1207
1491
|
message: `Directory ${outputDir} already exists. Overwrite?`,
|
|
1208
1492
|
initialValue: false
|
|
@@ -1215,7 +1499,7 @@ async function scopeMigrateCommand(options) {
|
|
|
1215
1499
|
const spinner10 = p5.spinner();
|
|
1216
1500
|
spinner10.start("Migrating scopes to package...");
|
|
1217
1501
|
try {
|
|
1218
|
-
await
|
|
1502
|
+
await mkdir4(join6(outputDir, "src"), { recursive: true });
|
|
1219
1503
|
const packageJson = {
|
|
1220
1504
|
name: `@workflow/scopes-${packageName}`,
|
|
1221
1505
|
version: "1.0.0",
|
|
@@ -1255,8 +1539,8 @@ async function scopeMigrateCommand(options) {
|
|
|
1255
1539
|
access: "public"
|
|
1256
1540
|
}
|
|
1257
1541
|
};
|
|
1258
|
-
await
|
|
1259
|
-
|
|
1542
|
+
await writeFile4(
|
|
1543
|
+
join6(outputDir, "package.json"),
|
|
1260
1544
|
JSON.stringify(packageJson, null, 2),
|
|
1261
1545
|
"utf-8"
|
|
1262
1546
|
);
|
|
@@ -1268,8 +1552,8 @@ async function scopeMigrateCommand(options) {
|
|
|
1268
1552
|
},
|
|
1269
1553
|
include: ["src/**/*"]
|
|
1270
1554
|
};
|
|
1271
|
-
await
|
|
1272
|
-
|
|
1555
|
+
await writeFile4(
|
|
1556
|
+
join6(outputDir, "tsconfig.json"),
|
|
1273
1557
|
JSON.stringify(tsconfig, null, 2),
|
|
1274
1558
|
"utf-8"
|
|
1275
1559
|
);
|
|
@@ -1283,7 +1567,7 @@ export default defineConfig({
|
|
|
1283
1567
|
sourcemap: true,
|
|
1284
1568
|
});
|
|
1285
1569
|
`;
|
|
1286
|
-
await
|
|
1570
|
+
await writeFile4(join6(outputDir, "tsup.config.ts"), tsupConfig, "utf-8");
|
|
1287
1571
|
const indexTs = `import type { Scope } from '@hawkinside_out/workflow-agent/config';
|
|
1288
1572
|
|
|
1289
1573
|
export const scopes: Scope[] = ${JSON.stringify(config.scopes, null, 2)};
|
|
@@ -1297,7 +1581,7 @@ export const preset = {
|
|
|
1297
1581
|
|
|
1298
1582
|
export default preset;
|
|
1299
1583
|
`;
|
|
1300
|
-
await
|
|
1584
|
+
await writeFile4(join6(outputDir, "src", "index.ts"), indexTs, "utf-8");
|
|
1301
1585
|
const testFile = `import { describe, it, expect } from 'vitest';
|
|
1302
1586
|
import { scopes, preset } from './index.js';
|
|
1303
1587
|
import { ScopeSchema } from '@hawkinside_out/workflow-agent/config';
|
|
@@ -1340,11 +1624,11 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1340
1624
|
});
|
|
1341
1625
|
});
|
|
1342
1626
|
`;
|
|
1343
|
-
await
|
|
1627
|
+
await writeFile4(join6(outputDir, "src", "index.test.ts"), testFile, "utf-8");
|
|
1344
1628
|
spinner10.stop("\u2713 Package created from migrated scopes");
|
|
1345
1629
|
if (isMonorepo2) {
|
|
1346
|
-
const workspaceFile =
|
|
1347
|
-
const workspaceContent = await
|
|
1630
|
+
const workspaceFile = join6(cwd, "pnpm-workspace.yaml");
|
|
1631
|
+
const workspaceContent = await readFile3(workspaceFile, "utf-8");
|
|
1348
1632
|
const packagePath = `packages/scopes-${packageName}`;
|
|
1349
1633
|
if (!workspaceContent.includes(packagePath) && !workspaceContent.includes("packages/*")) {
|
|
1350
1634
|
console.log(
|
|
@@ -1360,7 +1644,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1360
1644
|
initialValue: false
|
|
1361
1645
|
});
|
|
1362
1646
|
if (!p5.isCancel(keepConfig) && !keepConfig) {
|
|
1363
|
-
const configPath =
|
|
1647
|
+
const configPath = join6(cwd, "workflow.config.json");
|
|
1364
1648
|
const updatedConfig = {
|
|
1365
1649
|
...config,
|
|
1366
1650
|
scopes: [],
|
|
@@ -1368,7 +1652,7 @@ describe('${presetName} Scope Preset (Migrated)', () => {
|
|
|
1368
1652
|
preset: `scopes-${packageName}`
|
|
1369
1653
|
// Reference the new package
|
|
1370
1654
|
};
|
|
1371
|
-
await
|
|
1655
|
+
await writeFile4(
|
|
1372
1656
|
configPath,
|
|
1373
1657
|
JSON.stringify(updatedConfig, null, 2),
|
|
1374
1658
|
"utf-8"
|
|
@@ -1796,14 +2080,14 @@ function formatAuditReportColored(report) {
|
|
|
1796
2080
|
// src/cli/commands/advisory.ts
|
|
1797
2081
|
import * as p7 from "@clack/prompts";
|
|
1798
2082
|
import chalk11 from "chalk";
|
|
1799
|
-
import { existsSync as
|
|
1800
|
-
import { readFile as
|
|
1801
|
-
import { join as
|
|
2083
|
+
import { existsSync as existsSync8 } from "fs";
|
|
2084
|
+
import { readFile as readFile5, writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
2085
|
+
import { join as join8 } from "path";
|
|
1802
2086
|
|
|
1803
2087
|
// src/utils/advisory-analyzer.ts
|
|
1804
|
-
import { existsSync as
|
|
1805
|
-
import { readFile as
|
|
1806
|
-
import { join as
|
|
2088
|
+
import { existsSync as existsSync7 } from "fs";
|
|
2089
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
2090
|
+
import { join as join7 } from "path";
|
|
1807
2091
|
import fg from "fast-glob";
|
|
1808
2092
|
var AdvisoryAnalyzer = class {
|
|
1809
2093
|
options;
|
|
@@ -2247,11 +2531,11 @@ var AdvisoryAnalyzer = class {
|
|
|
2247
2531
|
// Helper Methods
|
|
2248
2532
|
// ============================================================================
|
|
2249
2533
|
async readPackageJson() {
|
|
2250
|
-
const pkgPath =
|
|
2251
|
-
if (!
|
|
2534
|
+
const pkgPath = join7(this.options.cwd, "package.json");
|
|
2535
|
+
if (!existsSync7(pkgPath)) {
|
|
2252
2536
|
throw new Error("package.json not found");
|
|
2253
2537
|
}
|
|
2254
|
-
const content = await
|
|
2538
|
+
const content = await readFile4(pkgPath, "utf-8");
|
|
2255
2539
|
return JSON.parse(content);
|
|
2256
2540
|
}
|
|
2257
2541
|
async countFiles() {
|
|
@@ -3619,11 +3903,11 @@ async function advisoryCommand(options) {
|
|
|
3619
3903
|
let comparisonReport;
|
|
3620
3904
|
let comparator;
|
|
3621
3905
|
if (options.compare) {
|
|
3622
|
-
const comparisonPath = options.compare.endsWith(".json") ?
|
|
3623
|
-
if (
|
|
3906
|
+
const comparisonPath = options.compare.endsWith(".json") ? join8(cwd, options.compare) : join8(cwd, options.compare, "analysis.json");
|
|
3907
|
+
if (existsSync8(comparisonPath)) {
|
|
3624
3908
|
spinner10.start("Comparing with previous report...");
|
|
3625
3909
|
try {
|
|
3626
|
-
const previousContent = await
|
|
3910
|
+
const previousContent = await readFile5(comparisonPath, "utf-8");
|
|
3627
3911
|
const previousAnalysis = JSON.parse(previousContent);
|
|
3628
3912
|
comparator = new ReportComparator(previousAnalysis, analysis);
|
|
3629
3913
|
comparisonReport = comparator.compare();
|
|
@@ -3648,8 +3932,8 @@ async function advisoryCommand(options) {
|
|
|
3648
3932
|
console.log(chalk11.dim("\n--dry-run mode: No files written.\n"));
|
|
3649
3933
|
return;
|
|
3650
3934
|
}
|
|
3651
|
-
const fullOutputDir =
|
|
3652
|
-
await
|
|
3935
|
+
const fullOutputDir = join8(cwd, outputDir);
|
|
3936
|
+
await mkdir5(fullOutputDir, { recursive: true });
|
|
3653
3937
|
spinner10.start("Generating reports...");
|
|
3654
3938
|
try {
|
|
3655
3939
|
const timestamp = options.timestamp ? (/* @__PURE__ */ new Date()).toISOString().split("T")[0] : "";
|
|
@@ -3674,24 +3958,24 @@ async function advisoryCommand(options) {
|
|
|
3674
3958
|
console.log(chalk11.green("\u{1F4DD} Reports written to:"));
|
|
3675
3959
|
const suffix = options.timestamp ? `-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}` : "";
|
|
3676
3960
|
if (options.format === "json") {
|
|
3677
|
-
console.log(chalk11.dim(` ${
|
|
3678
|
-
console.log(chalk11.dim(` ${
|
|
3961
|
+
console.log(chalk11.dim(` ${join8(outputDir, `analysis${suffix}.json`)}`));
|
|
3962
|
+
console.log(chalk11.dim(` ${join8(outputDir, `questions${suffix}.json`)}`));
|
|
3679
3963
|
} else {
|
|
3680
3964
|
console.log(
|
|
3681
|
-
chalk11.dim(` ${
|
|
3965
|
+
chalk11.dim(` ${join8(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`)}`)
|
|
3682
3966
|
);
|
|
3683
3967
|
console.log(
|
|
3684
|
-
chalk11.dim(` ${
|
|
3968
|
+
chalk11.dim(` ${join8(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`)}`)
|
|
3685
3969
|
);
|
|
3686
3970
|
console.log(
|
|
3687
|
-
chalk11.dim(` ${
|
|
3971
|
+
chalk11.dim(` ${join8(outputDir, `STRATEGIC_ROADMAP${suffix}.md`)}`)
|
|
3688
3972
|
);
|
|
3689
3973
|
console.log(
|
|
3690
|
-
chalk11.dim(` ${
|
|
3974
|
+
chalk11.dim(` ${join8(outputDir, `BOARD_QUESTIONS${suffix}.md`)}`)
|
|
3691
3975
|
);
|
|
3692
3976
|
if (comparisonReport) {
|
|
3693
3977
|
console.log(
|
|
3694
|
-
chalk11.dim(` ${
|
|
3978
|
+
chalk11.dim(` ${join8(outputDir, `DIFF_REPORT${suffix}.md`)}`)
|
|
3695
3979
|
);
|
|
3696
3980
|
}
|
|
3697
3981
|
}
|
|
@@ -3784,47 +4068,47 @@ function displayComparisonSummary(comparison) {
|
|
|
3784
4068
|
}
|
|
3785
4069
|
async function writeAnalysisJson(outputDir, analysis, questions, timestamp) {
|
|
3786
4070
|
const suffix = timestamp ? `-${timestamp}` : "";
|
|
3787
|
-
await
|
|
3788
|
-
|
|
4071
|
+
await writeFile5(
|
|
4072
|
+
join8(outputDir, `analysis${suffix}.json`),
|
|
3789
4073
|
JSON.stringify(analysis, null, 2),
|
|
3790
4074
|
"utf-8"
|
|
3791
4075
|
);
|
|
3792
|
-
await
|
|
3793
|
-
|
|
4076
|
+
await writeFile5(
|
|
4077
|
+
join8(outputDir, `questions${suffix}.json`),
|
|
3794
4078
|
JSON.stringify(questions, null, 2),
|
|
3795
4079
|
"utf-8"
|
|
3796
4080
|
);
|
|
3797
4081
|
}
|
|
3798
4082
|
async function writeMarkdownReports(outputDir, analysis, questions, comparator, timestamp) {
|
|
3799
4083
|
const suffix = timestamp ? `-${timestamp}` : "";
|
|
3800
|
-
await
|
|
3801
|
-
|
|
4084
|
+
await writeFile5(
|
|
4085
|
+
join8(outputDir, `analysis.json`),
|
|
3802
4086
|
JSON.stringify(analysis, null, 2),
|
|
3803
4087
|
"utf-8"
|
|
3804
4088
|
);
|
|
3805
|
-
await
|
|
3806
|
-
|
|
4089
|
+
await writeFile5(
|
|
4090
|
+
join8(outputDir, `EXECUTIVE_SUMMARY${suffix}.md`),
|
|
3807
4091
|
generateExecutiveSummary(analysis, questions),
|
|
3808
4092
|
"utf-8"
|
|
3809
4093
|
);
|
|
3810
|
-
await
|
|
3811
|
-
|
|
4094
|
+
await writeFile5(
|
|
4095
|
+
join8(outputDir, `TECHNOLOGY_AUDIT${suffix}.md`),
|
|
3812
4096
|
generateTechnologyAudit(analysis),
|
|
3813
4097
|
"utf-8"
|
|
3814
4098
|
);
|
|
3815
|
-
await
|
|
3816
|
-
|
|
4099
|
+
await writeFile5(
|
|
4100
|
+
join8(outputDir, `STRATEGIC_ROADMAP${suffix}.md`),
|
|
3817
4101
|
generateStrategicRoadmap(analysis, questions),
|
|
3818
4102
|
"utf-8"
|
|
3819
4103
|
);
|
|
3820
|
-
await
|
|
3821
|
-
|
|
4104
|
+
await writeFile5(
|
|
4105
|
+
join8(outputDir, `BOARD_QUESTIONS${suffix}.md`),
|
|
3822
4106
|
generateBoardQuestions(questions),
|
|
3823
4107
|
"utf-8"
|
|
3824
4108
|
);
|
|
3825
4109
|
if (comparator) {
|
|
3826
|
-
await
|
|
3827
|
-
|
|
4110
|
+
await writeFile5(
|
|
4111
|
+
join8(outputDir, `DIFF_REPORT${suffix}.md`),
|
|
3828
4112
|
comparator.generateMarkdownSummary(),
|
|
3829
4113
|
"utf-8"
|
|
3830
4114
|
);
|
|
@@ -4441,20 +4725,20 @@ function checkCIThresholds(analysis, config) {
|
|
|
4441
4725
|
// src/cli/commands/generate-instructions.ts
|
|
4442
4726
|
import * as p8 from "@clack/prompts";
|
|
4443
4727
|
import chalk12 from "chalk";
|
|
4444
|
-
import { existsSync as
|
|
4445
|
-
import { join as
|
|
4728
|
+
import { existsSync as existsSync9 } from "fs";
|
|
4729
|
+
import { join as join9 } from "path";
|
|
4446
4730
|
async function generateInstructionsCommand(options) {
|
|
4447
4731
|
p8.intro(chalk12.bgBlue(" workflow-agent generate-instructions "));
|
|
4448
4732
|
const cwd = process.cwd();
|
|
4449
|
-
const guidelinesDir =
|
|
4450
|
-
const outputPath =
|
|
4451
|
-
if (!
|
|
4733
|
+
const guidelinesDir = join9(cwd, "guidelines");
|
|
4734
|
+
const outputPath = join9(cwd, ".github", "copilot-instructions.md");
|
|
4735
|
+
if (!existsSync9(guidelinesDir)) {
|
|
4452
4736
|
p8.cancel(
|
|
4453
4737
|
"No guidelines directory found. Run 'workflow init' first to generate guidelines."
|
|
4454
4738
|
);
|
|
4455
4739
|
process.exit(1);
|
|
4456
4740
|
}
|
|
4457
|
-
if (
|
|
4741
|
+
if (existsSync9(outputPath) && !options.force) {
|
|
4458
4742
|
const shouldRegenerate = await p8.confirm({
|
|
4459
4743
|
message: ".github/copilot-instructions.md already exists. Regenerate? (Custom content will be preserved)",
|
|
4460
4744
|
initialValue: true
|
|
@@ -4514,8 +4798,8 @@ Reason: ${error instanceof Error ? error.message : String(error)}`
|
|
|
4514
4798
|
// src/cli/commands/update-templates.ts
|
|
4515
4799
|
import * as p9 from "@clack/prompts";
|
|
4516
4800
|
import chalk13 from "chalk";
|
|
4517
|
-
import { existsSync as
|
|
4518
|
-
import { join as
|
|
4801
|
+
import { existsSync as existsSync10 } from "fs";
|
|
4802
|
+
import { join as join10, dirname as dirname3 } from "path";
|
|
4519
4803
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
4520
4804
|
var __filename3 = fileURLToPath3(import.meta.url);
|
|
4521
4805
|
var __dirname3 = dirname3(__filename3);
|
|
@@ -4523,13 +4807,13 @@ async function updateTemplatesCommand(options) {
|
|
|
4523
4807
|
const { force = false, skip = false } = options;
|
|
4524
4808
|
p9.intro(chalk13.bgBlue(" workflow-agent update-templates "));
|
|
4525
4809
|
const cwd = process.cwd();
|
|
4526
|
-
const guidelinesDir =
|
|
4810
|
+
const guidelinesDir = join10(cwd, "guidelines");
|
|
4527
4811
|
const templatesDir = findTemplatesDirectory(__dirname3);
|
|
4528
4812
|
if (!templatesDir) {
|
|
4529
4813
|
p9.cancel("Could not find templates directory");
|
|
4530
4814
|
process.exit(1);
|
|
4531
4815
|
}
|
|
4532
|
-
const guidelinesExist =
|
|
4816
|
+
const guidelinesExist = existsSync10(guidelinesDir);
|
|
4533
4817
|
if (!guidelinesExist) {
|
|
4534
4818
|
console.log(chalk13.yellow("\n\u26A0\uFE0F No guidelines directory found."));
|
|
4535
4819
|
console.log(chalk13.dim("Run 'workflow-agent init' to set up guidelines.\n"));
|
|
@@ -4818,8 +5102,124 @@ Fixed: ${fixedCount}, Skipped: ${skippedCount}`)
|
|
|
4818
5102
|
}
|
|
4819
5103
|
}
|
|
4820
5104
|
|
|
4821
|
-
// src/cli/commands/
|
|
5105
|
+
// src/cli/commands/hooks.ts
|
|
4822
5106
|
import chalk15 from "chalk";
|
|
5107
|
+
async function hooksCommand(action) {
|
|
5108
|
+
const cwd = process.cwd();
|
|
5109
|
+
switch (action) {
|
|
5110
|
+
case "install":
|
|
5111
|
+
await installHooksAction(cwd);
|
|
5112
|
+
break;
|
|
5113
|
+
case "uninstall":
|
|
5114
|
+
await uninstallHooksAction(cwd);
|
|
5115
|
+
break;
|
|
5116
|
+
case "status":
|
|
5117
|
+
await statusHooksAction(cwd);
|
|
5118
|
+
break;
|
|
5119
|
+
default:
|
|
5120
|
+
console.error(chalk15.red(`Unknown action: ${action}`));
|
|
5121
|
+
console.log(chalk15.dim("Available actions: install, uninstall, status"));
|
|
5122
|
+
process.exit(1);
|
|
5123
|
+
}
|
|
5124
|
+
}
|
|
5125
|
+
async function installHooksAction(cwd) {
|
|
5126
|
+
console.log(chalk15.bold.cyan("\n\u{1F517} Installing Workflow Agent Git Hooks\n"));
|
|
5127
|
+
if (!hasGitRepo(cwd)) {
|
|
5128
|
+
console.error(chalk15.red("\u2717 No git repository found"));
|
|
5129
|
+
console.log(chalk15.yellow(" Run: git init"));
|
|
5130
|
+
process.exit(1);
|
|
5131
|
+
}
|
|
5132
|
+
const config = await loadConfig();
|
|
5133
|
+
const hooksConfig = config?.hooks;
|
|
5134
|
+
const results = await installHooks(hooksConfig, cwd);
|
|
5135
|
+
let hasErrors = false;
|
|
5136
|
+
for (const result of results) {
|
|
5137
|
+
if (result.success) {
|
|
5138
|
+
if (result.wrappedExisting) {
|
|
5139
|
+
console.log(
|
|
5140
|
+
chalk15.green(
|
|
5141
|
+
`\u2713 Installed ${result.hookType} hook (wrapped existing hook)`
|
|
5142
|
+
)
|
|
5143
|
+
);
|
|
5144
|
+
} else {
|
|
5145
|
+
console.log(chalk15.green(`\u2713 Installed ${result.hookType} hook`));
|
|
5146
|
+
}
|
|
5147
|
+
} else {
|
|
5148
|
+
console.error(
|
|
5149
|
+
chalk15.red(`\u2717 Failed to install ${result.hookType}: ${result.error}`)
|
|
5150
|
+
);
|
|
5151
|
+
hasErrors = true;
|
|
5152
|
+
}
|
|
5153
|
+
}
|
|
5154
|
+
if (!hasErrors) {
|
|
5155
|
+
console.log(chalk15.green("\n\u2713 Git hooks installed successfully"));
|
|
5156
|
+
console.log(chalk15.dim("\nHooks will run automatically on commit."));
|
|
5157
|
+
console.log(chalk15.dim("They will be skipped in CI environments."));
|
|
5158
|
+
} else {
|
|
5159
|
+
process.exit(1);
|
|
5160
|
+
}
|
|
5161
|
+
}
|
|
5162
|
+
async function uninstallHooksAction(cwd) {
|
|
5163
|
+
console.log(chalk15.bold.cyan("\n\u{1F513} Uninstalling Workflow Agent Git Hooks\n"));
|
|
5164
|
+
if (!hasGitRepo(cwd)) {
|
|
5165
|
+
console.error(chalk15.red("\u2717 No git repository found"));
|
|
5166
|
+
process.exit(1);
|
|
5167
|
+
}
|
|
5168
|
+
const results = await uninstallHooks(cwd);
|
|
5169
|
+
let hasErrors = false;
|
|
5170
|
+
for (const result of results) {
|
|
5171
|
+
if (result.success) {
|
|
5172
|
+
if (result.wrappedExisting) {
|
|
5173
|
+
console.log(
|
|
5174
|
+
chalk15.green(`\u2713 Removed ${result.hookType} hook (restored original)`)
|
|
5175
|
+
);
|
|
5176
|
+
} else {
|
|
5177
|
+
console.log(chalk15.green(`\u2713 Removed ${result.hookType} hook`));
|
|
5178
|
+
}
|
|
5179
|
+
} else if (result.error) {
|
|
5180
|
+
console.error(
|
|
5181
|
+
chalk15.red(`\u2717 Failed to remove ${result.hookType}: ${result.error}`)
|
|
5182
|
+
);
|
|
5183
|
+
hasErrors = true;
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
if (!hasErrors) {
|
|
5187
|
+
console.log(chalk15.green("\n\u2713 Git hooks uninstalled successfully"));
|
|
5188
|
+
} else {
|
|
5189
|
+
process.exit(1);
|
|
5190
|
+
}
|
|
5191
|
+
}
|
|
5192
|
+
async function statusHooksAction(cwd) {
|
|
5193
|
+
console.log(chalk15.bold.cyan("\n\u{1F4CA} Workflow Agent Git Hooks Status\n"));
|
|
5194
|
+
if (!hasGitRepo(cwd)) {
|
|
5195
|
+
console.error(chalk15.red("\u2717 No git repository found"));
|
|
5196
|
+
process.exit(1);
|
|
5197
|
+
}
|
|
5198
|
+
const statuses = await getAllHooksStatus(cwd);
|
|
5199
|
+
for (const status of statuses) {
|
|
5200
|
+
const icon = status.installed ? "\u2713" : "\u2717";
|
|
5201
|
+
const color = status.installed ? chalk15.green : chalk15.yellow;
|
|
5202
|
+
let message = `${icon} ${status.hookType}`;
|
|
5203
|
+
if (status.installed) {
|
|
5204
|
+
message += " - installed";
|
|
5205
|
+
if (status.wrappedOriginal) {
|
|
5206
|
+
message += " (wrapping original hook)";
|
|
5207
|
+
}
|
|
5208
|
+
} else if (status.hasExistingHook) {
|
|
5209
|
+
message += " - existing hook (not managed by Workflow Agent)";
|
|
5210
|
+
} else {
|
|
5211
|
+
message += " - not installed";
|
|
5212
|
+
}
|
|
5213
|
+
console.log(color(message));
|
|
5214
|
+
}
|
|
5215
|
+
const allInstalled = statuses.every((s) => s.installed);
|
|
5216
|
+
if (!allInstalled) {
|
|
5217
|
+
console.log(chalk15.dim("\nTo install hooks: workflow hooks install"));
|
|
5218
|
+
}
|
|
5219
|
+
}
|
|
5220
|
+
|
|
5221
|
+
// src/cli/commands/learn.ts
|
|
5222
|
+
import chalk16 from "chalk";
|
|
4823
5223
|
import * as p11 from "@clack/prompts";
|
|
4824
5224
|
import {
|
|
4825
5225
|
PatternStore as PatternStore2,
|
|
@@ -4843,7 +5243,7 @@ function formatTags(tags) {
|
|
|
4843
5243
|
async function learnRecordCommand(options) {
|
|
4844
5244
|
const cwd = getWorkspacePath();
|
|
4845
5245
|
const store = new PatternStore2(cwd);
|
|
4846
|
-
console.log(
|
|
5246
|
+
console.log(chalk16.cyan("\n\u{1F4DA} Record a Learning Pattern\n"));
|
|
4847
5247
|
let patternType = options.type;
|
|
4848
5248
|
if (!patternType) {
|
|
4849
5249
|
const typeChoice = await p11.select({
|
|
@@ -5008,14 +5408,14 @@ async function learnRecordCommand(options) {
|
|
|
5008
5408
|
};
|
|
5009
5409
|
const result = await store.saveFixPattern(fixPattern);
|
|
5010
5410
|
if (result.success) {
|
|
5011
|
-
console.log(
|
|
5012
|
-
console.log(
|
|
5013
|
-
console.log(
|
|
5014
|
-
console.log(
|
|
5015
|
-
console.log(
|
|
5411
|
+
console.log(chalk16.green("\n\u2705 Fix pattern recorded successfully!\n"));
|
|
5412
|
+
console.log(chalk16.dim(` ID: ${fixPattern.id}`));
|
|
5413
|
+
console.log(chalk16.dim(` Name: ${name}`));
|
|
5414
|
+
console.log(chalk16.dim(` Category: ${category}`));
|
|
5415
|
+
console.log(chalk16.dim(` Framework: ${framework} ${version}`));
|
|
5016
5416
|
} else {
|
|
5017
|
-
console.log(
|
|
5018
|
-
console.log(
|
|
5417
|
+
console.log(chalk16.red("\n\u274C Failed to record pattern"));
|
|
5418
|
+
console.log(chalk16.dim(` Error: ${result.error}`));
|
|
5019
5419
|
process.exit(1);
|
|
5020
5420
|
}
|
|
5021
5421
|
} else {
|
|
@@ -5062,13 +5462,13 @@ async function learnRecordCommand(options) {
|
|
|
5062
5462
|
};
|
|
5063
5463
|
const result = await store.saveBlueprint(blueprint);
|
|
5064
5464
|
if (result.success) {
|
|
5065
|
-
console.log(
|
|
5066
|
-
console.log(
|
|
5067
|
-
console.log(
|
|
5068
|
-
console.log(
|
|
5465
|
+
console.log(chalk16.green("\n\u2705 Blueprint recorded successfully!\n"));
|
|
5466
|
+
console.log(chalk16.dim(` ID: ${blueprint.id}`));
|
|
5467
|
+
console.log(chalk16.dim(` Name: ${name}`));
|
|
5468
|
+
console.log(chalk16.dim(` Framework: ${framework} ${version}`));
|
|
5069
5469
|
} else {
|
|
5070
|
-
console.log(
|
|
5071
|
-
console.log(
|
|
5470
|
+
console.log(chalk16.red("\n\u274C Failed to record blueprint"));
|
|
5471
|
+
console.log(chalk16.dim(` Error: ${result.error}`));
|
|
5072
5472
|
process.exit(1);
|
|
5073
5473
|
}
|
|
5074
5474
|
}
|
|
@@ -5078,7 +5478,7 @@ async function learnListCommand(options) {
|
|
|
5078
5478
|
const store = new PatternStore2(cwd);
|
|
5079
5479
|
const patternType = options.type ?? "all";
|
|
5080
5480
|
const showDeprecated = options.deprecated ?? false;
|
|
5081
|
-
console.log(
|
|
5481
|
+
console.log(chalk16.cyan("\n\u{1F4DA} Recorded Learning Patterns\n"));
|
|
5082
5482
|
if (patternType === "all" || patternType === "fix") {
|
|
5083
5483
|
const fixResult = await store.listFixPatterns({
|
|
5084
5484
|
tags: options.tag ? [{ category: "framework", name: options.tag }] : void 0,
|
|
@@ -5086,29 +5486,29 @@ async function learnListCommand(options) {
|
|
|
5086
5486
|
includeDeprecated: showDeprecated
|
|
5087
5487
|
});
|
|
5088
5488
|
if (fixResult.success && fixResult.data && fixResult.data.length > 0) {
|
|
5089
|
-
console.log(
|
|
5489
|
+
console.log(chalk16.bold.yellow("\u{1F527} Fix Patterns:\n"));
|
|
5090
5490
|
for (const pattern of fixResult.data) {
|
|
5091
5491
|
const isDeprecated = pattern.deprecatedAt !== void 0;
|
|
5092
5492
|
const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
|
|
5093
|
-
const nameColor = isDeprecated ?
|
|
5493
|
+
const nameColor = isDeprecated ? chalk16.dim : chalk16.white;
|
|
5094
5494
|
console.log(` ${statusIcon} ${nameColor(pattern.name)}`);
|
|
5095
|
-
console.log(
|
|
5096
|
-
console.log(
|
|
5495
|
+
console.log(chalk16.dim(` ID: ${pattern.id}`));
|
|
5496
|
+
console.log(chalk16.dim(` Category: ${pattern.category}`));
|
|
5097
5497
|
console.log(
|
|
5098
|
-
|
|
5498
|
+
chalk16.dim(` Created: ${formatDate(pattern.createdAt)}`)
|
|
5099
5499
|
);
|
|
5100
5500
|
console.log(
|
|
5101
|
-
|
|
5501
|
+
chalk16.dim(
|
|
5102
5502
|
` Success Rate: ${(pattern.metrics.successRate * 100).toFixed(0)}% (${pattern.metrics.successes}/${pattern.metrics.applications})`
|
|
5103
5503
|
)
|
|
5104
5504
|
);
|
|
5105
5505
|
if (pattern.tags.length > 0) {
|
|
5106
|
-
console.log(
|
|
5506
|
+
console.log(chalk16.dim(` Tags: ${formatTags(pattern.tags)}`));
|
|
5107
5507
|
}
|
|
5108
5508
|
console.log("");
|
|
5109
5509
|
}
|
|
5110
5510
|
} else if (patternType === "fix") {
|
|
5111
|
-
console.log(
|
|
5511
|
+
console.log(chalk16.dim(" No fix patterns found.\n"));
|
|
5112
5512
|
}
|
|
5113
5513
|
}
|
|
5114
5514
|
if (patternType === "all" || patternType === "blueprint") {
|
|
@@ -5118,46 +5518,46 @@ async function learnListCommand(options) {
|
|
|
5118
5518
|
includeDeprecated: showDeprecated
|
|
5119
5519
|
});
|
|
5120
5520
|
if (bpResult.success && bpResult.data && bpResult.data.length > 0) {
|
|
5121
|
-
console.log(
|
|
5521
|
+
console.log(chalk16.bold.blue("\u{1F4D0} Blueprints:\n"));
|
|
5122
5522
|
for (const blueprint of bpResult.data) {
|
|
5123
5523
|
const isDeprecated = blueprint.deprecatedAt !== void 0;
|
|
5124
5524
|
const statusIcon = isDeprecated ? "\u26A0\uFE0F" : "\u2713";
|
|
5125
|
-
const nameColor = isDeprecated ?
|
|
5525
|
+
const nameColor = isDeprecated ? chalk16.dim : chalk16.white;
|
|
5126
5526
|
console.log(` ${statusIcon} ${nameColor(blueprint.name)}`);
|
|
5127
|
-
console.log(
|
|
5128
|
-
console.log(
|
|
5527
|
+
console.log(chalk16.dim(` ID: ${blueprint.id}`));
|
|
5528
|
+
console.log(chalk16.dim(` Language: ${blueprint.stack.language}`));
|
|
5129
5529
|
console.log(
|
|
5130
|
-
|
|
5530
|
+
chalk16.dim(` Created: ${formatDate(blueprint.createdAt)}`)
|
|
5131
5531
|
);
|
|
5132
5532
|
console.log(
|
|
5133
|
-
|
|
5533
|
+
chalk16.dim(
|
|
5134
5534
|
` Success Rate: ${(blueprint.metrics.successRate * 100).toFixed(0)}% (${blueprint.metrics.successes}/${blueprint.metrics.applications})`
|
|
5135
5535
|
)
|
|
5136
5536
|
);
|
|
5137
5537
|
if (blueprint.tags.length > 0) {
|
|
5138
|
-
console.log(
|
|
5538
|
+
console.log(chalk16.dim(` Tags: ${formatTags(blueprint.tags)}`));
|
|
5139
5539
|
}
|
|
5140
5540
|
console.log("");
|
|
5141
5541
|
}
|
|
5142
5542
|
} else if (patternType === "blueprint") {
|
|
5143
|
-
console.log(
|
|
5543
|
+
console.log(chalk16.dim(" No blueprints found.\n"));
|
|
5144
5544
|
}
|
|
5145
5545
|
}
|
|
5146
5546
|
const stats = await store.getStats();
|
|
5147
5547
|
const totalPatterns = stats.totalFixes + stats.totalBlueprints;
|
|
5148
5548
|
const totalDeprecated = stats.deprecatedFixes + stats.deprecatedBlueprints;
|
|
5149
|
-
console.log(
|
|
5150
|
-
console.log(
|
|
5151
|
-
console.log(
|
|
5152
|
-
console.log(
|
|
5153
|
-
console.log(
|
|
5549
|
+
console.log(chalk16.dim("\u2501".repeat(40)));
|
|
5550
|
+
console.log(chalk16.dim(`Total: ${totalPatterns} patterns`));
|
|
5551
|
+
console.log(chalk16.dim(` Fix Patterns: ${stats.totalFixes}`));
|
|
5552
|
+
console.log(chalk16.dim(` Blueprints: ${stats.totalBlueprints}`));
|
|
5553
|
+
console.log(chalk16.dim(` Deprecated: ${totalDeprecated}`));
|
|
5154
5554
|
console.log("");
|
|
5155
5555
|
}
|
|
5156
5556
|
async function learnApplyCommand(patternId, options) {
|
|
5157
5557
|
const cwd = getWorkspacePath();
|
|
5158
5558
|
const store = new PatternStore2(cwd);
|
|
5159
5559
|
const telemetry = new TelemetryCollector2(cwd);
|
|
5160
|
-
console.log(
|
|
5560
|
+
console.log(chalk16.cyan("\n\u{1F527} Apply Learning Pattern\n"));
|
|
5161
5561
|
let pattern = await store.getFixPattern(patternId);
|
|
5162
5562
|
let patternType = "fix";
|
|
5163
5563
|
if (!pattern.success || !pattern.data) {
|
|
@@ -5166,21 +5566,21 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5166
5566
|
pattern = bpResult;
|
|
5167
5567
|
patternType = "blueprint";
|
|
5168
5568
|
} else {
|
|
5169
|
-
console.log(
|
|
5569
|
+
console.log(chalk16.red(`
|
|
5170
5570
|
\u274C Pattern not found: ${patternId}`));
|
|
5171
5571
|
console.log(
|
|
5172
|
-
|
|
5572
|
+
chalk16.dim(" Use 'workflow learn:list' to see available patterns")
|
|
5173
5573
|
);
|
|
5174
5574
|
process.exit(1);
|
|
5175
5575
|
}
|
|
5176
5576
|
}
|
|
5177
5577
|
const patternData = pattern.data;
|
|
5178
|
-
console.log(
|
|
5179
|
-
console.log(
|
|
5180
|
-
console.log(
|
|
5578
|
+
console.log(chalk16.white(` Pattern: ${patternData.name}`));
|
|
5579
|
+
console.log(chalk16.dim(` Type: ${patternType}`));
|
|
5580
|
+
console.log(chalk16.dim(` Description: ${patternData.description}`));
|
|
5181
5581
|
if (options.dryRun) {
|
|
5182
5582
|
console.log(
|
|
5183
|
-
|
|
5583
|
+
chalk16.yellow("\n\u{1F4CB} DRY-RUN MODE: No changes will be applied\n")
|
|
5184
5584
|
);
|
|
5185
5585
|
}
|
|
5186
5586
|
const framework = options.framework ?? patternData.compatibility.frameworks[0]?.name ?? "unknown";
|
|
@@ -5188,27 +5588,27 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5188
5588
|
await telemetry.recordApplication(patternId, patternType, framework, version);
|
|
5189
5589
|
if (patternType === "fix") {
|
|
5190
5590
|
const fixPattern = patternData;
|
|
5191
|
-
console.log(
|
|
5591
|
+
console.log(chalk16.cyan("\n\u{1F4CB} Solution Steps:\n"));
|
|
5192
5592
|
if (fixPattern.solution.steps) {
|
|
5193
5593
|
for (let i = 0; i < fixPattern.solution.steps.length; i++) {
|
|
5194
5594
|
const step = fixPattern.solution.steps[i];
|
|
5195
5595
|
console.log(
|
|
5196
|
-
|
|
5596
|
+
chalk16.white(` ${i + 1}. [${step.action}] ${step.description}`)
|
|
5197
5597
|
);
|
|
5198
5598
|
if (step.file) {
|
|
5199
|
-
console.log(
|
|
5599
|
+
console.log(chalk16.dim(` File: ${step.file}`));
|
|
5200
5600
|
}
|
|
5201
5601
|
}
|
|
5202
5602
|
}
|
|
5203
5603
|
} else {
|
|
5204
5604
|
const blueprint = patternData;
|
|
5205
|
-
console.log(
|
|
5605
|
+
console.log(chalk16.cyan("\n\u{1F4CB} Setup Steps:\n"));
|
|
5206
5606
|
if (blueprint.setup.steps) {
|
|
5207
5607
|
for (let i = 0; i < blueprint.setup.steps.length; i++) {
|
|
5208
5608
|
const step = blueprint.setup.steps[i];
|
|
5209
|
-
console.log(
|
|
5609
|
+
console.log(chalk16.white(` ${i + 1}. ${step.description}`));
|
|
5210
5610
|
if (step.command) {
|
|
5211
|
-
console.log(
|
|
5611
|
+
console.log(chalk16.dim(` Command: ${step.command}`));
|
|
5212
5612
|
}
|
|
5213
5613
|
}
|
|
5214
5614
|
}
|
|
@@ -5225,7 +5625,7 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5225
5625
|
if (confirmed) {
|
|
5226
5626
|
await store.updatePatternMetrics(patternId, patternType, true);
|
|
5227
5627
|
await telemetry.recordSuccess(patternId, patternType, framework, version);
|
|
5228
|
-
console.log(
|
|
5628
|
+
console.log(chalk16.green("\n\u2705 Pattern marked as successfully applied!"));
|
|
5229
5629
|
} else {
|
|
5230
5630
|
await store.updatePatternMetrics(patternId, patternType, false);
|
|
5231
5631
|
await telemetry.recordFailure(
|
|
@@ -5236,7 +5636,7 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5236
5636
|
"unknown"
|
|
5237
5637
|
);
|
|
5238
5638
|
console.log(
|
|
5239
|
-
|
|
5639
|
+
chalk16.yellow("\n\u26A0\uFE0F Pattern application marked as unsuccessful.")
|
|
5240
5640
|
);
|
|
5241
5641
|
}
|
|
5242
5642
|
}
|
|
@@ -5244,32 +5644,32 @@ async function learnApplyCommand(patternId, options) {
|
|
|
5244
5644
|
async function learnSyncCommand(options) {
|
|
5245
5645
|
const cwd = getWorkspacePath();
|
|
5246
5646
|
const contributorManager = new ContributorManager2(cwd);
|
|
5247
|
-
console.log(
|
|
5647
|
+
console.log(chalk16.cyan("\n\u{1F504} Sync Learning Patterns\n"));
|
|
5248
5648
|
const config = await contributorManager.getConfig();
|
|
5249
5649
|
if (!config.success || !config.data?.syncOptIn) {
|
|
5250
|
-
console.log(
|
|
5251
|
-
console.log(
|
|
5252
|
-
console.log(
|
|
5650
|
+
console.log(chalk16.yellow("\u26A0\uFE0F Sync is not enabled.\n"));
|
|
5651
|
+
console.log(chalk16.dim(" To enable sync, run:"));
|
|
5652
|
+
console.log(chalk16.dim(" workflow learn:config --enable-sync\n"));
|
|
5253
5653
|
console.log(
|
|
5254
|
-
|
|
5654
|
+
chalk16.dim(
|
|
5255
5655
|
" This allows you to share anonymized patterns with the community."
|
|
5256
5656
|
)
|
|
5257
5657
|
);
|
|
5258
5658
|
process.exit(0);
|
|
5259
5659
|
}
|
|
5260
5660
|
if (options.dryRun) {
|
|
5261
|
-
console.log(
|
|
5661
|
+
console.log(chalk16.yellow("\u{1F4CB} DRY-RUN MODE: No changes will be synced\n"));
|
|
5262
5662
|
}
|
|
5263
5663
|
const store = new PatternStore2(cwd);
|
|
5264
5664
|
const anonymizer = new PatternAnonymizer();
|
|
5265
5665
|
const { fixes, blueprints } = await store.getPatternsForSync();
|
|
5266
5666
|
console.log(
|
|
5267
|
-
|
|
5667
|
+
chalk16.dim(
|
|
5268
5668
|
` Patterns ready to sync: ${fixes.length} fixes, ${blueprints.length} blueprints`
|
|
5269
5669
|
)
|
|
5270
5670
|
);
|
|
5271
5671
|
if (options.push) {
|
|
5272
|
-
console.log(
|
|
5672
|
+
console.log(chalk16.cyan("\n\u{1F4E4} Pushing patterns...\n"));
|
|
5273
5673
|
let anonymizedFixes = 0;
|
|
5274
5674
|
let anonymizedBlueprints = 0;
|
|
5275
5675
|
for (const fix of fixes) {
|
|
@@ -5277,7 +5677,7 @@ async function learnSyncCommand(options) {
|
|
|
5277
5677
|
if (result.success) {
|
|
5278
5678
|
anonymizedFixes++;
|
|
5279
5679
|
if (!options.dryRun) {
|
|
5280
|
-
console.log(
|
|
5680
|
+
console.log(chalk16.dim(` \u2713 Anonymized: ${fix.name}`));
|
|
5281
5681
|
}
|
|
5282
5682
|
}
|
|
5283
5683
|
}
|
|
@@ -5286,73 +5686,73 @@ async function learnSyncCommand(options) {
|
|
|
5286
5686
|
if (result.success) {
|
|
5287
5687
|
anonymizedBlueprints++;
|
|
5288
5688
|
if (!options.dryRun) {
|
|
5289
|
-
console.log(
|
|
5689
|
+
console.log(chalk16.dim(` \u2713 Anonymized: ${bp.name}`));
|
|
5290
5690
|
}
|
|
5291
5691
|
}
|
|
5292
5692
|
}
|
|
5293
5693
|
console.log(
|
|
5294
|
-
|
|
5694
|
+
chalk16.green(
|
|
5295
5695
|
`
|
|
5296
5696
|
\u2705 Ready to push ${anonymizedFixes} fixes and ${anonymizedBlueprints} blueprints`
|
|
5297
5697
|
)
|
|
5298
5698
|
);
|
|
5299
|
-
console.log(
|
|
5699
|
+
console.log(chalk16.dim(" (Registry push not yet implemented)"));
|
|
5300
5700
|
}
|
|
5301
5701
|
if (options.pull) {
|
|
5302
|
-
console.log(
|
|
5303
|
-
console.log(
|
|
5702
|
+
console.log(chalk16.cyan("\n\u{1F4E5} Pulling patterns from registry...\n"));
|
|
5703
|
+
console.log(chalk16.dim(" (Registry pull not yet implemented)"));
|
|
5304
5704
|
}
|
|
5305
5705
|
if (!options.push && !options.pull) {
|
|
5306
5706
|
console.log(
|
|
5307
|
-
|
|
5707
|
+
chalk16.dim(" Specify --push to upload or --pull to download patterns.\n")
|
|
5308
5708
|
);
|
|
5309
5709
|
}
|
|
5310
5710
|
}
|
|
5311
5711
|
async function learnConfigCommand(options) {
|
|
5312
5712
|
const cwd = getWorkspacePath();
|
|
5313
5713
|
const contributorManager = new ContributorManager2(cwd);
|
|
5314
|
-
console.log(
|
|
5714
|
+
console.log(chalk16.cyan("\n\u2699\uFE0F Learning Configuration\n"));
|
|
5315
5715
|
if (options.enableSync) {
|
|
5316
5716
|
const result = await contributorManager.enableSync();
|
|
5317
5717
|
if (result.success) {
|
|
5318
|
-
console.log(
|
|
5718
|
+
console.log(chalk16.green("\u2705 Sync enabled"));
|
|
5319
5719
|
console.log(
|
|
5320
|
-
|
|
5720
|
+
chalk16.dim(" Your patterns will be anonymized before sharing.")
|
|
5321
5721
|
);
|
|
5322
5722
|
} else {
|
|
5323
|
-
console.log(
|
|
5723
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5324
5724
|
}
|
|
5325
5725
|
return;
|
|
5326
5726
|
}
|
|
5327
5727
|
if (options.disableSync) {
|
|
5328
5728
|
const result = await contributorManager.disableSync();
|
|
5329
5729
|
if (result.success) {
|
|
5330
|
-
console.log(
|
|
5730
|
+
console.log(chalk16.green("\u2705 Sync disabled"));
|
|
5331
5731
|
} else {
|
|
5332
|
-
console.log(
|
|
5732
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5333
5733
|
}
|
|
5334
5734
|
return;
|
|
5335
5735
|
}
|
|
5336
5736
|
if (options.enableTelemetry) {
|
|
5337
5737
|
const result = await contributorManager.enableTelemetry();
|
|
5338
5738
|
if (result.success) {
|
|
5339
|
-
console.log(
|
|
5739
|
+
console.log(chalk16.green("\u2705 Telemetry enabled"));
|
|
5340
5740
|
console.log(
|
|
5341
|
-
|
|
5741
|
+
chalk16.dim(
|
|
5342
5742
|
" Anonymous usage data helps improve pattern recommendations."
|
|
5343
5743
|
)
|
|
5344
5744
|
);
|
|
5345
5745
|
} else {
|
|
5346
|
-
console.log(
|
|
5746
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5347
5747
|
}
|
|
5348
5748
|
return;
|
|
5349
5749
|
}
|
|
5350
5750
|
if (options.disableTelemetry) {
|
|
5351
5751
|
const result = await contributorManager.disableTelemetry();
|
|
5352
5752
|
if (result.success) {
|
|
5353
|
-
console.log(
|
|
5753
|
+
console.log(chalk16.green("\u2705 Telemetry disabled"));
|
|
5354
5754
|
} else {
|
|
5355
|
-
console.log(
|
|
5755
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5356
5756
|
}
|
|
5357
5757
|
return;
|
|
5358
5758
|
}
|
|
@@ -5367,36 +5767,36 @@ async function learnConfigCommand(options) {
|
|
|
5367
5767
|
}
|
|
5368
5768
|
const result = await contributorManager.resetId();
|
|
5369
5769
|
if (result.success) {
|
|
5370
|
-
console.log(
|
|
5371
|
-
console.log(
|
|
5770
|
+
console.log(chalk16.green("\u2705 Contributor ID reset"));
|
|
5771
|
+
console.log(chalk16.dim(` New ID: ${result.data?.id}`));
|
|
5372
5772
|
} else {
|
|
5373
|
-
console.log(
|
|
5773
|
+
console.log(chalk16.red(`\u274C Failed: ${result.error}`));
|
|
5374
5774
|
}
|
|
5375
5775
|
return;
|
|
5376
5776
|
}
|
|
5377
5777
|
const config = await contributorManager.getConfig();
|
|
5378
5778
|
if (config.success && config.data) {
|
|
5379
|
-
console.log(
|
|
5380
|
-
console.log(
|
|
5381
|
-
console.log(
|
|
5779
|
+
console.log(chalk16.white(" Current Settings:\n"));
|
|
5780
|
+
console.log(chalk16.dim(` Contributor ID: ${config.data.id}`));
|
|
5781
|
+
console.log(chalk16.dim(` Created: ${formatDate(config.data.createdAt)}`));
|
|
5382
5782
|
console.log(
|
|
5383
|
-
|
|
5783
|
+
chalk16.dim(` Sync Enabled: ${config.data.syncOptIn ? "Yes" : "No"}`)
|
|
5384
5784
|
);
|
|
5385
5785
|
console.log(
|
|
5386
|
-
|
|
5786
|
+
chalk16.dim(
|
|
5387
5787
|
` Telemetry Enabled: ${config.data.telemetryEnabled ? "Yes" : "No"}`
|
|
5388
5788
|
)
|
|
5389
5789
|
);
|
|
5390
5790
|
if (config.data.syncEnabledAt) {
|
|
5391
5791
|
console.log(
|
|
5392
|
-
|
|
5792
|
+
chalk16.dim(
|
|
5393
5793
|
` Sync Enabled At: ${formatDate(config.data.syncEnabledAt)}`
|
|
5394
5794
|
)
|
|
5395
5795
|
);
|
|
5396
5796
|
}
|
|
5397
5797
|
} else {
|
|
5398
5798
|
console.log(
|
|
5399
|
-
|
|
5799
|
+
chalk16.dim(
|
|
5400
5800
|
" No configuration found. Settings will be created on first use.\n"
|
|
5401
5801
|
)
|
|
5402
5802
|
);
|
|
@@ -5405,7 +5805,7 @@ async function learnConfigCommand(options) {
|
|
|
5405
5805
|
async function learnDeprecateCommand(patternId, reason) {
|
|
5406
5806
|
const cwd = getWorkspacePath();
|
|
5407
5807
|
const store = new PatternStore2(cwd);
|
|
5408
|
-
console.log(
|
|
5808
|
+
console.log(chalk16.cyan("\n\u26A0\uFE0F Deprecate Pattern\n"));
|
|
5409
5809
|
let patternType = "fix";
|
|
5410
5810
|
let pattern = await store.getFixPattern(patternId);
|
|
5411
5811
|
if (!pattern.success || !pattern.data) {
|
|
@@ -5414,13 +5814,13 @@ async function learnDeprecateCommand(patternId, reason) {
|
|
|
5414
5814
|
pattern = bpResult;
|
|
5415
5815
|
patternType = "blueprint";
|
|
5416
5816
|
} else {
|
|
5417
|
-
console.log(
|
|
5817
|
+
console.log(chalk16.red(`
|
|
5418
5818
|
\u274C Pattern not found: ${patternId}`));
|
|
5419
5819
|
process.exit(1);
|
|
5420
5820
|
}
|
|
5421
5821
|
}
|
|
5422
|
-
console.log(
|
|
5423
|
-
console.log(
|
|
5822
|
+
console.log(chalk16.white(` Pattern: ${pattern.data.name}`));
|
|
5823
|
+
console.log(chalk16.dim(` Reason: ${reason}`));
|
|
5424
5824
|
const confirmed = await p11.confirm({
|
|
5425
5825
|
message: "Are you sure you want to deprecate this pattern?",
|
|
5426
5826
|
initialValue: false
|
|
@@ -5431,9 +5831,9 @@ async function learnDeprecateCommand(patternId, reason) {
|
|
|
5431
5831
|
}
|
|
5432
5832
|
const result = await store.deprecatePattern(patternId, patternType, reason);
|
|
5433
5833
|
if (result.success) {
|
|
5434
|
-
console.log(
|
|
5834
|
+
console.log(chalk16.green("\n\u2705 Pattern deprecated successfully"));
|
|
5435
5835
|
} else {
|
|
5436
|
-
console.log(
|
|
5836
|
+
console.log(chalk16.red(`
|
|
5437
5837
|
\u274C Failed: ${result.error}`));
|
|
5438
5838
|
process.exit(1);
|
|
5439
5839
|
}
|
|
@@ -5442,31 +5842,31 @@ async function learnStatsCommand() {
|
|
|
5442
5842
|
const cwd = getWorkspacePath();
|
|
5443
5843
|
const store = new PatternStore2(cwd);
|
|
5444
5844
|
const telemetry = new TelemetryCollector2(cwd);
|
|
5445
|
-
console.log(
|
|
5845
|
+
console.log(chalk16.cyan("\n\u{1F4CA} Learning Statistics\n"));
|
|
5446
5846
|
const storeStats = await store.getStats();
|
|
5447
5847
|
const totalPatterns = storeStats.totalFixes + storeStats.totalBlueprints;
|
|
5448
5848
|
const totalDeprecated = storeStats.deprecatedFixes + storeStats.deprecatedBlueprints;
|
|
5449
|
-
console.log(
|
|
5450
|
-
console.log(
|
|
5451
|
-
console.log(
|
|
5452
|
-
console.log(
|
|
5453
|
-
console.log(
|
|
5849
|
+
console.log(chalk16.bold.white(" Patterns:\n"));
|
|
5850
|
+
console.log(chalk16.dim(` Total: ${totalPatterns}`));
|
|
5851
|
+
console.log(chalk16.dim(` Fix Patterns: ${storeStats.totalFixes}`));
|
|
5852
|
+
console.log(chalk16.dim(` Blueprints: ${storeStats.totalBlueprints}`));
|
|
5853
|
+
console.log(chalk16.dim(` Deprecated: ${totalDeprecated}`));
|
|
5454
5854
|
const telemetryStats = await telemetry.getStats();
|
|
5455
|
-
console.log(
|
|
5456
|
-
console.log(
|
|
5855
|
+
console.log(chalk16.bold.white("\n Telemetry:\n"));
|
|
5856
|
+
console.log(chalk16.dim(` Pending Events: ${telemetryStats.pendingEvents}`));
|
|
5457
5857
|
console.log(
|
|
5458
|
-
|
|
5858
|
+
chalk16.dim(` Total Events Sent: ${telemetryStats.totalEventsSent}`)
|
|
5459
5859
|
);
|
|
5460
5860
|
if (telemetryStats.lastFlushAt) {
|
|
5461
5861
|
console.log(
|
|
5462
|
-
|
|
5862
|
+
chalk16.dim(` Last Flush: ${formatDate(telemetryStats.lastFlushAt)}`)
|
|
5463
5863
|
);
|
|
5464
5864
|
}
|
|
5465
5865
|
console.log("");
|
|
5466
5866
|
}
|
|
5467
5867
|
|
|
5468
5868
|
// src/cli/commands/solution.ts
|
|
5469
|
-
import
|
|
5869
|
+
import chalk17 from "chalk";
|
|
5470
5870
|
import * as p12 from "@clack/prompts";
|
|
5471
5871
|
import * as path2 from "path";
|
|
5472
5872
|
import {
|
|
@@ -5509,7 +5909,7 @@ function truncate(str, maxLen) {
|
|
|
5509
5909
|
async function solutionCaptureCommand(options) {
|
|
5510
5910
|
const cwd = getWorkspacePath2();
|
|
5511
5911
|
const store = new PatternStore3(cwd);
|
|
5512
|
-
console.log(
|
|
5912
|
+
console.log(chalk17.cyan("\n\u{1F4E6} Capture Solution Pattern\n"));
|
|
5513
5913
|
let targetPath = options.path;
|
|
5514
5914
|
if (!targetPath) {
|
|
5515
5915
|
const pathInput = await p12.text({
|
|
@@ -5617,22 +6017,22 @@ async function solutionCaptureCommand(options) {
|
|
|
5617
6017
|
keywords
|
|
5618
6018
|
);
|
|
5619
6019
|
spinner10.stop("Solution analyzed");
|
|
5620
|
-
console.log(
|
|
5621
|
-
console.log(
|
|
5622
|
-
console.log(`${
|
|
6020
|
+
console.log(chalk17.green("\n\u2713 Solution captured successfully!\n"));
|
|
6021
|
+
console.log(chalk17.dim("\u2500".repeat(50)));
|
|
6022
|
+
console.log(`${chalk17.bold("Name:")} ${pattern.name}`);
|
|
5623
6023
|
console.log(
|
|
5624
|
-
`${
|
|
6024
|
+
`${chalk17.bold("Category:")} ${formatCategory(pattern.category)}`
|
|
5625
6025
|
);
|
|
5626
6026
|
console.log(
|
|
5627
|
-
`${
|
|
6027
|
+
`${chalk17.bold("Files:")} ${pattern.implementation.files.length}`
|
|
5628
6028
|
);
|
|
5629
6029
|
console.log(
|
|
5630
|
-
`${
|
|
6030
|
+
`${chalk17.bold("Dependencies:")} ${pattern.implementation.dependencies.length}`
|
|
5631
6031
|
);
|
|
5632
6032
|
console.log(
|
|
5633
|
-
`${
|
|
6033
|
+
`${chalk17.bold("Framework:")} ${pattern.compatibility.framework || "generic"}`
|
|
5634
6034
|
);
|
|
5635
|
-
console.log(
|
|
6035
|
+
console.log(chalk17.dim("\u2500".repeat(50)));
|
|
5636
6036
|
const confirm10 = await p12.confirm({
|
|
5637
6037
|
message: "Save this solution pattern?",
|
|
5638
6038
|
initialValue: true
|
|
@@ -5642,12 +6042,12 @@ async function solutionCaptureCommand(options) {
|
|
|
5642
6042
|
process.exit(0);
|
|
5643
6043
|
}
|
|
5644
6044
|
await store.saveSolution(pattern);
|
|
5645
|
-
console.log(
|
|
6045
|
+
console.log(chalk17.green(`
|
|
5646
6046
|
\u2713 Solution saved with ID: ${pattern.id}
|
|
5647
6047
|
`));
|
|
5648
6048
|
} catch (error) {
|
|
5649
6049
|
spinner10.stop("Analysis failed");
|
|
5650
|
-
console.error(
|
|
6050
|
+
console.error(chalk17.red(`
|
|
5651
6051
|
\u2717 Error: ${error.message}
|
|
5652
6052
|
`));
|
|
5653
6053
|
process.exit(1);
|
|
@@ -5656,7 +6056,7 @@ async function solutionCaptureCommand(options) {
|
|
|
5656
6056
|
async function solutionSearchCommand(query, options) {
|
|
5657
6057
|
const cwd = getWorkspacePath2();
|
|
5658
6058
|
const store = new PatternStore3(cwd);
|
|
5659
|
-
console.log(
|
|
6059
|
+
console.log(chalk17.cyan("\n\u{1F50D} Search Solution Patterns\n"));
|
|
5660
6060
|
const keywords = query.split(/\s+/).filter((k) => k.length > 0);
|
|
5661
6061
|
const result = await store.searchSolutions(keywords, {
|
|
5662
6062
|
category: options.category,
|
|
@@ -5664,39 +6064,39 @@ async function solutionSearchCommand(query, options) {
|
|
|
5664
6064
|
limit: options.limit ?? 10
|
|
5665
6065
|
});
|
|
5666
6066
|
if (!result.success || !result.data) {
|
|
5667
|
-
console.error(
|
|
6067
|
+
console.error(chalk17.red(`
|
|
5668
6068
|
\u2717 Search failed: ${result.error}
|
|
5669
6069
|
`));
|
|
5670
6070
|
return;
|
|
5671
6071
|
}
|
|
5672
6072
|
const solutions = result.data;
|
|
5673
6073
|
if (solutions.length === 0) {
|
|
5674
|
-
console.log(
|
|
5675
|
-
console.log(
|
|
6074
|
+
console.log(chalk17.yellow("No solutions found matching your query.\n"));
|
|
6075
|
+
console.log(chalk17.dim("Try different keywords or fewer filters."));
|
|
5676
6076
|
return;
|
|
5677
6077
|
}
|
|
5678
|
-
console.log(
|
|
6078
|
+
console.log(chalk17.green(`Found ${solutions.length} solution(s):
|
|
5679
6079
|
`));
|
|
5680
|
-
console.log(
|
|
6080
|
+
console.log(chalk17.dim("\u2500".repeat(70)));
|
|
5681
6081
|
for (const solution of solutions) {
|
|
5682
6082
|
console.log(
|
|
5683
|
-
`${
|
|
6083
|
+
`${chalk17.bold(solution.name)} ${chalk17.dim(`(${solution.id.slice(0, 8)})`)}`
|
|
5684
6084
|
);
|
|
5685
6085
|
console.log(` ${formatCategory(solution.category)}`);
|
|
5686
|
-
console.log(` ${
|
|
6086
|
+
console.log(` ${chalk17.dim(truncate(solution.description, 60))}`);
|
|
5687
6087
|
console.log(
|
|
5688
6088
|
` Files: ${solution.implementation.files.length} | Framework: ${solution.compatibility.framework || "generic"} | Uses: ${solution.metrics.applications}`
|
|
5689
6089
|
);
|
|
5690
|
-
console.log(
|
|
6090
|
+
console.log(chalk17.dim("\u2500".repeat(70)));
|
|
5691
6091
|
}
|
|
5692
6092
|
console.log(
|
|
5693
|
-
|
|
6093
|
+
chalk17.dim("\nUse 'workflow solution:apply <id>' to apply a solution.")
|
|
5694
6094
|
);
|
|
5695
6095
|
}
|
|
5696
6096
|
async function solutionListCommand(options) {
|
|
5697
6097
|
const cwd = getWorkspacePath2();
|
|
5698
6098
|
const store = new PatternStore3(cwd);
|
|
5699
|
-
console.log(
|
|
6099
|
+
console.log(chalk17.cyan("\n\u{1F4CB} Solution Patterns\n"));
|
|
5700
6100
|
const result = await store.listSolutions({
|
|
5701
6101
|
category: options.category,
|
|
5702
6102
|
framework: options.framework,
|
|
@@ -5704,20 +6104,20 @@ async function solutionListCommand(options) {
|
|
|
5704
6104
|
limit: options.limit ?? 20
|
|
5705
6105
|
});
|
|
5706
6106
|
if (!result.success || !result.data) {
|
|
5707
|
-
console.error(
|
|
6107
|
+
console.error(chalk17.red(`
|
|
5708
6108
|
\u2717 List failed: ${result.error}
|
|
5709
6109
|
`));
|
|
5710
6110
|
return;
|
|
5711
6111
|
}
|
|
5712
6112
|
const solutions = result.data;
|
|
5713
6113
|
if (solutions.length === 0) {
|
|
5714
|
-
console.log(
|
|
6114
|
+
console.log(chalk17.yellow("No solutions found.\n"));
|
|
5715
6115
|
console.log(
|
|
5716
|
-
|
|
6116
|
+
chalk17.dim("Use 'workflow solution:capture' to capture a solution.")
|
|
5717
6117
|
);
|
|
5718
6118
|
return;
|
|
5719
6119
|
}
|
|
5720
|
-
console.log(
|
|
6120
|
+
console.log(chalk17.green(`${solutions.length} solution(s):
|
|
5721
6121
|
`));
|
|
5722
6122
|
const byCategory = /* @__PURE__ */ new Map();
|
|
5723
6123
|
for (const solution of solutions) {
|
|
@@ -5726,24 +6126,24 @@ async function solutionListCommand(options) {
|
|
|
5726
6126
|
byCategory.set(solution.category, list);
|
|
5727
6127
|
}
|
|
5728
6128
|
for (const [category, items] of byCategory) {
|
|
5729
|
-
console.log(
|
|
6129
|
+
console.log(chalk17.bold(`
|
|
5730
6130
|
${formatCategory(category)}`));
|
|
5731
|
-
console.log(
|
|
6131
|
+
console.log(chalk17.dim("\u2500".repeat(50)));
|
|
5732
6132
|
for (const solution of items) {
|
|
5733
|
-
const deprecated = solution.deprecatedAt ?
|
|
6133
|
+
const deprecated = solution.deprecatedAt ? chalk17.red(" [DEPRECATED]") : "";
|
|
5734
6134
|
console.log(
|
|
5735
|
-
` ${
|
|
6135
|
+
` ${chalk17.cyan(solution.id.slice(0, 8))} ${solution.name}${deprecated}`
|
|
5736
6136
|
);
|
|
5737
|
-
console.log(` ${
|
|
6137
|
+
console.log(` ${chalk17.dim(truncate(solution.description, 50))}`);
|
|
5738
6138
|
console.log(
|
|
5739
|
-
|
|
6139
|
+
chalk17.dim(
|
|
5740
6140
|
` Created: ${formatDate2(solution.createdAt)} | Files: ${solution.implementation.files.length}`
|
|
5741
6141
|
)
|
|
5742
6142
|
);
|
|
5743
6143
|
}
|
|
5744
6144
|
}
|
|
5745
6145
|
console.log(
|
|
5746
|
-
|
|
6146
|
+
chalk17.dim(
|
|
5747
6147
|
"\nUse 'workflow solution:search <query>' to find specific solutions."
|
|
5748
6148
|
)
|
|
5749
6149
|
);
|
|
@@ -5751,10 +6151,10 @@ ${formatCategory(category)}`));
|
|
|
5751
6151
|
async function solutionApplyCommand(solutionId, options) {
|
|
5752
6152
|
const cwd = getWorkspacePath2();
|
|
5753
6153
|
const store = new PatternStore3(cwd);
|
|
5754
|
-
console.log(
|
|
6154
|
+
console.log(chalk17.cyan("\n\u{1F680} Apply Solution Pattern\n"));
|
|
5755
6155
|
const result = await store.getSolution(solutionId);
|
|
5756
6156
|
if (!result.success || !result.data) {
|
|
5757
|
-
console.error(
|
|
6157
|
+
console.error(chalk17.red(`
|
|
5758
6158
|
\u2717 Solution not found: ${solutionId}
|
|
5759
6159
|
`));
|
|
5760
6160
|
process.exit(1);
|
|
@@ -5762,7 +6162,7 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5762
6162
|
const solution = result.data;
|
|
5763
6163
|
if (solution.deprecatedAt) {
|
|
5764
6164
|
console.log(
|
|
5765
|
-
|
|
6165
|
+
chalk17.yellow(
|
|
5766
6166
|
`\u26A0\uFE0F This solution is deprecated: ${solution.deprecationReason || "No reason provided"}
|
|
5767
6167
|
`
|
|
5768
6168
|
)
|
|
@@ -5776,34 +6176,34 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5776
6176
|
process.exit(0);
|
|
5777
6177
|
}
|
|
5778
6178
|
}
|
|
5779
|
-
console.log(
|
|
5780
|
-
console.log(
|
|
6179
|
+
console.log(chalk17.bold(`Solution: ${solution.name}`));
|
|
6180
|
+
console.log(chalk17.dim(solution.description));
|
|
5781
6181
|
console.log();
|
|
5782
|
-
console.log(
|
|
6182
|
+
console.log(chalk17.bold("Files to create:"));
|
|
5783
6183
|
const filesToApply = options.includeTests ? solution.implementation.files : solution.implementation.files.filter(
|
|
5784
6184
|
(f) => f.role !== "test"
|
|
5785
6185
|
);
|
|
5786
6186
|
for (const file of filesToApply) {
|
|
5787
|
-
console.log(
|
|
6187
|
+
console.log(chalk17.dim(` \u2022 ${file.path} (${file.role})`));
|
|
5788
6188
|
}
|
|
5789
6189
|
console.log();
|
|
5790
6190
|
if (solution.implementation.dependencies.length > 0) {
|
|
5791
|
-
console.log(
|
|
6191
|
+
console.log(chalk17.bold("Dependencies to install:"));
|
|
5792
6192
|
for (const dep of solution.implementation.dependencies) {
|
|
5793
|
-
console.log(
|
|
6193
|
+
console.log(chalk17.dim(` \u2022 ${dep.name}@${dep.version}`));
|
|
5794
6194
|
}
|
|
5795
6195
|
console.log();
|
|
5796
6196
|
}
|
|
5797
6197
|
if (solution.implementation.envVars.length > 0) {
|
|
5798
|
-
console.log(
|
|
6198
|
+
console.log(chalk17.bold("Environment variables needed:"));
|
|
5799
6199
|
for (const env of solution.implementation.envVars) {
|
|
5800
|
-
const required = env.required ?
|
|
5801
|
-
console.log(
|
|
6200
|
+
const required = env.required ? chalk17.red("*") : "";
|
|
6201
|
+
console.log(chalk17.dim(` \u2022 ${env.name}${required}`));
|
|
5802
6202
|
}
|
|
5803
6203
|
console.log();
|
|
5804
6204
|
}
|
|
5805
6205
|
if (options.dryRun) {
|
|
5806
|
-
console.log(
|
|
6206
|
+
console.log(chalk17.yellow("Dry run mode - no files were created.\n"));
|
|
5807
6207
|
return;
|
|
5808
6208
|
}
|
|
5809
6209
|
const confirm10 = await p12.confirm({
|
|
@@ -5828,19 +6228,19 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5828
6228
|
}
|
|
5829
6229
|
await store.updateSolutionMetrics(solution.id, true);
|
|
5830
6230
|
spinner10.stop("Solution applied");
|
|
5831
|
-
console.log(
|
|
6231
|
+
console.log(chalk17.green(`
|
|
5832
6232
|
\u2713 Solution applied successfully!
|
|
5833
6233
|
`));
|
|
5834
|
-
console.log(
|
|
6234
|
+
console.log(chalk17.dim(`Created ${filesToApply.length} file(s).`));
|
|
5835
6235
|
if (solution.implementation.dependencies.length > 0) {
|
|
5836
|
-
console.log(
|
|
6236
|
+
console.log(chalk17.cyan("\nNext step: Install dependencies with:"));
|
|
5837
6237
|
const deps = solution.implementation.dependencies.map((d) => `${d.name}@${d.version}`).join(" ");
|
|
5838
|
-
console.log(
|
|
6238
|
+
console.log(chalk17.dim(` npm install ${deps}`));
|
|
5839
6239
|
}
|
|
5840
6240
|
} catch (error) {
|
|
5841
6241
|
spinner10.stop("Application failed");
|
|
5842
6242
|
await store.updateSolutionMetrics(solution.id, false);
|
|
5843
|
-
console.error(
|
|
6243
|
+
console.error(chalk17.red(`
|
|
5844
6244
|
\u2717 Error: ${error.message}
|
|
5845
6245
|
`));
|
|
5846
6246
|
process.exit(1);
|
|
@@ -5849,16 +6249,16 @@ async function solutionApplyCommand(solutionId, options) {
|
|
|
5849
6249
|
async function solutionDeprecateCommand(solutionId, reason) {
|
|
5850
6250
|
const cwd = getWorkspacePath2();
|
|
5851
6251
|
const store = new PatternStore3(cwd);
|
|
5852
|
-
console.log(
|
|
6252
|
+
console.log(chalk17.cyan("\n\u26A0\uFE0F Deprecate Solution Pattern\n"));
|
|
5853
6253
|
const result = await store.getSolution(solutionId);
|
|
5854
6254
|
if (!result.success || !result.data) {
|
|
5855
|
-
console.error(
|
|
6255
|
+
console.error(chalk17.red(`
|
|
5856
6256
|
\u2717 Solution not found: ${solutionId}
|
|
5857
6257
|
`));
|
|
5858
6258
|
process.exit(1);
|
|
5859
6259
|
}
|
|
5860
6260
|
const solution = result.data;
|
|
5861
|
-
console.log(`Solution: ${
|
|
6261
|
+
console.log(`Solution: ${chalk17.bold(solution.name)}`);
|
|
5862
6262
|
console.log(`Reason: ${reason}
|
|
5863
6263
|
`);
|
|
5864
6264
|
const confirm10 = await p12.confirm({
|
|
@@ -5870,27 +6270,27 @@ async function solutionDeprecateCommand(solutionId, reason) {
|
|
|
5870
6270
|
process.exit(0);
|
|
5871
6271
|
}
|
|
5872
6272
|
await store.deprecateSolution(solutionId, reason);
|
|
5873
|
-
console.log(
|
|
6273
|
+
console.log(chalk17.green(`
|
|
5874
6274
|
\u2713 Solution deprecated.
|
|
5875
6275
|
`));
|
|
5876
6276
|
}
|
|
5877
6277
|
async function solutionStatsCommand() {
|
|
5878
6278
|
const cwd = getWorkspacePath2();
|
|
5879
6279
|
const store = new PatternStore3(cwd);
|
|
5880
|
-
console.log(
|
|
6280
|
+
console.log(chalk17.cyan("\n\u{1F4CA} Solution Pattern Statistics\n"));
|
|
5881
6281
|
const stats = await store.getStats();
|
|
5882
|
-
console.log(
|
|
5883
|
-
console.log(`${
|
|
6282
|
+
console.log(chalk17.dim("\u2500".repeat(40)));
|
|
6283
|
+
console.log(`${chalk17.bold("Solutions:")} ${stats.totalSolutions}`);
|
|
5884
6284
|
console.log(` Active: ${stats.totalSolutions - stats.deprecatedSolutions}`);
|
|
5885
6285
|
console.log(` Deprecated: ${stats.deprecatedSolutions}`);
|
|
5886
6286
|
console.log(` Private: ${stats.privateSolutions}`);
|
|
5887
6287
|
console.log(` Synced: ${stats.syncedSolutions}`);
|
|
5888
|
-
console.log(
|
|
5889
|
-
console.log(`${
|
|
5890
|
-
console.log(`${
|
|
5891
|
-
console.log(
|
|
6288
|
+
console.log(chalk17.dim("\u2500".repeat(40)));
|
|
6289
|
+
console.log(`${chalk17.bold("Fixes:")} ${stats.totalFixes}`);
|
|
6290
|
+
console.log(`${chalk17.bold("Blueprints:")} ${stats.totalBlueprints}`);
|
|
6291
|
+
console.log(chalk17.dim("\u2500".repeat(40)));
|
|
5892
6292
|
console.log(`
|
|
5893
|
-
${
|
|
6293
|
+
${chalk17.bold("By Category:")}`);
|
|
5894
6294
|
const listResult = await store.listSolutions({ limit: 1e3 });
|
|
5895
6295
|
if (listResult.success && listResult.data) {
|
|
5896
6296
|
const categories = /* @__PURE__ */ new Map();
|
|
@@ -5921,12 +6321,40 @@ program.command("validate <type>").description("Validate branch name, commit mes
|
|
|
5921
6321
|
"Offer improvement suggestions on validation errors"
|
|
5922
6322
|
).action(validateCommand);
|
|
5923
6323
|
program.command("config <action>").description("Manage workflow configuration").argument("<action>", "Action: get, set, add, remove").argument("[key]", "Config key").argument("[value]", "Config value").action(configCommand);
|
|
6324
|
+
program.command("config:fix").description("Automatically fix common configuration validation issues").action(async () => {
|
|
6325
|
+
const chalk18 = (await import("chalk")).default;
|
|
6326
|
+
const { autoFixConfigFile: autoFixConfigFile2 } = await import("../config/index.js");
|
|
6327
|
+
console.log(chalk18.bold.cyan("\n\u{1F527} Workflow Configuration Auto-Fix\n"));
|
|
6328
|
+
const result = await autoFixConfigFile2();
|
|
6329
|
+
if (result.success) {
|
|
6330
|
+
if (result.changes.length === 0) {
|
|
6331
|
+
console.log(chalk18.green("\u2713 Configuration is already valid!"));
|
|
6332
|
+
} else {
|
|
6333
|
+
console.log(chalk18.green("\u2713 Configuration fixed successfully!\n"));
|
|
6334
|
+
console.log(chalk18.dim("Changes made:"));
|
|
6335
|
+
for (const change of result.changes) {
|
|
6336
|
+
console.log(chalk18.dim(` \u2022 ${change}`));
|
|
6337
|
+
}
|
|
6338
|
+
console.log();
|
|
6339
|
+
}
|
|
6340
|
+
process.exit(0);
|
|
6341
|
+
} else {
|
|
6342
|
+
if (result.configPath) {
|
|
6343
|
+
console.log(chalk18.red(`\u2717 Failed to fix configuration: ${result.error}`));
|
|
6344
|
+
} else {
|
|
6345
|
+
console.log(chalk18.red("\u2717 No workflow configuration file found"));
|
|
6346
|
+
console.log(chalk18.yellow(" Run: workflow init"));
|
|
6347
|
+
}
|
|
6348
|
+
process.exit(1);
|
|
6349
|
+
}
|
|
6350
|
+
});
|
|
5924
6351
|
program.command("suggest").description("Submit an improvement suggestion").argument("<feedback>", "Your improvement suggestion").option("--author <author>", "Your name or username").option(
|
|
5925
6352
|
"--category <category>",
|
|
5926
6353
|
"Category: feature, bug, documentation, performance, other"
|
|
5927
6354
|
).action(suggestCommand);
|
|
5928
6355
|
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);
|
|
6356
|
+
program.command("doctor").description("Run health check and get optimization suggestions").option("--check-guidelines-only", "Only check guidelines presence").option("--fix", "Automatically fix validation issues in configuration").action(doctorCommand);
|
|
6357
|
+
program.command("hooks <action>").description("Manage git hooks").action(hooksCommand);
|
|
5930
6358
|
program.command("scope:create").description("Create a custom scope package").option("--name <name>", 'Package name (e.g., "fintech", "gaming")').option(
|
|
5931
6359
|
"--scopes <scopes>",
|
|
5932
6360
|
"Comma-separated scopes (format: name:description:emoji:category)"
|