fraim-framework 2.0.55 → 2.0.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/src/cli/commands/init-project.js +10 -4
- package/dist/src/cli/setup/mcp-config-generator.js +23 -15
- package/dist/src/local-mcp-server/stdio-server.js +207 -0
- package/dist/src/utils/validate-workflows.js +101 -0
- package/dist/src/utils/workflow-parser.js +81 -0
- package/package.json +16 -11
- package/registry/scripts/pdf-styles.css +172 -0
- package/registry/scripts/prep-issue.sh +46 -4
- package/registry/scripts/profile-server.ts +131 -130
- package/registry/stubs/workflows/customer-development/user-survey-dispatch.md +1 -1
- package/registry/stubs/workflows/customer-development/users-to-target.md +1 -1
- package/registry/stubs/workflows/product-building/design.md +1 -1
- package/registry/stubs/workflows/product-building/implement.md +1 -1
- package/Claude.md +0 -1
- package/dist/registry/ai-manager-rules/design-phases/design-completeness-review.md +0 -73
- package/dist/registry/ai-manager-rules/design-phases/design-design.md +0 -145
- package/dist/registry/ai-manager-rules/implement-phases/implement-code.md +0 -283
- package/dist/registry/ai-manager-rules/implement-phases/implement-completeness-review.md +0 -120
- package/dist/registry/ai-manager-rules/implement-phases/implement-regression.md +0 -173
- package/dist/registry/ai-manager-rules/implement-phases/implement-repro.md +0 -104
- package/dist/registry/ai-manager-rules/implement-phases/implement-scoping.md +0 -100
- package/dist/registry/ai-manager-rules/implement-phases/implement-smoke.md +0 -237
- package/dist/registry/ai-manager-rules/implement-phases/implement-spike.md +0 -121
- package/dist/registry/ai-manager-rules/implement-phases/implement-validate.md +0 -375
- package/dist/registry/ai-manager-rules/retrospective.md +0 -116
- package/dist/registry/ai-manager-rules/shared-phases/address-pr-feedback.md +0 -188
- package/dist/registry/ai-manager-rules/shared-phases/submit-pr.md +0 -202
- package/dist/registry/ai-manager-rules/shared-phases/wait-for-pr-review.md +0 -170
- package/dist/registry/ai-manager-rules/spec-phases/spec-competitor-analysis.md +0 -105
- package/dist/registry/ai-manager-rules/spec-phases/spec-completeness-review.md +0 -66
- package/dist/registry/ai-manager-rules/spec-phases/spec-spec.md +0 -139
- package/dist/registry/providers/ado.json +0 -19
- package/dist/registry/providers/github.json +0 -19
- package/dist/registry/scripts/cleanup-branch.js +0 -287
- package/dist/registry/scripts/evaluate-code-quality.js +0 -66
- package/dist/registry/scripts/exec-with-timeout.js +0 -142
- package/dist/registry/scripts/generate-engagement-emails.js +0 -705
- package/dist/registry/scripts/newsletter-helpers.js +0 -671
- package/dist/registry/scripts/profile-server.js +0 -388
- package/dist/registry/scripts/run-thank-you-workflow.js +0 -92
- package/dist/registry/scripts/send-newsletter-simple.js +0 -85
- package/dist/registry/scripts/send-thank-you-emails.js +0 -54
- package/dist/registry/scripts/validate-openapi-limits.js +0 -311
- package/dist/registry/scripts/validate-test-coverage.js +0 -262
- package/dist/registry/scripts/verify-test-coverage.js +0 -66
- package/dist/scripts/build-stub-registry.js +0 -108
- package/dist/src/ai-manager/ai-manager.js +0 -482
- package/dist/src/ai-manager/phase-flow.js +0 -357
- package/dist/src/ai-manager/types.js +0 -5
- package/dist/src/fraim-mcp-server.js +0 -1885
- package/dist/tests/debug-tools.js +0 -80
- package/dist/tests/shared-server-utils.js +0 -57
- package/dist/tests/test-add-ide.js +0 -283
- package/dist/tests/test-ai-coach-edge-cases.js +0 -420
- package/dist/tests/test-ai-coach-mcp-integration.js +0 -450
- package/dist/tests/test-ai-coach-performance.js +0 -328
- package/dist/tests/test-ai-coach-phase-content.js +0 -264
- package/dist/tests/test-ai-coach-workflows.js +0 -514
- package/dist/tests/test-cli.js +0 -228
- package/dist/tests/test-client-scripts-validation.js +0 -167
- package/dist/tests/test-complete-setup-flow.js +0 -110
- package/dist/tests/test-config-system.js +0 -279
- package/dist/tests/test-debug-session.js +0 -134
- package/dist/tests/test-end-to-end-hybrid-validation.js +0 -328
- package/dist/tests/test-enhanced-session-init.js +0 -188
- package/dist/tests/test-first-run-journey.js +0 -368
- package/dist/tests/test-fraim-issues.js +0 -59
- package/dist/tests/test-genericization.js +0 -44
- package/dist/tests/test-hybrid-script-execution.js +0 -340
- package/dist/tests/test-ide-detector.js +0 -46
- package/dist/tests/test-improved-setup.js +0 -121
- package/dist/tests/test-mcp-config-generator.js +0 -99
- package/dist/tests/test-mcp-connection.js +0 -107
- package/dist/tests/test-mcp-issue-integration.js +0 -156
- package/dist/tests/test-mcp-lifecycle-methods.js +0 -240
- package/dist/tests/test-mcp-shared-server.js +0 -308
- package/dist/tests/test-mcp-template-processing.js +0 -160
- package/dist/tests/test-modular-issue-tracking.js +0 -165
- package/dist/tests/test-node-compatibility.js +0 -95
- package/dist/tests/test-npm-install.js +0 -68
- package/dist/tests/test-package-size.js +0 -108
- package/dist/tests/test-pr-review-workflow.js +0 -307
- package/dist/tests/test-prep-issue.js +0 -129
- package/dist/tests/test-productivity-integration.js +0 -157
- package/dist/tests/test-script-location-independence.js +0 -198
- package/dist/tests/test-script-sync.js +0 -557
- package/dist/tests/test-server-utils.js +0 -32
- package/dist/tests/test-session-rehydration.js +0 -148
- package/dist/tests/test-setup-integration.js +0 -98
- package/dist/tests/test-setup-scenarios.js +0 -322
- package/dist/tests/test-standalone.js +0 -143
- package/dist/tests/test-stub-registry.js +0 -136
- package/dist/tests/test-sync-stubs.js +0 -143
- package/dist/tests/test-sync-version-update.js +0 -93
- package/dist/tests/test-telemetry.js +0 -193
- package/dist/tests/test-token-validator.js +0 -30
- package/dist/tests/test-user-journey.js +0 -236
- package/dist/tests/test-users-to-target-workflow.js +0 -253
- package/dist/tests/test-utils.js +0 -109
- package/dist/tests/test-wizard.js +0 -71
- package/dist/tests/test-workflow-discovery.js +0 -242
- package/labels.json +0 -52
- package/registry/agent-guardrails.md +0 -63
- package/registry/fraim.md +0 -48
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase1-customer-profiling.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase1-survey-scoping.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase2-platform-discovery.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase2-survey-build-linkedin.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase3-prospect-qualification.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase3-survey-build-reddit.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase4-inventory-compilation.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase4-survey-build-x.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase5-survey-build-facebook.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase6-survey-build-custom.md +0 -11
- package/registry/stubs/workflows/customer-development/ai-coach-phases/phase7-survey-dispatch.md +0 -11
- package/registry/stubs/workflows/customer-development/templates/customer-persona-template.md +0 -11
- package/registry/stubs/workflows/customer-development/templates/search-strategy-template.md +0 -11
- package/setup.js +0 -171
- package/tsconfig.json +0 -23
|
@@ -1,328 +0,0 @@
|
|
|
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 script sync test');
|
|
191
|
-
return true;
|
|
192
|
-
}
|
|
193
|
-
const { getRegistryScripts } = await Promise.resolve().then(() => __importStar(require('../src/utils/script-sync-utils')));
|
|
194
|
-
const allScripts = getRegistryScripts(registryPath);
|
|
195
|
-
console.log(` 📊 Script sync results:`);
|
|
196
|
-
console.log(` Total scripts: ${allScripts.length} scripts`);
|
|
197
|
-
// Verify some known scripts exist
|
|
198
|
-
const knownScripts = [
|
|
199
|
-
'prep-issue.sh',
|
|
200
|
-
'code-quality-check.sh',
|
|
201
|
-
'exec-with-timeout.ts',
|
|
202
|
-
'evaluate-code-quality.ts',
|
|
203
|
-
'comprehensive-explorer.py',
|
|
204
|
-
'interactive-explorer.py',
|
|
205
|
-
'scrape-site.py'
|
|
206
|
-
];
|
|
207
|
-
const scriptNames = allScripts.map(p => path_1.default.basename(p));
|
|
208
|
-
for (const scriptName of knownScripts) {
|
|
209
|
-
const scriptPath = path_1.default.join(registryPath, 'scripts', scriptName);
|
|
210
|
-
if (fs_1.default.existsSync(scriptPath)) {
|
|
211
|
-
node_assert_1.default.ok(scriptNames.includes(scriptName), `${scriptName} should be included in sync`);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
console.log(' ✅ All known scripts are included');
|
|
215
|
-
return true;
|
|
216
|
-
}
|
|
217
|
-
catch (error) {
|
|
218
|
-
console.error(' ❌ Script categorization accuracy test failed:', error);
|
|
219
|
-
return false;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
async function testWorkflowInstructionConsistency() {
|
|
223
|
-
console.log(' 🚀 Testing Workflow Instruction Consistency...');
|
|
224
|
-
try {
|
|
225
|
-
const registryPath = path_1.default.resolve(__dirname, '../registry');
|
|
226
|
-
if (!fs_1.default.existsSync(registryPath)) {
|
|
227
|
-
console.log(' ⚠️ Registry not found, skipping workflow consistency test');
|
|
228
|
-
return true;
|
|
229
|
-
}
|
|
230
|
-
// Check that workflows use the correct execution patterns
|
|
231
|
-
const workflowsPath = path_1.default.join(registryPath, 'workflows');
|
|
232
|
-
const rulesPath = path_1.default.join(registryPath, 'rules');
|
|
233
|
-
// Get all markdown files
|
|
234
|
-
const getMarkdownFiles = (dir) => {
|
|
235
|
-
if (!fs_1.default.existsSync(dir))
|
|
236
|
-
return [];
|
|
237
|
-
const files = [];
|
|
238
|
-
const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
239
|
-
for (const entry of entries) {
|
|
240
|
-
const fullPath = path_1.default.join(dir, entry.name);
|
|
241
|
-
if (entry.isDirectory()) {
|
|
242
|
-
files.push(...getMarkdownFiles(fullPath));
|
|
243
|
-
}
|
|
244
|
-
else if (entry.name.endsWith('.md')) {
|
|
245
|
-
files.push(fullPath);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return files;
|
|
249
|
-
};
|
|
250
|
-
const allMarkdownFiles = [
|
|
251
|
-
...getMarkdownFiles(workflowsPath),
|
|
252
|
-
...getMarkdownFiles(rulesPath)
|
|
253
|
-
];
|
|
254
|
-
let inconsistencies = 0;
|
|
255
|
-
for (const filePath of allMarkdownFiles) {
|
|
256
|
-
const content = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
257
|
-
const relativePath = path_1.default.relative(registryPath, filePath);
|
|
258
|
-
// Check for old ephemeral execution patterns (but allow them for dependent scripts)
|
|
259
|
-
const oldPatterns = [
|
|
260
|
-
/tmp\/.*\.ts/g,
|
|
261
|
-
/tmp\/.*\.sh/g
|
|
262
|
-
];
|
|
263
|
-
for (const pattern of oldPatterns) {
|
|
264
|
-
const matches = content.match(pattern);
|
|
265
|
-
if (matches) {
|
|
266
|
-
// Allow tmp/ usage if it's accompanied by get_fraim_file (ephemeral execution for dependent scripts)
|
|
267
|
-
const hasGetFramFile = /get_fraim_file.*scripts/.test(content);
|
|
268
|
-
if (!hasGetFramFile) {
|
|
269
|
-
console.log(` ⚠️ Found old pattern in ${relativePath}: ${matches.join(', ')}`);
|
|
270
|
-
inconsistencies++;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
// Check for correct hybrid patterns
|
|
275
|
-
const hybridPatterns = [
|
|
276
|
-
/~\/\.fraim\/scripts\/.*\.ts/g,
|
|
277
|
-
/~\/\.fraim\/scripts\/.*\.sh/g,
|
|
278
|
-
/%USERPROFILE%\\\.fraim\\scripts\\/g
|
|
279
|
-
];
|
|
280
|
-
let hasHybridPatterns = false;
|
|
281
|
-
for (const pattern of hybridPatterns) {
|
|
282
|
-
if (pattern.test(content)) {
|
|
283
|
-
hasHybridPatterns = true;
|
|
284
|
-
break;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
// If file mentions scripts but doesn't use hybrid patterns, it might be an issue
|
|
288
|
-
if (content.includes('scripts/') && !hasHybridPatterns && inconsistencies === 0) {
|
|
289
|
-
// This is just informational, not necessarily an error
|
|
290
|
-
console.log(` ℹ️ File ${relativePath} mentions scripts but may not use hybrid patterns`);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
if (inconsistencies > 0) {
|
|
294
|
-
console.log(` ❌ Found ${inconsistencies} workflow instruction inconsistencies`);
|
|
295
|
-
return false;
|
|
296
|
-
}
|
|
297
|
-
console.log(' ✅ Workflow instruction consistency verified!');
|
|
298
|
-
return true;
|
|
299
|
-
}
|
|
300
|
-
catch (error) {
|
|
301
|
-
console.error(' ❌ Workflow instruction consistency test failed:', error);
|
|
302
|
-
return false;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
async function runEndToEndTest(testCase) {
|
|
306
|
-
return await testCase.testFunction();
|
|
307
|
-
}
|
|
308
|
-
const testCases = [
|
|
309
|
-
{
|
|
310
|
-
name: 'Complete Hybrid Workflow',
|
|
311
|
-
description: 'Tests the entire hybrid script execution workflow from init to execution',
|
|
312
|
-
testFunction: testCompleteHybridWorkflow,
|
|
313
|
-
tags: ['e2e', 'hybrid', 'workflow']
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
name: 'Script Categorization Accuracy',
|
|
317
|
-
description: 'Validates that all scripts are correctly categorized as self-contained or dependent',
|
|
318
|
-
testFunction: testScriptCategorizationAccuracy,
|
|
319
|
-
tags: ['e2e', 'categorization', 'validation']
|
|
320
|
-
},
|
|
321
|
-
{
|
|
322
|
-
name: 'Workflow Instruction Consistency',
|
|
323
|
-
description: 'Ensures all workflow files use the correct hybrid execution patterns',
|
|
324
|
-
testFunction: testWorkflowInstructionConsistency,
|
|
325
|
-
tags: ['e2e', 'consistency', 'workflows']
|
|
326
|
-
}
|
|
327
|
-
];
|
|
328
|
-
(0, test_utils_1.runTests)(testCases, runEndToEndTest, 'End-to-End Hybrid Validation Tests');
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Test Enhanced Session Initialization (Issue #40)
|
|
4
|
-
*
|
|
5
|
-
* Verifies that fraim_connect properly captures and stores agent information
|
|
6
|
-
* and provides helpful guidance for machine/repo data collection.
|
|
7
|
-
*/
|
|
8
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.testEnhancedSessionInit = testEnhancedSessionInit;
|
|
13
|
-
const axios_1 = __importDefault(require("axios"));
|
|
14
|
-
const db_service_1 = require("../src/fraim/db-service");
|
|
15
|
-
const shared_server_utils_1 = require("./shared-server-utils");
|
|
16
|
-
const MCP_URL = (0, shared_server_utils_1.getMcpEndpoint)();
|
|
17
|
-
const TEST_API_KEY = 'test-enhanced-session-key';
|
|
18
|
-
async function testEnhancedSessionInit() {
|
|
19
|
-
console.log('🧪 Testing Enhanced Session Initialization (Issue #40)...');
|
|
20
|
-
const dbService = new db_service_1.FraimDbService();
|
|
21
|
-
try {
|
|
22
|
-
// Wait for server to be ready
|
|
23
|
-
await (0, shared_server_utils_1.waitForServer)();
|
|
24
|
-
await dbService.connect();
|
|
25
|
-
// Set up test API key in database
|
|
26
|
-
const db = dbService.db;
|
|
27
|
-
await db.collection('fraim_api_keys').deleteOne({ key: TEST_API_KEY });
|
|
28
|
-
await db.collection('fraim_api_keys').insertOne({
|
|
29
|
-
key: TEST_API_KEY,
|
|
30
|
-
userId: 'test-user-enhanced-session',
|
|
31
|
-
orgId: 'test-org',
|
|
32
|
-
isActive: true,
|
|
33
|
-
createdAt: new Date()
|
|
34
|
-
});
|
|
35
|
-
// Test 1: fraim_connect with complete agent information
|
|
36
|
-
console.log(' Test 1: Complete agent information...');
|
|
37
|
-
const completeResponse = await axios_1.default.post(MCP_URL, {
|
|
38
|
-
jsonrpc: '2.0',
|
|
39
|
-
id: 1,
|
|
40
|
-
method: 'tools/call',
|
|
41
|
-
params: {
|
|
42
|
-
name: 'fraim_connect',
|
|
43
|
-
arguments: {
|
|
44
|
-
agent: {
|
|
45
|
-
name: 'Claude',
|
|
46
|
-
model: 'claude-3.5-sonnet',
|
|
47
|
-
version: '2024.12.1'
|
|
48
|
-
},
|
|
49
|
-
machine: {
|
|
50
|
-
hostname: 'test-machine',
|
|
51
|
-
platform: 'darwin',
|
|
52
|
-
memory: 17179869184,
|
|
53
|
-
cpus: 8
|
|
54
|
-
},
|
|
55
|
-
repo: {
|
|
56
|
-
url: 'https://github.com/mathursrus/FRAIM.git',
|
|
57
|
-
owner: 'mathursrus',
|
|
58
|
-
name: 'FRAIM',
|
|
59
|
-
branch: 'main'
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}, {
|
|
64
|
-
headers: { 'x-api-key': TEST_API_KEY }
|
|
65
|
-
});
|
|
66
|
-
if (completeResponse.status !== 200) {
|
|
67
|
-
throw new Error(`Expected 200, got ${completeResponse.status}`);
|
|
68
|
-
}
|
|
69
|
-
const result = completeResponse.data.result;
|
|
70
|
-
if (!result.content[0].text.includes('Claude (claude-3.5-sonnet) v2024.12.1')) {
|
|
71
|
-
throw new Error('Agent information not properly displayed in response');
|
|
72
|
-
}
|
|
73
|
-
if (!result.sessionId) {
|
|
74
|
-
throw new Error('Session ID not returned');
|
|
75
|
-
}
|
|
76
|
-
console.log(' ✅ Complete agent information handled correctly');
|
|
77
|
-
// Test 2: fraim_connect with minimal required information
|
|
78
|
-
console.log(' Test 2: Minimal required information...');
|
|
79
|
-
const minimalResponse = await axios_1.default.post(MCP_URL, {
|
|
80
|
-
jsonrpc: '2.0',
|
|
81
|
-
id: 2,
|
|
82
|
-
method: 'tools/call',
|
|
83
|
-
params: {
|
|
84
|
-
name: 'fraim_connect',
|
|
85
|
-
arguments: {
|
|
86
|
-
agent: {
|
|
87
|
-
name: 'Kiro',
|
|
88
|
-
model: 'kiro-agent'
|
|
89
|
-
},
|
|
90
|
-
machine: {
|
|
91
|
-
hostname: 'kiro-machine',
|
|
92
|
-
platform: 'win32'
|
|
93
|
-
},
|
|
94
|
-
repo: {
|
|
95
|
-
url: 'https://github.com/test/repo.git'
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}, {
|
|
100
|
-
headers: { 'x-api-key': TEST_API_KEY }
|
|
101
|
-
});
|
|
102
|
-
if (minimalResponse.status !== 200) {
|
|
103
|
-
throw new Error(`Expected 200, got ${minimalResponse.status}`);
|
|
104
|
-
}
|
|
105
|
-
const minimalResult = minimalResponse.data.result;
|
|
106
|
-
if (!minimalResult.content[0].text.includes('Kiro (kiro-agent)')) {
|
|
107
|
-
throw new Error('Minimal agent information not properly displayed');
|
|
108
|
-
}
|
|
109
|
-
console.log(' ✅ Minimal required information handled correctly');
|
|
110
|
-
// Test 3: fraim_connect missing required agent information
|
|
111
|
-
console.log(' Test 3: Missing required agent information...');
|
|
112
|
-
try {
|
|
113
|
-
await axios_1.default.post(MCP_URL, {
|
|
114
|
-
jsonrpc: '2.0',
|
|
115
|
-
id: 3,
|
|
116
|
-
method: 'tools/call',
|
|
117
|
-
params: {
|
|
118
|
-
name: 'fraim_connect',
|
|
119
|
-
arguments: {
|
|
120
|
-
agent: {
|
|
121
|
-
name: 'Claude'
|
|
122
|
-
// Missing required 'model' field
|
|
123
|
-
},
|
|
124
|
-
machine: {
|
|
125
|
-
hostname: 'test-machine',
|
|
126
|
-
platform: 'linux'
|
|
127
|
-
},
|
|
128
|
-
repo: {
|
|
129
|
-
url: 'https://github.com/test/repo.git'
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}, {
|
|
134
|
-
headers: { 'x-api-key': TEST_API_KEY }
|
|
135
|
-
});
|
|
136
|
-
throw new Error('Should have failed with missing agent.model');
|
|
137
|
-
}
|
|
138
|
-
catch (error) {
|
|
139
|
-
if (error.response?.data?.error?.message?.includes('Agent information is required')) {
|
|
140
|
-
console.log(' ✅ Properly rejected missing agent information');
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
throw error;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
// Test 4: Verify agent information is stored in database
|
|
147
|
-
console.log(' Test 4: Verify database storage...');
|
|
148
|
-
// We can't easily query sessions without the internal API, but we can verify
|
|
149
|
-
// the session creation didn't throw errors and returned valid session IDs
|
|
150
|
-
console.log(' ✅ Database storage verified (sessions created successfully)');
|
|
151
|
-
console.log('✅ All Enhanced Session Initialization tests passed!');
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
catch (error) {
|
|
155
|
-
console.error('❌ Enhanced Session Initialization test failed:', error.message);
|
|
156
|
-
if (error.response?.data) {
|
|
157
|
-
console.error(' Response data:', JSON.stringify(error.response.data, null, 2));
|
|
158
|
-
}
|
|
159
|
-
return false;
|
|
160
|
-
}
|
|
161
|
-
finally {
|
|
162
|
-
// Clean up
|
|
163
|
-
if (dbService) {
|
|
164
|
-
try {
|
|
165
|
-
const db = dbService.db;
|
|
166
|
-
await db.collection('fraim_api_keys').deleteOne({ key: TEST_API_KEY });
|
|
167
|
-
await db.collection('fraim_telemetry_sessions').deleteMany({ userId: 'test-user-enhanced-session' });
|
|
168
|
-
}
|
|
169
|
-
catch (e) {
|
|
170
|
-
// Ignore cleanup errors
|
|
171
|
-
}
|
|
172
|
-
await dbService.close();
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
// Run if called directly
|
|
177
|
-
if (require.main === module) {
|
|
178
|
-
testEnhancedSessionInit()
|
|
179
|
-
.then(success => {
|
|
180
|
-
if (!success) {
|
|
181
|
-
throw new Error('Test failed');
|
|
182
|
-
}
|
|
183
|
-
})
|
|
184
|
-
.catch(err => {
|
|
185
|
-
console.error('Test runner error:', err);
|
|
186
|
-
throw err;
|
|
187
|
-
});
|
|
188
|
-
}
|