fraim-framework 2.0.36 → 2.0.37

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 (165) hide show
  1. package/bin/fraim.js +5 -52
  2. package/dist/registry/scripts/build-scripts-generator.js +205 -0
  3. package/dist/registry/scripts/fraim-config.js +61 -0
  4. package/dist/registry/scripts/generic-issues-api.js +100 -0
  5. package/dist/registry/scripts/openapi-generator.js +664 -0
  6. package/dist/registry/scripts/performance/profile-server.js +390 -0
  7. package/dist/scripts/build-stub-registry.js +108 -0
  8. package/dist/src/cli/commands/doctor.js +5 -5
  9. package/dist/src/cli/commands/sync.js +33 -19
  10. package/dist/test-utils.js +96 -0
  11. package/dist/tests/esm-compat.js +11 -0
  12. package/dist/tests/test-chalk-esm-issue.js +159 -0
  13. package/dist/tests/test-chalk-real-world.js +265 -0
  14. package/dist/tests/test-chalk-regression.js +2 -18
  15. package/dist/tests/test-chalk-resolution-issue.js +304 -0
  16. package/dist/tests/test-fraim-install-chalk-issue.js +254 -0
  17. package/dist/tests/test-npm-resolution-diagnostic.js +140 -0
  18. package/dist/tests/test-package-size.js +88 -0
  19. package/dist/tests/test-prep-issue.js +34 -1
  20. package/dist/tests/test-stub-registry.js +120 -0
  21. package/dist/tests/test-sync-stubs.js +143 -0
  22. package/package.json +6 -8
  23. package/registry/agent-guardrails.md +62 -62
  24. package/registry/scripts/code-quality-check.sh +559 -559
  25. package/registry/scripts/detect-tautological-tests.sh +38 -38
  26. package/registry/scripts/prep-issue.sh +61 -30
  27. package/registry/scripts/validate-openapi-limits.ts +366 -366
  28. package/registry/scripts/validate-test-coverage.ts +280 -280
  29. package/registry/scripts/verify-pr-comments.sh +70 -70
  30. package/registry/stubs/workflows/bootstrap/create-architecture.md +11 -0
  31. package/registry/stubs/workflows/bootstrap/detect-broken-windows.md +11 -0
  32. package/registry/stubs/workflows/bootstrap/evaluate-code-quality.md +11 -0
  33. package/registry/stubs/workflows/bootstrap/verify-test-coverage.md +11 -0
  34. package/registry/stubs/workflows/business-development/create-business-plan.md +11 -0
  35. package/registry/stubs/workflows/business-development/ideate-business-opportunity.md +11 -0
  36. package/registry/stubs/workflows/business-development/price-product.md +18 -0
  37. package/registry/stubs/workflows/convert-to-pdf.md +11 -0
  38. package/registry/stubs/workflows/customer-development/insight-analysis.md +11 -0
  39. package/registry/stubs/workflows/customer-development/insight-triage.md +11 -0
  40. package/registry/stubs/workflows/customer-development/interview-preparation.md +11 -0
  41. package/registry/stubs/workflows/customer-development/linkedin-outreach.md +11 -0
  42. package/registry/stubs/workflows/customer-development/strategic-brainstorming.md +11 -0
  43. package/registry/stubs/workflows/customer-development/thank-customers.md +11 -0
  44. package/registry/stubs/workflows/customer-development/weekly-newsletter.md +11 -0
  45. package/registry/stubs/workflows/deploy/cloud-deployment.md +11 -0
  46. package/registry/stubs/workflows/improve-fraim/contribute.md +11 -0
  47. package/registry/stubs/workflows/improve-fraim/file-issue.md +11 -0
  48. package/registry/stubs/workflows/marketing/content-creation.md +11 -0
  49. package/registry/stubs/workflows/marketing/hbr-article.md +11 -0
  50. package/registry/stubs/workflows/marketing/launch-checklist.md +11 -0
  51. package/registry/stubs/workflows/marketing/marketing-strategy.md +11 -0
  52. package/registry/stubs/workflows/marketing/storytelling.md +11 -0
  53. package/registry/stubs/workflows/performance/analyze-performance.md +11 -0
  54. package/registry/stubs/workflows/product-building/design.md +11 -0
  55. package/registry/stubs/workflows/product-building/implement.md +12 -0
  56. package/registry/stubs/workflows/product-building/iterate-on-pr-comments.md +11 -0
  57. package/registry/stubs/workflows/product-building/prep-issue.md +11 -0
  58. package/registry/stubs/workflows/product-building/prototype.md +11 -0
  59. package/registry/stubs/workflows/product-building/resolve.md +11 -0
  60. package/registry/stubs/workflows/product-building/retrospect.md +11 -0
  61. package/registry/stubs/workflows/product-building/spec.md +11 -0
  62. package/registry/stubs/workflows/product-building/test.md +11 -0
  63. package/registry/stubs/workflows/quality-assurance/browser-validation.md +11 -0
  64. package/registry/stubs/workflows/quality-assurance/iterative-improvement-cycle.md +11 -0
  65. package/registry/stubs/workflows/replicate/replicate-discovery.md +11 -0
  66. package/registry/stubs/workflows/replicate/replicate-to-issues.md +11 -0
  67. package/registry/stubs/workflows/reviewer/review-implementation-vs-design-spec.md +11 -0
  68. package/registry/stubs/workflows/reviewer/review-implementation-vs-feature-spec.md +11 -0
  69. package/registry/stubs/workflows/startup-credits/aws-activate-application.md +11 -0
  70. package/registry/stubs/workflows/startup-credits/google-cloud-application.md +11 -0
  71. package/registry/stubs/workflows/startup-credits/microsoft-azure-application.md +11 -0
  72. package/.github/workflows/ci.yml +0 -65
  73. package/.github/workflows/deploy-fraim.yml +0 -87
  74. package/.github/workflows/phase-change.yml +0 -251
  75. package/.github/workflows/status-change.yml +0 -68
  76. package/.github/workflows/sync-on-pr-review.yml +0 -66
  77. package/examples/simple-webapp/TESTING.md +0 -62
  78. package/examples/simple-webapp/example-test.ts +0 -186
  79. package/registry/github/workflows/ci.yml +0 -51
  80. package/registry/github/workflows/phase-change.yml +0 -251
  81. package/registry/github/workflows/status-change.yml +0 -68
  82. package/registry/github/workflows/sync-on-pr-review.yml +0 -66
  83. package/registry/mcp-template.jsonc +0 -29
  84. package/registry/rules/agent-success-criteria.md +0 -52
  85. package/registry/rules/agent-testing-guidelines.md +0 -502
  86. package/registry/rules/architecture.md +0 -52
  87. package/registry/rules/communication.md +0 -122
  88. package/registry/rules/continuous-learning.md +0 -55
  89. package/registry/rules/debugging-multitenancy-issues.md +0 -85
  90. package/registry/rules/ephemeral-execution.md +0 -57
  91. package/registry/rules/git-safe-commands.md +0 -34
  92. package/registry/rules/hitl-ppe-record-analysis.md +0 -302
  93. package/registry/rules/integrity-and-test-ethics.md +0 -275
  94. package/registry/rules/local-development.md +0 -254
  95. package/registry/rules/merge-requirements.md +0 -231
  96. package/registry/rules/simplicity.md +0 -118
  97. package/registry/rules/software-development-lifecycle.md +0 -105
  98. package/registry/rules/spike-first-development.md +0 -205
  99. package/registry/rules/successful-debugging-patterns.md +0 -491
  100. package/registry/rules/telemetry.md +0 -67
  101. package/registry/templates/bootstrap/ARCHITECTURE-TEMPLATE.md +0 -53
  102. package/registry/templates/bootstrap/CODE-QUALITY-REPORT-TEMPLATE.md +0 -37
  103. package/registry/templates/bootstrap/TEST-COVERAGE-REPORT-TEMPLATE.md +0 -35
  104. package/registry/templates/business-development/IDEATION-REPORT-TEMPLATE.md +0 -29
  105. package/registry/templates/business-development/PRICING-STRATEGY-TEMPLATE.md +0 -126
  106. package/registry/templates/customer-development/customer-interview-template.md +0 -99
  107. package/registry/templates/customer-development/follow-up-email-templates.md +0 -132
  108. package/registry/templates/customer-development/insight-analysis-template.md +0 -74
  109. package/registry/templates/customer-development/strategic-recommendations-template.md +0 -53
  110. package/registry/templates/customer-development/thank-you-email-template.html +0 -124
  111. package/registry/templates/customer-development/thank-you-note-template.md +0 -16
  112. package/registry/templates/customer-development/triage-log-template.md +0 -278
  113. package/registry/templates/customer-development/weekly-newsletter-template.html +0 -204
  114. package/registry/templates/evidence/Design-Evidence.md +0 -30
  115. package/registry/templates/evidence/Implementation-BugEvidence.md +0 -86
  116. package/registry/templates/evidence/Implementation-FeatureEvidence.md +0 -121
  117. package/registry/templates/evidence/Spec-Evidence.md +0 -19
  118. package/registry/templates/help/HelpNeeded.md +0 -14
  119. package/registry/templates/marketing/HBR-ARTICLE-TEMPLATE.md +0 -66
  120. package/registry/templates/replicate/implementation-checklist.md +0 -39
  121. package/registry/templates/replicate/use-cases-template.md +0 -88
  122. package/registry/templates/retrospective/RETROSPECTIVE-TEMPLATE.md +0 -55
  123. package/registry/templates/specs/BUGSPEC-TEMPLATE.md +0 -37
  124. package/registry/templates/specs/FEATURESPEC-TEMPLATE.md +0 -29
  125. package/registry/templates/specs/TECHSPEC-TEMPLATE.md +0 -39
  126. package/registry/workflows/bootstrap/create-architecture.md +0 -38
  127. package/registry/workflows/bootstrap/evaluate-code-quality.md +0 -36
  128. package/registry/workflows/bootstrap/verify-test-coverage.md +0 -37
  129. package/registry/workflows/business-development/create-business-plan.md +0 -737
  130. package/registry/workflows/business-development/ideate-business-opportunity.md +0 -55
  131. package/registry/workflows/business-development/price-product.md +0 -325
  132. package/registry/workflows/convert-to-pdf.md +0 -235
  133. package/registry/workflows/customer-development/insight-analysis.md +0 -156
  134. package/registry/workflows/customer-development/insight-triage.md +0 -933
  135. package/registry/workflows/customer-development/interview-preparation.md +0 -421
  136. package/registry/workflows/customer-development/linkedin-outreach.md +0 -593
  137. package/registry/workflows/customer-development/strategic-brainstorming.md +0 -146
  138. package/registry/workflows/customer-development/thank-customers.md +0 -203
  139. package/registry/workflows/customer-development/weekly-newsletter.md +0 -366
  140. package/registry/workflows/deploy/cloud-deployment.md +0 -310
  141. package/registry/workflows/improve-fraim/contribute.md +0 -32
  142. package/registry/workflows/improve-fraim/file-issue.md +0 -32
  143. package/registry/workflows/marketing/content-creation.md +0 -37
  144. package/registry/workflows/marketing/hbr-article.md +0 -73
  145. package/registry/workflows/marketing/launch-checklist.md +0 -37
  146. package/registry/workflows/marketing/marketing-strategy.md +0 -45
  147. package/registry/workflows/performance/analyze-performance.md +0 -65
  148. package/registry/workflows/product-building/design.md +0 -130
  149. package/registry/workflows/product-building/implement.md +0 -315
  150. package/registry/workflows/product-building/iterate-on-pr-comments.md +0 -70
  151. package/registry/workflows/product-building/prep-issue.md +0 -43
  152. package/registry/workflows/product-building/prototype.md +0 -60
  153. package/registry/workflows/product-building/resolve.md +0 -164
  154. package/registry/workflows/product-building/retrospect.md +0 -86
  155. package/registry/workflows/product-building/spec.md +0 -117
  156. package/registry/workflows/product-building/test.md +0 -120
  157. package/registry/workflows/quality-assurance/browser-validation.md +0 -221
  158. package/registry/workflows/quality-assurance/iterative-improvement-cycle.md +0 -562
  159. package/registry/workflows/replicate/replicate-discovery.md +0 -336
  160. package/registry/workflows/replicate/replicate-to-issues.md +0 -319
  161. package/registry/workflows/reviewer/review-implementation-vs-design-spec.md +0 -632
  162. package/registry/workflows/reviewer/review-implementation-vs-feature-spec.md +0 -669
  163. package/registry/workflows/startup-credits/aws-activate-application.md +0 -535
  164. package/registry/workflows/startup-credits/google-cloud-application.md +0 -647
  165. package/registry/workflows/startup-credits/microsoft-azure-application.md +0 -538
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ /**
3
+ * Diagnostic test to understand npm's chalk resolution behavior
4
+ *
5
+ * This test will show us exactly what npm does when there's a version conflict
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ const node_child_process_1 = require("node:child_process");
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const path_1 = __importDefault(require("path"));
14
+ const os_1 = __importDefault(require("os"));
15
+ async function main() {
16
+ console.log('🔍 NPM Chalk Resolution Diagnostic\n');
17
+ const tempDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'npm-diagnostic-'));
18
+ console.log(`📂 Temp dir: ${tempDir}\n`);
19
+ try {
20
+ // 1. Pack fraim-framework
21
+ console.log('📦 Packing fraim-framework...');
22
+ const projectRoot = process.cwd();
23
+ const packResult = (0, node_child_process_1.execSync)('npm pack', {
24
+ cwd: projectRoot,
25
+ encoding: 'utf-8'
26
+ });
27
+ const tarballName = packResult.trim().split('\n').pop()?.trim();
28
+ if (!tarballName) {
29
+ console.log('❌ Failed to pack');
30
+ return;
31
+ }
32
+ const tarballPath = path_1.default.join(projectRoot, tarballName);
33
+ console.log(`✅ Created: ${tarballName}\n`);
34
+ // 2. Create test project with chalk v5
35
+ console.log('📝 Creating test project with chalk v5 dependency...');
36
+ const packageJson = {
37
+ name: 'diagnostic-test',
38
+ version: '1.0.0',
39
+ dependencies: {
40
+ 'chalk': '^5.0.0',
41
+ 'fraim-framework': `file:${tarballPath}`
42
+ }
43
+ };
44
+ fs_1.default.writeFileSync(path_1.default.join(tempDir, 'package.json'), JSON.stringify(packageJson, null, 2));
45
+ // 3. Install
46
+ console.log('📥 Running npm install...\n');
47
+ try {
48
+ const installOutput = (0, node_child_process_1.execSync)('npm install', {
49
+ cwd: tempDir,
50
+ encoding: 'utf-8',
51
+ stdio: 'pipe'
52
+ });
53
+ console.log('✅ Install completed\n');
54
+ }
55
+ catch (error) {
56
+ console.log('⚠️ Install had issues:\n', error.stdout || error.message);
57
+ }
58
+ // 4. Check what was installed
59
+ console.log('📋 Checking installed chalk versions...\n');
60
+ // Root chalk
61
+ const rootChalkPath = path_1.default.join(tempDir, 'node_modules', 'chalk', 'package.json');
62
+ if (fs_1.default.existsSync(rootChalkPath)) {
63
+ const pkg = JSON.parse(fs_1.default.readFileSync(rootChalkPath, 'utf-8'));
64
+ console.log(` Root chalk: ${pkg.version}`);
65
+ console.log(` Type: ${pkg.type || 'commonjs'}`);
66
+ console.log(` Main: ${pkg.main || 'N/A'}`);
67
+ console.log(` Exports: ${pkg.exports ? 'Yes' : 'No'}\n`);
68
+ }
69
+ else {
70
+ console.log(' ❌ No root chalk found\n');
71
+ }
72
+ // Fraim's chalk
73
+ const fraimChalkPath = path_1.default.join(tempDir, 'node_modules', 'fraim-framework', 'node_modules', 'chalk', 'package.json');
74
+ if (fs_1.default.existsSync(fraimChalkPath)) {
75
+ const pkg = JSON.parse(fs_1.default.readFileSync(fraimChalkPath, 'utf-8'));
76
+ console.log(` fraim-framework's chalk: ${pkg.version}`);
77
+ console.log(` Type: ${pkg.type || 'commonjs'}`);
78
+ console.log(` Main: ${pkg.main || 'N/A'}\n`);
79
+ }
80
+ else {
81
+ console.log(' ℹ️ fraim-framework has no separate chalk (using root)\n');
82
+ }
83
+ // 5. Run npm ls to see the dependency tree
84
+ console.log('🌳 Dependency tree (npm ls chalk):\n');
85
+ try {
86
+ const lsOutput = (0, node_child_process_1.execSync)('npm ls chalk', {
87
+ cwd: tempDir,
88
+ encoding: 'utf-8'
89
+ });
90
+ console.log(lsOutput);
91
+ }
92
+ catch (error) {
93
+ console.log(error.stdout || error.message);
94
+ }
95
+ // 6. Check fraim-framework's package.json in node_modules
96
+ console.log('\n📋 fraim-framework\'s chalk dependency in node_modules:\n');
97
+ const fraimPkgPath = path_1.default.join(tempDir, 'node_modules', 'fraim-framework', 'package.json');
98
+ if (fs_1.default.existsSync(fraimPkgPath)) {
99
+ const fraimPkg = JSON.parse(fs_1.default.readFileSync(fraimPkgPath, 'utf-8'));
100
+ console.log(` Chalk version in package.json: ${fraimPkg.dependencies?.chalk || 'N/A'}\n`);
101
+ }
102
+ // 7. Try to load fraim CLI
103
+ console.log('🚀 Testing fraim CLI load...\n');
104
+ const testScript = `
105
+ try {
106
+ const fraimCli = require('./node_modules/fraim-framework/dist/src/cli/fraim.js');
107
+ console.log('✅ SUCCESS: fraim CLI loaded');
108
+ } catch (error) {
109
+ console.log('❌ ERROR:', error.code || 'Unknown');
110
+ console.log('Message:', error.message.substring(0, 200));
111
+ }
112
+ `;
113
+ fs_1.default.writeFileSync(path_1.default.join(tempDir, 'test.js'), testScript);
114
+ try {
115
+ const testOutput = (0, node_child_process_1.execSync)('node test.js', {
116
+ cwd: tempDir,
117
+ encoding: 'utf-8'
118
+ });
119
+ console.log(testOutput);
120
+ }
121
+ catch (error) {
122
+ console.log(error.stdout || error.message);
123
+ }
124
+ // Cleanup
125
+ fs_1.default.unlinkSync(tarballPath);
126
+ console.log('\n✅ Diagnostic complete');
127
+ }
128
+ catch (error) {
129
+ console.error('\n❌ Diagnostic failed:', error);
130
+ }
131
+ finally {
132
+ try {
133
+ fs_1.default.rmSync(tempDir, { recursive: true, force: true });
134
+ }
135
+ catch (e) {
136
+ console.log('\n⚠️ Could not clean up temp directory');
137
+ }
138
+ }
139
+ }
140
+ main();
@@ -0,0 +1,88 @@
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
+ (0, node_test_1.test)('Stub registry is significantly smaller than full registry', () => {
15
+ const fullWorkflowsPath = path_1.default.join(__dirname, '..', 'registry', 'workflows');
16
+ const stubWorkflowsPath = path_1.default.join(__dirname, '..', 'registry', 'stubs', 'workflows');
17
+ (0, node_assert_1.default)(fs_1.default.existsSync(fullWorkflowsPath), 'Full workflows directory should exist');
18
+ (0, node_assert_1.default)(fs_1.default.existsSync(stubWorkflowsPath), 'Stub workflows directory should exist');
19
+ // Calculate sizes
20
+ const fullSize = getDirectorySize(fullWorkflowsPath);
21
+ const stubSize = getDirectorySize(stubWorkflowsPath);
22
+ console.log(`Full workflows size: ${fullSize} bytes`);
23
+ console.log(`Stub workflows size: ${stubSize} bytes`);
24
+ console.log(`Size reduction: ${Math.round((1 - stubSize / fullSize) * 100)}%`);
25
+ // Stubs should be significantly smaller
26
+ (0, node_assert_1.default)(stubSize < fullSize * 0.3, `Stubs should be <30% of full size (actual: ${Math.round(stubSize / fullSize * 100)}%)`);
27
+ // Should have same number of files
28
+ const fullFiles = getAllFiles(fullWorkflowsPath, '.md');
29
+ const stubFiles = getAllFiles(stubWorkflowsPath, '.md');
30
+ node_assert_1.default.strictEqual(stubFiles.length, fullFiles.length, 'Should have same number of workflow files');
31
+ console.log(`✅ Package size reduced by ${Math.round((1 - stubSize / fullSize) * 100)}% while maintaining all ${stubFiles.length} workflows`);
32
+ });
33
+ (0, node_test_1.test)('Package excludes full workflows and templates', () => {
34
+ const packageJsonPath = path_1.default.join(__dirname, '..', 'package.json');
35
+ const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
36
+ const files = packageJson.files || [];
37
+ // Calculate what would be excluded
38
+ const fullWorkflowsSize = getDirectorySize(path_1.default.join(__dirname, '..', 'registry', 'workflows'));
39
+ const templatesSize = getDirectorySize(path_1.default.join(__dirname, '..', 'registry', 'templates'));
40
+ const rulesSize = getDirectorySize(path_1.default.join(__dirname, '..', 'registry', 'rules'));
41
+ const excludedSize = fullWorkflowsSize + templatesSize + rulesSize;
42
+ // What's included
43
+ const stubsSize = getDirectorySize(path_1.default.join(__dirname, '..', 'registry', 'stubs'));
44
+ const scriptsSize = getDirectorySize(path_1.default.join(__dirname, '..', 'registry', 'scripts'));
45
+ const includedSize = stubsSize + scriptsSize;
46
+ console.log(`Excluded from package: ${excludedSize} bytes (workflows + templates + rules)`);
47
+ console.log(`Included in package: ${includedSize} bytes (stubs + scripts)`);
48
+ console.log(`Total registry size reduction: ${Math.round((1 - includedSize / (includedSize + excludedSize)) * 100)}%`);
49
+ // Verify significant size reduction
50
+ (0, node_assert_1.default)(includedSize < excludedSize, 'Package should exclude more content than it includes');
51
+ console.log('✅ Package correctly excludes heavy content while keeping essentials');
52
+ });
53
+ function getDirectorySize(dirPath) {
54
+ if (!fs_1.default.existsSync(dirPath)) {
55
+ return 0;
56
+ }
57
+ let totalSize = 0;
58
+ const files = getAllFiles(dirPath);
59
+ for (const file of files) {
60
+ try {
61
+ const stats = fs_1.default.statSync(file);
62
+ totalSize += stats.size;
63
+ }
64
+ catch (e) {
65
+ // Skip files that can't be read
66
+ }
67
+ }
68
+ return totalSize;
69
+ }
70
+ function getAllFiles(dir, extension) {
71
+ const files = [];
72
+ if (!fs_1.default.existsSync(dir)) {
73
+ return files;
74
+ }
75
+ const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
76
+ for (const entry of entries) {
77
+ const fullPath = path_1.default.join(dir, entry.name);
78
+ if (entry.isDirectory()) {
79
+ files.push(...getAllFiles(fullPath, extension));
80
+ }
81
+ else if (entry.isFile()) {
82
+ if (!extension || entry.name.endsWith(extension)) {
83
+ files.push(fullPath);
84
+ }
85
+ }
86
+ }
87
+ return files;
88
+ }
@@ -57,7 +57,7 @@ async function verifyPrepIssueConfigParsing() {
57
57
  }
58
58
  };
59
59
  const output = runParsingLogic(nodeScript, validConfig);
60
- assert_1.default.strictEqual(output, 'test-owner:test-repo:https://github.com/test-owner/test-repo.git');
60
+ assert_1.default.strictEqual(output, 'test-owner|test-repo|https://github.com/test-owner/test-repo.git|master');
61
61
  console.log(' ✅ Valid config parsed correctly');
62
62
  // 4. Test Missing Config
63
63
  assert_1.default.throws(() => {
@@ -69,6 +69,39 @@ async function verifyPrepIssueConfigParsing() {
69
69
  runParsingLogic(nodeScript, { repository: { owner: 'test-owner' } });
70
70
  }, /Script failed/);
71
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');
72
105
  return true;
73
106
  }
74
107
  catch (error) {
@@ -0,0 +1,120 @@
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
+ const build_stub_registry_1 = require("../scripts/build-stub-registry");
12
+ /**
13
+ * Tests for stub registry build process
14
+ * Ensures that the npm package contains only stubs and scripts, not full workflows
15
+ */
16
+ (0, node_test_1.test)('Stub registry build generates correct structure', async () => {
17
+ // Clean up any existing stubs
18
+ const stubsPath = path_1.default.join(__dirname, '..', 'registry', 'stubs');
19
+ if (fs_1.default.existsSync(stubsPath)) {
20
+ fs_1.default.rmSync(stubsPath, { recursive: true, force: true });
21
+ }
22
+ // Build stub registry
23
+ await (0, build_stub_registry_1.buildStubRegistry)();
24
+ // Verify stubs directory exists
25
+ (0, node_assert_1.default)(fs_1.default.existsSync(stubsPath), 'Stubs directory should exist');
26
+ // Verify workflows stubs directory exists
27
+ const workflowsStubsPath = path_1.default.join(stubsPath, 'workflows');
28
+ (0, node_assert_1.default)(fs_1.default.existsSync(workflowsStubsPath), 'Workflows stubs directory should exist');
29
+ // Verify at least some stubs were generated
30
+ const stubFiles = getAllFiles(workflowsStubsPath, '.md');
31
+ (0, node_assert_1.default)(stubFiles.length > 0, 'Should generate at least one workflow stub');
32
+ console.log(`✅ Generated ${stubFiles.length} workflow stubs`);
33
+ });
34
+ (0, node_test_1.test)('Generated stubs are lightweight and contain correct format', async () => {
35
+ const stubsPath = path_1.default.join(__dirname, '..', 'registry', 'stubs', 'workflows');
36
+ // Find a stub file to test
37
+ const stubFiles = getAllFiles(stubsPath, '.md');
38
+ (0, node_assert_1.default)(stubFiles.length > 0, 'Should have stub files to test');
39
+ const testStubPath = stubFiles[0];
40
+ const stubContent = fs_1.default.readFileSync(testStubPath, 'utf8');
41
+ // Verify stub format
42
+ (0, node_assert_1.default)(stubContent.includes('# FRAIM Workflow:'), 'Stub should have workflow title');
43
+ (0, node_assert_1.default)(stubContent.includes('FRAIM-managed workflow stub'), 'Stub should identify itself as a stub');
44
+ (0, node_assert_1.default)(stubContent.includes('get_fraim_workflow('), 'Stub should contain MCP call instruction');
45
+ (0, node_assert_1.default)(stubContent.includes('## Intent'), 'Stub should contain intent section');
46
+ (0, node_assert_1.default)(stubContent.includes('DO NOT EXECUTE'), 'Stub should contain execution warning');
47
+ // Verify stub is lightweight (should be much smaller than full workflow)
48
+ const stubLines = stubContent.split('\n').length;
49
+ (0, node_assert_1.default)(stubLines < 20, `Stub should be lightweight (${stubLines} lines), not a full workflow`);
50
+ console.log(`✅ Stub format verified (${stubLines} lines)`);
51
+ });
52
+ (0, node_test_1.test)('Stubs do not contain full workflow content', async () => {
53
+ const stubsPath = path_1.default.join(__dirname, '..', 'registry', 'stubs', 'workflows');
54
+ const fullWorkflowsPath = path_1.default.join(__dirname, '..', 'registry', 'workflows');
55
+ const stubFiles = getAllFiles(stubsPath, '.md');
56
+ (0, node_assert_1.default)(stubFiles.length > 0, 'Should have stub files to test');
57
+ for (const stubFile of stubFiles.slice(0, 3)) { // Test first 3 stubs
58
+ const stubContent = fs_1.default.readFileSync(stubFile, 'utf8');
59
+ // Find corresponding full workflow
60
+ const relativePath = path_1.default.relative(stubsPath, stubFile);
61
+ const fullWorkflowPath = path_1.default.join(fullWorkflowsPath, relativePath);
62
+ if (fs_1.default.existsSync(fullWorkflowPath)) {
63
+ const fullContent = fs_1.default.readFileSync(fullWorkflowPath, 'utf8');
64
+ // Stub should be much smaller than full workflow
65
+ (0, node_assert_1.default)(stubContent.length < fullContent.length * 0.5, `Stub should be <50% size of full workflow (stub: ${stubContent.length}, full: ${fullContent.length})`);
66
+ // More importantly, stub should not contain full workflow sections
67
+ (0, node_assert_1.default)(!stubContent.includes('## WORKFLOW TRIGGER'), 'Stub should not contain WORKFLOW TRIGGER section');
68
+ (0, node_assert_1.default)(!stubContent.includes('## AI AGENT PROCESS'), 'Stub should not contain AI AGENT PROCESS section');
69
+ (0, node_assert_1.default)(!stubContent.includes('## EXAMPLES'), 'Stub should not contain EXAMPLES section');
70
+ }
71
+ }
72
+ console.log('✅ Stubs are properly lightweight');
73
+ });
74
+ (0, node_test_1.test)('Package.json files array excludes full workflows', () => {
75
+ const packageJsonPath = path_1.default.join(__dirname, '..', 'package.json');
76
+ const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
77
+ const files = packageJson.files || [];
78
+ // Should include stubs
79
+ (0, node_assert_1.default)(files.includes('registry/stubs/'), 'Should include registry/stubs/');
80
+ // Should include scripts
81
+ (0, node_assert_1.default)(files.includes('registry/scripts/'), 'Should include registry/scripts/');
82
+ // Should NOT include full registry
83
+ (0, node_assert_1.default)(!files.includes('registry/'), 'Should NOT include full registry/');
84
+ (0, node_assert_1.default)(!files.includes('registry/workflows/'), 'Should NOT include registry/workflows/');
85
+ (0, node_assert_1.default)(!files.includes('registry/templates/'), 'Should NOT include registry/templates/');
86
+ (0, node_assert_1.default)(!files.includes('registry/rules/'), 'Should NOT include registry/rules/');
87
+ console.log('✅ Package.json correctly excludes full workflows');
88
+ });
89
+ (0, node_test_1.test)('Scripts are still included in package', () => {
90
+ const scriptsPath = path_1.default.join(__dirname, '..', 'registry', 'scripts');
91
+ (0, node_assert_1.default)(fs_1.default.existsSync(scriptsPath), 'Scripts directory should exist');
92
+ const scriptFiles = getAllFiles(scriptsPath);
93
+ (0, node_assert_1.default)(scriptFiles.length > 0, 'Should have script files');
94
+ // Verify package.json includes scripts
95
+ const packageJsonPath = path_1.default.join(__dirname, '..', 'package.json');
96
+ const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
97
+ const files = packageJson.files || [];
98
+ (0, node_assert_1.default)(files.includes('registry/scripts/'), 'Package should include scripts');
99
+ console.log(`✅ ${scriptFiles.length} scripts are included in package`);
100
+ });
101
+ // Helper function to get all files recursively
102
+ function getAllFiles(dir, extension) {
103
+ const files = [];
104
+ if (!fs_1.default.existsSync(dir)) {
105
+ return files;
106
+ }
107
+ const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
108
+ for (const entry of entries) {
109
+ const fullPath = path_1.default.join(dir, entry.name);
110
+ if (entry.isDirectory()) {
111
+ files.push(...getAllFiles(fullPath, extension));
112
+ }
113
+ else if (entry.isFile()) {
114
+ if (!extension || entry.name.endsWith(extension)) {
115
+ files.push(fullPath);
116
+ }
117
+ }
118
+ }
119
+ return files;
120
+ }
@@ -0,0 +1,143 @@
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
+ const os_1 = __importDefault(require("os"));
12
+ const sync_1 = require("../src/cli/commands/sync");
13
+ /**
14
+ * Tests for sync command with stub registry
15
+ * Ensures sync works correctly with pre-generated stubs
16
+ */
17
+ // Use a temporary directory for testing
18
+ const TEST_PROJECT_DIR = path_1.default.join(os_1.default.tmpdir(), 'fraim-test-sync-' + Date.now());
19
+ const TEST_FRAIM_DIR = path_1.default.join(TEST_PROJECT_DIR, '.fraim');
20
+ const TEST_WORKFLOWS_DIR = path_1.default.join(TEST_FRAIM_DIR, 'workflows');
21
+ (0, node_test_1.test)('Sync command works with stub registry', async () => {
22
+ // Setup test environment
23
+ setupTestProject();
24
+ // Change to test directory
25
+ const originalCwd = process.cwd();
26
+ process.chdir(TEST_PROJECT_DIR);
27
+ try {
28
+ // Run sync
29
+ await (0, sync_1.runSync)({ force: true });
30
+ // Verify workflows directory was created
31
+ (0, node_assert_1.default)(fs_1.default.existsSync(TEST_WORKFLOWS_DIR), 'Workflows directory should be created');
32
+ // Verify stubs were copied
33
+ const stubFiles = getAllFiles(TEST_WORKFLOWS_DIR, '.md');
34
+ (0, node_assert_1.default)(stubFiles.length > 0, 'Should copy workflow stubs');
35
+ // Verify stubs have correct format
36
+ const testStub = fs_1.default.readFileSync(stubFiles[0], 'utf8');
37
+ (0, node_assert_1.default)(testStub.includes('FRAIM-managed workflow stub'), 'Copied files should be stubs');
38
+ (0, node_assert_1.default)(testStub.includes('get_fraim_workflow('), 'Stubs should contain MCP call instruction');
39
+ console.log(`✅ Sync copied ${stubFiles.length} workflow stubs`);
40
+ }
41
+ finally {
42
+ // Restore original directory
43
+ process.chdir(originalCwd);
44
+ // Cleanup test directory
45
+ if (fs_1.default.existsSync(TEST_PROJECT_DIR)) {
46
+ fs_1.default.rmSync(TEST_PROJECT_DIR, { recursive: true, force: true });
47
+ }
48
+ }
49
+ });
50
+ (0, node_test_1.test)('Sync uses stub registry, not full workflows', async () => {
51
+ // Setup test environment
52
+ setupTestProject();
53
+ const originalCwd = process.cwd();
54
+ process.chdir(TEST_PROJECT_DIR);
55
+ try {
56
+ // Run sync
57
+ await (0, sync_1.runSync)({ force: true });
58
+ // Verify synced files are stubs, not full workflows
59
+ const stubFiles = getAllFiles(TEST_WORKFLOWS_DIR, '.md');
60
+ (0, node_assert_1.default)(stubFiles.length > 0, 'Should have synced files');
61
+ for (const stubFile of stubFiles.slice(0, 3)) { // Test first 3 files
62
+ const content = fs_1.default.readFileSync(stubFile, 'utf8');
63
+ const lines = content.split('\n').length;
64
+ // Should be lightweight stubs
65
+ (0, node_assert_1.default)(lines < 20, `File should be a stub (${lines} lines), not a full workflow`);
66
+ (0, node_assert_1.default)(content.includes('DO NOT EXECUTE'), 'Should contain stub warning');
67
+ (0, node_assert_1.default)(!content.includes('## WORKFLOW TRIGGER'), 'Should not contain full workflow sections');
68
+ (0, node_assert_1.default)(!content.includes('## AI AGENT PROCESS'), 'Should not contain full workflow sections');
69
+ }
70
+ console.log('✅ Sync correctly uses stubs, not full workflows');
71
+ }
72
+ finally {
73
+ process.chdir(originalCwd);
74
+ if (fs_1.default.existsSync(TEST_PROJECT_DIR)) {
75
+ fs_1.default.rmSync(TEST_PROJECT_DIR, { recursive: true, force: true });
76
+ }
77
+ }
78
+ });
79
+ (0, node_test_1.test)('Sync preserves directory structure from stub registry', async () => {
80
+ setupTestProject();
81
+ const originalCwd = process.cwd();
82
+ process.chdir(TEST_PROJECT_DIR);
83
+ try {
84
+ await (0, sync_1.runSync)({ force: true });
85
+ // Verify directory structure is preserved
86
+ const expectedDirs = [
87
+ 'bootstrap',
88
+ 'product-building',
89
+ 'customer-development',
90
+ 'marketing'
91
+ ];
92
+ for (const expectedDir of expectedDirs) {
93
+ const dirPath = path_1.default.join(TEST_WORKFLOWS_DIR, expectedDir);
94
+ if (fs_1.default.existsSync(dirPath)) {
95
+ (0, node_assert_1.default)(fs_1.default.statSync(dirPath).isDirectory(), `${expectedDir} should be a directory`);
96
+ // Should contain stub files
97
+ const files = fs_1.default.readdirSync(dirPath).filter(f => f.endsWith('.md'));
98
+ (0, node_assert_1.default)(files.length > 0, `${expectedDir} should contain workflow stubs`);
99
+ }
100
+ }
101
+ console.log('✅ Directory structure preserved correctly');
102
+ }
103
+ finally {
104
+ process.chdir(originalCwd);
105
+ if (fs_1.default.existsSync(TEST_PROJECT_DIR)) {
106
+ fs_1.default.rmSync(TEST_PROJECT_DIR, { recursive: true, force: true });
107
+ }
108
+ }
109
+ });
110
+ function setupTestProject() {
111
+ // Create test project directory
112
+ if (fs_1.default.existsSync(TEST_PROJECT_DIR)) {
113
+ fs_1.default.rmSync(TEST_PROJECT_DIR, { recursive: true, force: true });
114
+ }
115
+ fs_1.default.mkdirSync(TEST_PROJECT_DIR, { recursive: true });
116
+ // Create .fraim directory
117
+ fs_1.default.mkdirSync(TEST_FRAIM_DIR, { recursive: true });
118
+ // Create basic config.json
119
+ const config = {
120
+ version: "2.0.36",
121
+ customizations: {}
122
+ };
123
+ fs_1.default.writeFileSync(path_1.default.join(TEST_FRAIM_DIR, 'config.json'), JSON.stringify(config, null, 2));
124
+ }
125
+ function getAllFiles(dir, extension) {
126
+ const files = [];
127
+ if (!fs_1.default.existsSync(dir)) {
128
+ return files;
129
+ }
130
+ const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
131
+ for (const entry of entries) {
132
+ const fullPath = path_1.default.join(dir, entry.name);
133
+ if (entry.isDirectory()) {
134
+ files.push(...getAllFiles(fullPath, extension));
135
+ }
136
+ else if (entry.isFile()) {
137
+ if (!extension || entry.name.endsWith(extension)) {
138
+ files.push(fullPath);
139
+ }
140
+ }
141
+ }
142
+ return files;
143
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fraim-framework",
3
- "version": "2.0.36",
3
+ "version": "2.0.37",
4
4
  "description": "FRAIM v2: Framework for Rigor-based AI Management - Transform from solo developer to AI manager orchestrating production-ready code with enterprise-grade discipline",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -10,7 +10,8 @@
10
10
  "scripts": {
11
11
  "setup": "node setup.js",
12
12
  "dev": "tsx --watch src/fraim-mcp-server.ts",
13
- "build": "tsc && npm run validate:registry",
13
+ "build": "tsc && npm run build:stubs && npm run validate:registry",
14
+ "build:stubs": "tsx scripts/build-stub-registry.ts",
14
15
  "test": "tsx --test > test.log 2>&1",
15
16
  "start:fraim": "tsx src/fraim-mcp-server.ts",
16
17
  "dev:fraim": "tsx --watch src/fraim-mcp-server.ts",
@@ -21,7 +22,7 @@
21
22
  "postinstall": "fraim sync || echo 'FRAIM setup skipped.'",
22
23
  "prepublishOnly": "npm run build",
23
24
  "release": "npm version patch && npm publish",
24
- "test-smoke-ci": "tsx --test tests/test-genericization.ts tests/test-cli.ts",
25
+ "test-smoke-ci": "tsx --test tests/test-genericization.ts tests/test-cli.ts tests/test-stub-registry.ts tests/test-sync-stubs.ts",
25
26
  "test-all-ci": "tsx --test tests/test-*.ts",
26
27
  "validate:registry": "tsx scripts/verify-registry-paths.ts"
27
28
  },
@@ -67,11 +68,8 @@
67
68
  },
68
69
  "files": [
69
70
  "dist/",
70
- "registry/",
71
- ".cursor/",
72
- ".windsurf/",
73
- ".github/",
74
- "examples/",
71
+ "registry/stubs/",
72
+ "registry/scripts/",
75
73
  "bin/",
76
74
  "*.js",
77
75
  "*.ts",