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,95 +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 test_utils_1 = require("./test-utils");
8
- const fs_1 = __importDefault(require("fs"));
9
- const path_1 = __importDefault(require("path"));
10
- const os_1 = __importDefault(require("os"));
11
- async function testInitOnNodeVersion(version) {
12
- console.log(` ๐Ÿงช Testing Node v${version}...`);
13
- // Create a temp directory for each version test
14
- const tempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), `fraim-node-${version}-`));
15
- try {
16
- // Set up git repository (required for new init logic)
17
- const { execSync } = require('child_process');
18
- execSync('git init', { cwd: tempDir });
19
- execSync('git remote add origin https://github.com/test-owner/test-repo.git', { cwd: tempDir });
20
- const platform = process.platform;
21
- const npx = platform === 'win32' ? 'npx.cmd' : 'npx';
22
- const binPath = (0, test_utils_1.resolveProjectPath)('dist/src/cli/fraim.js');
23
- // Run: npx -y -p node@<version> node bin/fraim.js init
24
- // We use -y to skip prompt, and -p node@version to ensure that specific node binary is used
25
- const execNode = (args) => {
26
- return new Promise((resolve) => {
27
- const ps = (0, node_child_process_1.spawn)(npx, ['-y', '-p', `node@${version}`, 'node', `"${binPath}"`, ...args], {
28
- cwd: tempDir,
29
- env: { ...process.env, TEST_MODE: 'true' },
30
- shell: true
31
- });
32
- let stdout = '';
33
- let stderr = '';
34
- let timedOut = false;
35
- // Set a timeout of 30 seconds for npx to download and run
36
- const timeout = setTimeout(() => {
37
- timedOut = true;
38
- ps.kill();
39
- }, 30000);
40
- ps.stdout.on('data', d => stdout += d.toString());
41
- ps.stderr.on('data', d => stderr += d.toString());
42
- ps.on('close', (code) => {
43
- clearTimeout(timeout);
44
- resolve({ stdout, stderr, code, timedOut });
45
- });
46
- });
47
- };
48
- console.log(` Running "fraim init" on Node ${version}...`);
49
- const result = await execNode(['init']);
50
- if (result.timedOut) {
51
- console.log(` โš ๏ธ Skipped Node ${version} (timeout - version may not be available)`);
52
- return true; // Don't fail the test, just skip it
53
- }
54
- if (result.code !== 0) {
55
- // Check if it's a version availability issue
56
- if (result.stderr.includes('ETARGET') || result.stderr.includes('No matching version')) {
57
- console.log(` โš ๏ธ Skipped Node ${version} (version not available)`);
58
- return true; // Don't fail the test
59
- }
60
- console.error(` โŒ Failed on Node ${version}`);
61
- console.error(` Error: ${result.stderr}`);
62
- return false;
63
- }
64
- const configPath = path_1.default.join(tempDir, '.fraim', 'config.json');
65
- if (fs_1.default.existsSync(configPath)) {
66
- console.log(` โœ… Success on Node ${version}`);
67
- return true;
68
- }
69
- else {
70
- console.error(` โŒ Config not found on Node ${version}`);
71
- return false;
72
- }
73
- }
74
- catch (e) {
75
- console.error(` โŒ Test Logic Error on Node ${version}:`, e.message);
76
- return false;
77
- }
78
- finally {
79
- try {
80
- fs_1.default.rmSync(tempDir, { recursive: true, force: true });
81
- }
82
- catch (e) { }
83
- }
84
- }
85
- const nodeVersions = ['16', '18', '20', '22'];
86
- const testCases = nodeVersions.map(v => ({
87
- name: `Node v${v} Compatibility`,
88
- version: v,
89
- tags: ['node', 'compatibility']
90
- }));
91
- (0, test_utils_1.runTests)(testCases, async (t) => await testInitOnNodeVersion(t.version), 'Node Compatibility Matrix')
92
- .catch((err) => {
93
- console.error('Test runner failed:', err);
94
- throw err;
95
- });
@@ -1,68 +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 test_utils_1 = require("./test-utils");
8
- const fs_1 = __importDefault(require("fs"));
9
- const path_1 = __importDefault(require("path"));
10
- const os_1 = __importDefault(require("os"));
11
- async function testCleanNpmInstall(version) {
12
- console.log(` ๐Ÿงช Testing NPM Install on Node v${version}...`);
13
- // Create a temp directory for the install test
14
- const tempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), `fraim-npm-${version}-`));
15
- try {
16
- const platform = process.platform;
17
- const npx = platform === 'win32' ? 'npx.cmd' : 'npx';
18
- // Copy package.json to temp dir
19
- const packageJsonPath = path_1.default.resolve(__dirname, '../package.json');
20
- fs_1.default.copyFileSync(packageJsonPath, path_1.default.join(tempDir, 'package.json'));
21
- // Run: npx -p node@<version> npm install --package-lock-only
22
- // This uses the npm bundled with that specific Node version
23
- const execNpm = () => {
24
- return new Promise((resolve) => {
25
- const ps = (0, node_child_process_1.spawn)(npx, ['-y', '-p', `node@${version}`, 'npm', 'install', '--package-lock-only', '--quiet', '--no-audit'], {
26
- cwd: tempDir,
27
- env: { ...process.env },
28
- shell: true
29
- });
30
- let stdout = '';
31
- let stderr = '';
32
- ps.stdout.on('data', d => stdout += d.toString());
33
- ps.stderr.on('data', d => stderr += d.toString());
34
- ps.on('close', (code) => resolve({ stdout, stderr, code }));
35
- });
36
- };
37
- console.log(` Running "npm install" with Node ${version}...`);
38
- const result = await execNpm();
39
- if (result.code !== 0) {
40
- console.error(` โŒ NPM Install Failed on Node ${version}`);
41
- console.error(` Stderr: ${result.stderr}`);
42
- return false;
43
- }
44
- console.log(` โœ… NPM Resolution Success on Node ${version}`);
45
- return true;
46
- }
47
- catch (e) {
48
- console.error(` โŒ Test Logic Error on Node ${version}:`, e.message);
49
- return false;
50
- }
51
- finally {
52
- try {
53
- fs_1.default.rmSync(tempDir, { recursive: true, force: true });
54
- }
55
- catch (e) { }
56
- }
57
- }
58
- const nodeVersions = ['16', '18', '20', '22'];
59
- const testCases = nodeVersions.map(v => ({
60
- name: `NPM Compatibility (Node v${v})`,
61
- version: v,
62
- tags: ['npm', 'compatibility']
63
- }));
64
- (0, test_utils_1.runTests)(testCases, async (t) => await testCleanNpmInstall(t.version), 'NPM Configuration Matrix')
65
- .catch((err) => {
66
- console.error('Test runner failed:', err);
67
- throw err;
68
- });
@@ -1,108 +0,0 @@
1
- #!/usr/bin/env tsx
2
- "use strict";
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- const node_test_1 = require("node:test");
8
- const node_assert_1 = __importDefault(require("node:assert"));
9
- const fs_1 = __importDefault(require("fs"));
10
- const path_1 = __importDefault(require("path"));
11
- /**
12
- * Test to verify package size reduction from stub-only registry
13
- */
14
- // Find project root by looking for package.json
15
- function findProjectRoot() {
16
- let currentDir = __dirname;
17
- while (currentDir !== path_1.default.dirname(currentDir)) {
18
- if (fs_1.default.existsSync(path_1.default.join(currentDir, 'package.json'))) {
19
- return currentDir;
20
- }
21
- currentDir = path_1.default.dirname(currentDir);
22
- }
23
- throw new Error('Could not find project root (package.json not found)');
24
- }
25
- (0, node_test_1.test)('Stub registry is significantly smaller than full registry', () => {
26
- const projectRoot = findProjectRoot();
27
- const fullWorkflowsPath = path_1.default.join(projectRoot, 'registry', 'workflows');
28
- const stubWorkflowsPath = path_1.default.join(projectRoot, 'registry', 'stubs', 'workflows');
29
- console.log(`Project root: ${projectRoot}`);
30
- console.log(`Full workflows path: ${fullWorkflowsPath}`);
31
- console.log(`Stub workflows path: ${stubWorkflowsPath}`);
32
- (0, node_assert_1.default)(fs_1.default.existsSync(fullWorkflowsPath), 'Full workflows directory should exist');
33
- (0, node_assert_1.default)(fs_1.default.existsSync(stubWorkflowsPath), 'Stub workflows directory should exist');
34
- // Calculate sizes
35
- const fullSize = getDirectorySize(fullWorkflowsPath);
36
- const stubSize = getDirectorySize(stubWorkflowsPath);
37
- console.log(`Full workflows size: ${fullSize} bytes`);
38
- console.log(`Stub workflows size: ${stubSize} bytes`);
39
- console.log(`Size reduction: ${Math.round((1 - stubSize / fullSize) * 100)}%`);
40
- // Stubs should be significantly smaller
41
- (0, node_assert_1.default)(stubSize < fullSize * 0.3, `Stubs should be <30% of full size (actual: ${Math.round(stubSize / fullSize * 100)}%)`);
42
- // Should have same number of files
43
- const fullFiles = getAllFiles(fullWorkflowsPath, '.md');
44
- const stubFiles = getAllFiles(stubWorkflowsPath, '.md');
45
- console.log(`Full files found: ${fullFiles.length}`);
46
- console.log(`Stub files found: ${stubFiles.length}`);
47
- console.log(`First few full files: ${fullFiles.slice(0, 3).join(', ')}`);
48
- console.log(`First few stub files: ${stubFiles.slice(0, 3).join(', ')}`);
49
- node_assert_1.default.strictEqual(stubFiles.length, fullFiles.length, 'Should have same number of workflow files');
50
- console.log(`โœ… Package size reduced by ${Math.round((1 - stubSize / fullSize) * 100)}% while maintaining all ${stubFiles.length} workflows`);
51
- });
52
- (0, node_test_1.test)('Package excludes full workflows and templates', () => {
53
- const projectRoot = findProjectRoot();
54
- const packageJsonPath = path_1.default.join(projectRoot, 'package.json');
55
- const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
56
- const files = packageJson.files || [];
57
- // Calculate what would be excluded
58
- const fullWorkflowsSize = getDirectorySize(path_1.default.join(projectRoot, 'registry', 'workflows'));
59
- const templatesSize = getDirectorySize(path_1.default.join(projectRoot, 'registry', 'templates'));
60
- const rulesSize = getDirectorySize(path_1.default.join(projectRoot, 'registry', 'rules'));
61
- const excludedSize = fullWorkflowsSize + templatesSize + rulesSize;
62
- // What's included
63
- const stubsSize = getDirectorySize(path_1.default.join(projectRoot, 'registry', 'stubs'));
64
- const scriptsSize = getDirectorySize(path_1.default.join(projectRoot, 'registry', 'scripts'));
65
- const includedSize = stubsSize + scriptsSize;
66
- console.log(`Excluded from package: ${excludedSize} bytes (workflows + templates + rules)`);
67
- console.log(`Included in package: ${includedSize} bytes (stubs + scripts)`);
68
- console.log(`Total registry size reduction: ${Math.round((1 - includedSize / (includedSize + excludedSize)) * 100)}%`);
69
- // Verify significant size reduction
70
- (0, node_assert_1.default)(includedSize < excludedSize, 'Package should exclude more content than it includes');
71
- console.log('โœ… Package correctly excludes heavy content while keeping essentials');
72
- });
73
- function getDirectorySize(dirPath) {
74
- if (!fs_1.default.existsSync(dirPath)) {
75
- return 0;
76
- }
77
- let totalSize = 0;
78
- const files = getAllFiles(dirPath);
79
- for (const file of files) {
80
- try {
81
- const stats = fs_1.default.statSync(file);
82
- totalSize += stats.size;
83
- }
84
- catch (e) {
85
- // Skip files that can't be read
86
- }
87
- }
88
- return totalSize;
89
- }
90
- function getAllFiles(dir, extension) {
91
- const files = [];
92
- if (!fs_1.default.existsSync(dir)) {
93
- return files;
94
- }
95
- const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
96
- for (const entry of entries) {
97
- const fullPath = path_1.default.join(dir, entry.name);
98
- if (entry.isDirectory()) {
99
- files.push(...getAllFiles(fullPath, extension));
100
- }
101
- else if (entry.isFile()) {
102
- if (!extension || entry.name.endsWith(extension)) {
103
- files.push(fullPath);
104
- }
105
- }
106
- }
107
- return files;
108
- }
@@ -1,307 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const node_assert_1 = require("node:assert");
4
- const test_utils_1 = require("./test-utils");
5
- const phase_flow_js_1 = require("../src/ai-manager/phase-flow.js");
6
- const fs_1 = require("fs");
7
- const path_1 = require("path");
8
- /**
9
- * Test PR Review Workflow Phase Flow
10
- */
11
- async function testPRReviewPhaseFlow() {
12
- try {
13
- console.log('๐Ÿงช Testing PR review phase flow...');
14
- // Test bug workflow includes new phases
15
- const bugPhases = (0, phase_flow_js_1.getPhasesForWorkflow)('implement', 'bug');
16
- (0, node_assert_1.strict)(bugPhases.includes('submit-pr'), 'Bug workflow should include submit-pr phase');
17
- (0, node_assert_1.strict)(bugPhases.includes('wait-for-pr-review'), 'Bug workflow should include wait-for-pr-review phase');
18
- // Test feature workflow includes new phases
19
- const featurePhases = (0, phase_flow_js_1.getPhasesForWorkflow)('implement', 'feature');
20
- (0, node_assert_1.strict)(featurePhases.includes('submit-pr'), 'Feature workflow should include submit-pr phase');
21
- (0, node_assert_1.strict)(featurePhases.includes('wait-for-pr-review'), 'Feature workflow should include wait-for-pr-review phase');
22
- // Test phase progression
23
- const nextAfterCompleteness = (0, phase_flow_js_1.getNextPhase)('implement-completeness-review', 'implement', 'bug');
24
- node_assert_1.strict.equal(nextAfterCompleteness, 'submit-pr', 'After completeness-review should go to submit-pr');
25
- const nextAfterSubmitPR = (0, phase_flow_js_1.getNextPhase)('submit-pr', 'implement', 'bug');
26
- node_assert_1.strict.equal(nextAfterSubmitPR, 'wait-for-pr-review', 'After submit-pr should go to wait-for-pr-review');
27
- const nextAfterWaitPR = (0, phase_flow_js_1.getNextPhase)('wait-for-pr-review', 'implement', 'bug');
28
- node_assert_1.strict.equal(nextAfterWaitPR, 'retrospective', 'After wait-for-pr-review should go to retrospective');
29
- const nextAfterRetrospective = (0, phase_flow_js_1.getNextPhase)('retrospective', 'implement', 'bug');
30
- node_assert_1.strict.equal(nextAfterRetrospective, null, 'retrospective should be the last phase');
31
- console.log('โœ… PR review phase flow tests passed');
32
- return true;
33
- }
34
- catch (error) {
35
- console.error('โŒ PR review phase flow test failed:', error.message);
36
- return false;
37
- }
38
- }
39
- /**
40
- * Test PR Review Failure Handling
41
- */
42
- async function testPRReviewFailureHandling() {
43
- try {
44
- console.log('๐Ÿงช Testing PR review failure handling...');
45
- // Test submit-pr failure
46
- const submitPRFailure = (0, phase_flow_js_1.getPhaseOnFailure)('submit-pr', 'implement', 'bug');
47
- node_assert_1.strict.equal(submitPRFailure, 'implement-completeness-review', 'submit-pr failure should return to completeness-review');
48
- // Test wait-for-pr-review failure (should go to address-pr-feedback)
49
- const waitPRFailure = (0, phase_flow_js_1.getPhaseOnFailure)('wait-for-pr-review', 'implement', 'bug');
50
- node_assert_1.strict.equal(waitPRFailure, 'address-pr-feedback', 'wait-for-pr-review failure should go to address-pr-feedback');
51
- // Test all workflow types have new phases
52
- const specPhases = (0, phase_flow_js_1.getPhasesForWorkflow)('spec');
53
- (0, node_assert_1.strict)(specPhases.includes('submit-pr'), 'Spec workflow should include submit-pr');
54
- (0, node_assert_1.strict)(specPhases.includes('wait-for-pr-review'), 'Spec workflow should include wait-for-pr-review');
55
- const designPhases = (0, phase_flow_js_1.getPhasesForWorkflow)('design');
56
- (0, node_assert_1.strict)(designPhases.includes('submit-pr'), 'Design workflow should include submit-pr');
57
- (0, node_assert_1.strict)(designPhases.includes('wait-for-pr-review'), 'Design workflow should include wait-for-pr-review');
58
- console.log('โœ… PR review failure handling tests passed');
59
- return true;
60
- }
61
- catch (error) {
62
- console.error('โŒ PR review failure handling test failed:', error.message);
63
- return false;
64
- }
65
- }
66
- /**
67
- * Test PR Comment Polling Script (Mock)
68
- */
69
- async function testPRCommentPollingScript() {
70
- try {
71
- console.log('๐Ÿงช Testing PR comment polling script...');
72
- // Create mock .fraim/config.json
73
- const testDir = (0, path_1.join)(process.cwd(), 'test_temp');
74
- const fraimDir = (0, path_1.join)(testDir, '.fraim');
75
- if ((0, fs_1.existsSync)(testDir)) {
76
- (0, fs_1.rmSync)(testDir, { recursive: true, force: true });
77
- }
78
- (0, fs_1.mkdirSync)(fraimDir, { recursive: true });
79
- const mockConfig = {
80
- git: {
81
- repoOwner: 'test-owner',
82
- repoName: 'test-repo'
83
- }
84
- };
85
- (0, fs_1.writeFileSync)((0, path_1.join)(fraimDir, 'config.json'), JSON.stringify(mockConfig, null, 2));
86
- // Test script exists and is executable
87
- const scriptPath = (0, path_1.join)(process.cwd(), 'scripts', 'sleep-and-continue.js');
88
- (0, node_assert_1.strict)((0, fs_1.existsSync)(scriptPath), 'Sleep utility script should exist');
89
- // Test script can be executed (syntax check)
90
- const { execSync } = require('child_process');
91
- try {
92
- // Test help output
93
- execSync('node scripts/sleep-and-continue.js --help', { stdio: 'pipe' });
94
- }
95
- catch (error) {
96
- // Expected to fail with usage message, which is fine
97
- (0, node_assert_1.strict)(error.message.includes('Usage:'), 'Script should show usage when called incorrectly');
98
- }
99
- // Cleanup
100
- (0, fs_1.rmSync)(testDir, { recursive: true, force: true });
101
- console.log('โœ… PR comment polling script tests passed');
102
- return true;
103
- }
104
- catch (error) {
105
- console.error('โŒ PR comment polling script test failed:', error.message);
106
- return false;
107
- }
108
- }
109
- /**
110
- * Test PR Feedback File System
111
- */
112
- async function testPRCommentVerificationScript() {
113
- try {
114
- console.log('๐Ÿงช Testing PR feedback file system...');
115
- const testDir = (0, path_1.join)(process.cwd(), 'test_temp');
116
- const evidenceDir = (0, path_1.join)(testDir, 'evidence');
117
- if ((0, fs_1.existsSync)(testDir)) {
118
- (0, fs_1.rmSync)(testDir, { recursive: true, force: true });
119
- }
120
- (0, fs_1.mkdirSync)(evidenceDir, { recursive: true });
121
- // Create mock feedback document using new format
122
- const mockFeedbackDoc = `# PR Feedback for Issue #123 - Implement Workflow
123
-
124
- ## Round 1 Feedback
125
- *Received: 2024-01-15T10:30:00Z*
126
-
127
- ### Comment 1 - ADDRESSED
128
- - **Author**: reviewer1
129
- - **Type**: review_comment
130
- - **File**: src/test.ts
131
- - **Line**: 45
132
- - **Comment**: This function needs error handling
133
- - **Status**: ADDRESSED
134
- - **Resolution**: Added try-catch block and proper error handling
135
-
136
- ### Comment 2 - ADDRESSED
137
- - **Author**: reviewer2
138
- - **Type**: pr_comment
139
- - **Comment**: Please add unit tests for this feature
140
- - **Status**: ADDRESSED
141
- - **Resolution**: Added comprehensive unit tests in test/feature.test.ts
142
- `;
143
- const feedbackDocPath = (0, path_1.join)(evidenceDir, '123-implement-feedback.md');
144
- (0, fs_1.writeFileSync)(feedbackDocPath, mockFeedbackDoc);
145
- // Test that feedback document was created and has expected content
146
- (0, node_assert_1.strict)((0, fs_1.existsSync)(feedbackDocPath), 'PR feedback document should exist');
147
- const content = (0, fs_1.readFileSync)(feedbackDocPath, 'utf-8');
148
- (0, node_assert_1.strict)(content.includes('## Round 1 Feedback'), 'Document should contain Round 1 Feedback');
149
- (0, node_assert_1.strict)(content.includes('### Comment 1 - ADDRESSED'), 'Document should contain Comment 1 with status');
150
- (0, node_assert_1.strict)(content.includes('### Comment 2 - ADDRESSED'), 'Document should contain Comment 2 with status');
151
- (0, node_assert_1.strict)(content.includes('reviewer1'), 'Document should contain reviewer1');
152
- (0, node_assert_1.strict)(content.includes('reviewer2'), 'Document should contain reviewer2');
153
- (0, node_assert_1.strict)(content.includes('Status**: ADDRESSED'), 'Comments should be marked as ADDRESSED');
154
- // Cleanup
155
- (0, fs_1.rmSync)(testDir, { recursive: true, force: true });
156
- console.log('โœ… PR feedback file system tests passed');
157
- return true;
158
- }
159
- catch (error) {
160
- console.error('โŒ PR feedback file system test failed:', error.message);
161
- return false;
162
- }
163
- }
164
- /**
165
- * Test Real-World PR Review Scenario
166
- */
167
- async function testRealWorldPRReviewScenario() {
168
- try {
169
- console.log('๐Ÿงช Testing real-world PR review scenario...');
170
- // Scenario: Feature implementation with PR feedback
171
- let currentPhase = 'implement-scoping';
172
- const workflowType = 'implement';
173
- const issueType = 'feature';
174
- // Progress through normal phases
175
- const expectedFlow = [
176
- 'implement-scoping',
177
- 'implement-spike',
178
- 'implement-code',
179
- 'implement-validate',
180
- 'implement-smoke',
181
- 'implement-regression',
182
- 'implement-completeness-review',
183
- 'submit-pr',
184
- 'wait-for-pr-review'
185
- ];
186
- for (let i = 0; i < expectedFlow.length - 1; i++) {
187
- const nextPhase = (0, phase_flow_js_1.getNextPhase)(currentPhase, workflowType, issueType);
188
- node_assert_1.strict.equal(nextPhase, expectedFlow[i + 1], `After ${currentPhase} should go to ${expectedFlow[i + 1]}`);
189
- currentPhase = nextPhase;
190
- }
191
- // Test PR review completion (approved)
192
- const nextPhaseAfterPR = (0, phase_flow_js_1.getNextPhase)('wait-for-pr-review', workflowType, issueType);
193
- node_assert_1.strict.equal(nextPhaseAfterPR, 'retrospective', 'wait-for-pr-review should go to retrospective when approved');
194
- const finalPhase = (0, phase_flow_js_1.getNextPhase)('retrospective', workflowType, issueType);
195
- node_assert_1.strict.equal(finalPhase, null, 'retrospective should be final phase when approved');
196
- // Test PR review with changes requested (failure scenario)
197
- const failurePhase = (0, phase_flow_js_1.getPhaseOnFailure)('wait-for-pr-review', workflowType, issueType);
198
- node_assert_1.strict.equal(failurePhase, 'address-pr-feedback', 'PR changes requested should route to address-pr-feedback');
199
- // Test iteration: after addressing feedback, go through validation again
200
- let iterationPhase = 'address-pr-feedback';
201
- // After addressing feedback, should go to validation phase
202
- const nextAfterFeedback = (0, phase_flow_js_1.getNextPhase)(iterationPhase, workflowType, issueType);
203
- node_assert_1.strict.equal(nextAfterFeedback, 'implement-validate', 'After address-pr-feedback should go to implement-validate');
204
- iterationPhase = nextAfterFeedback;
205
- const iterationFlow = ['implement-smoke', 'implement-regression', 'implement-completeness-review', 'submit-pr', 'wait-for-pr-review'];
206
- for (const expectedNext of iterationFlow) {
207
- const nextPhase = (0, phase_flow_js_1.getNextPhase)(iterationPhase, workflowType, issueType);
208
- node_assert_1.strict.equal(nextPhase, expectedNext, `Iteration: after ${iterationPhase} should go to ${expectedNext}`);
209
- iterationPhase = nextPhase;
210
- }
211
- console.log('โœ… Real-world PR review scenario tests passed');
212
- return true;
213
- }
214
- catch (error) {
215
- console.error('โŒ Real-world PR review scenario test failed:', error.message);
216
- return false;
217
- }
218
- }
219
- /**
220
- * Test PR Comment Routing Logic
221
- */
222
- async function testPRCommentRoutingLogic() {
223
- try {
224
- console.log('๐Ÿงช Testing PR comment routing logic...');
225
- // Test different comment types should route to different phases
226
- // This would be implemented in the wait-for-pr-review phase logic
227
- // Mock comment analysis scenarios
228
- const commentScenarios = [
229
- {
230
- comment: "This doesn't match the requirements in the spec",
231
- expectedRoute: 'implement-scoping', // or spec-spec for spec workflow
232
- category: 'requirements'
233
- },
234
- {
235
- comment: "The API design doesn't follow our patterns",
236
- expectedRoute: 'design-design',
237
- category: 'design'
238
- },
239
- {
240
- comment: "This code has a memory leak",
241
- expectedRoute: 'implement-code',
242
- category: 'code_quality'
243
- },
244
- {
245
- comment: "Missing test coverage for edge cases",
246
- expectedRoute: 'implement-validate',
247
- category: 'testing'
248
- },
249
- {
250
- comment: "The documentation is incomplete",
251
- expectedRoute: 'implement-completeness-review',
252
- category: 'documentation'
253
- }
254
- ];
255
- // For now, just verify the routing logic exists in the failure handling
256
- for (const scenario of commentScenarios) {
257
- // The actual routing would be implemented in the wait-for-pr-review phase
258
- // For now, we test that the failure handling provides reasonable defaults
259
- const routePhase = (0, phase_flow_js_1.getPhaseOnFailure)('wait-for-pr-review', 'implement', 'feature');
260
- (0, node_assert_1.strict)(typeof routePhase === 'string', `Should return a valid phase for routing`);
261
- }
262
- console.log('โœ… PR comment routing logic tests passed');
263
- return true;
264
- }
265
- catch (error) {
266
- console.error('โŒ PR comment routing logic test failed:', error.message);
267
- return false;
268
- }
269
- }
270
- /**
271
- * Test Phase Validation
272
- */
273
- async function testPhaseValidation() {
274
- try {
275
- console.log('๐Ÿงช Testing phase validation...');
276
- // Test new phases are valid for all workflow types
277
- (0, node_assert_1.strict)((0, phase_flow_js_1.isPhaseValidForWorkflow)('submit-pr', 'implement', 'bug'), 'submit-pr should be valid for implement workflow');
278
- (0, node_assert_1.strict)((0, phase_flow_js_1.isPhaseValidForWorkflow)('wait-for-pr-review', 'implement', 'bug'), 'wait-for-pr-review should be valid for implement workflow');
279
- (0, node_assert_1.strict)((0, phase_flow_js_1.isPhaseValidForWorkflow)('submit-pr', 'spec'), 'submit-pr should be valid for spec workflow');
280
- (0, node_assert_1.strict)((0, phase_flow_js_1.isPhaseValidForWorkflow)('wait-for-pr-review', 'spec'), 'wait-for-pr-review should be valid for spec workflow');
281
- (0, node_assert_1.strict)((0, phase_flow_js_1.isPhaseValidForWorkflow)('submit-pr', 'design'), 'submit-pr should be valid for design workflow');
282
- (0, node_assert_1.strict)((0, phase_flow_js_1.isPhaseValidForWorkflow)('wait-for-pr-review', 'design'), 'wait-for-pr-review should be valid for design workflow');
283
- (0, node_assert_1.strict)((0, phase_flow_js_1.isPhaseValidForWorkflow)('submit-pr', 'test'), 'submit-pr should be valid for test workflow');
284
- (0, node_assert_1.strict)((0, phase_flow_js_1.isPhaseValidForWorkflow)('wait-for-pr-review', 'test'), 'wait-for-pr-review should be valid for test workflow');
285
- // Test old finalize phase is no longer valid
286
- (0, node_assert_1.strict)(!(0, phase_flow_js_1.isPhaseValidForWorkflow)('finalize', 'implement', 'bug'), 'finalize should no longer be valid for implement workflow');
287
- (0, node_assert_1.strict)(!(0, phase_flow_js_1.isPhaseValidForWorkflow)('finalize', 'spec'), 'finalize should no longer be valid for spec workflow');
288
- console.log('โœ… Phase validation tests passed');
289
- return true;
290
- }
291
- catch (error) {
292
- console.error('โŒ Phase validation test failed:', error.message);
293
- return false;
294
- }
295
- }
296
- // Test cases
297
- const testCases = [
298
- { name: 'PR Review Phase Flow', testFn: testPRReviewPhaseFlow },
299
- { name: 'PR Review Failure Handling', testFn: testPRReviewFailureHandling },
300
- { name: 'PR Comment Polling Script', testFn: testPRCommentPollingScript },
301
- { name: 'PR Feedback File System', testFn: testPRCommentVerificationScript },
302
- { name: 'Real-World PR Review Scenario', testFn: testRealWorldPRReviewScenario },
303
- { name: 'PR Comment Routing Logic', testFn: testPRCommentRoutingLogic },
304
- { name: 'Phase Validation', testFn: testPhaseValidation }
305
- ];
306
- // Run tests
307
- (0, test_utils_1.runTests)(testCases, async (t) => t.testFn(), 'PR Review Workflow Tests');