fraim-framework 2.0.30 → 2.0.33

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 (67) hide show
  1. package/dist/src/cli/commands/init.js +29 -2
  2. package/dist/src/cli/commands/sync.js +18 -1
  3. package/dist/src/utils/script-sync-utils.js +218 -0
  4. package/dist/tests/debug-tools.js +6 -5
  5. package/dist/tests/test-chalk-regression.js +58 -8
  6. package/dist/tests/test-cli.js +70 -5
  7. package/dist/tests/test-end-to-end-hybrid-validation.js +349 -0
  8. package/dist/tests/test-first-run-journey.js +43 -3
  9. package/dist/tests/test-hybrid-script-execution.js +369 -0
  10. package/dist/tests/test-mcp-connection.js +2 -2
  11. package/dist/tests/test-mcp-issue-integration.js +12 -4
  12. package/dist/tests/test-mcp-lifecycle-methods.js +4 -4
  13. package/dist/tests/test-node-compatibility.js +24 -2
  14. package/dist/tests/test-prep-issue.js +4 -1
  15. package/dist/tests/test-script-location-independence.js +173 -0
  16. package/dist/tests/test-script-sync.js +557 -0
  17. package/dist/tests/test-session-rehydration.js +2 -2
  18. package/dist/tests/test-standalone.js +3 -3
  19. package/dist/tests/test-sync-version-update.js +1 -1
  20. package/dist/tests/test-telemetry.js +2 -2
  21. package/dist/tests/test-user-journey.js +8 -4
  22. package/dist/tests/test-utils.js +13 -0
  23. package/dist/tests/test-wizard.js +2 -2
  24. package/package.json +3 -3
  25. package/registry/rules/agent-testing-guidelines.md +502 -502
  26. package/registry/rules/ephemeral-execution.md +37 -27
  27. package/registry/rules/local-development.md +253 -251
  28. package/registry/rules/successful-debugging-patterns.md +491 -482
  29. package/registry/scripts/prep-issue.sh +468 -468
  30. package/registry/workflows/bootstrap/evaluate-code-quality.md +8 -2
  31. package/registry/workflows/bootstrap/verify-test-coverage.md +8 -2
  32. package/registry/workflows/customer-development/thank-customers.md +203 -193
  33. package/registry/workflows/customer-development/weekly-newsletter.md +366 -362
  34. package/registry/workflows/performance/analyze-performance.md +65 -63
  35. package/registry/workflows/product-building/implement.md +6 -2
  36. package/registry/workflows/product-building/prep-issue.md +11 -24
  37. package/registry/workflows/product-building/resolve.md +5 -1
  38. package/registry/workflows/replicate/replicate-discovery.md +336 -0
  39. package/registry/workflows/replicate/replicate-to-issues.md +319 -0
  40. package/registry/workflows/reviewer/review-implementation-vs-design-spec.md +632 -632
  41. package/.windsurf/rules/windsurf-rules.md +0 -7
  42. package/.windsurf/workflows/resolve-issue.md +0 -6
  43. package/.windsurf/workflows/retrospect.md +0 -6
  44. package/.windsurf/workflows/start-design.md +0 -6
  45. package/.windsurf/workflows/start-impl.md +0 -6
  46. package/.windsurf/workflows/start-spec.md +0 -6
  47. package/.windsurf/workflows/start-tests.md +0 -6
  48. package/bin/fraim.js +0 -23
  49. package/registry/scripts/build-scripts-generator.ts +0 -216
  50. package/registry/scripts/cleanup-branch.ts +0 -303
  51. package/registry/scripts/fraim-config.ts +0 -63
  52. package/registry/scripts/generate-engagement-emails.ts +0 -744
  53. package/registry/scripts/generic-issues-api.ts +0 -110
  54. package/registry/scripts/newsletter-helpers.ts +0 -874
  55. package/registry/scripts/openapi-generator.ts +0 -695
  56. package/registry/scripts/performance/profile-server.ts +0 -370
  57. package/registry/scripts/run-thank-you-workflow.ts +0 -122
  58. package/registry/scripts/send-newsletter-simple.ts +0 -104
  59. package/registry/scripts/send-thank-you-emails.ts +0 -57
  60. package/registry/workflows/replicate/re-implementation-strategy.md +0 -226
  61. package/registry/workflows/replicate/use-case-extraction.md +0 -135
  62. package/registry/workflows/replicate/visual-analysis.md +0 -154
  63. package/registry/workflows/replicate/website-discovery-analysis.md +0 -231
  64. package/sample_package.json +0 -18
  65. /package/registry/scripts/{replicate/comprehensive-explorer.py → comprehensive-explorer.py} +0 -0
  66. /package/registry/scripts/{replicate/interactive-explorer.py → interactive-explorer.py} +0 -0
  67. /package/registry/scripts/{replicate/scrape-site.py → scrape-site.py} +0 -0
@@ -0,0 +1,349 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const node_child_process_1 = require("node:child_process");
40
+ const test_utils_1 = require("./test-utils");
41
+ const node_assert_1 = __importDefault(require("node:assert"));
42
+ const fs_1 = __importDefault(require("fs"));
43
+ const path_1 = __importDefault(require("path"));
44
+ const os_1 = __importDefault(require("os"));
45
+ async function testCompleteHybridWorkflow() {
46
+ console.log(' 🚀 Testing Complete Hybrid Workflow...');
47
+ const tempProjectDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'fraim-e2e-hybrid-'));
48
+ const userFraimDir = path_1.default.join(os_1.default.homedir(), '.fraim-e2e-test');
49
+ try {
50
+ // Clean up any existing test user directory
51
+ if (fs_1.default.existsSync(userFraimDir)) {
52
+ fs_1.default.rmSync(userFraimDir, { recursive: true, force: true });
53
+ }
54
+ console.log(` 📂 Project dir: ${tempProjectDir}`);
55
+ console.log(` 🏠 User dir: ${userFraimDir}`);
56
+ // Set up git repository
57
+ const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
58
+ execSync('git init', { cwd: tempProjectDir });
59
+ execSync('git remote add origin https://github.com/test-owner/e2e-hybrid-test.git', { cwd: tempProjectDir });
60
+ // Run fraim init with custom user directory
61
+ const platform = process.platform;
62
+ const npx = platform === 'win32' ? 'npx.cmd' : 'npx';
63
+ const cliScript = (0, test_utils_1.resolveProjectPath)('dist/src/cli/fraim.js');
64
+ const runFraim = (args) => {
65
+ return new Promise((resolve) => {
66
+ const ps = (0, node_child_process_1.spawn)(npx, ['node', `"${cliScript}"`, ...args], {
67
+ cwd: tempProjectDir,
68
+ env: {
69
+ ...process.env,
70
+ TEST_MODE: 'true',
71
+ FRAIM_USER_DIR: userFraimDir
72
+ },
73
+ shell: true
74
+ });
75
+ let stdout = '';
76
+ let stderr = '';
77
+ ps.stdout.on('data', d => stdout += d.toString());
78
+ ps.stderr.on('data', d => stderr += d.toString());
79
+ ps.on('close', (code) => {
80
+ resolve({ stdout, stderr, code });
81
+ });
82
+ });
83
+ };
84
+ // Initialize FRAIM
85
+ console.log(' Initializing FRAIM...');
86
+ const initRes = await runFraim(['init']);
87
+ node_assert_1.default.strictEqual(initRes.code, 0, 'Init should succeed');
88
+ // Verify user scripts directory was created and populated
89
+ const userScriptsDir = path_1.default.join(userFraimDir, 'scripts');
90
+ node_assert_1.default.ok(fs_1.default.existsSync(userScriptsDir), 'User scripts directory should exist');
91
+ // Verify self-contained scripts were synced
92
+ const expectedSelfContainedScripts = [
93
+ 'prep-issue.sh',
94
+ 'code-quality-check.sh',
95
+ 'exec-with-timeout.ts',
96
+ 'evaluate-code-quality.ts'
97
+ ];
98
+ for (const scriptName of expectedSelfContainedScripts) {
99
+ const scriptPath = path_1.default.join(userScriptsDir, scriptName);
100
+ node_assert_1.default.ok(fs_1.default.existsSync(scriptPath), `Self-contained script ${scriptName} should be synced`);
101
+ }
102
+ // Verify dependent scripts were NOT synced
103
+ const expectedDependentScripts = [
104
+ 'fraim-config.ts',
105
+ 'build-scripts-generator.ts'
106
+ ];
107
+ for (const scriptName of expectedDependentScripts) {
108
+ const scriptPath = path_1.default.join(userScriptsDir, scriptName);
109
+ node_assert_1.default.ok(!fs_1.default.existsSync(scriptPath), `Dependent script ${scriptName} should NOT be synced`);
110
+ }
111
+ // Test that self-contained scripts can execute from user directory
112
+ console.log(' Testing self-contained script execution...');
113
+ // Create a simple test script to verify execution context
114
+ const testScript = `#!/usr/bin/env node
115
+ console.log('WORKING_DIR=' + process.cwd());
116
+ console.log('SCRIPT_DIR=' + __dirname);
117
+
118
+ // Verify we can read project config
119
+ const fs = require('fs');
120
+ const path = require('path');
121
+
122
+ try {
123
+ const configPath = path.join(process.cwd(), '.fraim', 'config.json');
124
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
125
+ console.log('PROJECT_NAME=' + config.project.name);
126
+ console.log('SUCCESS=true');
127
+ } catch (error) {
128
+ console.log('ERROR=' + error.message);
129
+ console.log('SUCCESS=false');
130
+ }
131
+ `;
132
+ const testScriptPath = path_1.default.join(userScriptsDir, 'test-execution.js');
133
+ fs_1.default.writeFileSync(testScriptPath, testScript);
134
+ // Execute the test script from project directory
135
+ let output;
136
+ try {
137
+ output = execSync(`node "${testScriptPath}"`, {
138
+ cwd: tempProjectDir,
139
+ encoding: 'utf-8'
140
+ });
141
+ }
142
+ catch (error) {
143
+ throw new Error(`Script execution failed: ${error.message}`);
144
+ }
145
+ // Validate execution results
146
+ node_assert_1.default.ok(output.includes('SUCCESS=true'), 'Script should execute successfully');
147
+ node_assert_1.default.ok(output.includes('PROJECT_NAME=e2e-hybrid-test'), 'Should read project config correctly');
148
+ // Verify working directory vs script directory are different
149
+ const workingDirMatch = output.match(/WORKING_DIR=(.+)/);
150
+ const scriptDirMatch = output.match(/SCRIPT_DIR=(.+)/);
151
+ if (workingDirMatch && scriptDirMatch) {
152
+ const workingDir = workingDirMatch[1].trim();
153
+ const scriptDir = scriptDirMatch[1].trim();
154
+ node_assert_1.default.notStrictEqual(workingDir, scriptDir, 'Working directory should be different from script directory');
155
+ }
156
+ // Test sync command updates
157
+ console.log(' Testing sync command...');
158
+ const syncRes = await runFraim(['sync']);
159
+ // Sync might warn but should not fail completely
160
+ if (syncRes.code !== 0) {
161
+ console.log(' ⚠️ Sync returned non-zero (environment dependent)');
162
+ }
163
+ // Verify scripts are still present after sync
164
+ for (const scriptName of expectedSelfContainedScripts) {
165
+ const scriptPath = path_1.default.join(userScriptsDir, scriptName);
166
+ node_assert_1.default.ok(fs_1.default.existsSync(scriptPath), `Script ${scriptName} should still exist after sync`);
167
+ }
168
+ console.log(' ✅ Complete hybrid workflow verified!');
169
+ return true;
170
+ }
171
+ catch (error) {
172
+ console.error(' ❌ End-to-end hybrid test failed:', error);
173
+ return false;
174
+ }
175
+ finally {
176
+ try {
177
+ fs_1.default.rmSync(tempProjectDir, { recursive: true, force: true });
178
+ if (fs_1.default.existsSync(userFraimDir)) {
179
+ fs_1.default.rmSync(userFraimDir, { recursive: true, force: true });
180
+ }
181
+ }
182
+ catch (e) { }
183
+ }
184
+ }
185
+ async function testScriptCategorizationAccuracy() {
186
+ console.log(' 🚀 Testing Script Categorization Accuracy...');
187
+ try {
188
+ const registryPath = path_1.default.resolve(__dirname, '../registry');
189
+ if (!fs_1.default.existsSync(registryPath)) {
190
+ console.log(' ⚠️ Registry not found, skipping categorization accuracy test');
191
+ return true;
192
+ }
193
+ const { getRegistryScripts, getDependentRegistryScripts, isScriptSelfContained } = await Promise.resolve().then(() => __importStar(require('../src/utils/script-sync-utils')));
194
+ const selfContainedScripts = getRegistryScripts(registryPath);
195
+ const dependentScripts = getDependentRegistryScripts(registryPath);
196
+ console.log(` 📊 Categorization results:`);
197
+ console.log(` Self-contained: ${selfContainedScripts.length} scripts`);
198
+ console.log(` Dependent: ${dependentScripts.length} scripts`);
199
+ // Verify specific known categorizations
200
+ const knownSelfContained = [
201
+ 'prep-issue.sh',
202
+ 'code-quality-check.sh',
203
+ 'exec-with-timeout.ts',
204
+ 'evaluate-code-quality.ts'
205
+ ];
206
+ const knownDependent = [
207
+ 'fraim-config.ts',
208
+ 'build-scripts-generator.ts'
209
+ ];
210
+ const selfContainedNames = selfContainedScripts.map(p => path_1.default.basename(p));
211
+ const dependentNames = dependentScripts.map(p => path_1.default.basename(p));
212
+ for (const scriptName of knownSelfContained) {
213
+ const scriptPath = path_1.default.join(registryPath, 'scripts', scriptName);
214
+ if (fs_1.default.existsSync(scriptPath)) {
215
+ node_assert_1.default.ok(selfContainedNames.includes(scriptName), `${scriptName} should be categorized as self-contained`);
216
+ node_assert_1.default.ok(isScriptSelfContained(scriptPath), `${scriptName} should be detected as self-contained`);
217
+ }
218
+ }
219
+ for (const scriptName of knownDependent) {
220
+ const scriptPath = path_1.default.join(registryPath, 'scripts', scriptName);
221
+ if (fs_1.default.existsSync(scriptPath)) {
222
+ node_assert_1.default.ok(dependentNames.includes(scriptName), `${scriptName} should be categorized as dependent`);
223
+ node_assert_1.default.ok(!isScriptSelfContained(scriptPath), `${scriptName} should be detected as dependent`);
224
+ }
225
+ }
226
+ // Verify no script is in both categories
227
+ const intersection = selfContainedNames.filter(name => dependentNames.includes(name));
228
+ node_assert_1.default.strictEqual(intersection.length, 0, 'No script should be in both categories');
229
+ // Verify all scripts are categorized
230
+ const allScripts = fs_1.default.readdirSync(path_1.default.join(registryPath, 'scripts'))
231
+ .filter(file => file.endsWith('.sh') || file.endsWith('.ts') || file.endsWith('.js'));
232
+ const categorizedScripts = [...selfContainedNames, ...dependentNames];
233
+ const uncategorized = allScripts.filter(script => !categorizedScripts.includes(script));
234
+ node_assert_1.default.strictEqual(uncategorized.length, 0, `All scripts should be categorized. Uncategorized: ${uncategorized.join(', ')}`);
235
+ console.log(' ✅ Script categorization accuracy verified!');
236
+ return true;
237
+ }
238
+ catch (error) {
239
+ console.error(' ❌ Script categorization accuracy test failed:', error);
240
+ return false;
241
+ }
242
+ }
243
+ async function testWorkflowInstructionConsistency() {
244
+ console.log(' 🚀 Testing Workflow Instruction Consistency...');
245
+ try {
246
+ const registryPath = path_1.default.resolve(__dirname, '../registry');
247
+ if (!fs_1.default.existsSync(registryPath)) {
248
+ console.log(' ⚠️ Registry not found, skipping workflow consistency test');
249
+ return true;
250
+ }
251
+ // Check that workflows use the correct execution patterns
252
+ const workflowsPath = path_1.default.join(registryPath, 'workflows');
253
+ const rulesPath = path_1.default.join(registryPath, 'rules');
254
+ // Get all markdown files
255
+ const getMarkdownFiles = (dir) => {
256
+ if (!fs_1.default.existsSync(dir))
257
+ return [];
258
+ const files = [];
259
+ const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
260
+ for (const entry of entries) {
261
+ const fullPath = path_1.default.join(dir, entry.name);
262
+ if (entry.isDirectory()) {
263
+ files.push(...getMarkdownFiles(fullPath));
264
+ }
265
+ else if (entry.name.endsWith('.md')) {
266
+ files.push(fullPath);
267
+ }
268
+ }
269
+ return files;
270
+ };
271
+ const allMarkdownFiles = [
272
+ ...getMarkdownFiles(workflowsPath),
273
+ ...getMarkdownFiles(rulesPath)
274
+ ];
275
+ let inconsistencies = 0;
276
+ for (const filePath of allMarkdownFiles) {
277
+ const content = fs_1.default.readFileSync(filePath, 'utf-8');
278
+ const relativePath = path_1.default.relative(registryPath, filePath);
279
+ // Check for old ephemeral execution patterns (but allow them for dependent scripts)
280
+ const oldPatterns = [
281
+ /tmp\/.*\.ts/g,
282
+ /tmp\/.*\.sh/g
283
+ ];
284
+ for (const pattern of oldPatterns) {
285
+ const matches = content.match(pattern);
286
+ if (matches) {
287
+ // Allow tmp/ usage if it's accompanied by get_fraim_file (ephemeral execution for dependent scripts)
288
+ const hasGetFramFile = /get_fraim_file.*scripts/.test(content);
289
+ if (!hasGetFramFile) {
290
+ console.log(` ⚠️ Found old pattern in ${relativePath}: ${matches.join(', ')}`);
291
+ inconsistencies++;
292
+ }
293
+ }
294
+ }
295
+ // Check for correct hybrid patterns
296
+ const hybridPatterns = [
297
+ /~\/\.fraim\/scripts\/.*\.ts/g,
298
+ /~\/\.fraim\/scripts\/.*\.sh/g,
299
+ /%USERPROFILE%\\\.fraim\\scripts\\/g
300
+ ];
301
+ let hasHybridPatterns = false;
302
+ for (const pattern of hybridPatterns) {
303
+ if (pattern.test(content)) {
304
+ hasHybridPatterns = true;
305
+ break;
306
+ }
307
+ }
308
+ // If file mentions scripts but doesn't use hybrid patterns, it might be an issue
309
+ if (content.includes('scripts/') && !hasHybridPatterns && inconsistencies === 0) {
310
+ // This is just informational, not necessarily an error
311
+ console.log(` ℹ️ File ${relativePath} mentions scripts but may not use hybrid patterns`);
312
+ }
313
+ }
314
+ if (inconsistencies > 0) {
315
+ console.log(` ❌ Found ${inconsistencies} workflow instruction inconsistencies`);
316
+ return false;
317
+ }
318
+ console.log(' ✅ Workflow instruction consistency verified!');
319
+ return true;
320
+ }
321
+ catch (error) {
322
+ console.error(' ❌ Workflow instruction consistency test failed:', error);
323
+ return false;
324
+ }
325
+ }
326
+ async function runEndToEndTest(testCase) {
327
+ return await testCase.testFunction();
328
+ }
329
+ const testCases = [
330
+ {
331
+ name: 'Complete Hybrid Workflow',
332
+ description: 'Tests the entire hybrid script execution workflow from init to execution',
333
+ testFunction: testCompleteHybridWorkflow,
334
+ tags: ['e2e', 'hybrid', 'workflow']
335
+ },
336
+ {
337
+ name: 'Script Categorization Accuracy',
338
+ description: 'Validates that all scripts are correctly categorized as self-contained or dependent',
339
+ testFunction: testScriptCategorizationAccuracy,
340
+ tags: ['e2e', 'categorization', 'validation']
341
+ },
342
+ {
343
+ name: 'Workflow Instruction Consistency',
344
+ description: 'Ensures all workflow files use the correct hybrid execution patterns',
345
+ testFunction: testWorkflowInstructionConsistency,
346
+ tags: ['e2e', 'consistency', 'workflows']
347
+ }
348
+ ];
349
+ (0, test_utils_1.runTests)(testCases, runEndToEndTest, 'End-to-End Hybrid Validation Tests');
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
@@ -13,11 +46,10 @@ const os_1 = __importDefault(require("os"));
13
46
  * Helper to run the interactive first-run experience within 'fraim init'
14
47
  */
15
48
  async function runInteractiveInit(cwd, interactions) {
16
- const projectRoot = path_1.default.resolve(__dirname, '..');
17
- const cliScript = path_1.default.resolve(projectRoot, 'src/cli/fraim.ts');
49
+ const cliScript = (0, test_utils_1.resolveProjectPath)('dist/src/cli/fraim.js');
18
50
  const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx';
19
51
  return new Promise(resolve => {
20
- const ps = (0, node_child_process_1.spawn)(npx, ['tsx', `"${cliScript}"`, 'init'], {
52
+ const ps = (0, node_child_process_1.spawn)(npx, ['node', `"${cliScript}"`, 'init'], {
21
53
  cwd,
22
54
  env: { ...process.env, CI: 'false', TEST_MODE: 'false' },
23
55
  shell: true,
@@ -57,6 +89,10 @@ const testCases = [
57
89
  testFunction: async () => {
58
90
  const tempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'fraim-jour-1-'));
59
91
  try {
92
+ // Set up git repository with remote (required for new init logic)
93
+ const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
94
+ execSync('git init', { cwd: tempDir });
95
+ execSync('git remote add origin https://github.com/test-owner/test-repo.git', { cwd: tempDir });
60
96
  const res = await runInteractiveInit(tempDir, [
61
97
  { prompt: 'Do you have a FRAIM key?', response: 'key-123' },
62
98
  { prompt: 'Do you have an architecture document', response: 'n' }
@@ -83,6 +119,10 @@ const testCases = [
83
119
  const tempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'fraim-jour-2-'));
84
120
  const archPath = 'docs/my-architecture.md';
85
121
  try {
122
+ // Set up git repository with remote (required for new init logic)
123
+ const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
124
+ execSync('git init', { cwd: tempDir });
125
+ execSync('git remote add origin https://github.com/test-owner/test-repo.git', { cwd: tempDir });
86
126
  fs_1.default.mkdirSync(path_1.default.join(tempDir, '.fraim'), { recursive: true });
87
127
  fs_1.default.writeFileSync(path_1.default.join(tempDir, '.fraim', 'config.json'), JSON.stringify({ version: '1.0.0' }));
88
128
  fs_1.default.mkdirSync(path_1.default.join(tempDir, 'docs'), { recursive: true });