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.
Files changed (120) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/src/cli/commands/init-project.js +10 -4
  3. package/dist/src/cli/setup/mcp-config-generator.js +23 -15
  4. package/dist/src/local-mcp-server/stdio-server.js +207 -0
  5. package/dist/src/utils/validate-workflows.js +101 -0
  6. package/dist/src/utils/workflow-parser.js +81 -0
  7. package/package.json +16 -11
  8. package/registry/scripts/pdf-styles.css +172 -0
  9. package/registry/scripts/prep-issue.sh +46 -4
  10. package/registry/scripts/profile-server.ts +131 -130
  11. package/registry/stubs/workflows/customer-development/user-survey-dispatch.md +1 -1
  12. package/registry/stubs/workflows/customer-development/users-to-target.md +1 -1
  13. package/registry/stubs/workflows/product-building/design.md +1 -1
  14. package/registry/stubs/workflows/product-building/implement.md +1 -1
  15. package/Claude.md +0 -1
  16. package/dist/registry/ai-manager-rules/design-phases/design-completeness-review.md +0 -73
  17. package/dist/registry/ai-manager-rules/design-phases/design-design.md +0 -145
  18. package/dist/registry/ai-manager-rules/implement-phases/implement-code.md +0 -283
  19. package/dist/registry/ai-manager-rules/implement-phases/implement-completeness-review.md +0 -120
  20. package/dist/registry/ai-manager-rules/implement-phases/implement-regression.md +0 -173
  21. package/dist/registry/ai-manager-rules/implement-phases/implement-repro.md +0 -104
  22. package/dist/registry/ai-manager-rules/implement-phases/implement-scoping.md +0 -100
  23. package/dist/registry/ai-manager-rules/implement-phases/implement-smoke.md +0 -237
  24. package/dist/registry/ai-manager-rules/implement-phases/implement-spike.md +0 -121
  25. package/dist/registry/ai-manager-rules/implement-phases/implement-validate.md +0 -375
  26. package/dist/registry/ai-manager-rules/retrospective.md +0 -116
  27. package/dist/registry/ai-manager-rules/shared-phases/address-pr-feedback.md +0 -188
  28. package/dist/registry/ai-manager-rules/shared-phases/submit-pr.md +0 -202
  29. package/dist/registry/ai-manager-rules/shared-phases/wait-for-pr-review.md +0 -170
  30. package/dist/registry/ai-manager-rules/spec-phases/spec-competitor-analysis.md +0 -105
  31. package/dist/registry/ai-manager-rules/spec-phases/spec-completeness-review.md +0 -66
  32. package/dist/registry/ai-manager-rules/spec-phases/spec-spec.md +0 -139
  33. package/dist/registry/providers/ado.json +0 -19
  34. package/dist/registry/providers/github.json +0 -19
  35. package/dist/registry/scripts/cleanup-branch.js +0 -287
  36. package/dist/registry/scripts/evaluate-code-quality.js +0 -66
  37. package/dist/registry/scripts/exec-with-timeout.js +0 -142
  38. package/dist/registry/scripts/generate-engagement-emails.js +0 -705
  39. package/dist/registry/scripts/newsletter-helpers.js +0 -671
  40. package/dist/registry/scripts/profile-server.js +0 -388
  41. package/dist/registry/scripts/run-thank-you-workflow.js +0 -92
  42. package/dist/registry/scripts/send-newsletter-simple.js +0 -85
  43. package/dist/registry/scripts/send-thank-you-emails.js +0 -54
  44. package/dist/registry/scripts/validate-openapi-limits.js +0 -311
  45. package/dist/registry/scripts/validate-test-coverage.js +0 -262
  46. package/dist/registry/scripts/verify-test-coverage.js +0 -66
  47. package/dist/scripts/build-stub-registry.js +0 -108
  48. package/dist/src/ai-manager/ai-manager.js +0 -482
  49. package/dist/src/ai-manager/phase-flow.js +0 -357
  50. package/dist/src/ai-manager/types.js +0 -5
  51. package/dist/src/fraim-mcp-server.js +0 -1885
  52. package/dist/tests/debug-tools.js +0 -80
  53. package/dist/tests/shared-server-utils.js +0 -57
  54. package/dist/tests/test-add-ide.js +0 -283
  55. package/dist/tests/test-ai-coach-edge-cases.js +0 -420
  56. package/dist/tests/test-ai-coach-mcp-integration.js +0 -450
  57. package/dist/tests/test-ai-coach-performance.js +0 -328
  58. package/dist/tests/test-ai-coach-phase-content.js +0 -264
  59. package/dist/tests/test-ai-coach-workflows.js +0 -514
  60. package/dist/tests/test-cli.js +0 -228
  61. package/dist/tests/test-client-scripts-validation.js +0 -167
  62. package/dist/tests/test-complete-setup-flow.js +0 -110
  63. package/dist/tests/test-config-system.js +0 -279
  64. package/dist/tests/test-debug-session.js +0 -134
  65. package/dist/tests/test-end-to-end-hybrid-validation.js +0 -328
  66. package/dist/tests/test-enhanced-session-init.js +0 -188
  67. package/dist/tests/test-first-run-journey.js +0 -368
  68. package/dist/tests/test-fraim-issues.js +0 -59
  69. package/dist/tests/test-genericization.js +0 -44
  70. package/dist/tests/test-hybrid-script-execution.js +0 -340
  71. package/dist/tests/test-ide-detector.js +0 -46
  72. package/dist/tests/test-improved-setup.js +0 -121
  73. package/dist/tests/test-mcp-config-generator.js +0 -99
  74. package/dist/tests/test-mcp-connection.js +0 -107
  75. package/dist/tests/test-mcp-issue-integration.js +0 -156
  76. package/dist/tests/test-mcp-lifecycle-methods.js +0 -240
  77. package/dist/tests/test-mcp-shared-server.js +0 -308
  78. package/dist/tests/test-mcp-template-processing.js +0 -160
  79. package/dist/tests/test-modular-issue-tracking.js +0 -165
  80. package/dist/tests/test-node-compatibility.js +0 -95
  81. package/dist/tests/test-npm-install.js +0 -68
  82. package/dist/tests/test-package-size.js +0 -108
  83. package/dist/tests/test-pr-review-workflow.js +0 -307
  84. package/dist/tests/test-prep-issue.js +0 -129
  85. package/dist/tests/test-productivity-integration.js +0 -157
  86. package/dist/tests/test-script-location-independence.js +0 -198
  87. package/dist/tests/test-script-sync.js +0 -557
  88. package/dist/tests/test-server-utils.js +0 -32
  89. package/dist/tests/test-session-rehydration.js +0 -148
  90. package/dist/tests/test-setup-integration.js +0 -98
  91. package/dist/tests/test-setup-scenarios.js +0 -322
  92. package/dist/tests/test-standalone.js +0 -143
  93. package/dist/tests/test-stub-registry.js +0 -136
  94. package/dist/tests/test-sync-stubs.js +0 -143
  95. package/dist/tests/test-sync-version-update.js +0 -93
  96. package/dist/tests/test-telemetry.js +0 -193
  97. package/dist/tests/test-token-validator.js +0 -30
  98. package/dist/tests/test-user-journey.js +0 -236
  99. package/dist/tests/test-users-to-target-workflow.js +0 -253
  100. package/dist/tests/test-utils.js +0 -109
  101. package/dist/tests/test-wizard.js +0 -71
  102. package/dist/tests/test-workflow-discovery.js +0 -242
  103. package/labels.json +0 -52
  104. package/registry/agent-guardrails.md +0 -63
  105. package/registry/fraim.md +0 -48
  106. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase1-customer-profiling.md +0 -11
  107. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase1-survey-scoping.md +0 -11
  108. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase2-platform-discovery.md +0 -11
  109. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase2-survey-build-linkedin.md +0 -11
  110. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase3-prospect-qualification.md +0 -11
  111. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase3-survey-build-reddit.md +0 -11
  112. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase4-inventory-compilation.md +0 -11
  113. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase4-survey-build-x.md +0 -11
  114. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase5-survey-build-facebook.md +0 -11
  115. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase6-survey-build-custom.md +0 -11
  116. package/registry/stubs/workflows/customer-development/ai-coach-phases/phase7-survey-dispatch.md +0 -11
  117. package/registry/stubs/workflows/customer-development/templates/customer-persona-template.md +0 -11
  118. package/registry/stubs/workflows/customer-development/templates/search-strategy-template.md +0 -11
  119. package/setup.js +0 -171
  120. package/tsconfig.json +0 -23
@@ -1,129 +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 fs_1 = __importDefault(require("fs"));
7
- const path_1 = __importDefault(require("path"));
8
- const child_process_1 = require("child_process");
9
- const assert_1 = __importDefault(require("assert"));
10
- const test_utils_1 = require("./test-utils");
11
- // Path to the shell script
12
- // Handle both source (tests/) and compiled (dist/tests/) execution
13
- const SCRIPT_PATH = fs_1.default.existsSync(path_1.default.join(__dirname, '../registry/scripts/prep-issue.sh'))
14
- ? path_1.default.join(__dirname, '../registry/scripts/prep-issue.sh')
15
- : path_1.default.resolve(__dirname, '../../registry/scripts/prep-issue.sh');
16
- function extractNodeScript() {
17
- const content = fs_1.default.readFileSync(SCRIPT_PATH, 'utf8');
18
- // Regex to capture the content inside NODE_SCRIPT="..."
19
- const match = content.match(/NODE_SCRIPT="([\s\S]*?)"/);
20
- if (!match || !match[1]) {
21
- throw new Error('Could not find NODE_SCRIPT variable in prep-issue.sh');
22
- }
23
- // Unescape characters that are escaped in Bash double-quoted string
24
- // specifically: \` \$ \" \\
25
- return match[1]
26
- .replace(/\\`/g, '`')
27
- .replace(/\\\$/g, '$')
28
- .replace(/\\"/g, '"')
29
- .replace(/\\\\/g, '\\');
30
- }
31
- function runParsingLogic(script, config) {
32
- const input = JSON.stringify(config);
33
- const result = (0, child_process_1.spawnSync)('node', ['-e', script], {
34
- input,
35
- encoding: 'utf-8'
36
- });
37
- if (result.status !== 0) {
38
- throw new Error(`Script failed to run (status ${result.status}). Stderr: ${result.stderr}`);
39
- }
40
- return result.stdout.trim();
41
- }
42
- async function verifyPrepIssueConfigParsing() {
43
- console.log(' 🔍 Verifying prep-issue.sh config parsing logic...');
44
- try {
45
- // 1. Verify script exists
46
- assert_1.default.ok(fs_1.default.existsSync(SCRIPT_PATH), `prep-issue.sh not found at ${SCRIPT_PATH}`);
47
- // 2. Extract the Node.js parsing logic
48
- const nodeScript = extractNodeScript();
49
- assert_1.default.ok(nodeScript.length > 0, 'Extracted script is empty');
50
- console.log(' ✅ Extracted Node.js parsing logic');
51
- // 3. Test Valid Configuration
52
- const validConfig = {
53
- repository: {
54
- owner: 'test-owner',
55
- name: 'test-repo',
56
- url: 'https://github.com/test-owner/test-repo.git'
57
- }
58
- };
59
- const output = runParsingLogic(nodeScript, validConfig);
60
- assert_1.default.strictEqual(output, 'test-owner|test-repo|https://github.com/test-owner/test-repo.git|master');
61
- console.log(' ✅ Valid config parsed correctly');
62
- // 4. Test Missing Config
63
- assert_1.default.throws(() => {
64
- runParsingLogic(nodeScript, { name: 'Create-Project' });
65
- }, /Script failed/);
66
- console.log(' ✅ Missing config correctly failed');
67
- // 5. Test Incomplete Config
68
- assert_1.default.throws(() => {
69
- runParsingLogic(nodeScript, { repository: { owner: 'test-owner' } });
70
- }, /Script failed/);
71
- console.log(' ✅ Incomplete config correctly failed');
72
- // 6. Test Default Branch Extraction (git schema)
73
- const gitConfig = {
74
- git: {
75
- repoOwner: 'test-owner',
76
- repoName: 'test-repo',
77
- defaultBranch: 'master'
78
- }
79
- };
80
- const gitOutput = runParsingLogic(nodeScript, gitConfig);
81
- assert_1.default.strictEqual(gitOutput, 'test-owner|test-repo|https://github.com/test-owner/test-repo.git|master');
82
- console.log(' ✅ Git config with defaultBranch parsed correctly');
83
- // 7. Test Default Branch Extraction (repository schema)
84
- const repoConfig = {
85
- repository: {
86
- owner: 'test-owner',
87
- name: 'test-repo',
88
- url: 'https://github.com/test-owner/test-repo.git',
89
- defaultBranch: 'main'
90
- }
91
- };
92
- const repoOutput = runParsingLogic(nodeScript, repoConfig);
93
- assert_1.default.strictEqual(repoOutput, 'test-owner|test-repo|https://github.com/test-owner/test-repo.git|main');
94
- console.log(' ✅ Repository config with defaultBranch parsed correctly');
95
- // 8. Test Default Branch Fallback
96
- const noDefaultConfig = {
97
- git: {
98
- repoOwner: 'test-owner',
99
- repoName: 'test-repo'
100
- }
101
- };
102
- const fallbackOutput = runParsingLogic(nodeScript, noDefaultConfig);
103
- assert_1.default.strictEqual(fallbackOutput, 'test-owner|test-repo|https://github.com/test-owner/test-repo.git|master');
104
- console.log(' ✅ Default branch fallback to master works correctly');
105
- return true;
106
- }
107
- catch (error) {
108
- console.error(' ❌ Test failed:', error);
109
- return false;
110
- }
111
- }
112
- // Define test cases
113
- const testCases = [
114
- {
115
- name: 'Prep Issue Config Parsing',
116
- description: 'Verifies correct parsing of repo config from .fraim/config.json',
117
- testFn: verifyPrepIssueConfigParsing,
118
- tags: ['unit', 'scripts']
119
- }
120
- ];
121
- // Run strict check if executed directly
122
- if (require.main === module) {
123
- (0, test_utils_1.runTests)(testCases, async (testCase) => {
124
- if (testCase.testFn) {
125
- return await testCase.testFn();
126
- }
127
- return false;
128
- }, 'Prep Issue Script Tests');
129
- }
@@ -1,157 +0,0 @@
1
- "use strict";
2
- /**
3
- * Test suite for productivity report integration
4
- * Tests the workflow and associated scripts integration
5
- */
6
- var __importDefault = (this && this.__importDefault) || function (mod) {
7
- return (mod && mod.__esModule) ? mod : { "default": mod };
8
- };
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- const node_test_1 = require("node:test");
11
- const node_assert_1 = __importDefault(require("node:assert"));
12
- const fs_1 = __importDefault(require("fs"));
13
- const path_1 = __importDefault(require("path"));
14
- // Test configuration
15
- const WORKFLOW_PATH = 'registry/workflows/productivity-report/productivity-report.md';
16
- const SCRIPTS_DIR = 'registry/scripts/productivity';
17
- const EXPECTED_SCRIPTS = [
18
- 'productivity-report.sh',
19
- 'build-productivity-csv.mjs',
20
- 'fetch-pr-details.mjs'
21
- ];
22
- (0, node_test_1.test)('Productivity Report Workflow Integration', async (t) => {
23
- await t.test('workflow file exists and is accessible', () => {
24
- node_assert_1.default.ok(fs_1.default.existsSync(WORKFLOW_PATH), `Workflow file should exist at ${WORKFLOW_PATH}`);
25
- const content = fs_1.default.readFileSync(WORKFLOW_PATH, 'utf-8');
26
- node_assert_1.default.ok(content.length > 0, 'Workflow file should not be empty');
27
- node_assert_1.default.ok(content.includes('# Productivity Report Workflow'), 'Should contain proper workflow header');
28
- node_assert_1.default.ok(content.includes('**Category:** Performance Analysis'), 'Should be categorized as Performance Analysis');
29
- });
30
- await t.test('workflow content is generalized', () => {
31
- const content = fs_1.default.readFileSync(WORKFLOW_PATH, 'utf-8');
32
- // Should not contain Ashley-Calendar-AI specific references
33
- node_assert_1.default.ok(!content.includes('mathursrus/Ashley-Calendar-AI'), 'Should not contain hardcoded Ashley-Calendar-AI repository reference');
34
- // Should contain generalized instructions
35
- node_assert_1.default.ok(content.includes('any GitHub repository'), 'Should mention compatibility with any GitHub repository');
36
- node_assert_1.default.ok(content.includes('automatically detects'), 'Should mention auto-detection capability');
37
- node_assert_1.default.ok(content.includes('scripts/productivity/'), 'Should reference correct FRAIM script location');
38
- });
39
- await t.test('scripts directory exists with correct structure', () => {
40
- node_assert_1.default.ok(fs_1.default.existsSync(SCRIPTS_DIR), `Scripts directory should exist at ${SCRIPTS_DIR}`);
41
- const dirStats = fs_1.default.statSync(SCRIPTS_DIR);
42
- node_assert_1.default.ok(dirStats.isDirectory(), 'Should be a directory');
43
- });
44
- await t.test('all expected scripts are present', () => {
45
- for (const scriptName of EXPECTED_SCRIPTS) {
46
- const scriptPath = path_1.default.join(SCRIPTS_DIR, scriptName);
47
- node_assert_1.default.ok(fs_1.default.existsSync(scriptPath), `Script ${scriptName} should exist at ${scriptPath}`);
48
- const content = fs_1.default.readFileSync(scriptPath, 'utf-8');
49
- node_assert_1.default.ok(content.length > 0, `Script ${scriptName} should not be empty`);
50
- }
51
- });
52
- await t.test('main script is generalized and repository-agnostic', () => {
53
- const scriptPath = path_1.default.join(SCRIPTS_DIR, 'productivity-report.sh');
54
- const content = fs_1.default.readFileSync(scriptPath, 'utf-8');
55
- // Should not contain hardcoded repository
56
- node_assert_1.default.ok(!content.includes('mathursrus/Ashley-Calendar-AI'), 'Main script should not contain hardcoded repository reference');
57
- // Should contain repository detection logic
58
- node_assert_1.default.ok(content.includes('detect_repository()'), 'Should contain repository detection function');
59
- node_assert_1.default.ok(content.includes('git remote get-url origin'), 'Should use git remote for auto-detection');
60
- // Should handle environment variables
61
- node_assert_1.default.ok(content.includes('REPO_FULL'), 'Should support REPO_FULL environment variable');
62
- node_assert_1.default.ok(content.includes('REPO_OWNER') && content.includes('REPO_NAME'), 'Should support REPO_OWNER/REPO_NAME environment variables');
63
- // Should have proper error handling
64
- node_assert_1.default.ok(content.includes('validate_repo_format'), 'Should validate repository format');
65
- node_assert_1.default.ok(content.includes('gh auth status'), 'Should check GitHub CLI authentication');
66
- });
67
- await t.test('fetch-pr-details script is generalized', () => {
68
- const scriptPath = path_1.default.join(SCRIPTS_DIR, 'fetch-pr-details.mjs');
69
- const content = fs_1.default.readFileSync(scriptPath, 'utf-8');
70
- // Should not contain hardcoded repository
71
- node_assert_1.default.ok(!content.includes('mathursrus/Ashley-Calendar-AI'), 'PR details script should not contain hardcoded repository');
72
- // Should contain repository detection
73
- node_assert_1.default.ok(content.includes('detectRepository()'), 'Should contain repository detection function');
74
- node_assert_1.default.ok(content.includes('process.env.REPO_FULL'), 'Should check REPO_FULL environment variable');
75
- // Should have proper error handling
76
- node_assert_1.default.ok(content.includes('Invalid repository format'), 'Should validate repository format');
77
- node_assert_1.default.ok(content.includes('timeout:'), 'Should have timeout handling for API calls');
78
- });
79
- await t.test('build-csv script is generalized', () => {
80
- const scriptPath = path_1.default.join(SCRIPTS_DIR, 'build-productivity-csv.mjs');
81
- const content = fs_1.default.readFileSync(scriptPath, 'utf-8');
82
- // Should be repository-agnostic (no hardcoded repos)
83
- node_assert_1.default.ok(!content.includes('mathursrus/Ashley-Calendar-AI'), 'CSV builder should not contain hardcoded repository');
84
- // Should have proper error handling
85
- node_assert_1.default.ok(content.includes('Data directory not found'), 'Should handle missing data directory');
86
- node_assert_1.default.ok(content.includes('Warning:'), 'Should have warning messages for data issues');
87
- // Should handle file locking
88
- node_assert_1.default.ok(content.includes('productivity-report-new.csv'), 'Should handle locked files with alternative naming');
89
- });
90
- await t.test('scripts have proper Node.js shebang and are executable', () => {
91
- const nodeScripts = ['build-productivity-csv.mjs', 'fetch-pr-details.mjs'];
92
- for (const scriptName of nodeScripts) {
93
- const scriptPath = path_1.default.join(SCRIPTS_DIR, scriptName);
94
- const content = fs_1.default.readFileSync(scriptPath, 'utf-8');
95
- node_assert_1.default.ok(content.startsWith('#!/usr/bin/env node'), `${scriptName} should have proper Node.js shebang`);
96
- }
97
- // Check bash script shebang
98
- const bashScriptPath = path_1.default.join(SCRIPTS_DIR, 'productivity-report.sh');
99
- const bashContent = fs_1.default.readFileSync(bashScriptPath, 'utf-8');
100
- node_assert_1.default.ok(bashContent.startsWith('#!/bin/bash'), 'Bash script should have proper bash shebang');
101
- });
102
- await t.test('workflow references correct script locations', () => {
103
- const content = fs_1.default.readFileSync(WORKFLOW_PATH, 'utf-8');
104
- // Should reference FRAIM registry location
105
- node_assert_1.default.ok(content.includes('~/.fraim/scripts/productivity/'), 'Should reference correct FRAIM script registry location');
106
- // Should mention all three scripts
107
- for (const scriptName of EXPECTED_SCRIPTS) {
108
- node_assert_1.default.ok(content.includes(scriptName), `Should mention script ${scriptName}`);
109
- }
110
- // Should have proper usage instructions
111
- node_assert_1.default.ok(content.includes('bash ~/.fraim/scripts/productivity/productivity-report.sh'), 'Should provide correct usage command');
112
- });
113
- await t.test('integration maintains FRAIM patterns', () => {
114
- // Check that existing FRAIM structure is preserved
115
- node_assert_1.default.ok(fs_1.default.existsSync('registry/scripts'), 'Existing scripts directory should be preserved');
116
- node_assert_1.default.ok(fs_1.default.existsSync('registry/workflows'), 'Existing workflows directory should be preserved');
117
- node_assert_1.default.ok(fs_1.default.existsSync('registry/workflows/productivity-report'), 'Productivity report workflows directory should exist');
118
- // Check that new structure follows FRAIM patterns
119
- const workflowContent = fs_1.default.readFileSync(WORKFLOW_PATH, 'utf-8');
120
- node_assert_1.default.ok(workflowContent.includes('**Category:**'), 'Should follow FRAIM workflow format with category');
121
- node_assert_1.default.ok(workflowContent.includes('## OVERVIEW'), 'Should follow FRAIM workflow format with OVERVIEW section');
122
- node_assert_1.default.ok(workflowContent.includes('## WHEN TO USE'), 'Should follow FRAIM workflow format with WHEN TO USE section');
123
- });
124
- await t.test('scripts contain proper documentation and help', () => {
125
- const mainScriptPath = path_1.default.join(SCRIPTS_DIR, 'productivity-report.sh');
126
- const content = fs_1.default.readFileSync(mainScriptPath, 'utf-8');
127
- // Should have usage information
128
- node_assert_1.default.ok(content.includes('Usage:'), 'Main script should contain usage information');
129
- node_assert_1.default.ok(content.includes('export REPO_FULL'), 'Should document environment variable usage');
130
- // Should have dependency information
131
- node_assert_1.default.ok(content.includes('gh CLI'), 'Should mention GitHub CLI dependency');
132
- node_assert_1.default.ok(content.includes('node'), 'Should mention Node.js dependency');
133
- node_assert_1.default.ok(content.includes('jq'), 'Should mention jq dependency');
134
- });
135
- });
136
- // Integration test with MCP server (if available)
137
- (0, node_test_1.test)('MCP Server Integration', async (t) => {
138
- await t.test('workflow is accessible via get_fraim_workflow pattern', () => {
139
- // This test verifies the file is in the correct location for MCP access
140
- const expectedPath = 'registry/workflows/productivity-report/productivity-report.md';
141
- node_assert_1.default.ok(fs_1.default.existsSync(expectedPath), 'Workflow should be accessible at expected MCP path');
142
- // Verify it follows the expected workflow format
143
- const content = fs_1.default.readFileSync(expectedPath, 'utf-8');
144
- node_assert_1.default.ok(content.includes('# Productivity Report Workflow'), 'Should have proper workflow header for MCP access');
145
- });
146
- await t.test('scripts are in registry location for FRAIM access', () => {
147
- // Verify scripts are in the correct registry location
148
- const registryPath = 'registry/scripts/productivity';
149
- node_assert_1.default.ok(fs_1.default.existsSync(registryPath), 'Scripts should be in FRAIM registry location');
150
- // Verify all scripts are accessible
151
- for (const scriptName of EXPECTED_SCRIPTS) {
152
- const scriptPath = path_1.default.join(registryPath, scriptName);
153
- node_assert_1.default.ok(fs_1.default.existsSync(scriptPath), `Script ${scriptName} should be accessible in registry`);
154
- }
155
- });
156
- });
157
- console.log('✅ Productivity integration tests completed');
@@ -1,198 +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 test_utils_1 = require("./test-utils");
40
- const fs_1 = __importDefault(require("fs"));
41
- const path_1 = __importDefault(require("path"));
42
- const os_1 = __importDefault(require("os"));
43
- async function testScriptLocationIndependence() {
44
- console.log(' 🚀 Testing Script Location Independence...');
45
- // Use timestamp to ensure unique directories even in concurrent runs
46
- const timestamp = Date.now();
47
- const tempProjectDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), `fraim-location-test-${timestamp}-`));
48
- const userFraimDir = path_1.default.join(os_1.default.homedir(), `.fraim-location-test-${timestamp}`);
49
- const userScriptsDir = path_1.default.join(userFraimDir, 'scripts');
50
- console.log(` 📂 Created temp project dir: ${tempProjectDir}`);
51
- console.log(` 🏠 Using test user dir: ${userFraimDir}`);
52
- try {
53
- // Clean up any existing test user directory (with timestamp, should be unique)
54
- if (fs_1.default.existsSync(userFraimDir)) {
55
- fs_1.default.rmSync(userFraimDir, { recursive: true, force: true });
56
- }
57
- // Create user scripts directory and copy actual registry scripts
58
- fs_1.default.mkdirSync(userScriptsDir, { recursive: true });
59
- // Copy a few key scripts to test
60
- const scriptsToTest = [
61
- 'prep-issue.sh',
62
- 'code-quality-check.sh',
63
- 'detect-tautological-tests.sh'
64
- ];
65
- for (const scriptName of scriptsToTest) {
66
- const sourcePath = path_1.default.resolve(__dirname, '../registry/scripts', scriptName);
67
- const targetPath = path_1.default.join(userScriptsDir, scriptName);
68
- if (fs_1.default.existsSync(sourcePath)) {
69
- fs_1.default.copyFileSync(sourcePath, targetPath);
70
- // Make executable on Unix systems
71
- if (process.platform !== 'win32') {
72
- fs_1.default.chmodSync(targetPath, 0o755);
73
- }
74
- }
75
- }
76
- // Set up project directory with .fraim/config.json
77
- const projectFraimDir = path_1.default.join(tempProjectDir, '.fraim');
78
- fs_1.default.mkdirSync(projectFraimDir, { recursive: true });
79
- const testConfig = {
80
- project: { name: `location-test-${timestamp}` },
81
- git: {
82
- repoOwner: 'test',
83
- repoName: `location-test-${timestamp}`,
84
- url: `https://github.com/test/location-test-${timestamp}.git`
85
- }
86
- };
87
- fs_1.default.writeFileSync(path_1.default.join(projectFraimDir, 'config.json'), JSON.stringify(testConfig, null, 2));
88
- // Test 1: Try to execute prep-issue.sh from user directory
89
- console.log(' Testing prep-issue.sh execution from user directory...');
90
- const prepIssueScript = path_1.default.join(userScriptsDir, 'prep-issue.sh');
91
- if (fs_1.default.existsSync(prepIssueScript)) {
92
- try {
93
- const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
94
- // On Windows, we need to check if Git Bash is available
95
- if (process.platform === 'win32') {
96
- const gitBashPaths = [
97
- 'C:\\Program Files\\Git\\bin\\bash.exe',
98
- 'C:\\Program Files (x86)\\Git\\bin\\bash.exe'
99
- ];
100
- let bashPath = null;
101
- for (const path of gitBashPaths) {
102
- if (fs_1.default.existsSync(path)) {
103
- bashPath = path;
104
- break;
105
- }
106
- }
107
- if (!bashPath) {
108
- console.log(' ⚠️ Git Bash not found on Windows, skipping bash script tests');
109
- console.log(' ✅ Script location independence test completed (Windows limitation)');
110
- return true;
111
- }
112
- const bashCommand = `"${bashPath}" "${prepIssueScript}" --help`;
113
- const output = execSync(bashCommand, {
114
- cwd: tempProjectDir,
115
- encoding: 'utf-8',
116
- timeout: 15000 // Increased timeout for concurrent runs
117
- });
118
- }
119
- else {
120
- // Unix systems
121
- const output = execSync(`"${prepIssueScript}" --help`, {
122
- cwd: tempProjectDir,
123
- encoding: 'utf-8',
124
- timeout: 15000 // Increased timeout for concurrent runs
125
- });
126
- }
127
- // If we get here, the script at least started successfully
128
- console.log(' ✅ prep-issue.sh executed successfully from user directory');
129
- }
130
- catch (error) {
131
- // Check for timeout specifically
132
- if (error.message.includes('ETIMEDOUT') || error.signal === 'SIGTERM') {
133
- console.log(' ❌ prep-issue.sh failed: spawnSync', error.syscall, 'ETIMEDOUT');
134
- return false;
135
- }
136
- // The script may fail due to missing repo, but as long as it started, that's OK
137
- if (error.message.includes('Repository not found') ||
138
- error.message.includes('fatal: repository') ||
139
- error.message.includes('not a git repository')) {
140
- // This is expected - the test repo doesn't exist, but the script ran
141
- console.log(' ✅ prep-issue.sh executed from user directory (repo not found is expected)');
142
- }
143
- else {
144
- console.log(' ❌ prep-issue.sh failed:', error.message);
145
- return false;
146
- }
147
- }
148
- }
149
- else {
150
- console.log(' ⚠️ prep-issue.sh not found, skipping test');
151
- }
152
- // Skip the second test to reduce interference - the first test is sufficient
153
- console.log(' ✅ Script location independence test completed');
154
- return true;
155
- }
156
- catch (error) {
157
- console.error(' ❌ Script location independence test failed:', error);
158
- return false;
159
- }
160
- finally {
161
- // Enhanced cleanup with retry logic
162
- const cleanup = async (retries = 3) => {
163
- for (let i = 0; i < retries; i++) {
164
- try {
165
- if (fs_1.default.existsSync(tempProjectDir)) {
166
- fs_1.default.rmSync(tempProjectDir, { recursive: true, force: true });
167
- }
168
- if (fs_1.default.existsSync(userFraimDir)) {
169
- fs_1.default.rmSync(userFraimDir, { recursive: true, force: true });
170
- }
171
- break; // Success
172
- }
173
- catch (e) {
174
- if (i === retries - 1) {
175
- console.warn(' ⚠️ Cleanup failed after retries:', e);
176
- }
177
- else {
178
- // Wait a bit before retry
179
- await new Promise(resolve => setTimeout(resolve, 100));
180
- }
181
- }
182
- }
183
- };
184
- await cleanup();
185
- }
186
- }
187
- async function runScriptLocationTest(testCase) {
188
- return await testCase.testFunction();
189
- }
190
- const testCases = [
191
- {
192
- name: 'Script Location Independence',
193
- description: 'Tests that actual registry scripts work when executed from ~/.fraim/scripts/',
194
- testFunction: testScriptLocationIndependence,
195
- tags: ['script-location', 'validation']
196
- }
197
- ];
198
- (0, test_utils_1.runTests)(testCases, runScriptLocationTest, 'Script Location Independence Tests');