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
@@ -124,17 +124,9 @@ try {
124
124
  }
125
125
 
126
126
  try {
127
- const fraimBin = require('./node_modules/fraim-framework/bin/fraim.js');
127
+ const fraimCli = require('./node_modules/fraim-framework/dist/src/cli/fraim.js');
128
128
  console.log('โœ“ FRAIM CLI loaded successfully');
129
129
  console.log('โœ“ No ERR_REQUIRE_ESM error');
130
-
131
- // Test that we can access the loadCli function
132
- if (fraimBin && typeof fraimBin.loadCli === 'function') {
133
- console.log('โœ“ loadCli function available');
134
- } else {
135
- console.log('โš ๏ธ loadCli function not found, but require succeeded');
136
- }
137
-
138
130
  process.exit(0);
139
131
  } catch (error) {
140
132
  if (error.code === 'ERR_REQUIRE_ESM') {
@@ -287,16 +279,8 @@ async function testFreshInstall() {
287
279
  console.log(' ๐Ÿš€ Testing if fraim CLI can be required...');
288
280
  const testScript = `
289
281
  try {
290
- const fraimBin = require('./node_modules/fraim-framework/bin/fraim.js');
282
+ const fraimCli = require('./node_modules/fraim-framework/dist/src/cli/fraim.js');
291
283
  console.log('โœ“ FRAIM CLI loaded successfully');
292
-
293
- // Test that we can access the loadCli function
294
- if (fraimBin && typeof fraimBin.loadCli === 'function') {
295
- console.log('โœ“ loadCli function available');
296
- } else {
297
- console.log('โš ๏ธ loadCli function not found, but require succeeded');
298
- }
299
-
300
284
  process.exit(0);
301
285
  } catch (error) {
302
286
  if (error.code === 'ERR_REQUIRE_ESM') {
@@ -0,0 +1,304 @@
1
+ "use strict";
2
+ /**
3
+ * Test to reproduce and verify the fix for the chalk v5 resolution issue
4
+ *
5
+ * This test creates a scenario where npm might resolve chalk to v5 by:
6
+ * 1. Creating a dependency that requires chalk v5
7
+ * 2. Testing if fraim-framework with ^4.1.2 gets upgraded
8
+ * 3. Testing if fraim-framework with 4.1.2 (pinned) stays at v4
9
+ */
10
+ var __importDefault = (this && this.__importDefault) || function (mod) {
11
+ return (mod && mod.__esModule) ? mod : { "default": mod };
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ const node_child_process_1 = require("node:child_process");
15
+ const test_utils_1 = require("./test-utils");
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const os_1 = __importDefault(require("os"));
19
+ async function runCommand(command, args, cwd) {
20
+ return new Promise((resolve) => {
21
+ const proc = (0, node_child_process_1.spawn)(command, args, {
22
+ cwd,
23
+ stdio: 'pipe',
24
+ shell: true
25
+ });
26
+ let stdout = '';
27
+ let stderr = '';
28
+ proc.stdout?.on('data', (data) => {
29
+ stdout += data.toString();
30
+ });
31
+ proc.stderr?.on('data', (data) => {
32
+ stderr += data.toString();
33
+ });
34
+ proc.on('close', (code) => {
35
+ resolve({ code, stdout, stderr });
36
+ });
37
+ });
38
+ }
39
+ async function testChalkResolutionWithConflict() {
40
+ console.log(' ๐Ÿงช Testing chalk resolution with conflicting dependency...');
41
+ const tempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'chalk-conflict-'));
42
+ console.log(` ๐Ÿ“‚ Created temp dir: ${tempDir}`);
43
+ try {
44
+ // 1. Create a package that depends on chalk v5
45
+ console.log(' ๐Ÿ“ฆ Creating fake package that requires chalk v5...');
46
+ const fakePackageDir = path_1.default.join(tempDir, 'fake-chalk5-package');
47
+ fs_1.default.mkdirSync(fakePackageDir, { recursive: true });
48
+ const fakePackageJson = {
49
+ name: 'fake-chalk5-package',
50
+ version: '1.0.0',
51
+ dependencies: {
52
+ 'chalk': '^5.0.0'
53
+ }
54
+ };
55
+ fs_1.default.writeFileSync(path_1.default.join(fakePackageDir, 'package.json'), JSON.stringify(fakePackageJson, null, 2));
56
+ // Create a simple index.js that uses chalk
57
+ fs_1.default.writeFileSync(path_1.default.join(fakePackageDir, 'index.js'), 'export { default as chalk } from "chalk";\n');
58
+ // 2. Pack fraim-framework with ^4.1.2 (unpinned)
59
+ console.log(' ๐Ÿ“ฆ Packing fraim-framework with ^4.1.2...');
60
+ const projectRoot = process.cwd();
61
+ const packageJsonPath = path_1.default.join(projectRoot, 'package.json');
62
+ const originalPackageJson = fs_1.default.readFileSync(packageJsonPath, 'utf-8');
63
+ const packageJson = JSON.parse(originalPackageJson);
64
+ // Temporarily change to ^4.1.2
65
+ packageJson.dependencies.chalk = '^4.1.2';
66
+ fs_1.default.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
67
+ const packResult = (0, node_child_process_1.execSync)('npm pack', {
68
+ cwd: projectRoot,
69
+ encoding: 'utf-8'
70
+ });
71
+ const tarballName = packResult.trim().split('\n').pop()?.trim();
72
+ if (!tarballName) {
73
+ fs_1.default.writeFileSync(packageJsonPath, originalPackageJson);
74
+ return false;
75
+ }
76
+ const tarballPath = path_1.default.join(projectRoot, tarballName);
77
+ // Restore original package.json
78
+ fs_1.default.writeFileSync(packageJsonPath, originalPackageJson);
79
+ // 3. Create test project that depends on BOTH packages
80
+ console.log(' ๐Ÿ”ง Creating test project with conflicting dependencies...');
81
+ const testPackageJson = {
82
+ name: 'chalk-conflict-test',
83
+ version: '1.0.0',
84
+ dependencies: {
85
+ 'fake-chalk5-package': 'file:./fake-chalk5-package',
86
+ 'fraim-framework': `file:${tarballPath}`
87
+ }
88
+ };
89
+ fs_1.default.writeFileSync(path_1.default.join(tempDir, 'package.json'), JSON.stringify(testPackageJson, null, 2));
90
+ // 4. Install dependencies - npm will try to resolve chalk
91
+ console.log(' ๐Ÿ“ฅ Installing with conflicting chalk requirements...');
92
+ console.log(' โš ๏ธ fake-chalk5-package wants chalk ^5.0.0');
93
+ console.log(' โš ๏ธ fraim-framework wants chalk ^4.1.2');
94
+ const installResult = await runCommand('npm', ['install'], tempDir);
95
+ if (installResult.code !== 0) {
96
+ console.log(' โš ๏ธ npm install failed (might be expected)');
97
+ console.log(` stderr: ${installResult.stderr.substring(0, 300)}`);
98
+ }
99
+ // 5. Check what version of chalk was installed for fraim-framework
100
+ const fraimChalkPath = path_1.default.join(tempDir, 'node_modules', 'fraim-framework', 'node_modules', 'chalk', 'package.json');
101
+ const rootChalkPath = path_1.default.join(tempDir, 'node_modules', 'chalk', 'package.json');
102
+ let fraimChalkVersion = null;
103
+ let rootChalkVersion = null;
104
+ if (fs_1.default.existsSync(fraimChalkPath)) {
105
+ const chalkPkg = JSON.parse(fs_1.default.readFileSync(fraimChalkPath, 'utf-8'));
106
+ fraimChalkVersion = chalkPkg.version;
107
+ console.log(` ๐Ÿ“‹ fraim-framework's chalk: ${fraimChalkVersion}`);
108
+ }
109
+ if (fs_1.default.existsSync(rootChalkPath)) {
110
+ const chalkPkg = JSON.parse(fs_1.default.readFileSync(rootChalkPath, 'utf-8'));
111
+ rootChalkVersion = chalkPkg.version;
112
+ console.log(` ๐Ÿ“‹ Root chalk: ${rootChalkVersion}`);
113
+ }
114
+ // 6. Try to load fraim CLI
115
+ console.log(' ๐Ÿš€ Testing if fraim CLI loads...');
116
+ const testScript = `
117
+ try {
118
+ const fraimCli = require('./node_modules/fraim-framework/dist/src/cli/fraim.js');
119
+ console.log('SUCCESS: fraim CLI loaded');
120
+ process.exit(0);
121
+ } catch (error) {
122
+ if (error.code === 'ERR_REQUIRE_ESM') {
123
+ console.log('ERROR: ERR_REQUIRE_ESM - chalk v5 was used!');
124
+ console.log('Chalk version caused issue:', error.message);
125
+ process.exit(1);
126
+ } else {
127
+ console.log('ERROR: Other error:', error.message);
128
+ process.exit(2);
129
+ }
130
+ }
131
+ `;
132
+ fs_1.default.writeFileSync(path_1.default.join(tempDir, 'test.js'), testScript);
133
+ const testResult = await runCommand('node', ['test.js'], tempDir);
134
+ if (testResult.code === 1) {
135
+ console.log(' โŒ REPRODUCED THE BUG! npm resolved chalk to v5');
136
+ console.log(' โŒ fraim-framework with ^4.1.2 got chalk v5 due to conflict');
137
+ console.log(' โœ… This proves the issue exists with ^4.1.2');
138
+ // Cleanup
139
+ fs_1.default.unlinkSync(tarballPath);
140
+ return true; // We successfully reproduced the bug!
141
+ }
142
+ else if (testResult.code === 0) {
143
+ console.log(' โ„น๏ธ fraim CLI loaded successfully');
144
+ console.log(' โ„น๏ธ npm resolved the conflict without upgrading to v5');
145
+ console.log(' โ„น๏ธ This scenario didn\'t trigger the bug, but it could in other environments');
146
+ }
147
+ else {
148
+ console.log(' โš ๏ธ Got unexpected error');
149
+ console.log(` stdout: ${testResult.stdout}`);
150
+ }
151
+ // Cleanup
152
+ fs_1.default.unlinkSync(tarballPath);
153
+ return true;
154
+ }
155
+ catch (error) {
156
+ console.error(' โŒ Test failed with error:', error);
157
+ return false;
158
+ }
159
+ finally {
160
+ try {
161
+ fs_1.default.rmSync(tempDir, { recursive: true, force: true });
162
+ console.log(' ๐Ÿงน Cleaned up temp directory');
163
+ }
164
+ catch (e) {
165
+ console.log(' โš ๏ธ Could not clean up temp directory');
166
+ }
167
+ }
168
+ }
169
+ async function testChalkResolutionWithPinnedVersion() {
170
+ console.log(' ๐Ÿงช Testing chalk resolution with PINNED version (4.1.2)...');
171
+ const tempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'chalk-pinned-'));
172
+ console.log(` ๐Ÿ“‚ Created temp dir: ${tempDir}`);
173
+ try {
174
+ // 1. Create a package that depends on chalk v5
175
+ console.log(' ๐Ÿ“ฆ Creating fake package that requires chalk v5...');
176
+ const fakePackageDir = path_1.default.join(tempDir, 'fake-chalk5-package');
177
+ fs_1.default.mkdirSync(fakePackageDir, { recursive: true });
178
+ const fakePackageJson = {
179
+ name: 'fake-chalk5-package',
180
+ version: '1.0.0',
181
+ dependencies: {
182
+ 'chalk': '^5.0.0'
183
+ }
184
+ };
185
+ fs_1.default.writeFileSync(path_1.default.join(fakePackageDir, 'package.json'), JSON.stringify(fakePackageJson, null, 2));
186
+ fs_1.default.writeFileSync(path_1.default.join(fakePackageDir, 'index.js'), 'export { default as chalk } from "chalk";\n');
187
+ // 2. Pack fraim-framework with 4.1.2 (PINNED - current state)
188
+ console.log(' ๐Ÿ“ฆ Packing fraim-framework with pinned 4.1.2...');
189
+ const projectRoot = process.cwd();
190
+ const packResult = (0, node_child_process_1.execSync)('npm pack', {
191
+ cwd: projectRoot,
192
+ encoding: 'utf-8'
193
+ });
194
+ const tarballName = packResult.trim().split('\n').pop()?.trim();
195
+ if (!tarballName) {
196
+ return false;
197
+ }
198
+ const tarballPath = path_1.default.join(projectRoot, tarballName);
199
+ // 3. Create test project with conflicting dependencies
200
+ console.log(' ๐Ÿ”ง Creating test project with conflicting dependencies...');
201
+ const testPackageJson = {
202
+ name: 'chalk-pinned-test',
203
+ version: '1.0.0',
204
+ dependencies: {
205
+ 'fake-chalk5-package': 'file:./fake-chalk5-package',
206
+ 'fraim-framework': `file:${tarballPath}`
207
+ }
208
+ };
209
+ fs_1.default.writeFileSync(path_1.default.join(tempDir, 'package.json'), JSON.stringify(testPackageJson, null, 2));
210
+ // 4. Install dependencies
211
+ console.log(' ๐Ÿ“ฅ Installing with conflicting chalk requirements...');
212
+ console.log(' โš ๏ธ fake-chalk5-package wants chalk ^5.0.0');
213
+ console.log(' โœ… fraim-framework wants chalk 4.1.2 (PINNED)');
214
+ const installResult = await runCommand('npm', ['install'], tempDir);
215
+ if (installResult.code !== 0) {
216
+ console.log(' โš ๏ธ npm install failed');
217
+ }
218
+ // 5. Check chalk versions
219
+ const fraimChalkPath = path_1.default.join(tempDir, 'node_modules', 'fraim-framework', 'node_modules', 'chalk', 'package.json');
220
+ const rootChalkPath = path_1.default.join(tempDir, 'node_modules', 'chalk', 'package.json');
221
+ let fraimChalkVersion = null;
222
+ let rootChalkVersion = null;
223
+ if (fs_1.default.existsSync(fraimChalkPath)) {
224
+ const chalkPkg = JSON.parse(fs_1.default.readFileSync(fraimChalkPath, 'utf-8'));
225
+ fraimChalkVersion = chalkPkg.version;
226
+ console.log(` ๐Ÿ“‹ fraim-framework's chalk: ${fraimChalkVersion}`);
227
+ }
228
+ if (fs_1.default.existsSync(rootChalkPath)) {
229
+ const chalkPkg = JSON.parse(fs_1.default.readFileSync(rootChalkPath, 'utf-8'));
230
+ rootChalkVersion = chalkPkg.version;
231
+ console.log(` ๐Ÿ“‹ Root chalk: ${rootChalkVersion}`);
232
+ }
233
+ // Verify fraim has v4
234
+ if (fraimChalkVersion && !fraimChalkVersion.startsWith('4.')) {
235
+ console.log(` โŒ PINNED version failed! Got chalk ${fraimChalkVersion}`);
236
+ fs_1.default.unlinkSync(tarballPath);
237
+ return false;
238
+ }
239
+ // 6. Try to load fraim CLI
240
+ console.log(' ๐Ÿš€ Testing if fraim CLI loads...');
241
+ const testScript = `
242
+ try {
243
+ const fraimCli = require('./node_modules/fraim-framework/dist/src/cli/fraim.js');
244
+ console.log('SUCCESS: fraim CLI loaded with pinned chalk');
245
+ process.exit(0);
246
+ } catch (error) {
247
+ if (error.code === 'ERR_REQUIRE_ESM') {
248
+ console.log('ERROR: ERR_REQUIRE_ESM even with pinned version!');
249
+ process.exit(1);
250
+ } else {
251
+ console.log('ERROR: Other error:', error.message);
252
+ process.exit(2);
253
+ }
254
+ }
255
+ `;
256
+ fs_1.default.writeFileSync(path_1.default.join(tempDir, 'test.js'), testScript);
257
+ const testResult = await runCommand('node', ['test.js'], tempDir);
258
+ if (testResult.code === 0) {
259
+ console.log(' โœ… SUCCESS! Pinned version prevents chalk v5 upgrade');
260
+ console.log(' โœ… fraim CLI works even with chalk v5 dependency nearby');
261
+ console.log(' โœ… This proves the fix works!');
262
+ }
263
+ else if (testResult.code === 1) {
264
+ console.log(' โŒ FAILED! Even pinned version got chalk v5');
265
+ console.log(' โŒ The fix doesn\'t work!');
266
+ fs_1.default.unlinkSync(tarballPath);
267
+ return false;
268
+ }
269
+ // Cleanup
270
+ fs_1.default.unlinkSync(tarballPath);
271
+ return true;
272
+ }
273
+ catch (error) {
274
+ console.error(' โŒ Test failed with error:', error);
275
+ return false;
276
+ }
277
+ finally {
278
+ try {
279
+ fs_1.default.rmSync(tempDir, { recursive: true, force: true });
280
+ console.log(' ๐Ÿงน Cleaned up temp directory');
281
+ }
282
+ catch (e) {
283
+ console.log(' โš ๏ธ Could not clean up temp directory');
284
+ }
285
+ }
286
+ }
287
+ async function runChalkResolutionTest(testCase) {
288
+ return await testCase.testFunction();
289
+ }
290
+ const testCases = [
291
+ {
292
+ name: 'Chalk Resolution with Conflict (^4.1.2)',
293
+ description: 'Tests if ^4.1.2 allows npm to upgrade to chalk v5 when there\'s a conflicting dependency',
294
+ testFunction: testChalkResolutionWithConflict,
295
+ tags: ['chalk', 'resolution', 'conflict']
296
+ },
297
+ {
298
+ name: 'Chalk Resolution with Pinned Version (4.1.2)',
299
+ description: 'Tests if pinned 4.1.2 prevents npm from upgrading to chalk v5',
300
+ testFunction: testChalkResolutionWithPinnedVersion,
301
+ tags: ['chalk', 'resolution', 'pinned', 'fix']
302
+ }
303
+ ];
304
+ (0, test_utils_1.runTests)(testCases, runChalkResolutionTest, 'Chalk Resolution Issue Test');
@@ -8,10 +8,28 @@ const child_process_1 = require("child_process");
8
8
  const fs_1 = require("fs");
9
9
  const path_1 = require("path");
10
10
  const node_assert_1 = __importDefault(require("node:assert"));
11
+ const path_2 = __importDefault(require("path"));
12
+ /**
13
+ * Client-side script validation tests
14
+ * Ensures scripts can run without FRAIM internal imports
15
+ * Following the project's standard test structure from test-utils.ts
16
+ */
17
+ // Find project root by looking for package.json
18
+ function findProjectRoot() {
19
+ let currentDir = __dirname;
20
+ while (currentDir !== path_2.default.dirname(currentDir)) {
21
+ if ((0, fs_1.existsSync)(path_2.default.join(currentDir, 'package.json'))) {
22
+ return currentDir;
23
+ }
24
+ currentDir = path_2.default.dirname(currentDir);
25
+ }
26
+ throw new Error('Could not find project root (package.json not found)');
27
+ }
11
28
  async function testNoFraimInternalImports() {
12
29
  console.log(' ๐Ÿงช Testing registry scripts do not import FRAIM internals...');
13
30
  try {
14
- const scriptsDir = (0, path_1.join)(process.cwd(), 'registry', 'scripts');
31
+ const projectRoot = findProjectRoot();
32
+ const scriptsDir = (0, path_1.join)(projectRoot, 'registry', 'scripts');
15
33
  const scriptFiles = ['cleanup-branch.ts', 'generate-engagement-emails.ts', 'newsletter-helpers.ts'];
16
34
  for (const scriptFile of scriptFiles) {
17
35
  const scriptPath = (0, path_1.join)(scriptsDir, scriptFile);
@@ -35,7 +53,8 @@ async function testNoFraimInternalImports() {
35
53
  async function testInlineUtilityFunctions() {
36
54
  console.log(' ๐Ÿงช Testing scripts have inline utility functions...');
37
55
  try {
38
- const scriptsDir = (0, path_1.join)(process.cwd(), 'registry', 'scripts');
56
+ const projectRoot = findProjectRoot();
57
+ const scriptsDir = (0, path_1.join)(projectRoot, 'registry', 'scripts');
39
58
  const scriptPath = (0, path_1.join)(scriptsDir, 'cleanup-branch.ts');
40
59
  if ((0, fs_1.existsSync)(scriptPath)) {
41
60
  const content = (0, fs_1.readFileSync)(scriptPath, 'utf-8');
@@ -54,7 +73,8 @@ async function testInlineUtilityFunctions() {
54
73
  async function testConfigLoadingFromJson() {
55
74
  console.log(' ๐Ÿงช Testing scripts load config from .fraim/config.json...');
56
75
  try {
57
- const scriptsDir = (0, path_1.join)(process.cwd(), 'registry', 'scripts');
76
+ const projectRoot = findProjectRoot();
77
+ const scriptsDir = (0, path_1.join)(projectRoot, 'registry', 'scripts');
58
78
  const scriptPath = (0, path_1.join)(scriptsDir, 'generate-engagement-emails.ts');
59
79
  if ((0, fs_1.existsSync)(scriptPath)) {
60
80
  const content = (0, fs_1.readFileSync)(scriptPath, 'utf-8');
@@ -73,7 +93,8 @@ async function testConfigLoadingFromJson() {
73
93
  async function testRegistryPathValidator() {
74
94
  console.log(' ๐Ÿงช Testing registry path validator passes...');
75
95
  try {
76
- (0, child_process_1.execSync)('npm run validate:registry', { stdio: 'pipe' });
96
+ const projectRoot = findProjectRoot();
97
+ (0, child_process_1.execSync)('npm run validate:registry', { stdio: 'pipe', cwd: projectRoot });
77
98
  return true;
78
99
  }
79
100
  catch (error) {
@@ -84,7 +105,8 @@ async function testRegistryPathValidator() {
84
105
  async function testScriptExecutability() {
85
106
  console.log(' ๐Ÿงช Testing scripts are executable without import errors...');
86
107
  try {
87
- const scriptsDir = (0, path_1.join)(process.cwd(), 'registry', 'scripts');
108
+ const projectRoot = findProjectRoot();
109
+ const scriptsDir = (0, path_1.join)(projectRoot, 'registry', 'scripts');
88
110
  const scriptPath = (0, path_1.join)(scriptsDir, 'cleanup-branch.ts');
89
111
  if ((0, fs_1.existsSync)(scriptPath)) {
90
112
  // Test that the script can be parsed without import errors
@@ -0,0 +1,110 @@
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
+ const node_test_1 = require("node:test");
7
+ const node_assert_1 = __importDefault(require("node:assert"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const os_1 = __importDefault(require("os"));
11
+ const ide_detector_1 = require("../src/cli/setup/ide-detector");
12
+ const mcp_config_generator_1 = require("../src/cli/setup/mcp-config-generator");
13
+ const token_validator_1 = require("../src/cli/setup/token-validator");
14
+ (0, node_test_1.test)('Complete setup flow - end to end simulation', async () => {
15
+ const testFraimKey = 'fraim_test123456789012345';
16
+ const testGithubToken = 'ghp_test123456789012345';
17
+ // Step 1: Validate tokens (as setup command would)
18
+ (0, node_assert_1.default)((0, token_validator_1.isValidTokenFormat)(testFraimKey, 'fraim'), 'FRAIM key should be valid format');
19
+ (0, node_assert_1.default)((0, token_validator_1.isValidTokenFormat)(testGithubToken, 'github'), 'GitHub token should be valid format');
20
+ (0, node_assert_1.default)(await (0, token_validator_1.validateFraimKey)(testFraimKey), 'FRAIM key should validate');
21
+ // Step 2: Detect IDEs (as setup command would)
22
+ const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
23
+ console.log(`Detected ${detectedIDEs.length} IDEs in test environment`);
24
+ // Step 3: Generate configs for each detected IDE type
25
+ const configTypes = ['standard', 'kiro', 'codex', 'windsurf'];
26
+ for (const configType of configTypes) {
27
+ const config = (0, mcp_config_generator_1.generateMCPConfig)(configType, testFraimKey, testGithubToken);
28
+ if (configType === 'codex') {
29
+ // TOML config
30
+ (0, node_assert_1.default)(typeof config === 'string', `${configType} should return string`);
31
+ (0, node_assert_1.default)(config.includes(testFraimKey), `${configType} should contain FRAIM key`);
32
+ }
33
+ else {
34
+ // JSON configs
35
+ (0, node_assert_1.default)(typeof config === 'object', `${configType} should return object`);
36
+ (0, node_assert_1.default)(config.mcpServers, `${configType} should have mcpServers`);
37
+ (0, node_assert_1.default)(config.mcpServers.fraim, `${configType} should have fraim server`);
38
+ }
39
+ }
40
+ // Step 4: Simulate global config creation
41
+ const testGlobalDir = path_1.default.join(os_1.default.tmpdir(), 'fraim-global-test-' + Date.now());
42
+ fs_1.default.mkdirSync(testGlobalDir, { recursive: true });
43
+ const globalConfig = {
44
+ version: '2.0.37',
45
+ apiKey: testFraimKey,
46
+ configuredAt: new Date().toISOString(),
47
+ userPreferences: {
48
+ autoSync: true,
49
+ backupConfigs: true
50
+ }
51
+ };
52
+ const globalConfigPath = path_1.default.join(testGlobalDir, 'config.json');
53
+ fs_1.default.writeFileSync(globalConfigPath, JSON.stringify(globalConfig, null, 2));
54
+ (0, node_assert_1.default)(fs_1.default.existsSync(globalConfigPath), 'Global config should be created');
55
+ // Step 5: Simulate project config creation (as init-project would)
56
+ const testProjectDir = path_1.default.join(os_1.default.tmpdir(), 'fraim-project-test-' + Date.now());
57
+ fs_1.default.mkdirSync(testProjectDir, { recursive: true });
58
+ const fraimProjectDir = path_1.default.join(testProjectDir, '.fraim');
59
+ fs_1.default.mkdirSync(fraimProjectDir, { recursive: true });
60
+ const projectConfig = {
61
+ version: '2.0.37',
62
+ project: {
63
+ name: 'test-project'
64
+ },
65
+ git: {
66
+ defaultBranch: 'master',
67
+ repoOwner: 'test-owner',
68
+ repoName: 'test-project'
69
+ }
70
+ };
71
+ const projectConfigPath = path_1.default.join(fraimProjectDir, 'config.json');
72
+ fs_1.default.writeFileSync(projectConfigPath, JSON.stringify(projectConfig, null, 2));
73
+ (0, node_assert_1.default)(fs_1.default.existsSync(projectConfigPath), 'Project config should be created');
74
+ // Step 6: Verify configs can be read back correctly
75
+ const savedGlobalConfig = JSON.parse(fs_1.default.readFileSync(globalConfigPath, 'utf8'));
76
+ const savedProjectConfig = JSON.parse(fs_1.default.readFileSync(projectConfigPath, 'utf8'));
77
+ (0, node_assert_1.default)(savedGlobalConfig.apiKey === testFraimKey, 'Global config should contain API key');
78
+ (0, node_assert_1.default)(savedProjectConfig.project.name === 'test-project', 'Project config should contain project name');
79
+ // Cleanup
80
+ fs_1.default.rmSync(testGlobalDir, { recursive: true, force: true });
81
+ fs_1.default.rmSync(testProjectDir, { recursive: true, force: true });
82
+ console.log('โœ… Complete setup flow simulation passed');
83
+ });
84
+ (0, node_test_1.test)('Error handling - invalid tokens should be rejected', async () => {
85
+ const invalidFraimKey = 'invalid_key';
86
+ const invalidGithubToken = 'invalid_token';
87
+ const shortFraimKey = 'fraim_short';
88
+ (0, node_assert_1.default)(!(0, token_validator_1.isValidTokenFormat)(invalidFraimKey, 'fraim'), 'Invalid FRAIM key should be rejected');
89
+ (0, node_assert_1.default)(!(0, token_validator_1.isValidTokenFormat)(invalidGithubToken, 'github'), 'Invalid GitHub token should be rejected');
90
+ (0, node_assert_1.default)(!(0, token_validator_1.isValidTokenFormat)(shortFraimKey, 'fraim'), 'Short FRAIM key should be rejected');
91
+ (0, node_assert_1.default)(!await (0, token_validator_1.validateFraimKey)(invalidFraimKey), 'Invalid FRAIM key should not validate');
92
+ (0, node_assert_1.default)(!await (0, token_validator_1.validateFraimKey)(shortFraimKey), 'Short FRAIM key should not validate');
93
+ console.log('โœ… Error handling tests passed');
94
+ });
95
+ (0, node_test_1.test)('Path expansion works correctly across platforms', () => {
96
+ const testPaths = [
97
+ '~/.fraim/config.json',
98
+ '~/.claude/settings.json',
99
+ '~/.kiro/settings/mcp.json'
100
+ ];
101
+ testPaths.forEach(testPath => {
102
+ const expanded = (0, ide_detector_1.expandPath)(testPath);
103
+ (0, node_assert_1.default)(expanded.includes(os_1.default.homedir()), `${testPath} should expand to include home directory`);
104
+ (0, node_assert_1.default)(!expanded.includes('~'), `${testPath} should not contain tilde after expansion`);
105
+ });
106
+ // Test absolute paths remain unchanged
107
+ const absolutePath = '/usr/local/bin/fraim';
108
+ (0, node_assert_1.default)((0, ide_detector_1.expandPath)(absolutePath) === absolutePath, 'Absolute paths should remain unchanged');
109
+ console.log('โœ… Path expansion tests passed');
110
+ });