fraim-framework 2.0.36 → 2.0.38

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.
Files changed (192) hide show
  1. package/bin/fraim.js +5 -52
  2. package/dist/registry/scripts/build-scripts-generator.js +205 -0
  3. package/dist/registry/scripts/fraim-config.js +61 -0
  4. package/dist/registry/scripts/generic-issues-api.js +100 -0
  5. package/dist/registry/scripts/openapi-generator.js +664 -0
  6. package/dist/registry/scripts/performance/profile-server.js +390 -0
  7. package/dist/scripts/build-stub-registry.js +108 -0
  8. package/dist/src/cli/commands/doctor.js +5 -5
  9. package/dist/src/cli/commands/init-project.js +74 -0
  10. package/dist/src/cli/commands/setup.js +176 -0
  11. package/dist/src/cli/commands/sync.js +33 -19
  12. package/dist/src/cli/commands/test-mcp.js +135 -0
  13. package/dist/src/cli/fraim.js +6 -0
  14. package/dist/src/cli/setup/auto-mcp-setup.js +367 -0
  15. package/dist/src/cli/setup/ide-detector.js +163 -0
  16. package/dist/src/cli/setup/mcp-config-generator.js +115 -0
  17. package/dist/src/cli/setup/token-validator.js +49 -0
  18. package/dist/test-utils.js +96 -0
  19. package/dist/tests/debug-tools.js +2 -2
  20. package/dist/tests/esm-compat.js +11 -0
  21. package/dist/tests/shared-server-utils.js +57 -0
  22. package/dist/tests/test-chalk-esm-issue.js +159 -0
  23. package/dist/tests/test-chalk-real-world.js +265 -0
  24. package/dist/tests/test-chalk-regression.js +2 -18
  25. package/dist/tests/test-chalk-resolution-issue.js +304 -0
  26. package/dist/tests/test-client-scripts-validation.js +27 -5
  27. package/dist/tests/test-complete-setup-flow.js +110 -0
  28. package/dist/tests/test-fraim-install-chalk-issue.js +254 -0
  29. package/dist/tests/test-ide-detector.js +46 -0
  30. package/dist/tests/test-improved-setup.js +121 -0
  31. package/dist/tests/test-mcp-config-generator.js +70 -0
  32. package/dist/tests/test-mcp-connection.js +58 -117
  33. package/dist/tests/test-mcp-issue-integration.js +2 -2
  34. package/dist/tests/test-mcp-lifecycle-methods.js +34 -100
  35. package/dist/tests/test-mcp-shared-server.js +308 -0
  36. package/dist/tests/test-npm-resolution-diagnostic.js +140 -0
  37. package/dist/tests/test-package-size.js +101 -0
  38. package/dist/tests/test-prep-issue.js +34 -1
  39. package/dist/tests/test-script-location-independence.js +39 -62
  40. package/dist/tests/test-server-utils.js +32 -0
  41. package/dist/tests/test-session-rehydration.js +2 -2
  42. package/dist/tests/test-setup-integration.js +98 -0
  43. package/dist/tests/test-standalone.js +2 -2
  44. package/dist/tests/test-stub-registry.js +136 -0
  45. package/dist/tests/test-sync-stubs.js +143 -0
  46. package/dist/tests/test-telemetry.js +2 -2
  47. package/dist/tests/test-token-validator.js +30 -0
  48. package/dist/tests/test-user-journey.js +2 -1
  49. package/package.json +7 -9
  50. package/registry/agent-guardrails.md +62 -62
  51. package/registry/scripts/code-quality-check.sh +559 -559
  52. package/registry/scripts/detect-tautological-tests.sh +38 -38
  53. package/registry/scripts/prep-issue.sh +61 -30
  54. package/registry/scripts/validate-openapi-limits.ts +366 -366
  55. package/registry/scripts/validate-test-coverage.ts +280 -280
  56. package/registry/scripts/verify-pr-comments.sh +70 -70
  57. package/registry/stubs/workflows/bootstrap/create-architecture.md +11 -0
  58. package/registry/stubs/workflows/bootstrap/detect-broken-windows.md +11 -0
  59. package/registry/stubs/workflows/bootstrap/evaluate-code-quality.md +11 -0
  60. package/registry/stubs/workflows/bootstrap/verify-test-coverage.md +11 -0
  61. package/registry/stubs/workflows/business-development/create-business-plan.md +11 -0
  62. package/registry/stubs/workflows/business-development/ideate-business-opportunity.md +11 -0
  63. package/registry/stubs/workflows/business-development/price-product.md +18 -0
  64. package/registry/stubs/workflows/convert-to-pdf.md +11 -0
  65. package/registry/stubs/workflows/customer-development/insight-analysis.md +11 -0
  66. package/registry/stubs/workflows/customer-development/insight-triage.md +11 -0
  67. package/registry/stubs/workflows/customer-development/interview-preparation.md +11 -0
  68. package/registry/stubs/workflows/customer-development/linkedin-outreach.md +11 -0
  69. package/registry/stubs/workflows/customer-development/strategic-brainstorming.md +11 -0
  70. package/registry/stubs/workflows/customer-development/thank-customers.md +11 -0
  71. package/registry/stubs/workflows/customer-development/weekly-newsletter.md +11 -0
  72. package/registry/stubs/workflows/deploy/cloud-deployment.md +11 -0
  73. package/registry/stubs/workflows/improve-fraim/contribute.md +11 -0
  74. package/registry/stubs/workflows/improve-fraim/file-issue.md +11 -0
  75. package/registry/stubs/workflows/marketing/content-creation.md +11 -0
  76. package/registry/stubs/workflows/marketing/hbr-article.md +11 -0
  77. package/registry/stubs/workflows/marketing/launch-checklist.md +11 -0
  78. package/registry/stubs/workflows/marketing/marketing-strategy.md +11 -0
  79. package/registry/stubs/workflows/marketing/storytelling.md +11 -0
  80. package/registry/stubs/workflows/performance/analyze-performance.md +11 -0
  81. package/registry/stubs/workflows/product-building/design.md +11 -0
  82. package/registry/stubs/workflows/product-building/implement.md +12 -0
  83. package/registry/stubs/workflows/product-building/iterate-on-pr-comments.md +11 -0
  84. package/registry/stubs/workflows/product-building/prep-issue.md +11 -0
  85. package/registry/stubs/workflows/product-building/prototype.md +11 -0
  86. package/registry/stubs/workflows/product-building/resolve.md +11 -0
  87. package/registry/stubs/workflows/product-building/retrospect.md +11 -0
  88. package/registry/stubs/workflows/product-building/spec.md +11 -0
  89. package/registry/stubs/workflows/product-building/test.md +11 -0
  90. package/registry/stubs/workflows/quality-assurance/browser-validation.md +11 -0
  91. package/registry/stubs/workflows/quality-assurance/iterative-improvement-cycle.md +11 -0
  92. package/registry/stubs/workflows/replicate/replicate-discovery.md +11 -0
  93. package/registry/stubs/workflows/replicate/replicate-to-issues.md +11 -0
  94. package/registry/stubs/workflows/reviewer/review-implementation-vs-design-spec.md +11 -0
  95. package/registry/stubs/workflows/reviewer/review-implementation-vs-feature-spec.md +11 -0
  96. package/registry/stubs/workflows/startup-credits/aws-activate-application.md +11 -0
  97. package/registry/stubs/workflows/startup-credits/google-cloud-application.md +11 -0
  98. package/registry/stubs/workflows/startup-credits/microsoft-azure-application.md +11 -0
  99. package/.github/workflows/ci.yml +0 -65
  100. package/.github/workflows/deploy-fraim.yml +0 -87
  101. package/.github/workflows/phase-change.yml +0 -251
  102. package/.github/workflows/status-change.yml +0 -68
  103. package/.github/workflows/sync-on-pr-review.yml +0 -66
  104. package/examples/simple-webapp/TESTING.md +0 -62
  105. package/examples/simple-webapp/example-test.ts +0 -186
  106. package/registry/github/workflows/ci.yml +0 -51
  107. package/registry/github/workflows/phase-change.yml +0 -251
  108. package/registry/github/workflows/status-change.yml +0 -68
  109. package/registry/github/workflows/sync-on-pr-review.yml +0 -66
  110. package/registry/mcp-template.jsonc +0 -29
  111. package/registry/rules/agent-success-criteria.md +0 -52
  112. package/registry/rules/agent-testing-guidelines.md +0 -502
  113. package/registry/rules/architecture.md +0 -52
  114. package/registry/rules/communication.md +0 -122
  115. package/registry/rules/continuous-learning.md +0 -55
  116. package/registry/rules/debugging-multitenancy-issues.md +0 -85
  117. package/registry/rules/ephemeral-execution.md +0 -57
  118. package/registry/rules/git-safe-commands.md +0 -34
  119. package/registry/rules/hitl-ppe-record-analysis.md +0 -302
  120. package/registry/rules/integrity-and-test-ethics.md +0 -275
  121. package/registry/rules/local-development.md +0 -254
  122. package/registry/rules/merge-requirements.md +0 -231
  123. package/registry/rules/simplicity.md +0 -118
  124. package/registry/rules/software-development-lifecycle.md +0 -105
  125. package/registry/rules/spike-first-development.md +0 -205
  126. package/registry/rules/successful-debugging-patterns.md +0 -491
  127. package/registry/rules/telemetry.md +0 -67
  128. package/registry/templates/bootstrap/ARCHITECTURE-TEMPLATE.md +0 -53
  129. package/registry/templates/bootstrap/CODE-QUALITY-REPORT-TEMPLATE.md +0 -37
  130. package/registry/templates/bootstrap/TEST-COVERAGE-REPORT-TEMPLATE.md +0 -35
  131. package/registry/templates/business-development/IDEATION-REPORT-TEMPLATE.md +0 -29
  132. package/registry/templates/business-development/PRICING-STRATEGY-TEMPLATE.md +0 -126
  133. package/registry/templates/customer-development/customer-interview-template.md +0 -99
  134. package/registry/templates/customer-development/follow-up-email-templates.md +0 -132
  135. package/registry/templates/customer-development/insight-analysis-template.md +0 -74
  136. package/registry/templates/customer-development/strategic-recommendations-template.md +0 -53
  137. package/registry/templates/customer-development/thank-you-email-template.html +0 -124
  138. package/registry/templates/customer-development/thank-you-note-template.md +0 -16
  139. package/registry/templates/customer-development/triage-log-template.md +0 -278
  140. package/registry/templates/customer-development/weekly-newsletter-template.html +0 -204
  141. package/registry/templates/evidence/Design-Evidence.md +0 -30
  142. package/registry/templates/evidence/Implementation-BugEvidence.md +0 -86
  143. package/registry/templates/evidence/Implementation-FeatureEvidence.md +0 -121
  144. package/registry/templates/evidence/Spec-Evidence.md +0 -19
  145. package/registry/templates/help/HelpNeeded.md +0 -14
  146. package/registry/templates/marketing/HBR-ARTICLE-TEMPLATE.md +0 -66
  147. package/registry/templates/replicate/implementation-checklist.md +0 -39
  148. package/registry/templates/replicate/use-cases-template.md +0 -88
  149. package/registry/templates/retrospective/RETROSPECTIVE-TEMPLATE.md +0 -55
  150. package/registry/templates/specs/BUGSPEC-TEMPLATE.md +0 -37
  151. package/registry/templates/specs/FEATURESPEC-TEMPLATE.md +0 -29
  152. package/registry/templates/specs/TECHSPEC-TEMPLATE.md +0 -39
  153. package/registry/workflows/bootstrap/create-architecture.md +0 -38
  154. package/registry/workflows/bootstrap/evaluate-code-quality.md +0 -36
  155. package/registry/workflows/bootstrap/verify-test-coverage.md +0 -37
  156. package/registry/workflows/business-development/create-business-plan.md +0 -737
  157. package/registry/workflows/business-development/ideate-business-opportunity.md +0 -55
  158. package/registry/workflows/business-development/price-product.md +0 -325
  159. package/registry/workflows/convert-to-pdf.md +0 -235
  160. package/registry/workflows/customer-development/insight-analysis.md +0 -156
  161. package/registry/workflows/customer-development/insight-triage.md +0 -933
  162. package/registry/workflows/customer-development/interview-preparation.md +0 -421
  163. package/registry/workflows/customer-development/linkedin-outreach.md +0 -593
  164. package/registry/workflows/customer-development/strategic-brainstorming.md +0 -146
  165. package/registry/workflows/customer-development/thank-customers.md +0 -203
  166. package/registry/workflows/customer-development/weekly-newsletter.md +0 -366
  167. package/registry/workflows/deploy/cloud-deployment.md +0 -310
  168. package/registry/workflows/improve-fraim/contribute.md +0 -32
  169. package/registry/workflows/improve-fraim/file-issue.md +0 -32
  170. package/registry/workflows/marketing/content-creation.md +0 -37
  171. package/registry/workflows/marketing/hbr-article.md +0 -73
  172. package/registry/workflows/marketing/launch-checklist.md +0 -37
  173. package/registry/workflows/marketing/marketing-strategy.md +0 -45
  174. package/registry/workflows/performance/analyze-performance.md +0 -65
  175. package/registry/workflows/product-building/design.md +0 -130
  176. package/registry/workflows/product-building/implement.md +0 -315
  177. package/registry/workflows/product-building/iterate-on-pr-comments.md +0 -70
  178. package/registry/workflows/product-building/prep-issue.md +0 -43
  179. package/registry/workflows/product-building/prototype.md +0 -60
  180. package/registry/workflows/product-building/resolve.md +0 -164
  181. package/registry/workflows/product-building/retrospect.md +0 -86
  182. package/registry/workflows/product-building/spec.md +0 -117
  183. package/registry/workflows/product-building/test.md +0 -120
  184. package/registry/workflows/quality-assurance/browser-validation.md +0 -221
  185. package/registry/workflows/quality-assurance/iterative-improvement-cycle.md +0 -562
  186. package/registry/workflows/replicate/replicate-discovery.md +0 -336
  187. package/registry/workflows/replicate/replicate-to-issues.md +0 -319
  188. package/registry/workflows/reviewer/review-implementation-vs-design-spec.md +0 -632
  189. package/registry/workflows/reviewer/review-implementation-vs-feature-spec.md +0 -669
  190. package/registry/workflows/startup-credits/aws-activate-application.md +0 -535
  191. package/registry/workflows/startup-credits/google-cloud-application.md +0 -647
  192. package/registry/workflows/startup-credits/microsoft-azure-application.md +0 -538
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setupCommand = exports.runSetup = void 0;
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const prompts_1 = __importDefault(require("prompts"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const os_1 = __importDefault(require("os"));
13
+ const token_validator_1 = require("../setup/token-validator");
14
+ const auto_mcp_setup_1 = require("../setup/auto-mcp-setup");
15
+ const script_sync_utils_1 = require("../../utils/script-sync-utils");
16
+ const version_utils_1 = require("../../utils/version-utils");
17
+ const promptForFraimKey = async () => {
18
+ console.log(chalk_1.default.blue('šŸ”‘ FRAIM Key Setup'));
19
+ console.log('FRAIM requires a valid API key to access workflows and features.\n');
20
+ let key = null;
21
+ let attempts = 0;
22
+ const maxAttempts = 3;
23
+ while (!key && attempts < maxAttempts) {
24
+ const keyResponse = await (0, prompts_1.default)({
25
+ type: 'password',
26
+ name: 'key',
27
+ message: attempts === 0
28
+ ? 'Enter your FRAIM key (required)'
29
+ : `Enter your FRAIM key (attempt ${attempts + 1}/${maxAttempts})`,
30
+ validate: (value) => {
31
+ if (!value)
32
+ return 'FRAIM key is required';
33
+ if ((0, token_validator_1.isValidTokenFormat)(value, 'fraim'))
34
+ return true;
35
+ return 'Please enter a valid FRAIM key (starts with fraim_)';
36
+ }
37
+ });
38
+ if (!keyResponse.key) {
39
+ console.log(chalk_1.default.red('\nāŒ FRAIM key is required to proceed.'));
40
+ console.log(chalk_1.default.gray('If you need a key, please email sid.mathur@gmail.com to request one.\n'));
41
+ const retry = await (0, prompts_1.default)({
42
+ type: 'confirm',
43
+ name: 'retry',
44
+ message: 'Would you like to try entering the FRAIM key again?',
45
+ initial: true
46
+ });
47
+ if (!retry.retry) {
48
+ console.log(chalk_1.default.red('Setup cancelled. Please obtain a FRAIM key and try again.'));
49
+ process.exit(1);
50
+ }
51
+ attempts++;
52
+ continue;
53
+ }
54
+ // Validate key
55
+ const isValid = await (0, token_validator_1.validateFraimKey)(keyResponse.key);
56
+ if (isValid) {
57
+ console.log(chalk_1.default.green('āœ… FRAIM key validated\n'));
58
+ return keyResponse.key;
59
+ }
60
+ else {
61
+ console.log(chalk_1.default.red('āŒ Invalid FRAIM key\n'));
62
+ attempts++;
63
+ }
64
+ }
65
+ console.log(chalk_1.default.red('\nāŒ Maximum attempts reached. Setup cancelled.'));
66
+ console.log(chalk_1.default.gray('Please ensure you have a valid FRAIM key and try again.'));
67
+ process.exit(1);
68
+ };
69
+ const saveGlobalConfig = (fraimKey) => {
70
+ const globalConfigDir = path_1.default.join(os_1.default.homedir(), '.fraim');
71
+ const globalConfigPath = path_1.default.join(globalConfigDir, 'config.json');
72
+ if (!fs_1.default.existsSync(globalConfigDir)) {
73
+ fs_1.default.mkdirSync(globalConfigDir, { recursive: true });
74
+ }
75
+ const config = {
76
+ version: (0, version_utils_1.getFraimVersion)(),
77
+ apiKey: fraimKey,
78
+ configuredAt: new Date().toISOString(),
79
+ userPreferences: {
80
+ autoSync: true,
81
+ backupConfigs: true
82
+ }
83
+ };
84
+ fs_1.default.writeFileSync(globalConfigPath, JSON.stringify(config, null, 2));
85
+ console.log(chalk_1.default.green('āœ… Global FRAIM configuration saved'));
86
+ };
87
+ const syncGlobalScripts = () => {
88
+ console.log(chalk_1.default.blue('šŸ”„ Syncing FRAIM scripts to user directory...'));
89
+ // Find registry path
90
+ let registryPath = path_1.default.join(__dirname, '../../../../registry');
91
+ if (!fs_1.default.existsSync(registryPath)) {
92
+ registryPath = path_1.default.join(__dirname, '../../../registry');
93
+ }
94
+ if (fs_1.default.existsSync(registryPath)) {
95
+ const syncResult = (0, script_sync_utils_1.syncScriptsToUserDirectory)(registryPath);
96
+ console.log(chalk_1.default.green(`āœ… Synced ${syncResult.synced} scripts to user directory.`));
97
+ if (syncResult.ephemeral > 0) {
98
+ console.log(chalk_1.default.gray(` ${syncResult.ephemeral} dependent scripts will use ephemeral execution.`));
99
+ }
100
+ }
101
+ else {
102
+ console.log(chalk_1.default.yellow('āš ļø Registry not found, skipping script sync.'));
103
+ }
104
+ };
105
+ const runSetup = async (options) => {
106
+ console.log(chalk_1.default.blue('šŸš€ Welcome to FRAIM! Let\'s get you set up.\n'));
107
+ // Show what we're about to do
108
+ console.log(chalk_1.default.yellow('šŸ“‹ This setup will:'));
109
+ console.log(chalk_1.default.gray(' • Validate your FRAIM and GitHub tokens'));
110
+ console.log(chalk_1.default.gray(' • Create global FRAIM configuration'));
111
+ console.log(chalk_1.default.gray(' • Detect and configure supported IDEs'));
112
+ console.log(chalk_1.default.gray(' • Sync FRAIM scripts to your system'));
113
+ console.log(chalk_1.default.gray(' • Set up MCP servers for AI integration\n'));
114
+ // Get FRAIM key
115
+ let fraimKey = options.key;
116
+ if (!fraimKey) {
117
+ fraimKey = await promptForFraimKey();
118
+ }
119
+ else {
120
+ if (!(0, token_validator_1.isValidTokenFormat)(fraimKey, 'fraim')) {
121
+ console.log(chalk_1.default.red('āŒ Invalid FRAIM key format. Key must start with fraim_'));
122
+ process.exit(1);
123
+ }
124
+ console.log(chalk_1.default.blue('šŸ”‘ Validating FRAIM key...'));
125
+ const isValid = await (0, token_validator_1.validateFraimKey)(fraimKey);
126
+ if (!isValid) {
127
+ console.log(chalk_1.default.red('āŒ Invalid FRAIM key'));
128
+ process.exit(1);
129
+ }
130
+ console.log(chalk_1.default.green('āœ… FRAIM key validated\n'));
131
+ }
132
+ // Get GitHub token
133
+ let githubToken = options.githubToken;
134
+ if (!githubToken) {
135
+ githubToken = await (0, auto_mcp_setup_1.promptForGitHubToken)();
136
+ }
137
+ else {
138
+ if (!(0, token_validator_1.isValidTokenFormat)(githubToken, 'github')) {
139
+ console.log(chalk_1.default.red('āŒ Invalid GitHub token format. Token must start with ghp_ or github_pat_'));
140
+ process.exit(1);
141
+ }
142
+ console.log(chalk_1.default.blue('šŸ” Validating GitHub token...'));
143
+ const isValid = await (0, token_validator_1.validateGitHubToken)(githubToken);
144
+ if (!isValid) {
145
+ console.log(chalk_1.default.red('āŒ Invalid GitHub token'));
146
+ process.exit(1);
147
+ }
148
+ console.log(chalk_1.default.green('āœ… GitHub token validated\n'));
149
+ }
150
+ // Save global configuration
151
+ console.log(chalk_1.default.blue('šŸ’¾ Saving global configuration...'));
152
+ saveGlobalConfig(fraimKey);
153
+ // Sync global scripts
154
+ syncGlobalScripts();
155
+ // Configure IDEs
156
+ const selectedIDEs = options.ide ? options.ide.split(',') : undefined;
157
+ const autoAll = options.all;
158
+ if (autoAll && selectedIDEs) {
159
+ console.log(chalk_1.default.yellow('āš ļø Both --all and --ide specified. Using --ide selection.'));
160
+ }
161
+ await (0, auto_mcp_setup_1.autoConfigureMCP)(fraimKey, githubToken, selectedIDEs);
162
+ console.log(chalk_1.default.green('\nšŸŽÆ Setup complete! Next steps:'));
163
+ console.log(chalk_1.default.cyan(' 1. Restart your configured IDEs'));
164
+ console.log(chalk_1.default.cyan(' 2. Go to any project directory'));
165
+ console.log(chalk_1.default.cyan(' 3. Run: fraim init-project'));
166
+ console.log(chalk_1.default.cyan(' 4. Ask your AI agent: "list fraim workflows"'));
167
+ console.log(chalk_1.default.blue('\nšŸ’” Use "fraim test-mcp" to verify your setup anytime.'));
168
+ };
169
+ exports.runSetup = runSetup;
170
+ exports.setupCommand = new commander_1.Command('setup')
171
+ .description('Complete global FRAIM setup with IDE configuration')
172
+ .option('--key <key>', 'FRAIM API key')
173
+ .option('--github-token <token>', 'GitHub Personal Access Token')
174
+ .option('--all', 'Auto-configure all detected IDEs')
175
+ .option('--ide <ides>', 'Configure specific IDEs (comma-separated: claude,cursor,kiro)')
176
+ .action(exports.runSetup);
@@ -9,7 +9,6 @@ const fs_1 = __importDefault(require("fs"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const chalk_1 = __importDefault(require("chalk"));
11
11
  const digest_utils_1 = require("../../utils/digest-utils");
12
- const stub_generator_1 = require("../../utils/stub-generator");
13
12
  const config_loader_1 = require("../../fraim/config-loader");
14
13
  const version_utils_1 = require("../../utils/version-utils");
15
14
  const script_sync_utils_1 = require("../../utils/script-sync-utils");
@@ -20,20 +19,20 @@ const runSync = async (options) => {
20
19
  const workflowsRelativePath = config.customizations?.workflowsPath || '.fraim/workflows';
21
20
  const workflowsDir = path_1.default.resolve(projectRoot, workflowsRelativePath);
22
21
  const digestPath = path_1.default.join(fraimDir, '.digest');
23
- // In a real npm package, registry would be in node_modules/@fraim/framework/registry
22
+ // In npm package, stubs are in node_modules/@fraim/framework/registry/stubs/workflows
24
23
  // We need to handle both "running from source" (src/cli/commands) and "running from dist" (dist/src/cli/commands)
25
24
  // Try 4 levels up (dist/src/cli/commands -> root)
26
- let registryPath = path_1.default.join(__dirname, '../../../../registry');
25
+ let registryPath = path_1.default.join(__dirname, '../../../../registry/stubs');
27
26
  if (!fs_1.default.existsSync(registryPath)) {
28
27
  // Try 3 levels up (src/cli/commands -> root)
29
- registryPath = path_1.default.join(__dirname, '../../../registry');
28
+ registryPath = path_1.default.join(__dirname, '../../../registry/stubs');
30
29
  }
31
30
  // Fallback for local development if running from within the framework repo itself
32
31
  if (!fs_1.default.existsSync(registryPath)) {
33
- registryPath = path_1.default.join(projectRoot, 'registry');
32
+ registryPath = path_1.default.join(projectRoot, 'registry/stubs');
34
33
  }
35
34
  if (!fs_1.default.existsSync(registryPath)) {
36
- console.error(chalk_1.default.red('āŒ Registry not found. Ensure @fraim/framework is installed.'));
35
+ console.error(chalk_1.default.red('āŒ Stub registry not found. Ensure @fraim/framework is installed and built.'));
37
36
  process.exit(1);
38
37
  }
39
38
  if (!fs_1.default.existsSync(workflowsDir)) {
@@ -64,10 +63,10 @@ const runSync = async (options) => {
64
63
  else {
65
64
  const registryWorkflowsPath = path_1.default.join(registryPath, 'workflows');
66
65
  if (!fs_1.default.existsSync(registryWorkflowsPath)) {
67
- console.log(chalk_1.default.yellow('āš ļø No workflows found in registry.'));
66
+ console.log(chalk_1.default.yellow('āš ļø No workflow stubs found in registry.'));
68
67
  }
69
68
  else {
70
- // Get all workflows from registry (recursive)
69
+ // Get all workflow stubs from registry (recursive)
71
70
  const getFiles = (dir) => {
72
71
  const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
73
72
  const files = entries
@@ -80,13 +79,12 @@ const runSync = async (options) => {
80
79
  return files;
81
80
  };
82
81
  const registryFiles = getFiles(registryWorkflowsPath);
83
- const generatedStubs = [];
82
+ const copiedStubs = [];
84
83
  for (const file of registryFiles) {
85
- const content = fs_1.default.readFileSync(file, 'utf8');
86
- const { intent, principles } = (0, stub_generator_1.parseRegistryWorkflow)(content);
84
+ // These are already stubs, just copy them directly
87
85
  const fileName = path_1.default.basename(file);
88
86
  const workflowName = fileName.replace('.md', '');
89
- // Calculate relative path from registry/workflows to preserve structure
87
+ // Calculate relative path from registry/stubs/workflows to preserve structure
90
88
  const relativePath = path_1.default.relative(registryWorkflowsPath, file);
91
89
  const relativeDir = path_1.default.dirname(relativePath);
92
90
  // Ensure target directory exists
@@ -94,10 +92,11 @@ const runSync = async (options) => {
94
92
  if (!fs_1.default.existsSync(targetDir)) {
95
93
  fs_1.default.mkdirSync(targetDir, { recursive: true });
96
94
  }
97
- const stubContent = (0, stub_generator_1.generateWorkflowStub)(workflowName, file, intent, principles);
95
+ // Copy stub file directly
96
+ const stubContent = fs_1.default.readFileSync(file, 'utf8');
98
97
  const stubPath = path_1.default.join(targetDir, fileName);
99
98
  fs_1.default.writeFileSync(stubPath, stubContent);
100
- generatedStubs.push(relativePath); // Store relative path for cleanup tracking
99
+ copiedStubs.push(relativePath); // Store relative path for cleanup tracking
101
100
  console.log(chalk_1.default.gray(` + ${workflowName} (${relativeDir === '.' ? 'root' : relativeDir})`));
102
101
  }
103
102
  // Cleanup stubs that no longer exist in registry
@@ -119,8 +118,8 @@ const runSync = async (options) => {
119
118
  for (const stub of localStubs) {
120
119
  // standardise path separators for comparison
121
120
  const normalizedStub = stub.replace(/\\/g, '/');
122
- const normalizedGenerated = generatedStubs.map(s => s.replace(/\\/g, '/'));
123
- if (!normalizedGenerated.includes(normalizedStub)) {
121
+ const normalizedCopied = copiedStubs.map(s => s.replace(/\\/g, '/'));
122
+ if (!normalizedCopied.includes(normalizedStub)) {
124
123
  fs_1.default.unlinkSync(path_1.default.join(workflowsDir, stub));
125
124
  console.log(chalk_1.default.yellow(` - ${stub} (removed from registry)`));
126
125
  // Cleanup empty directories
@@ -134,13 +133,28 @@ const runSync = async (options) => {
134
133
  }
135
134
  }
136
135
  fs_1.default.writeFileSync(digestPath, currentDigest);
137
- console.log(chalk_1.default.green(`\nāœ… Workflow sync complete. Generated ${generatedStubs.length} stubs.`));
136
+ console.log(chalk_1.default.green(`\nāœ… Workflow sync complete. Copied ${copiedStubs.length} stubs.`));
138
137
  }
139
138
  }
140
139
  // Always sync scripts, regardless of workflow sync status
141
140
  console.log(chalk_1.default.blue('\nšŸ”„ Syncing FRAIM scripts to user directory...'));
142
- const syncResult = (0, script_sync_utils_1.syncScriptsToUserDirectory)(registryPath);
143
- const cleanedScriptCount = (0, script_sync_utils_1.cleanupObsoleteUserScripts)(registryPath);
141
+ // Scripts are packaged separately from stubs, find the correct registry path
142
+ // Try 4 levels up (dist/src/cli/commands -> root)
143
+ let scriptsRegistryPath = path_1.default.join(__dirname, '../../../../registry');
144
+ if (!fs_1.default.existsSync(path_1.default.join(scriptsRegistryPath, 'scripts'))) {
145
+ // Try 3 levels up (src/cli/commands -> root)
146
+ scriptsRegistryPath = path_1.default.join(__dirname, '../../../registry');
147
+ }
148
+ // Fallback for local development if running from within the framework repo itself
149
+ if (!fs_1.default.existsSync(path_1.default.join(scriptsRegistryPath, 'scripts'))) {
150
+ scriptsRegistryPath = path_1.default.join(projectRoot, 'registry');
151
+ }
152
+ if (!fs_1.default.existsSync(path_1.default.join(scriptsRegistryPath, 'scripts'))) {
153
+ console.error(chalk_1.default.red('āŒ Scripts registry not found. Ensure @fraim/framework is installed and built.'));
154
+ process.exit(1);
155
+ }
156
+ const syncResult = (0, script_sync_utils_1.syncScriptsToUserDirectory)(scriptsRegistryPath);
157
+ const cleanedScriptCount = (0, script_sync_utils_1.cleanupObsoleteUserScripts)(scriptsRegistryPath);
144
158
  if (syncResult.synced > 0 || cleanedScriptCount > 0) {
145
159
  console.log(chalk_1.default.green(`āœ… Script sync complete. Updated ${syncResult.synced} scripts, removed ${cleanedScriptCount} obsolete scripts.`));
146
160
  }
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.testMCPCommand = exports.runTestMCP = void 0;
7
+ const commander_1 = require("commander");
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const os_1 = __importDefault(require("os"));
12
+ const ide_detector_1 = require("../setup/ide-detector");
13
+ const testIDEConfig = async (ide) => {
14
+ const result = {
15
+ ide: ide.name,
16
+ configExists: false,
17
+ configValid: false,
18
+ mcpServers: [],
19
+ errors: []
20
+ };
21
+ const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
22
+ if (!fs_1.default.existsSync(configPath)) {
23
+ result.errors.push('Config file does not exist');
24
+ return result;
25
+ }
26
+ result.configExists = true;
27
+ try {
28
+ if (ide.configFormat === 'json') {
29
+ const configContent = fs_1.default.readFileSync(configPath, 'utf8');
30
+ const config = JSON.parse(configContent);
31
+ if (config.mcpServers) {
32
+ result.configValid = true;
33
+ result.mcpServers = Object.keys(config.mcpServers);
34
+ }
35
+ else {
36
+ result.errors.push('No mcpServers section found');
37
+ }
38
+ }
39
+ else if (ide.configFormat === 'toml') {
40
+ const configContent = fs_1.default.readFileSync(configPath, 'utf8');
41
+ // Simple TOML parsing for MCP servers
42
+ const serverMatches = configContent.match(/\[mcp_servers\.(\w+)\]/g);
43
+ if (serverMatches) {
44
+ result.configValid = true;
45
+ result.mcpServers = serverMatches.map(match => match.replace(/\[mcp_servers\.(\w+)\]/, '$1'));
46
+ }
47
+ else {
48
+ result.errors.push('No mcp_servers sections found');
49
+ }
50
+ }
51
+ }
52
+ catch (error) {
53
+ result.errors.push(`Failed to parse config: ${error instanceof Error ? error.message : 'Unknown error'}`);
54
+ }
55
+ return result;
56
+ };
57
+ const checkGlobalSetup = () => {
58
+ const globalConfigPath = path_1.default.join(os_1.default.homedir(), '.fraim', 'config.json');
59
+ return fs_1.default.existsSync(globalConfigPath);
60
+ };
61
+ const runTestMCP = async () => {
62
+ console.log(chalk_1.default.blue('šŸ” Testing MCP configuration...\n'));
63
+ // Check global setup
64
+ if (!checkGlobalSetup()) {
65
+ console.log(chalk_1.default.red('āŒ Global FRAIM setup not found.'));
66
+ console.log(chalk_1.default.yellow('Please run: fraim setup --key=<your-fraim-key>'));
67
+ return;
68
+ }
69
+ console.log(chalk_1.default.green('āœ… Global FRAIM setup found'));
70
+ // Detect IDEs
71
+ const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
72
+ if (detectedIDEs.length === 0) {
73
+ console.log(chalk_1.default.yellow('āš ļø No supported IDEs detected.'));
74
+ return;
75
+ }
76
+ console.log(chalk_1.default.blue(`\nšŸ” Testing ${detectedIDEs.length} detected IDEs...\n`));
77
+ const results = await Promise.all(detectedIDEs.map(ide => testIDEConfig(ide)));
78
+ let totalConfigured = 0;
79
+ let totalWithFRAIM = 0;
80
+ for (const result of results) {
81
+ console.log(chalk_1.default.white(`šŸ“± ${result.ide}`));
82
+ if (!result.configExists) {
83
+ console.log(chalk_1.default.red(' āŒ No MCP config found'));
84
+ console.log(chalk_1.default.gray(` šŸ’” Run: fraim setup --ide=${result.ide.toLowerCase()}`));
85
+ }
86
+ else if (!result.configValid) {
87
+ console.log(chalk_1.default.yellow(' āš ļø Config exists but invalid'));
88
+ result.errors.forEach(error => {
89
+ console.log(chalk_1.default.red(` āŒ ${error}`));
90
+ });
91
+ }
92
+ else {
93
+ totalConfigured++;
94
+ console.log(chalk_1.default.green(` āœ… MCP config valid (${result.mcpServers.length} servers)`));
95
+ // Check for essential servers
96
+ const essentialServers = ['fraim', 'git', 'github', 'playwright'];
97
+ const hasEssential = essentialServers.filter(server => result.mcpServers.includes(server));
98
+ if (hasEssential.includes('fraim')) {
99
+ totalWithFRAIM++;
100
+ console.log(chalk_1.default.green(' āœ… FRAIM server configured'));
101
+ }
102
+ else {
103
+ console.log(chalk_1.default.yellow(' āš ļø FRAIM server missing'));
104
+ }
105
+ if (hasEssential.length > 1) {
106
+ console.log(chalk_1.default.green(` āœ… ${hasEssential.length - 1} additional servers: ${hasEssential.filter(s => s !== 'fraim').join(', ')}`));
107
+ }
108
+ const missingEssential = essentialServers.filter(server => !result.mcpServers.includes(server));
109
+ if (missingEssential.length > 0) {
110
+ console.log(chalk_1.default.yellow(` āš ļø Missing servers: ${missingEssential.join(', ')}`));
111
+ }
112
+ }
113
+ console.log(); // Empty line
114
+ }
115
+ // Summary
116
+ console.log(chalk_1.default.blue('šŸ“Š Summary:'));
117
+ console.log(chalk_1.default.green(` āœ… ${totalConfigured}/${detectedIDEs.length} IDEs have valid MCP configs`));
118
+ console.log(chalk_1.default.green(` āœ… ${totalWithFRAIM}/${detectedIDEs.length} IDEs have FRAIM configured`));
119
+ if (totalWithFRAIM === 0) {
120
+ console.log(chalk_1.default.red('\nāŒ No IDEs have FRAIM configured!'));
121
+ console.log(chalk_1.default.yellow('šŸ’” Run: fraim setup --key=<your-fraim-key>'));
122
+ }
123
+ else if (totalWithFRAIM < detectedIDEs.length) {
124
+ console.log(chalk_1.default.yellow(`\nāš ļø ${detectedIDEs.length - totalWithFRAIM} IDEs missing FRAIM configuration`));
125
+ console.log(chalk_1.default.yellow('šŸ’” Run: fraim setup to configure remaining IDEs'));
126
+ }
127
+ else {
128
+ console.log(chalk_1.default.green('\nšŸŽ‰ All detected IDEs have FRAIM configured!'));
129
+ console.log(chalk_1.default.blue('šŸ’” Try running: fraim init-project in any project'));
130
+ }
131
+ };
132
+ exports.runTestMCP = runTestMCP;
133
+ exports.testMCPCommand = new commander_1.Command('test-mcp')
134
+ .description('Test MCP server configurations for all detected IDEs')
135
+ .action(exports.runTestMCP);
@@ -10,6 +10,9 @@ const sync_1 = require("./commands/sync");
10
10
  const doctor_1 = require("./commands/doctor");
11
11
  const list_1 = require("./commands/list");
12
12
  const wizard_1 = require("./commands/wizard");
13
+ const setup_1 = require("./commands/setup");
14
+ const init_project_1 = require("./commands/init-project");
15
+ const test_mcp_1 = require("./commands/test-mcp");
13
16
  const fs_1 = __importDefault(require("fs"));
14
17
  const path_1 = __importDefault(require("path"));
15
18
  const program = new commander_1.Command();
@@ -42,4 +45,7 @@ program.addCommand(sync_1.syncCommand);
42
45
  program.addCommand(doctor_1.doctorCommand);
43
46
  program.addCommand(list_1.listCommand);
44
47
  program.addCommand(wizard_1.wizardCommand);
48
+ program.addCommand(setup_1.setupCommand);
49
+ program.addCommand(init_project_1.initProjectCommand);
50
+ program.addCommand(test_mcp_1.testMCPCommand);
45
51
  program.parse(process.argv);