faf-cli 4.2.2 → 4.3.1

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 (81) hide show
  1. package/README.md +266 -90
  2. package/assets/project-faf-screenshot.png +0 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +40 -22
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/git.d.ts.map +1 -1
  7. package/dist/commands/git.js +9 -7
  8. package/dist/commands/git.js.map +1 -1
  9. package/dist/commands/readme.d.ts +11 -6
  10. package/dist/commands/readme.d.ts.map +1 -1
  11. package/dist/commands/readme.js +167 -120
  12. package/dist/commands/readme.js.map +1 -1
  13. package/dist/commands/show.d.ts.map +1 -1
  14. package/dist/commands/show.js +22 -7
  15. package/dist/commands/show.js.map +1 -1
  16. package/dist/commands/sixws.d.ts +6 -0
  17. package/dist/commands/sixws.d.ts.map +1 -0
  18. package/dist/commands/sixws.js +154 -0
  19. package/dist/commands/sixws.js.map +1 -0
  20. package/dist/github/current-score-calculator.d.ts +15 -0
  21. package/dist/github/current-score-calculator.d.ts.map +1 -0
  22. package/dist/github/current-score-calculator.js +125 -0
  23. package/dist/github/current-score-calculator.js.map +1 -0
  24. package/dist/github/faf-git-generator.d.ts +58 -0
  25. package/dist/github/faf-git-generator.d.ts.map +1 -0
  26. package/dist/github/faf-git-generator.js +557 -0
  27. package/dist/github/faf-git-generator.js.map +1 -0
  28. package/dist/github/github-extractor.d.ts +4 -0
  29. package/dist/github/github-extractor.d.ts.map +1 -1
  30. package/dist/github/github-extractor.js +27 -0
  31. package/dist/github/github-extractor.js.map +1 -1
  32. package/dist/github/repo-selector.d.ts +2 -2
  33. package/dist/github/repo-selector.d.ts.map +1 -1
  34. package/dist/github/repo-selector.js +30 -23
  35. package/dist/github/repo-selector.js.map +1 -1
  36. package/dist/utils/file-utils.d.ts.map +1 -1
  37. package/dist/utils/file-utils.js +1 -4
  38. package/dist/utils/file-utils.js.map +1 -1
  39. package/dist/utils/slot-counter.d.ts +56 -0
  40. package/dist/utils/slot-counter.d.ts.map +1 -0
  41. package/dist/utils/slot-counter.js +100 -0
  42. package/dist/utils/slot-counter.js.map +1 -0
  43. package/dist/utils/yaml-generator.d.ts.map +1 -1
  44. package/dist/utils/yaml-generator.js +3 -7
  45. package/dist/utils/yaml-generator.js.map +1 -1
  46. package/package.json +7 -2
  47. package/project.faf +5 -9
  48. package/scripts/ANTHROPIC-DEMO.sh +203 -0
  49. package/scripts/boris-ready.sh +169 -0
  50. package/scripts/bundle-yaml.js +87 -0
  51. package/scripts/check-version.js +88 -0
  52. package/scripts/clean-build.js +34 -0
  53. package/scripts/cleanup-unused.sh +54 -0
  54. package/scripts/debug-django.txt +9 -0
  55. package/scripts/debug-mongo.txt +9 -0
  56. package/scripts/debug-react.txt +9 -0
  57. package/scripts/debug-rust.txt +9 -0
  58. package/scripts/debug-whisper.cpp.txt +9 -0
  59. package/scripts/evaluate-family-member.ts +300 -0
  60. package/scripts/generate-docs.ts +358 -0
  61. package/scripts/generate-drift-reports.sh +111 -0
  62. package/scripts/industry-showcase.json +122 -0
  63. package/scripts/mcp-ecosystem-research.sh +58 -0
  64. package/scripts/migrate-yaml-imports.sh +55 -0
  65. package/scripts/migrate-yaml.ts +132 -0
  66. package/scripts/performance-validation.ts +460 -0
  67. package/scripts/postinstall.js +30 -0
  68. package/scripts/prepare-release.ts +421 -0
  69. package/scripts/run-industry-showcase.ts +237 -0
  70. package/scripts/run-test-showcase.ts +244 -0
  71. package/scripts/setup-github-watch.sh +43 -0
  72. package/scripts/sync-version.js +35 -0
  73. package/scripts/test-integration-detection.ts +93 -0
  74. package/scripts/test-integration-simple.js +93 -0
  75. package/scripts/test-medal-progression.sh +143 -0
  76. package/scripts/test-showcase-results.json +109 -0
  77. package/scripts/test-showcase.json +32 -0
  78. package/scripts/update-version.js +148 -0
  79. package/scripts/verify-build.js +343 -0
  80. package/scripts/version-check.js +78 -0
  81. package/scripts/watch-discussions.sh +86 -0
@@ -0,0 +1,109 @@
1
+ {
2
+ "generated": "2026-02-09T01:39:39.488Z",
3
+ "totalRepos": 5,
4
+ "successCount": 0,
5
+ "failedCount": 5,
6
+ "avgImprovement": 0,
7
+ "categories": [
8
+ {
9
+ "name": "JavaScript/TypeScript",
10
+ "repos": [
11
+ {
12
+ "repo": "facebook/react",
13
+ "owner": "facebook",
14
+ "name": "react",
15
+ "category": "JavaScript/TypeScript",
16
+ "currentScore": 0,
17
+ "newScore": 0,
18
+ "improvement": 0,
19
+ "tier": "Failed",
20
+ "stack": {},
21
+ "projectType": "unknown",
22
+ "mainLanguage": "unknown",
23
+ "description": "",
24
+ "status": "failed",
25
+ "error": "Failed to parse output (saved to /Users/wolfejam/FAF/cli/scripts/debug-react.txt)"
26
+ }
27
+ ]
28
+ },
29
+ {
30
+ "name": "Python",
31
+ "repos": [
32
+ {
33
+ "repo": "django/django",
34
+ "owner": "django",
35
+ "name": "django",
36
+ "category": "Python",
37
+ "currentScore": 0,
38
+ "newScore": 0,
39
+ "improvement": 0,
40
+ "tier": "Failed",
41
+ "stack": {},
42
+ "projectType": "unknown",
43
+ "mainLanguage": "unknown",
44
+ "description": "",
45
+ "status": "failed",
46
+ "error": "Failed to parse output (saved to /Users/wolfejam/FAF/cli/scripts/debug-django.txt)"
47
+ }
48
+ ]
49
+ },
50
+ {
51
+ "name": "Systems/Low-level",
52
+ "repos": [
53
+ {
54
+ "repo": "ggml-org/whisper.cpp",
55
+ "owner": "ggml-org",
56
+ "name": "whisper.cpp",
57
+ "category": "Systems/Low-level",
58
+ "currentScore": 0,
59
+ "newScore": 0,
60
+ "improvement": 0,
61
+ "tier": "Failed",
62
+ "stack": {},
63
+ "projectType": "unknown",
64
+ "mainLanguage": "unknown",
65
+ "description": "",
66
+ "status": "failed",
67
+ "error": "Failed to parse output (saved to /Users/wolfejam/FAF/cli/scripts/debug-whisper.cpp.txt)"
68
+ },
69
+ {
70
+ "repo": "rust-lang/rust",
71
+ "owner": "rust-lang",
72
+ "name": "rust",
73
+ "category": "Systems/Low-level",
74
+ "currentScore": 0,
75
+ "newScore": 0,
76
+ "improvement": 0,
77
+ "tier": "Failed",
78
+ "stack": {},
79
+ "projectType": "unknown",
80
+ "mainLanguage": "unknown",
81
+ "description": "",
82
+ "status": "failed",
83
+ "error": "Failed to parse output (saved to /Users/wolfejam/FAF/cli/scripts/debug-rust.txt)"
84
+ }
85
+ ]
86
+ },
87
+ {
88
+ "name": "Databases",
89
+ "repos": [
90
+ {
91
+ "repo": "mongodb/mongo",
92
+ "owner": "mongodb",
93
+ "name": "mongo",
94
+ "category": "Databases",
95
+ "currentScore": 0,
96
+ "newScore": 0,
97
+ "improvement": 0,
98
+ "tier": "Failed",
99
+ "stack": {},
100
+ "projectType": "unknown",
101
+ "mainLanguage": "unknown",
102
+ "description": "",
103
+ "status": "failed",
104
+ "error": "Failed to parse output (saved to /Users/wolfejam/FAF/cli/scripts/debug-mongo.txt)"
105
+ }
106
+ ]
107
+ }
108
+ ]
109
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "title": "FAF Industry Showcase - Test Run",
3
+ "description": "Small test of 5 diverse repos before full showcase",
4
+ "updated": "2026-02-08",
5
+ "categories": [
6
+ {
7
+ "name": "JavaScript/TypeScript",
8
+ "repos": [
9
+ "facebook/react"
10
+ ]
11
+ },
12
+ {
13
+ "name": "Python",
14
+ "repos": [
15
+ "django/django"
16
+ ]
17
+ },
18
+ {
19
+ "name": "Systems/Low-level",
20
+ "repos": [
21
+ "ggml-org/whisper.cpp",
22
+ "rust-lang/rust"
23
+ ]
24
+ },
25
+ {
26
+ "name": "Databases",
27
+ "repos": [
28
+ "mongodb/mongo"
29
+ ]
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * šŸŽļø Version Update Script - Ensures all version references stay synchronized
5
+ * Run this BEFORE committing any version changes
6
+ * Usage: npm run version:update 2.8.0
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const glob = require('glob');
12
+
13
+ const VERSION_PATTERN = /v?\d+\.\d+\.\d+/g;
14
+
15
+ // Files that should always have the latest version
16
+ const VERSION_FILES = [
17
+ {
18
+ path: 'package.json',
19
+ pattern: /"version":\s*"[\d.]+"/,
20
+ replacement: (version) => `"version": "${version}"`
21
+ },
22
+ {
23
+ path: 'src/utils/championship-style.ts',
24
+ patterns: [
25
+ {
26
+ pattern: /FAF CLI v\d+\.\d+\.\d+/g,
27
+ replacement: (version) => `FAF CLI v${version}`
28
+ },
29
+ {
30
+ pattern: /šŸŽļøāš”ļøšŸ\s+v\d+\.\d+\.\d+/g,
31
+ replacement: (version) => `šŸŽļøāš”ļøšŸ v${version}`
32
+ },
33
+ {
34
+ pattern: /\(v\d+\.\d+\.\d+ [^)]+\)/g,
35
+ replacement: (version) => `(v${version} White Stripe Edition)`
36
+ }
37
+ ]
38
+ }
39
+ ];
40
+
41
+ // Files that should keep their specific version references (schemas, etc.)
42
+ const IGNORE_PATTERNS = [
43
+ 'tests/**/*.test.ts',
44
+ '**/node_modules/**',
45
+ 'dist/**',
46
+ '*.md' // Documentation can reference old versions
47
+ ];
48
+
49
+ function updateVersion(newVersion) {
50
+ if (!newVersion || !newVersion.match(/^\d+\.\d+\.\d+$/)) {
51
+ console.error('āŒ Invalid version format. Use: X.Y.Z (e.g., 2.8.0)');
52
+ process.exit(1);
53
+ }
54
+
55
+ console.log(`šŸŽļø Updating all version references to v${newVersion}...`);
56
+
57
+ let updatedFiles = [];
58
+
59
+ VERSION_FILES.forEach(file => {
60
+ const filePath = path.join(__dirname, '..', file.path);
61
+
62
+ if (!fs.existsSync(filePath)) {
63
+ console.warn(`āš ļø File not found: ${file.path}`);
64
+ return;
65
+ }
66
+
67
+ let content = fs.readFileSync(filePath, 'utf8');
68
+ let modified = false;
69
+
70
+ if (file.pattern) {
71
+ // Single pattern
72
+ const newContent = content.replace(file.pattern, file.replacement(newVersion));
73
+ if (newContent !== content) {
74
+ content = newContent;
75
+ modified = true;
76
+ }
77
+ } else if (file.patterns) {
78
+ // Multiple patterns
79
+ file.patterns.forEach(patternObj => {
80
+ const newContent = content.replace(patternObj.pattern, patternObj.replacement(newVersion));
81
+ if (newContent !== content) {
82
+ content = newContent;
83
+ modified = true;
84
+ }
85
+ });
86
+ }
87
+
88
+ if (modified) {
89
+ fs.writeFileSync(filePath, content);
90
+ updatedFiles.push(file.path);
91
+ console.log(`āœ… Updated: ${file.path}`);
92
+ }
93
+ });
94
+
95
+ // Check for any remaining old versions in critical files
96
+ console.log('\nšŸ” Checking for stray version references...');
97
+
98
+ const criticalFiles = glob.sync('src/**/*.ts', {
99
+ ignore: IGNORE_PATTERNS,
100
+ cwd: path.join(__dirname, '..')
101
+ });
102
+
103
+ let strayVersions = [];
104
+
105
+ criticalFiles.forEach(file => {
106
+ const content = fs.readFileSync(path.join(__dirname, '..', file), 'utf8');
107
+ const matches = content.match(/v2\.\d+\.\d+/g);
108
+
109
+ if (matches) {
110
+ const nonCurrentVersions = matches.filter(v => {
111
+ const version = v.replace('v', '');
112
+ return version !== newVersion && !isSchemaVersion(version);
113
+ });
114
+
115
+ if (nonCurrentVersions.length > 0) {
116
+ strayVersions.push({
117
+ file,
118
+ versions: [...new Set(nonCurrentVersions)]
119
+ });
120
+ }
121
+ }
122
+ });
123
+
124
+ if (strayVersions.length > 0) {
125
+ console.log('\nāš ļø Found stray version references (review these manually):');
126
+ strayVersions.forEach(item => {
127
+ console.log(` ${item.file}: ${item.versions.join(', ')}`);
128
+ });
129
+ } else {
130
+ console.log('āœ… No stray version references found!');
131
+ }
132
+
133
+ console.log(`\nšŸ Version update complete! Now at v${newVersion}`);
134
+ console.log('šŸ“ Remember to:');
135
+ console.log(' 1. Run: npm run build');
136
+ console.log(' 2. Test: npm test');
137
+ console.log(' 3. Commit with message: "chore: bump version to v' + newVersion + '"');
138
+ }
139
+
140
+ function isSchemaVersion(version) {
141
+ // These are schema versions that shouldn't change automatically
142
+ const schemaVersions = ['2.4.0', '2.5.0'];
143
+ return schemaVersions.includes(version);
144
+ }
145
+
146
+ // Get version from command line
147
+ const newVersion = process.argv[2];
148
+ updateVersion(newVersion);
@@ -0,0 +1,343 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * šŸŽļø Build Verification Script
4
+ * Prevents stale builds from reaching npm
5
+ *
6
+ * Checks:
7
+ * 1. All source commands exist in dist/
8
+ * 2. Dist is newer than source
9
+ * 3. All command imports resolve
10
+ * 4. Native parser has all registered commands
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+
16
+ // Colors for output
17
+ const colors = {
18
+ reset: '\x1b[0m',
19
+ red: '\x1b[31m',
20
+ green: '\x1b[32m',
21
+ yellow: '\x1b[33m',
22
+ cyan: '\x1b[36m',
23
+ orange: '\x1b[38;5;208m'
24
+ };
25
+
26
+ function log(message, color = 'reset') {
27
+ console.log(`${colors[color]}${message}${colors.reset}`);
28
+ }
29
+
30
+ function error(message) {
31
+ log(`āŒ ${message}`, 'red');
32
+ }
33
+
34
+ function success(message) {
35
+ log(`āœ… ${message}`, 'green');
36
+ }
37
+
38
+ function warning(message) {
39
+ log(`āš ļø ${message}`, 'yellow');
40
+ }
41
+
42
+ function info(message) {
43
+ log(`ā„¹ļø ${message}`, 'cyan');
44
+ }
45
+
46
+ // Get root directory
47
+ const rootDir = path.join(__dirname, '..');
48
+ const srcDir = path.join(rootDir, 'src');
49
+ const distDir = path.join(rootDir, 'dist');
50
+
51
+ let hasErrors = false;
52
+
53
+ /**
54
+ * Check 1: Verify dist directory exists and is built
55
+ */
56
+ function checkDistExists() {
57
+ info('Check 1: Verifying dist/ directory exists...');
58
+
59
+ if (!fs.existsSync(distDir)) {
60
+ error('dist/ directory does not exist!');
61
+ error('Run: npm run build');
62
+ hasErrors = true;
63
+ return false;
64
+ }
65
+
66
+ if (!fs.existsSync(path.join(distDir, 'cli.js'))) {
67
+ error('dist/cli.js does not exist!');
68
+ error('Run: npm run build');
69
+ hasErrors = true;
70
+ return false;
71
+ }
72
+
73
+ success('dist/ directory exists');
74
+ return true;
75
+ }
76
+
77
+ /**
78
+ * Check 2: Extract all command names from cli.ts
79
+ */
80
+ function extractCommandsFromSource() {
81
+ info('Check 2: Extracting registered commands from src/cli.ts...');
82
+
83
+ const cliPath = path.join(srcDir, 'cli.ts');
84
+ if (!fs.existsSync(cliPath)) {
85
+ error('src/cli.ts not found!');
86
+ hasErrors = true;
87
+ return [];
88
+ }
89
+
90
+ const content = fs.readFileSync(cliPath, 'utf8');
91
+
92
+ // Extract command registrations: program.command('name')
93
+ const commandRegex = /program\s*\.command\('([^']+)(?:\s+\[)?/g;
94
+ const commands = [];
95
+ let match;
96
+
97
+ while ((match = commandRegex.exec(content)) !== null) {
98
+ const commandName = match[1];
99
+ commands.push(commandName);
100
+ }
101
+
102
+ // Also check for .command() with template strings (rare but possible)
103
+ const templateCommandRegex = /program\s*\.command\(`([^`]+)(?:\s+\[)?/g;
104
+ while ((match = templateCommandRegex.exec(content)) !== null) {
105
+ const commandName = match[1];
106
+ commands.push(commandName);
107
+ }
108
+
109
+ // Remove duplicates and sort
110
+ const uniqueCommands = [...new Set(commands)].sort();
111
+
112
+ success(`Found ${uniqueCommands.length} registered commands`);
113
+ uniqueCommands.forEach(cmd => {
114
+ console.log(` • ${cmd}`);
115
+ });
116
+
117
+ return uniqueCommands;
118
+ }
119
+
120
+ /**
121
+ * Check 3: Verify all commands exist in dist/commands/
122
+ */
123
+ function verifyCommandsInDist(commands) {
124
+ info('Check 3: Verifying commands exist in dist/commands/...');
125
+
126
+ const distCommandsDir = path.join(distDir, 'commands');
127
+
128
+ if (!fs.existsSync(distCommandsDir)) {
129
+ error('dist/commands/ directory does not exist!');
130
+ hasErrors = true;
131
+ return false;
132
+ }
133
+
134
+ let allExist = true;
135
+
136
+ for (const cmd of commands) {
137
+ // Skip wildcard and special commands
138
+ if (cmd === '*' || cmd.includes('$')) continue;
139
+
140
+ const jsPath = path.join(distCommandsDir, `${cmd}.js`);
141
+ const tsPath = path.join(srcDir, 'commands', `${cmd}.ts`);
142
+
143
+ // Check if source exists first
144
+ if (!fs.existsSync(tsPath)) {
145
+ warning(`Source not found: src/commands/${cmd}.ts (inline command?)`);
146
+ continue;
147
+ }
148
+
149
+ // Check if built version exists
150
+ if (!fs.existsSync(jsPath)) {
151
+ error(`Built command missing: dist/commands/${cmd}.js`);
152
+ error(`Source exists at: src/commands/${cmd}.ts`);
153
+ hasErrors = true;
154
+ allExist = false;
155
+ } else {
156
+ success(`${cmd}.js exists in dist/commands/`);
157
+ }
158
+ }
159
+
160
+ return allExist;
161
+ }
162
+
163
+ /**
164
+ * Check 4: Verify dist is newer than source
165
+ */
166
+ function checkDistFreshness() {
167
+ info('Check 4: Verifying dist/ is up-to-date...');
168
+
169
+ const cliSrc = path.join(srcDir, 'cli.ts');
170
+ const cliDist = path.join(distDir, 'cli.js');
171
+
172
+ if (!fs.existsSync(cliDist)) {
173
+ error('dist/cli.js does not exist!');
174
+ hasErrors = true;
175
+ return false;
176
+ }
177
+
178
+ const srcStat = fs.statSync(cliSrc);
179
+ const distStat = fs.statSync(cliDist);
180
+
181
+ if (srcStat.mtime > distStat.mtime) {
182
+ error('src/cli.ts is newer than dist/cli.js!');
183
+ error('Source modified: ' + srcStat.mtime.toISOString());
184
+ error('Build created: ' + distStat.mtime.toISOString());
185
+ error('Run: npm run build');
186
+ hasErrors = true;
187
+ return false;
188
+ }
189
+
190
+ success('dist/cli.js is up-to-date');
191
+
192
+ // Also check commands directory
193
+ const srcCommandsDir = path.join(srcDir, 'commands');
194
+ const distCommandsDir = path.join(distDir, 'commands');
195
+
196
+ if (!fs.existsSync(srcCommandsDir)) {
197
+ warning('src/commands/ directory not found');
198
+ return true;
199
+ }
200
+
201
+ const srcFiles = fs.readdirSync(srcCommandsDir)
202
+ .filter(f => f.endsWith('.ts'));
203
+
204
+ let staleFound = false;
205
+
206
+ for (const file of srcFiles) {
207
+ const srcPath = path.join(srcCommandsDir, file);
208
+ const distPath = path.join(distCommandsDir, file.replace('.ts', '.js'));
209
+
210
+ if (!fs.existsSync(distPath)) {
211
+ warning(`${file} not built yet`);
212
+ continue;
213
+ }
214
+
215
+ const srcStat = fs.statSync(srcPath);
216
+ const distStat = fs.statSync(distPath);
217
+
218
+ if (srcStat.mtime > distStat.mtime) {
219
+ error(`src/commands/${file} is newer than built version!`);
220
+ staleFound = true;
221
+ hasErrors = true;
222
+ }
223
+ }
224
+
225
+ if (staleFound) {
226
+ error('Stale build detected! Run: npm run build');
227
+ return false;
228
+ }
229
+
230
+ success('All dist/commands/ files are up-to-date');
231
+ return true;
232
+ }
233
+
234
+ /**
235
+ * Check 5: Verify package.json version matches published
236
+ */
237
+ function checkVersionSync() {
238
+ info('Check 5: Checking version synchronization...');
239
+
240
+ const packagePath = path.join(rootDir, 'package.json');
241
+ const packageData = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
242
+
243
+ const currentVersion = packageData.version;
244
+ success(`Current package.json version: ${currentVersion}`);
245
+
246
+ // Note: We can't check npm registry without network call
247
+ // Just warn the user to verify
248
+ warning('Remember to verify this matches your last published version');
249
+ warning('Check with: npm view faf-cli version');
250
+
251
+ return true;
252
+ }
253
+
254
+ /**
255
+ * Check 6: Verify critical imports exist
256
+ */
257
+ function checkCriticalImports() {
258
+ info('Check 6: Verifying critical imports...');
259
+
260
+ const criticalPaths = [
261
+ 'dist/commands/index.js',
262
+ 'dist/commands/init.js',
263
+ 'dist/commands/score.js',
264
+ 'dist/commands/status.js',
265
+ 'dist/utils/native-cli-parser.js',
266
+ 'dist/fix-once/commander.js',
267
+ 'dist/fix-once/colors.js'
268
+ ];
269
+
270
+ let allExist = true;
271
+
272
+ for (const relativePath of criticalPaths) {
273
+ const fullPath = path.join(rootDir, relativePath);
274
+ if (!fs.existsSync(fullPath)) {
275
+ error(`Critical file missing: ${relativePath}`);
276
+ hasErrors = true;
277
+ allExist = false;
278
+ } else {
279
+ success(`${relativePath} āœ“`);
280
+ }
281
+ }
282
+
283
+ return allExist;
284
+ }
285
+
286
+ /**
287
+ * Main verification
288
+ */
289
+ function main() {
290
+ log('\nšŸŽļø FAF Build Verification - Championship Grade', 'cyan');
291
+ log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n', 'cyan');
292
+
293
+ // Run all checks
294
+ const distExists = checkDistExists();
295
+ console.log();
296
+
297
+ if (!distExists) {
298
+ log('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'red');
299
+ error('Build verification FAILED!');
300
+ error('Fix the errors above and try again');
301
+ log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n', 'red');
302
+ process.exit(1);
303
+ }
304
+
305
+ const commands = extractCommandsFromSource();
306
+ console.log();
307
+
308
+ verifyCommandsInDist(commands);
309
+ console.log();
310
+
311
+ checkDistFreshness();
312
+ console.log();
313
+
314
+ checkCriticalImports();
315
+ console.log();
316
+
317
+ checkVersionSync();
318
+ console.log();
319
+
320
+ // Final result
321
+ if (hasErrors) {
322
+ log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'red');
323
+ error('Build verification FAILED! āŒ');
324
+ error('Fix the errors above before publishing');
325
+ log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n', 'red');
326
+ process.exit(1);
327
+ } else {
328
+ log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', 'green');
329
+ success('Build verification PASSED! āœ…');
330
+ success('Safe to publish to npm');
331
+ log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n', 'green');
332
+
333
+ // Helpful next steps
334
+ info('Next steps:');
335
+ console.log(' 1. npm version patch # Bump to 2.4.15');
336
+ console.log(' 2. npm publish # Push to npm');
337
+ console.log(' 3. npm install -g faf-cli@latest # Update global');
338
+ console.log(' 4. faf index # Test it works!\n');
339
+ }
340
+ }
341
+
342
+ // Run verification
343
+ main();
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * šŸŽÆ VERSION SANITY CHECKER
4
+ * Never get surprised by version conflicts again!
5
+ */
6
+
7
+ const { execSync } = require('child_process');
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ console.log('šŸ” VERSION CHECK - No more surprises!\n');
12
+
13
+ // 1. Get local version
14
+ const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8'));
15
+ const localVersion = packageJson.version;
16
+
17
+ // 2. Get npm registry version
18
+ let npmVersion;
19
+ try {
20
+ npmVersion = execSync('npm view faf-cli version', { encoding: 'utf8' }).trim();
21
+ } catch (e) {
22
+ console.log('āš ļø Package not found on npm (first publish?)');
23
+ npmVersion = '0.0.0';
24
+ }
25
+
26
+ // 3. Get all published versions
27
+ let allVersions;
28
+ try {
29
+ allVersions = JSON.parse(execSync('npm view faf-cli versions --json', { encoding: 'utf8' }));
30
+ } catch (e) {
31
+ allVersions = [];
32
+ }
33
+
34
+ // 4. THE TRUTH
35
+ console.log('šŸ“Š VERSION REALITY CHECK:');
36
+ console.log('─────────────────────────');
37
+ console.log(`šŸ“ LOCAL (package.json): v${localVersion}`);
38
+ console.log(`ā˜ļø NPM LATEST: v${npmVersion}`);
39
+ console.log(`šŸ“š LAST 5 PUBLISHED: ${allVersions.slice(-5).join(', ')}`);
40
+ console.log('');
41
+
42
+ // 5. CONFLICT DETECTION
43
+ let hasConflict = false;
44
+ if (localVersion === npmVersion) {
45
+ console.log('āŒ CONFLICT: Local version matches npm!');
46
+ console.log(' You need to bump version before publishing:');
47
+ console.log(' → npm version patch');
48
+ console.log('');
49
+ hasConflict = true;
50
+ } else if (allVersions.includes(localVersion)) {
51
+ console.log('āŒ CONFLICT: Version already exists on npm!');
52
+ console.log(` v${localVersion} was already published`);
53
+ console.log(' → npm version patch');
54
+ console.log('');
55
+ hasConflict = true;
56
+ } else {
57
+ console.log('āœ… CLEAR: Ready to publish!');
58
+ console.log(` Will publish as v${localVersion}`);
59
+ console.log('');
60
+ }
61
+
62
+ // 6. SUGGESTED NEXT VERSION
63
+ const parts = npmVersion.split('.');
64
+ const suggestedPatch = `${parts[0]}.${parts[1]}.${parseInt(parts[2]) + 1}`;
65
+ const suggestedMinor = `${parts[0]}.${parseInt(parts[1]) + 1}.0`;
66
+ const suggestedMajor = `${parseInt(parts[0]) + 1}.0.0`;
67
+
68
+ console.log('šŸ“ˆ SUGGESTED VERSIONS:');
69
+ console.log(` Patch: v${suggestedPatch} (bug fixes)`)
70
+ console.log(` Minor: v${suggestedMinor} (new features)`);
71
+ console.log(` Major: v${suggestedMajor} (breaking changes)`);
72
+ console.log('');
73
+ console.log('šŸ’” Run: npm version patch|minor|major');
74
+
75
+ // Exit with error if conflict
76
+ if (hasConflict) {
77
+ process.exit(1);
78
+ }