fraim-framework 2.0.56 → 2.0.58

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 (224) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/bin/fraim-mcp.js +14 -0
  3. package/bin/fraim.js +23 -0
  4. package/dist/src/cli/commands/init-project.js +10 -4
  5. package/dist/src/cli/commands/mcp.js +65 -0
  6. package/dist/src/cli/setup/mcp-config-generator.js +19 -16
  7. package/dist/src/fraim/issue-tracking/ado-provider.js +304 -0
  8. package/dist/src/fraim/issue-tracking/factory.js +63 -0
  9. package/dist/src/fraim/issue-tracking/github-provider.js +200 -0
  10. package/dist/src/fraim/issue-tracking/types.js +7 -0
  11. package/dist/src/fraim/issue-tracking-config.js +83 -0
  12. package/dist/src/local-mcp-server/stdio-server.js +207 -0
  13. package/dist/src/utils/workflow-parser.js +81 -0
  14. package/package.json +17 -12
  15. package/registry/scripts/pdf-styles.css +172 -0
  16. package/registry/scripts/prep-issue.sh +46 -4
  17. package/registry/scripts/profile-server.ts +131 -130
  18. package/registry/stubs/workflows/customer-development/user-survey-dispatch.md +1 -1
  19. package/registry/stubs/workflows/customer-development/users-to-target.md +1 -1
  20. package/registry/stubs/workflows/product-building/design.md +1 -1
  21. package/registry/stubs/workflows/product-building/implement.md +1 -1
  22. package/Claude.md +0 -1
  23. package/dist/registry/ai-manager-rules/customer-development-phases/phase1-customer-profiling.md +0 -101
  24. package/dist/registry/ai-manager-rules/customer-development-phases/phase2-platform-discovery.md +0 -235
  25. package/dist/registry/ai-manager-rules/customer-development-phases/phase3-prospect-qualification.md +0 -243
  26. package/dist/registry/ai-manager-rules/customer-development-phases/phase4-inventory-compilation.md +0 -206
  27. package/dist/registry/ai-manager-rules/design-phases/design-completeness-review.md +0 -73
  28. package/dist/registry/ai-manager-rules/design-phases/design-design.md +0 -145
  29. package/dist/registry/ai-manager-rules/implement-phases/implement-code.md +0 -283
  30. package/dist/registry/ai-manager-rules/implement-phases/implement-completeness-review.md +0 -120
  31. package/dist/registry/ai-manager-rules/implement-phases/implement-regression.md +0 -173
  32. package/dist/registry/ai-manager-rules/implement-phases/implement-repro.md +0 -104
  33. package/dist/registry/ai-manager-rules/implement-phases/implement-scoping.md +0 -100
  34. package/dist/registry/ai-manager-rules/implement-phases/implement-smoke.md +0 -237
  35. package/dist/registry/ai-manager-rules/implement-phases/implement-spike.md +0 -121
  36. package/dist/registry/ai-manager-rules/implement-phases/implement-validate.md +0 -375
  37. package/dist/registry/ai-manager-rules/retrospective.md +0 -116
  38. package/dist/registry/ai-manager-rules/shared-phases/address-pr-feedback.md +0 -188
  39. package/dist/registry/ai-manager-rules/shared-phases/submit-pr.md +0 -202
  40. package/dist/registry/ai-manager-rules/shared-phases/wait-for-pr-review.md +0 -170
  41. package/dist/registry/ai-manager-rules/spec-phases/spec-competitor-analysis.md +0 -105
  42. package/dist/registry/ai-manager-rules/spec-phases/spec-completeness-review.md +0 -66
  43. package/dist/registry/ai-manager-rules/spec-phases/spec-spec.md +0 -139
  44. package/dist/registry/ai-manager-rules/user-survey-phases/phase1-survey-scoping.md +0 -60
  45. package/dist/registry/ai-manager-rules/user-survey-phases/phase2-survey-build-linkedin.md +0 -23
  46. package/dist/registry/ai-manager-rules/user-survey-phases/phase3-survey-build-reddit.md +0 -22
  47. package/dist/registry/ai-manager-rules/user-survey-phases/phase4-survey-build-x.md +0 -21
  48. package/dist/registry/ai-manager-rules/user-survey-phases/phase5-survey-build-facebook.md +0 -19
  49. package/dist/registry/ai-manager-rules/user-survey-phases/phase6-survey-build-custom.md +0 -15
  50. package/dist/registry/ai-manager-rules/user-survey-phases/phase7-survey-dispatch.md +0 -45
  51. package/dist/registry/providers/ado.json +0 -19
  52. package/dist/registry/providers/github.json +0 -19
  53. package/dist/registry/scripts/cleanup-branch.js +0 -287
  54. package/dist/registry/scripts/evaluate-code-quality.js +0 -66
  55. package/dist/registry/scripts/exec-with-timeout.js +0 -142
  56. package/dist/registry/scripts/generate-engagement-emails.js +0 -705
  57. package/dist/registry/scripts/newsletter-helpers.js +0 -671
  58. package/dist/registry/scripts/profile-server.js +0 -388
  59. package/dist/registry/scripts/run-thank-you-workflow.js +0 -92
  60. package/dist/registry/scripts/send-newsletter-simple.js +0 -85
  61. package/dist/registry/scripts/send-thank-you-emails.js +0 -54
  62. package/dist/registry/scripts/validate-openapi-limits.js +0 -311
  63. package/dist/registry/scripts/validate-test-coverage.js +0 -262
  64. package/dist/registry/scripts/verify-test-coverage.js +0 -66
  65. package/dist/registry/templates/bootstrap/ARCHITECTURE-TEMPLATE.md +0 -53
  66. package/dist/registry/templates/bootstrap/CODE-QUALITY-REPORT-TEMPLATE.md +0 -37
  67. package/dist/registry/templates/bootstrap/TEST-COVERAGE-REPORT-TEMPLATE.md +0 -35
  68. package/dist/registry/templates/business-development/IDEATION-REPORT-TEMPLATE.md +0 -29
  69. package/dist/registry/templates/business-development/PRICING-STRATEGY-TEMPLATE.md +0 -126
  70. package/dist/registry/templates/customer-development/customer-interview-template.md +0 -99
  71. package/dist/registry/templates/customer-development/customer-persona-template.md +0 -69
  72. package/dist/registry/templates/customer-development/follow-up-email-templates.md +0 -132
  73. package/dist/registry/templates/customer-development/insight-analysis-template.md +0 -74
  74. package/dist/registry/templates/customer-development/prospect-inventory-template.csv +0 -3
  75. package/dist/registry/templates/customer-development/search-strategy-template.md +0 -123
  76. package/dist/registry/templates/customer-development/strategic-recommendations-template.md +0 -53
  77. package/dist/registry/templates/customer-development/thank-you-email-template.html +0 -124
  78. package/dist/registry/templates/customer-development/thank-you-note-template.md +0 -16
  79. package/dist/registry/templates/customer-development/triage-log-template.md +0 -278
  80. package/dist/registry/templates/customer-development/weekly-newsletter-template.html +0 -204
  81. package/dist/registry/templates/evidence/Design-Evidence.md +0 -30
  82. package/dist/registry/templates/evidence/Implementation-BugEvidence.md +0 -94
  83. package/dist/registry/templates/evidence/Implementation-FeatureEvidence.md +0 -129
  84. package/dist/registry/templates/evidence/Spec-Evidence.md +0 -19
  85. package/dist/registry/templates/help/HelpNeeded.md +0 -14
  86. package/dist/registry/templates/legal/NDA-TEMPLATE.md +0 -170
  87. package/dist/registry/templates/legal/PATENT-TEMPLATE.md +0 -372
  88. package/dist/registry/templates/legal/TRADEMARK-TEMPLATE.md +0 -339
  89. package/dist/registry/templates/legal/contract-review-checklist.md +0 -193
  90. package/dist/registry/templates/legal/review-report-template.md +0 -198
  91. package/dist/registry/templates/legal/saas-terms-template.md +0 -174
  92. package/dist/registry/templates/legal/sow-template.md +0 -117
  93. package/dist/registry/templates/legal/template-variables.md +0 -131
  94. package/dist/registry/templates/marketing/DOMAIN-REGISTRATION-TEMPLATE.md +0 -194
  95. package/dist/registry/templates/marketing/HBR-ARTICLE-TEMPLATE.md +0 -66
  96. package/dist/registry/templates/marketing/STORYTELLING-TEMPLATE.md +0 -130
  97. package/dist/registry/templates/marketing/WEBSITE-TEMPLATE.md +0 -262
  98. package/dist/registry/templates/marketing/github-pages-workflow.yml +0 -64
  99. package/dist/registry/templates/replicate/implementation-checklist.md +0 -39
  100. package/dist/registry/templates/replicate/use-cases-template.md +0 -88
  101. package/dist/registry/templates/retrospective/RETROSPECTIVE-TEMPLATE.md +0 -55
  102. package/dist/registry/templates/specs/BUGSPEC-TEMPLATE.md +0 -37
  103. package/dist/registry/templates/specs/FEATURESPEC-TEMPLATE.md +0 -66
  104. package/dist/registry/templates/specs/TECHSPEC-TEMPLATE.md +0 -39
  105. package/dist/registry/workflows/bootstrap/create-architecture.md +0 -38
  106. package/dist/registry/workflows/bootstrap/detect-broken-windows.md +0 -300
  107. package/dist/registry/workflows/bootstrap/evaluate-code-quality.md +0 -35
  108. package/dist/registry/workflows/bootstrap/verify-test-coverage.md +0 -36
  109. package/dist/registry/workflows/brainstorming/blue-sky-brainstorming.md +0 -211
  110. package/dist/registry/workflows/brainstorming/codebase-brainstorming.md +0 -165
  111. package/dist/registry/workflows/business-development/create-business-plan.md +0 -737
  112. package/dist/registry/workflows/business-development/ideate-business-opportunity.md +0 -55
  113. package/dist/registry/workflows/business-development/price-product.md +0 -325
  114. package/dist/registry/workflows/compliance/detect-compliance-requirements.md +0 -78
  115. package/dist/registry/workflows/compliance/generate-audit-evidence.md +0 -75
  116. package/dist/registry/workflows/compliance/soc2-evidence-generator.md +0 -332
  117. package/dist/registry/workflows/customer-development/insight-analysis.md +0 -156
  118. package/dist/registry/workflows/customer-development/insight-triage.md +0 -938
  119. package/dist/registry/workflows/customer-development/interview-preparation.md +0 -452
  120. package/dist/registry/workflows/customer-development/linkedin-outreach.md +0 -593
  121. package/dist/registry/workflows/customer-development/strategic-brainstorming.md +0 -146
  122. package/dist/registry/workflows/customer-development/thank-customers.md +0 -203
  123. package/dist/registry/workflows/customer-development/user-survey-dispatch.md +0 -60
  124. package/dist/registry/workflows/customer-development/users-to-target.md +0 -112
  125. package/dist/registry/workflows/customer-development/weekly-newsletter.md +0 -366
  126. package/dist/registry/workflows/deploy/cloud-deployment.md +0 -310
  127. package/dist/registry/workflows/improve-fraim/contribute.md +0 -32
  128. package/dist/registry/workflows/improve-fraim/file-issue.md +0 -32
  129. package/dist/registry/workflows/learning/build-skillset.md +0 -212
  130. package/dist/registry/workflows/learning/synthesize-learnings.md +0 -284
  131. package/dist/registry/workflows/legal/contract-review-analysis.md +0 -382
  132. package/dist/registry/workflows/legal/nda.md +0 -69
  133. package/dist/registry/workflows/legal/patent-filing.md +0 -76
  134. package/dist/registry/workflows/legal/saas-contract-development.md +0 -213
  135. package/dist/registry/workflows/legal/trademark-filing.md +0 -77
  136. package/dist/registry/workflows/marketing/content-creation.md +0 -37
  137. package/dist/registry/workflows/marketing/convert-to-pdf.md +0 -235
  138. package/dist/registry/workflows/marketing/create-modern-website.md +0 -456
  139. package/dist/registry/workflows/marketing/domain-registration.md +0 -323
  140. package/dist/registry/workflows/marketing/hbr-article.md +0 -73
  141. package/dist/registry/workflows/marketing/launch-checklist.md +0 -37
  142. package/dist/registry/workflows/marketing/marketing-strategy.md +0 -45
  143. package/dist/registry/workflows/marketing/storytelling.md +0 -65
  144. package/dist/registry/workflows/performance/analyze-performance.md +0 -65
  145. package/dist/registry/workflows/product-building/design.md +0 -103
  146. package/dist/registry/workflows/product-building/implement.md +0 -74
  147. package/dist/registry/workflows/product-building/iterate-on-pr-comments.md +0 -70
  148. package/dist/registry/workflows/product-building/prep-issue.md +0 -41
  149. package/dist/registry/workflows/product-building/prototype.md +0 -65
  150. package/dist/registry/workflows/product-building/resolve.md +0 -168
  151. package/dist/registry/workflows/product-building/retrospect.md +0 -86
  152. package/dist/registry/workflows/product-building/spec.md +0 -181
  153. package/dist/registry/workflows/product-building/test.md +0 -125
  154. package/dist/registry/workflows/productivity-report/productivity-report.md +0 -263
  155. package/dist/registry/workflows/quality-assurance/browser-validation.md +0 -221
  156. package/dist/registry/workflows/quality-assurance/iterative-improvement-cycle.md +0 -562
  157. package/dist/registry/workflows/replicate/replicate-discovery.md +0 -336
  158. package/dist/registry/workflows/replicate/replicate-to-issues.md +0 -324
  159. package/dist/registry/workflows/reviewer/review-implementation-vs-design-spec.md +0 -638
  160. package/dist/registry/workflows/reviewer/review-implementation-vs-feature-spec.md +0 -675
  161. package/dist/registry/workflows/startup-credits/aws-activate-application.md +0 -535
  162. package/dist/registry/workflows/startup-credits/google-cloud-application.md +0 -647
  163. package/dist/registry/workflows/startup-credits/microsoft-azure-application.md +0 -538
  164. package/dist/scripts/build-stub-registry.js +0 -108
  165. package/dist/src/ai-manager/ai-manager.js +0 -480
  166. package/dist/src/ai-manager/phase-flow.js +0 -357
  167. package/dist/src/ai-manager/types.js +0 -5
  168. package/dist/src/fraim-mcp-server.js +0 -1885
  169. package/dist/tests/debug-tools.js +0 -80
  170. package/dist/tests/shared-server-utils.js +0 -57
  171. package/dist/tests/test-add-ide.js +0 -283
  172. package/dist/tests/test-ai-coach-edge-cases.js +0 -420
  173. package/dist/tests/test-ai-coach-mcp-integration.js +0 -450
  174. package/dist/tests/test-ai-coach-performance.js +0 -328
  175. package/dist/tests/test-ai-coach-phase-content.js +0 -264
  176. package/dist/tests/test-ai-coach-workflows.js +0 -514
  177. package/dist/tests/test-cli.js +0 -228
  178. package/dist/tests/test-client-scripts-validation.js +0 -167
  179. package/dist/tests/test-complete-setup-flow.js +0 -110
  180. package/dist/tests/test-config-system.js +0 -279
  181. package/dist/tests/test-debug-session.js +0 -134
  182. package/dist/tests/test-end-to-end-hybrid-validation.js +0 -328
  183. package/dist/tests/test-enhanced-session-init.js +0 -188
  184. package/dist/tests/test-first-run-journey.js +0 -368
  185. package/dist/tests/test-fraim-issues.js +0 -59
  186. package/dist/tests/test-genericization.js +0 -44
  187. package/dist/tests/test-hybrid-script-execution.js +0 -340
  188. package/dist/tests/test-ide-detector.js +0 -46
  189. package/dist/tests/test-improved-setup.js +0 -121
  190. package/dist/tests/test-mcp-config-generator.js +0 -99
  191. package/dist/tests/test-mcp-connection.js +0 -107
  192. package/dist/tests/test-mcp-issue-integration.js +0 -156
  193. package/dist/tests/test-mcp-lifecycle-methods.js +0 -240
  194. package/dist/tests/test-mcp-shared-server.js +0 -308
  195. package/dist/tests/test-mcp-template-processing.js +0 -160
  196. package/dist/tests/test-modular-issue-tracking.js +0 -165
  197. package/dist/tests/test-node-compatibility.js +0 -95
  198. package/dist/tests/test-npm-install.js +0 -68
  199. package/dist/tests/test-package-size.js +0 -108
  200. package/dist/tests/test-pr-review-workflow.js +0 -307
  201. package/dist/tests/test-prep-issue.js +0 -129
  202. package/dist/tests/test-productivity-integration.js +0 -157
  203. package/dist/tests/test-script-location-independence.js +0 -198
  204. package/dist/tests/test-script-sync.js +0 -557
  205. package/dist/tests/test-server-utils.js +0 -32
  206. package/dist/tests/test-session-rehydration.js +0 -148
  207. package/dist/tests/test-setup-integration.js +0 -98
  208. package/dist/tests/test-setup-scenarios.js +0 -322
  209. package/dist/tests/test-standalone.js +0 -143
  210. package/dist/tests/test-stub-registry.js +0 -136
  211. package/dist/tests/test-sync-stubs.js +0 -143
  212. package/dist/tests/test-sync-version-update.js +0 -93
  213. package/dist/tests/test-telemetry.js +0 -193
  214. package/dist/tests/test-token-validator.js +0 -30
  215. package/dist/tests/test-user-journey.js +0 -236
  216. package/dist/tests/test-users-to-target-workflow.js +0 -253
  217. package/dist/tests/test-utils.js +0 -109
  218. package/dist/tests/test-wizard.js +0 -71
  219. package/dist/tests/test-workflow-discovery.js +0 -242
  220. package/labels.json +0 -52
  221. package/registry/agent-guardrails.md +0 -63
  222. package/registry/fraim.md +0 -48
  223. package/setup.js +0 -171
  224. package/tsconfig.json +0 -23
@@ -1,193 +0,0 @@
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_child_process_1 = require("node:child_process");
7
- const axios_1 = __importDefault(require("axios"));
8
- const db_service_js_1 = require("../src/fraim/db-service.js");
9
- const test_utils_1 = require("./test-utils");
10
- const node_assert_1 = __importDefault(require("node:assert"));
11
- const tree_kill_1 = __importDefault(require("tree-kill"));
12
- const test_server_utils_1 = require("./test-server-utils");
13
- async function testTelemetryFlow() {
14
- console.log(' 🚀 Testing Fraim Telemetry System...');
15
- let fraimProcess;
16
- let dbService;
17
- const PORT = Math.floor(Math.random() * 1000) + 11000; // Use random port to avoid zombie conflicts
18
- console.log(` 🎲 Selected random port: ${PORT}`);
19
- const TEST_API_KEY = 'test-fraim-key-telemetry';
20
- const TEST_ADMIN_KEY = 'test-admin-key-telemetry';
21
- const BASE_URL = `http://localhost:${PORT}`;
22
- const DB_CHECK_DELAY = 1000;
23
- try {
24
- // 1. Setup DB and Key
25
- dbService = new db_service_js_1.FraimDbService();
26
- await dbService.connect();
27
- const db = dbService.db;
28
- // Clean previous test data
29
- await db.collection('fraim_api_keys').deleteOne({ key: TEST_API_KEY });
30
- await db.collection('fraim_telemetry_sessions').deleteMany({ userId: 'test-user-telemetry' });
31
- // Insert Test Key
32
- await db.collection('fraim_api_keys').insertOne({
33
- key: TEST_API_KEY,
34
- userId: 'test-user-telemetry',
35
- orgId: 'test-org',
36
- isActive: true,
37
- createdAt: new Date()
38
- });
39
- // 2. Start Server
40
- console.log(` Starting server on port ${PORT}...`);
41
- const npxCommand = process.platform === 'win32' ? 'npx.cmd' : 'npx';
42
- const serverScript = (0, test_server_utils_1.getServerScriptPath)();
43
- fraimProcess = (0, node_child_process_1.spawn)(npxCommand, ['node', `"${serverScript}"`], {
44
- env: {
45
- ...process.env,
46
- FRAIM_MCP_PORT: PORT.toString(),
47
- FRAIM_ADMIN_KEY: TEST_ADMIN_KEY,
48
- FRAIM_SKIP_INDEX_ON_START: 'true',
49
- FRAIM_TELEMETRY_FLUSH_INTERVAL: '200' // Short interval for testing
50
- },
51
- stdio: 'inherit',
52
- shell: true
53
- });
54
- // Wait for start
55
- let started = false;
56
- for (let i = 0; i < 15; i++) {
57
- try {
58
- await axios_1.default.get(`${BASE_URL}/health`, { timeout: 500 });
59
- started = true;
60
- break;
61
- }
62
- catch (e) {
63
- await new Promise(resolve => setTimeout(resolve, 1000));
64
- }
65
- }
66
- if (!started)
67
- throw new Error('Server failed to start');
68
- console.log(' Server started!');
69
- // 3. Test Enforcement: Call tool WITHOUT handshake -> Expect 400
70
- console.log(' Testing enforcement (No Session)...');
71
- try {
72
- const res = await axios_1.default.post(`${BASE_URL}/mcp`, {
73
- jsonrpc: '2.0', id: 1, method: 'tools/call',
74
- params: { name: 'get_fraim_workflow', arguments: { workflow: 'spec' } }
75
- }, { headers: { 'x-api-key': TEST_API_KEY }, timeout: 2000 });
76
- console.error(' ❌ Should have failed with 400 (Session Not Started)');
77
- console.error(' 🔍 Unexpected Success Response:', JSON.stringify(res.data, null, 2));
78
- return false;
79
- }
80
- catch (error) {
81
- if (error.response) {
82
- node_assert_1.default.strictEqual(error.response.status, 400);
83
- node_assert_1.default.match(error.response.data?.error?.message, /Session Not Started/);
84
- console.log(' ✅ Enforcement working: Request blocked.');
85
- }
86
- else {
87
- throw error; // Network error?
88
- }
89
- }
90
- // 4. Test Handshake: Call fraim_connect -> Expect 200 & DB Record
91
- console.log(' Testing fraim_connect...');
92
- const connectRes = await axios_1.default.post(`${BASE_URL}/mcp`, {
93
- jsonrpc: '2.0', id: 2, method: 'tools/call',
94
- params: {
95
- name: 'fraim_connect',
96
- arguments: {
97
- agent: {
98
- name: 'Claude',
99
- model: 'test-model'
100
- },
101
- machine: { hostname: 'test-host', platform: 'test-os' },
102
- repo: { url: 'http://github.com/test/repo' }
103
- }
104
- }
105
- }, { headers: { 'x-api-key': TEST_API_KEY }, timeout: 2000 });
106
- node_assert_1.default.strictEqual(connectRes.status, 200);
107
- const connectResult = connectRes.data.result;
108
- const connectedMsg = connectResult.content.find((c) => c.text.includes('Connected!'));
109
- node_assert_1.default.ok(connectedMsg, 'Should find Connected! message in response content');
110
- // Verify Session ID returned in payload
111
- node_assert_1.default.ok(connectResult.sessionId, 'Should return sessionId in response');
112
- console.log(` ✅ Handshake successful. Session ID: ${connectResult.sessionId}`);
113
- // Verify DB Record Created
114
- await new Promise(r => setTimeout(r, DB_CHECK_DELAY));
115
- const session = await db.collection('fraim_telemetry_sessions').findOne({ userId: 'test-user-telemetry' });
116
- node_assert_1.default.ok(session, 'Session should exist in DB');
117
- node_assert_1.default.strictEqual(session.machine.hostname, 'test-host');
118
- const initialLastActive = session.lastActive.getTime();
119
- console.log(` ✅ DB Session verified. Initial LastActive: ${initialLastActive}`);
120
- // 5. Test Implicit Flush (Write-Behind)
121
- // Wait > 200ms (flush interval)
122
- console.log(' Waiting 1s to exceed flush interval...');
123
- await new Promise(r => setTimeout(r, 1000));
124
- // Call a tool (Authorized) - Should trigger flush
125
- await axios_1.default.post(`${BASE_URL}/mcp`, {
126
- jsonrpc: '2.0', id: 3, method: 'tools/call',
127
- params: { name: 'get_fraim_workflow', arguments: { workflow: 'test' } }
128
- }, { headers: { 'x-api-key': TEST_API_KEY }, timeout: 2000 });
129
- console.log(' ✅ Tool call successful. Should trigger flush.');
130
- // Give DB a moment to update
131
- await new Promise(r => setTimeout(r, DB_CHECK_DELAY));
132
- const sessionUpdated = await db.collection('fraim_telemetry_sessions').findOne({ userId: 'test-user-telemetry' });
133
- const updatedLastActive = sessionUpdated.lastActive.getTime();
134
- console.log(` Updated LastActive: ${updatedLastActive}`);
135
- node_assert_1.default.ok(updatedLastActive > initialLastActive, 'Implicit flush should have updated the DB timestamp');
136
- console.log(' ✅ Implicit flush verified.');
137
- // 6. Test Shutdown Flush
138
- console.log(' Testing Shutdown Flush...');
139
- // Trigger ONE MORE activity, but don't wait for implicit flush
140
- await new Promise(r => setTimeout(r, 10)); // Ensure at least 10ms diff
141
- await axios_1.default.post(`${BASE_URL}/mcp`, {
142
- jsonrpc: '2.0', id: 4, method: 'tools/call',
143
- params: { name: 'get_fraim_workflow', arguments: { workflow: 'test-2' } }
144
- }, { headers: { 'x-api-key': TEST_API_KEY }, timeout: 2000 });
145
- console.log(' ✅ Late activity triggered (Pending Flush).');
146
- // Kill the server with SIGTERM to trigger graceful shutdown
147
- // Kill the server with SIGTERM to trigger graceful shutdown
148
- // Use tree-kill to ensure we reach the actual node process through the npx/shell wrapper
149
- if (fraimProcess && fraimProcess.pid) {
150
- await new Promise(resolve => (0, tree_kill_1.default)(fraimProcess.pid, 'SIGTERM', () => resolve()));
151
- }
152
- // Wait for process to exit and flush
153
- await new Promise(resolve => setTimeout(resolve, 3000));
154
- const sessionFinal = await db.collection('fraim_telemetry_sessions').findOne({ userId: 'test-user-telemetry' });
155
- const finalLastActive = sessionFinal.lastActive.getTime();
156
- console.log(` Final LastActive: ${finalLastActive}`);
157
- node_assert_1.default.ok(finalLastActive > updatedLastActive, 'Final Flush should have updated the DB timestamp with the pending activity');
158
- console.log(' ✅ Shutdown flush verified.');
159
- return true;
160
- }
161
- catch (error) {
162
- console.error(' ❌ Test failed:', error.message);
163
- if (error.response?.data) {
164
- console.error(' 🔍 Server Error Detail:', JSON.stringify(error.response.data, null, 2));
165
- }
166
- return false;
167
- }
168
- finally {
169
- if (dbService) {
170
- const db = dbService.db;
171
- await db.collection('fraim_api_keys').deleteOne({ key: TEST_API_KEY }).catch(() => { });
172
- await db.collection('fraim_telemetry_sessions').deleteMany({ userId: 'test-user-telemetry' }).catch(() => { });
173
- await dbService.close();
174
- }
175
- if (fraimProcess && fraimProcess.pid) {
176
- console.log(' 🔫 Cleanup: Killing server process tree:', fraimProcess.pid);
177
- await new Promise(resolve => (0, tree_kill_1.default)(fraimProcess.pid, 'SIGKILL', () => resolve()));
178
- }
179
- }
180
- }
181
- const testCases = [
182
- {
183
- name: 'Fraim Telemetry & Session Management',
184
- description: 'Tests handshake enforcement, session creation, implicit tracking, and write-behind caching',
185
- testFunction: testTelemetryFlow,
186
- tags: ['telemetry']
187
- }
188
- ];
189
- (0, test_utils_1.runTests)(testCases, async (t) => t.testFunction(), 'Fraim Telemetry System')
190
- .catch((err) => {
191
- console.error('Test runner failed:', err);
192
- throw err;
193
- });
@@ -1,30 +0,0 @@
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 token_validator_1 = require("../src/cli/setup/token-validator");
9
- (0, node_test_1.test)('isValidTokenFormat should validate FRAIM keys correctly', () => {
10
- (0, node_assert_1.default)((0, token_validator_1.isValidTokenFormat)('fraim_abc123456789012', 'fraim'), 'Valid FRAIM key should pass');
11
- (0, node_assert_1.default)(!(0, token_validator_1.isValidTokenFormat)('invalid_key', 'fraim'), 'Invalid FRAIM key should fail');
12
- (0, node_assert_1.default)(!(0, token_validator_1.isValidTokenFormat)('fraim_short', 'fraim'), 'Short FRAIM key should fail');
13
- (0, node_assert_1.default)(!(0, token_validator_1.isValidTokenFormat)('', 'fraim'), 'Empty string should fail');
14
- });
15
- (0, node_test_1.test)('isValidTokenFormat should validate GitHub tokens correctly', () => {
16
- (0, node_assert_1.default)((0, token_validator_1.isValidTokenFormat)('ghp_abc123456789', 'github'), 'Valid GitHub classic token should pass');
17
- (0, node_assert_1.default)((0, token_validator_1.isValidTokenFormat)('github_pat_abc123456789', 'github'), 'Valid GitHub PAT should pass');
18
- (0, node_assert_1.default)(!(0, token_validator_1.isValidTokenFormat)('invalid_token', 'github'), 'Invalid GitHub token should fail');
19
- (0, node_assert_1.default)(!(0, token_validator_1.isValidTokenFormat)('gho_abc123456789', 'github'), 'OAuth token should fail');
20
- (0, node_assert_1.default)(!(0, token_validator_1.isValidTokenFormat)('', 'github'), 'Empty string should fail');
21
- });
22
- (0, node_test_1.test)('validateFraimKey should validate format', async () => {
23
- const validKey = 'fraim_abc123456789012';
24
- const invalidKey = 'invalid_key';
25
- const shortKey = 'fraim_short';
26
- (0, node_assert_1.default)(await (0, token_validator_1.validateFraimKey)(validKey), 'Valid FRAIM key should pass');
27
- (0, node_assert_1.default)(!await (0, token_validator_1.validateFraimKey)(invalidKey), 'Invalid FRAIM key should fail');
28
- (0, node_assert_1.default)(!await (0, token_validator_1.validateFraimKey)(shortKey), 'Short FRAIM key should fail');
29
- (0, node_assert_1.default)(!await (0, token_validator_1.validateFraimKey)(''), 'Empty key should fail');
30
- });
@@ -1,236 +0,0 @@
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_child_process_1 = require("node:child_process");
7
- const axios_1 = __importDefault(require("axios"));
8
- const test_utils_1 = require("./test-utils");
9
- const db_service_1 = require("../src/fraim/db-service");
10
- const node_assert_1 = __importDefault(require("node:assert"));
11
- const tree_kill_1 = __importDefault(require("tree-kill"));
12
- const fs_1 = __importDefault(require("fs"));
13
- const path_1 = __importDefault(require("path"));
14
- const os_1 = __importDefault(require("os"));
15
- const test_server_utils_1 = require("./test-server-utils");
16
- async function testDualDiscoveryJourney() {
17
- console.log(' 🚀 Starting Dual Discovery User Journey Test...');
18
- // Setup
19
- const tempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'fraim-journey-'));
20
- console.log(` 📂 Project Context: ${tempDir}`);
21
- let fraimProcess;
22
- let dbService;
23
- const PORT = Math.floor(Math.random() * 1000) + 10000; // Random port to avoid conflicts
24
- const BASE_URL = `http://localhost:${PORT}`;
25
- const TEST_API_KEY = 'fraim-journey-key';
26
- try {
27
- // --- PRE-REQUISITE: DB Setup ---
28
- dbService = new db_service_1.FraimDbService();
29
- await dbService.connect();
30
- const db = dbService.db;
31
- await db.collection('fraim_api_keys').updateOne({ key: TEST_API_KEY }, { $set: { userId: 'journey-user', orgId: 'journey-org', isActive: true } }, { upsert: true });
32
- // --- SCENARIO 1: Project Initialization ---
33
- console.log('\n [1/4] Scenario: User initializes project');
34
- // Set up git repository (required for new init logic)
35
- const { execSync } = require('child_process');
36
- execSync('git init', { cwd: tempDir });
37
- execSync('git remote add origin https://github.com/test-owner/test-repo.git', { cwd: tempDir });
38
- // Mock registry in the repo for sync to work
39
- // We will point the test to use the repo's actual registry folder
40
- // But for 'init' we just need the script
41
- const cliScript = (0, test_utils_1.resolveProjectPath)('dist/src/cli/fraim.js');
42
- const tsxCli = (0, test_utils_1.resolveProjectPath)('node_modules/tsx/dist/cli.mjs');
43
- const runFraim = async (args) => {
44
- return new Promise(resolve => {
45
- const ps = (0, node_child_process_1.spawn)(process.execPath, [tsxCli, cliScript, ...args], {
46
- cwd: tempDir,
47
- env: { ...process.env, TEST_MODE: 'true' },
48
- shell: false
49
- });
50
- let stdout = '';
51
- let stderr = '';
52
- ps.stdout.on('data', d => stdout += d.toString());
53
- ps.stderr.on('data', d => stderr += d.toString());
54
- ps.on('close', code => resolve({ code, stdout: stdout + '\nSTDERR:\n' + stderr }));
55
- });
56
- };
57
- const initRes = await runFraim(['init']);
58
- node_assert_1.default.strictEqual(initRes.code, 0, 'Init failed');
59
- node_assert_1.default.ok(fs_1.default.existsSync(path_1.default.join(tempDir, '.fraim', 'config.json')), 'Config missing');
60
- console.log(' ✅ `fraim init` created project structure');
61
- // --- SEED REGISTRY ---
62
- // The CLI sync command looks for 'registry' in the project root if it can't find it relative to the script.
63
- // We simulate a valid environment by copying the registry to the temp project.
64
- const sourceRegistry = path_1.default.join(__dirname, '../registry');
65
- const targetRegistry = path_1.default.join(tempDir, 'registry');
66
- // Simple recursive copy helper
67
- const copyRecursiveSync = (src, dest) => {
68
- if (fs_1.default.existsSync(src)) {
69
- if (fs_1.default.lstatSync(src).isDirectory()) {
70
- if (!fs_1.default.existsSync(dest))
71
- fs_1.default.mkdirSync(dest);
72
- fs_1.default.readdirSync(src).forEach(child => {
73
- copyRecursiveSync(path_1.default.join(src, child), path_1.default.join(dest, child));
74
- });
75
- }
76
- else {
77
- fs_1.default.copyFileSync(src, dest);
78
- }
79
- }
80
- };
81
- copyRecursiveSync(sourceRegistry, targetRegistry);
82
- console.log(' 📂 Seeded test registry');
83
- // --- SCENARIO 2: Workflow Discovery (Stubbing) ---
84
- console.log('\n [2/4] Scenario: User expects stubs for discovery');
85
- // Create a fake registry workflow to test syncing
86
- // The registry is now seeded in tempDir/registry, so sync should find it via fallback.
87
- const syncRes = await runFraim(['sync']);
88
- if (syncRes.code !== 0) {
89
- console.error(' ❌ Sync failed. Output:', syncRes.stdout);
90
- // Spawn helper above captures stdout/stderr mixed or just stdout?
91
- // The helper captures stdout from ps.stdout and ignore stderr?
92
- // Let's check helper.
93
- }
94
- node_assert_1.default.strictEqual(syncRes.code, 0, 'Sync failed');
95
- // Verify Stub Content
96
- // The registry has 'product-building/design.md'.
97
- // Sync should now preserve the 'product-building/' folder.
98
- const localWorkflowsDir = path_1.default.join(tempDir, '.fraim', 'workflows');
99
- if (!fs_1.default.existsSync(localWorkflowsDir))
100
- fs_1.default.mkdirSync(localWorkflowsDir, { recursive: true });
101
- // Check specifically for the nested file
102
- // We know 'design.md' is inside 'product-building' in the registry
103
- // Wait, where is 'product-building/design.md' in the source registry provided to the test?
104
- // In Step 1, we recursively copied 'registry' to 'tempDir/registry'.
105
- // If the source registry has 'workflows/product-building/design.md', then sync should produce '.fraim/workflows/product-building/design.md'.
106
- // Let's verify recursively
107
- const countFiles = (dir) => {
108
- let count = 0;
109
- if (!fs_1.default.existsSync(dir))
110
- return 0;
111
- const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
112
- for (const e of entries) {
113
- if (e.isDirectory())
114
- count += countFiles(path_1.default.join(dir, e.name));
115
- else if (e.name.endsWith('.md'))
116
- count++;
117
- }
118
- return count;
119
- };
120
- const fileCount = countFiles(localWorkflowsDir);
121
- node_assert_1.default.ok(fileCount > 0, 'No stubs generated');
122
- // Check content of one file
123
- const findFirstStub = (dir) => {
124
- if (!fs_1.default.existsSync(dir))
125
- return null;
126
- const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
127
- for (const e of entries) {
128
- if (e.isDirectory()) {
129
- const f = findFirstStub(path_1.default.join(dir, e.name));
130
- if (f)
131
- return f;
132
- }
133
- else if (e.name.endsWith('.md'))
134
- return path_1.default.join(dir, e.name);
135
- }
136
- return null;
137
- };
138
- const firstStubPath = findFirstStub(localWorkflowsDir);
139
- if (firstStubPath) {
140
- const stubContent = fs_1.default.readFileSync(firstStubPath, 'utf8');
141
- node_assert_1.default.ok(stubContent.includes('## Intent'), 'Stub missing intent header');
142
- const intentContent = stubContent.match(/## Intent\n([\s\S]*?)$/)?.[1]?.trim();
143
- node_assert_1.default.ok(intentContent && intentContent !== 'No intent defined.', `Intent should be populated, found fallback in ${firstStubPath}`);
144
- node_assert_1.default.ok(intentContent && intentContent.length > 20, `Intent too short in ${firstStubPath}`);
145
- node_assert_1.default.ok(!stubContent.includes('Core Principles'), 'Stub should NOT have detailed principles');
146
- node_assert_1.default.ok(stubContent.includes('DO NOT EXECUTE'), 'Stub must warn agent');
147
- node_assert_1.default.ok(!stubContent.includes('Commit this file'), 'Stub footer should be removed');
148
- console.log(` ✅ "fraim sync" generated ${fileCount} lightweight stubs (Verified content & structure)`);
149
- }
150
- else {
151
- throw new Error('No stubs found to verify content');
152
- }
153
- // --- SCENARIO 3: Agent Interaction (Version Check) ---
154
- console.log('\n [3/4] Scenario: Agent connects to MCP Server');
155
- // Start Server in the project context
156
- // Mock a mismatched version in package.json
157
- fs_1.default.writeFileSync(path_1.default.join(tempDir, 'package.json'), JSON.stringify({
158
- dependencies: { "@fraim/framework": "1.0.0" }
159
- }));
160
- const serverScript = (0, test_server_utils_1.getServerScriptPath)();
161
- fraimProcess = (0, node_child_process_1.spawn)(process.execPath, [tsxCli, serverScript], {
162
- cwd: tempDir,
163
- env: { ...process.env, FRAIM_MCP_PORT: PORT.toString(), FRAIM_SKIP_INDEX_ON_START: 'true' },
164
- stdio: 'pipe', // Quiet outcome
165
- shell: false
166
- });
167
- let serverLog = '';
168
- if (fraimProcess.stdout)
169
- fraimProcess.stdout.on('data', d => serverLog += d.toString());
170
- if (fraimProcess.stderr)
171
- fraimProcess.stderr.on('data', d => serverLog += d.toString());
172
- // Loop wait for health
173
- let active = false;
174
- for (let i = 0; i < 60; i++) {
175
- try {
176
- await axios_1.default.get(`${BASE_URL}/health`);
177
- active = true;
178
- break;
179
- }
180
- catch {
181
- await new Promise(r => setTimeout(r, 500));
182
- }
183
- }
184
- if (!active) {
185
- console.error('❌ Server failed to start. Logs:\n', serverLog);
186
- throw new Error('Server failed to start');
187
- }
188
- // Test Version Header on Root Endpoint
189
- const mcpRes = await axios_1.default.post(`${BASE_URL}/`, {
190
- jsonrpc: '2.0', id: 1, method: 'initialize', params: {}
191
- }, { headers: { 'x-api-key': TEST_API_KEY } });
192
- node_assert_1.default.ok(mcpRes.headers['x-fraim-version-notice'], 'Missing Version Notice Header');
193
- console.log(' ✅ Server detected version mismatch and sent guidance header');
194
- // --- SCENARIO 4: Upgrade Guidance (Tool Result) ---
195
- console.log('\n [4/4] Scenario: Agent executes tool with outdated version');
196
- // Call a tool (e.g., list_tools is simple)
197
- const toolRes = await axios_1.default.post(`${BASE_URL}/`, {
198
- jsonrpc: '2.0', id: 2, method: 'tools/list', params: {}
199
- }, { headers: { 'x-api-key': TEST_API_KEY } });
200
- // The middleware injects the notice into the request.
201
- // The handler `handleToolCall` or logic usually injects it into CONTENT.
202
- // `tools/list` might not return 'content'. `handleToolCall` does.
203
- // Let's call a tool that doesn't really exist or fails?
204
- // Actually `versionCheck` middleware puts it in a header always.
205
- // Logic in `handleToolCall` injects it into text content.
206
- // Let's try to simulate a tool call. We need a valid tool or mocked one.
207
- // We can check if the header persists.
208
- node_assert_1.default.ok(toolRes.headers['x-fraim-version-notice'], 'Header missing on tool call');
209
- console.log(' ✅ Guidance persists on tool execution');
210
- return true;
211
- }
212
- catch (e) {
213
- console.error(' ❌ User Journey Logic Failed:', e);
214
- return false;
215
- }
216
- finally {
217
- if (dbService)
218
- await dbService.close();
219
- if (fraimProcess?.pid) {
220
- await new Promise((resolve) => (0, tree_kill_1.default)(fraimProcess.pid, 'SIGKILL', () => resolve()));
221
- }
222
- try {
223
- fs_1.default.rmSync(tempDir, { recursive: true, force: true });
224
- }
225
- catch { }
226
- }
227
- }
228
- async function runJourney(testCase) {
229
- return await testCase.testFunction();
230
- }
231
- (0, test_utils_1.runTests)([{
232
- name: 'Dual Discovery User Journey',
233
- description: 'End-to-End verification of the Developer -> Agent -> Framework loop',
234
- testFunction: testDualDiscoveryJourney,
235
- tags: ['e2e', 'journey']
236
- }], runJourney, 'Fraim User Journey');