faf-taf-git 2.0.4

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 (47) hide show
  1. package/.faf +126 -0
  2. package/.faf-dna +95 -0
  3. package/.fafignore +41 -0
  4. package/.taf +21 -0
  5. package/CHANGELOG.md +208 -0
  6. package/CLAUDE.md +30 -0
  7. package/CONTRIBUTING.md +286 -0
  8. package/LICENSE +21 -0
  9. package/README.md +496 -0
  10. package/action.yml +42 -0
  11. package/dist/bundle/index.js +36554 -0
  12. package/dist/cli.d.ts +31 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +380 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/index.d.ts +7 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +36560 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/licenses.txt +148 -0
  21. package/dist/main.d.ts +7 -0
  22. package/dist/main.d.ts.map +1 -0
  23. package/dist/main.js +147 -0
  24. package/dist/main.js.map +1 -0
  25. package/dist/parsers/jest.d.ts +38 -0
  26. package/dist/parsers/jest.d.ts.map +1 -0
  27. package/dist/parsers/jest.js +87 -0
  28. package/dist/parsers/jest.js.map +1 -0
  29. package/dist/sourcemap-register.js +1 -0
  30. package/dist/taf-core.d.ts +12 -0
  31. package/dist/taf-core.d.ts.map +1 -0
  32. package/dist/taf-core.js +136 -0
  33. package/dist/taf-core.js.map +1 -0
  34. package/docs/RELEASE-NOTES.md +200 -0
  35. package/docs/USER-GUIDE.md +301 -0
  36. package/jest.config.js +13 -0
  37. package/package.json +47 -0
  38. package/project.faf +259 -0
  39. package/src/cli.ts +393 -0
  40. package/src/index.ts +131 -0
  41. package/src/parsers/jest.ts +104 -0
  42. package/src/taf-core.ts +139 -0
  43. package/test-mcp.ts +83 -0
  44. package/test-standalone.ts +87 -0
  45. package/tests/jest-parser.test.ts +122 -0
  46. package/tests/wjttc-taf.test.ts +470 -0
  47. package/tsconfig.json +18 -0
package/project.faf ADDED
@@ -0,0 +1,259 @@
1
+ faf_version: 2.5.0
2
+ ai_scoring_system: 2025-09-20
3
+ ai_score: 65%
4
+ ai_confidence: MODERATE
5
+ ai_value: 30_seconds_replaces_20_minutes_of_questions
6
+ ai_tldr:
7
+ project: faf-taf-git v2.0.4 - Git-tracked testing timelines for ANY CI/CD
8
+ stack: TypeScript CLI + GitHub Action (pre-capture architecture)
9
+ quality_bar: ZERO_ERRORS_F1_STANDARDS
10
+ status: PRODUCTION_READY (working in faf-cli repo)
11
+ breakthrough: v2.0.0 pre-capture pattern (tested 19 methods before this)
12
+ current_focus: Ecosystem adoption and user onboarding
13
+ your_role: Support users, fix bugs, add test framework support
14
+ instant_context:
15
+ what_building: Platform-agnostic CLI + GitHub Action for TAF updates
16
+ tech_stack: TypeScript
17
+ main_language: TypeScript
18
+ deployment: npm + GitHub Actions Marketplace
19
+ architecture: v2.0.0 pre-capture pattern (separate test execution from receipt generation)
20
+ use_cases: Standalone CLI, GitHub Action, GitLab CI, Jenkins, CircleCI, Local
21
+ development
22
+ test_support: Jest (fully supported) with plans for Mocha, Vitest, Pytest, Go
23
+ test, Rust cargo
24
+ golden_triangle: .faf (project DNA) + repo (code) + .taf (test proof)
25
+ key_files:
26
+ - src/index.ts (v2.0.0 rewrite - reads test output file)
27
+ - src/parsers/jest.ts (v2.0.4 fix - correct pattern matching)
28
+ - src/taf-core.ts (MCP-portable core)
29
+ - action.yml (v2.0.2 fix - correct bundle path)
30
+ - README.md (6Ws format)
31
+ - CHANGELOG.md (22 versions documented)
32
+ documentation:
33
+ - README: 6Ws format (What/Who/Why/Where/When/How)
34
+ - CHANGELOG: Complete debugging journey (v1.0.4 โ†’ v2.0.4)
35
+ - Migration guide: v1.x โ†’ v2.x breaking changes
36
+ context_quality:
37
+ slots_filled: 11/21 (52%)
38
+ ai_confidence: MODERATE
39
+ handoff_ready: true
40
+ missing_context: []
41
+ project:
42
+ name: faf-taf-git
43
+ goal: Platform-agnostic TAF (Testing Activity Feed) updater - works in ANY CI/CD
44
+ innovation: On-the-fly Testing Audit Files - Unheard of in CI/CD
45
+ taf_meaning:
46
+ file: Testing Audit File (.taf)
47
+ feed: Testing Activity Feed (live updates)
48
+ main_language: TypeScript
49
+ type: typescript
50
+ generated: 2025-10-28T01:26:05.656Z
51
+ repository: https://github.com/Wolfe-Jam/faf-taf-git
52
+ license: MIT
53
+ author: wolfejam
54
+ keywords: testing, taf, ci-cd, github-actions, gitlab-ci, platform-agnostic,
55
+ jest, faf, git
56
+ mission: ๐Ÿš€ Make Your AI Happy! ๐Ÿงก Trust-Driven ๐Ÿค–
57
+ revolution: 30 seconds replaces 20 minutes of questions
58
+ brand: F1-Inspired Software Engineering - Championship AI Context
59
+ ai_instructions:
60
+ priority_order:
61
+ - 1. Read THIS .faf file first
62
+ - 2. Check CLAUDE.md for session context
63
+ - 3. Review package.json for dependencies
64
+ working_style:
65
+ code_first: true
66
+ explanations: minimal
67
+ quality_bar: zero_errors
68
+ testing: required
69
+ warnings:
70
+ - Never modify dial components without approval
71
+ - All TypeScript must pass strict mode
72
+ - Test coverage required for new features
73
+ stack:
74
+ frontend: None
75
+ css_framework: None
76
+ ui_library: None
77
+ state_management: None
78
+ backend: None
79
+ runtime: Node.js
80
+ database: None
81
+ build: TypeScript Compiler
82
+ package_manager: npm
83
+ api_type: REST
84
+ hosting: npm Registry
85
+ cicd: GitHub Actions
86
+ targetUser: developers
87
+ coreProblem: understanding project
88
+ missionPurpose: project documentation
89
+ packageManager: npm/yarn/pnpm
90
+ mainLanguage: JavaScript/TypeScript
91
+ cli_features:
92
+ commands:
93
+ - npx faf-taf-git
94
+ - --file (test output file - v2.0.0+)
95
+ - --command (custom test command - legacy v1.x)
96
+ - --commit (auto-commit .taf changes)
97
+ - --verbose (detailed output)
98
+ - --message (custom commit message)
99
+ - --cwd (working directory)
100
+ github_action_inputs:
101
+ test-output-file: required (v2.0.0+)
102
+ auto-commit: true (default)
103
+ commit-message: "chore(taf): update .taf receipt [skip ci] (default)"
104
+ architecture:
105
+ version: v2.0.0
106
+ pattern: pre-capture
107
+ breakthrough: Separate test execution from receipt generation
108
+ why: Avoids GitHub Actions execution context corruption
109
+ reliability: Tested 19 methods before this solution
110
+ benefits:
111
+ - More reliable (no execution context issues)
112
+ - Platform-agnostic (works everywhere)
113
+ - Simpler (400+ lines removed, 11KB smaller)
114
+ test_frameworks:
115
+ - Jest (fully supported)
116
+ supported_platforms:
117
+ - GitHub Actions
118
+ - GitLab CI
119
+ - Bitbucket Pipelines
120
+ - Jenkins
121
+ - CircleCI
122
+ - Travis CI
123
+ - Azure Pipelines
124
+ - Local development
125
+ taf_format:
126
+ format: YAML
127
+ file_location: .taf (hidden dotfile)
128
+ purpose: Git-tracked testing timeline - permanent proof your code works
129
+ links_to_faf: true
130
+ snapshots_faf_score: true
131
+ closed_loop_system: .faf (DNA) + repo (code) + .taf (proof) = Golden Triangle
132
+ deployment:
133
+ npm_package: faf-taf-git@2.0.4
134
+ github_action: Wolfe-Jam/faf-taf-git@v2.0.4
135
+ marketplaces:
136
+ - npm Registry
137
+ - GitHub Actions Marketplace
138
+ install: npx faf-taf-git
139
+ production_users:
140
+ - faf-cli (working in CI)
141
+ testing:
142
+ framework: Jest
143
+ coverage: Core functionality
144
+ ci_integration: GitHub Actions
145
+ test_files:
146
+ - tests/ (unit tests)
147
+ quality_gates:
148
+ - All tests must pass
149
+ - TypeScript strict mode
150
+ - Zero build errors
151
+ examples:
152
+ github_actions: README.md Quick Start section
153
+ standalone_cli: README.md Standalone CLI section
154
+ gitlab_ci: README.md GitLab CI section
155
+ jenkins: README.md Jenkins section
156
+ migration: README.md Migration from v1.x section
157
+ performance:
158
+ bundle_size: 1.2MB (v2.0.0 - reduced 11KB from v1.x)
159
+ startup_time: <100ms
160
+ parse_time: <10ms for typical Jest output
161
+ reliability: 100% success rate in faf-cli CI (after v2.0.4)
162
+ preferences:
163
+ quality_bar: zero_errors
164
+ commit_style: conventional_emoji
165
+ response_style: concise_code_first
166
+ explanation_level: minimal
167
+ communication: direct
168
+ testing: required
169
+ documentation: as_needed
170
+ contributing:
171
+ guidelines: CONTRIBUTING.md
172
+ code_style: TypeScript strict mode
173
+ pr_process: Fork, branch, PR with tests
174
+ commit_format: Conventional commits with Co-Authored-By
175
+ testing_required: true
176
+ documentation_required: For new features
177
+ resources:
178
+ readme: README.md (6Ws format)
179
+ changelog: CHANGELOG.md (22 versions documented)
180
+ license: MIT
181
+ repository: https://github.com/Wolfe-Jam/faf-taf-git
182
+ npm: https://npmjs.com/package/faf-taf-git
183
+ issues: https://github.com/Wolfe-Jam/faf-taf-git/issues
184
+ discussions: https://github.com/Wolfe-Jam/faf/discussions
185
+ state:
186
+ phase: production
187
+ version: 2.0.4
188
+ focus: ecosystem_adoption
189
+ status: production_ready
190
+ achievements:
191
+ - v2.0.0 architectural redesign (pre-capture pattern)
192
+ - v2.0.4 parser fix (working in CI)
193
+ - Updated README (6Ws format)
194
+ - Updated CHANGELOG (22 versions documented)
195
+ - TAF Receipt generating successfully in faf-cli repo
196
+ next_milestone: user_adoption
197
+ blockers: null
198
+ tags:
199
+ auto_generated:
200
+ - faf-taf-action
201
+ - none
202
+ - typescript
203
+ smart_defaults:
204
+ - .faf
205
+ - ai-ready
206
+ - "2025"
207
+ - software
208
+ - open-source
209
+ user_defined: null
210
+ human_context:
211
+ who: Development teams
212
+ what: TAF file updates in CI/CD pipelines
213
+ why: Improve development efficiency
214
+ where: Any CI/CD platform (GitHub, GitLab, Bitbucket)
215
+ when: During CI/CD test runs
216
+ how: Test-driven development
217
+ additional_context: Part of Golden Triangle (.faf + repo + .taf). Tracks test
218
+ runs permanently in git. Supports Jest, works as CLI or GitHub Action.
219
+ Platform-agnostic core - runs on ANY CI/CD with Node.js.
220
+ context_score: 0
221
+ total_prd_score: 65
222
+ success_rate: 50%
223
+ scores:
224
+ faf_score: 50
225
+ slot_based_percentage: 52
226
+ ai_score: 65
227
+ total_slots: 21
228
+ filled_slots: 11
229
+ scoring_method: Honest percentage - no fake minimums
230
+ trust_embedded: COUNT ONCE architecture - trust MY embedded scores
231
+ ai_scoring_details:
232
+ system_date: 2025-09-20
233
+ slot_based_percentage: 52
234
+ ai_score: 65
235
+ total_slots: 21
236
+ filled_slots: 11
237
+ scoring_method: Honest percentage - no fake minimums
238
+ trust_embedded: COUNT ONCE architecture - trust MY embedded scores
239
+ faf_dna:
240
+ birth_dna: 22
241
+ birth_certificate: FAF-2025-FAFTAFAC-TMZU
242
+ birth_date: 2025-10-28T01:26:05.692Z
243
+ current_score: 50
244
+ projectName: faf-taf-git
245
+ projectGoal: Platform-agnostic TAF (Testing Activity Feed) updater - works in ANY CI/CD
246
+ generated: 2026-02-17T20:14:09.215Z
247
+ last_major_update: v2.0.4 (2026-02-17)
248
+ production_status: Working in faf-cli repository
249
+ stack_signature: typescript-nodejs-javascript
250
+ detected_frameworks:
251
+ - Claude Code
252
+ - Jest
253
+ - Node.js
254
+ - JavaScript
255
+ - TypeScript
256
+ turbo_cat_intelligence: 260
257
+ stats:
258
+ last_auto_time: 0.6
259
+ times_run: 1
package/src/cli.ts ADDED
@@ -0,0 +1,393 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * faf-taf-git - Standalone CLI for TAF operations
4
+ *
5
+ * Platform-agnostic core that works in ANY CI/CD environment
6
+ * Can be used standalone or as a library by wrappers
7
+ */
8
+
9
+ import * as exec from '@actions/exec';
10
+ import * as fs from 'fs';
11
+ import * as os from 'os';
12
+ import * as path from 'path';
13
+ import { parseJestOutput } from './parsers/jest';
14
+ import { updateTafFile } from './taf-core';
15
+
16
+ export interface CLIOptions {
17
+ command?: string;
18
+ autoCommit?: boolean;
19
+ commitMessage?: string;
20
+ cwd?: string;
21
+ verbose?: boolean;
22
+ logger?: (message: string) => void;
23
+ }
24
+
25
+ export interface CLIResult {
26
+ success: boolean;
27
+ testResults?: {
28
+ total: number;
29
+ passed: number;
30
+ failed: number;
31
+ result: string;
32
+ };
33
+ tafUpdated: boolean;
34
+ error?: string;
35
+ }
36
+
37
+ /**
38
+ * Main CLI function - platform-agnostic
39
+ * Can be called from GitHub Actions, GitLab CI, or standalone
40
+ */
41
+ export async function runTafGit(options: CLIOptions = {}): Promise<CLIResult> {
42
+ const {
43
+ command = 'npm test',
44
+ autoCommit = false,
45
+ commitMessage = 'chore: update .taf with test results',
46
+ cwd = process.cwd(),
47
+ verbose = false,
48
+ logger = console.log,
49
+ } = options;
50
+
51
+ try {
52
+ if (verbose) console.log(`Running test command: ${command}`);
53
+
54
+ // Run tests and capture output using @actions/exec
55
+ let output = '';
56
+ let exitCode = 0;
57
+
58
+ try {
59
+ // Parse command into executable and args
60
+ // For "npm test" -> ["npm", "test"]
61
+ const commandParts = command.split(' ');
62
+ const executable = commandParts[0];
63
+ const args = commandParts.slice(1);
64
+
65
+ const options: exec.ExecOptions = {
66
+ cwd,
67
+ silent: false, // Show output in logs
68
+ ignoreReturnCode: true // Don't throw on non-zero exit
69
+ };
70
+
71
+ // --- [START NUCLEAR CANARY] ---
72
+ // Use getExecOutput to capture stdout/stderr
73
+ const result = await exec.getExecOutput(executable, args, options);
74
+
75
+ // THE NUCLEAR CANARY: Write directly to disk, bypassing stdout/stderr streams
76
+ // Write to MULTIPLE locations to ensure we find it!
77
+ const canaryContent = [
78
+ `=========================================`,
79
+ `TAF DEBUG CANARY REPORT`,
80
+ `Timestamp: ${new Date().toISOString()}`,
81
+ `CWD: ${cwd}`,
82
+ `Process CWD: ${process.cwd()}`,
83
+ `=========================================`,
84
+ `Exit Code: ${result.exitCode}`,
85
+ `Stdout Length: ${result.stdout.length}`,
86
+ `Stderr Length: ${result.stderr.length}`,
87
+ `-----------------------------------------`,
88
+ `STDOUT PREVIEW (First 500 chars):`,
89
+ `${result.stdout.substring(0, 500)}`,
90
+ `-----------------------------------------`,
91
+ `STDERR PREVIEW (First 500 chars):`,
92
+ `${result.stderr.substring(0, 500)}`,
93
+ `=========================================`
94
+ ].join('\n');
95
+
96
+ try {
97
+ // Try multiple locations!
98
+ const locations = [
99
+ path.join(cwd, 'TAF_DEBUG_CANARY.txt'), // Original cwd
100
+ path.join(process.cwd(), 'TAF_DEBUG_CANARY.txt'), // Process cwd
101
+ path.join(os.tmpdir(), 'TAF_DEBUG_CANARY.txt'), // OS temp directory
102
+ 'TAF_DEBUG_CANARY.txt' // Current directory
103
+ ];
104
+
105
+ let writeSuccess = false;
106
+ for (const loc of locations) {
107
+ try {
108
+ fs.writeFileSync(loc, canaryContent);
109
+ writeSuccess = true;
110
+ } catch (e) {
111
+ // Try next location
112
+ }
113
+ }
114
+
115
+ if (!writeSuccess) {
116
+ throw new Error('CRITICAL: Failed to write canary to ANY location!');
117
+ }
118
+ } catch (fsError: any) {
119
+ // If we can't write to disk, we are truly doomed
120
+ throw new Error(`CRITICAL: Failed to write canary file: ${fsError.message}`);
121
+ }
122
+
123
+ // Continue with original logic
124
+ exitCode = result.exitCode;
125
+ output = result.stdout + result.stderr;
126
+ // --- [END NUCLEAR CANARY] ---
127
+ } catch (error: any) {
128
+ exitCode = 1;
129
+ if (verbose) {
130
+ logger(`Test command failed with error: ${error.message}`);
131
+ logger(`Captured output length: ${output.length} bytes`);
132
+ }
133
+ }
134
+
135
+ // Debug: Write entire output to file for inspection
136
+ if (verbose) {
137
+ try {
138
+ const fs = require('fs');
139
+ const debugPath = path.join(os.tmpdir(), 'taf-debug-output.txt');
140
+ fs.writeFileSync(debugPath, output);
141
+ logger(`DEBUG: Wrote ${output.length} bytes to ${debugPath}`);
142
+ const lines = output.split('\n');
143
+ const testLine = lines.find(l => l.includes('Tests:'));
144
+ logger(`DEBUG: Output has ${lines.length} lines, Found "Tests:": ${testLine ? 'YES' : 'NO'}`);
145
+ if (testLine) {
146
+ logger(`DEBUG: Tests line: "${testLine}"`);
147
+ } else {
148
+ logger(`DEBUG: Last 10 lines of output:`);
149
+ lines.slice(-10).forEach((line, i) => {
150
+ logger(` ${i}: ${line.substring(0, 100)}`);
151
+ });
152
+ }
153
+ } catch (err) {
154
+ logger(`DEBUG: Error writing debug file: ${err}`);
155
+ }
156
+ }
157
+
158
+ // Parse test output
159
+ const testResults = parseJestOutput(output);
160
+
161
+ if (!testResults) {
162
+ if (verbose) {
163
+ logger(`DEBUG: Parser returned null`);
164
+ logger(`DEBUG: Output sample (first 500 chars): ${output.slice(0, 500)}`);
165
+ logger(`DEBUG: Output sample (last 500 chars): ${output.slice(-500)}`);
166
+ }
167
+ return {
168
+ success: false,
169
+ tafUpdated: false,
170
+ error: 'Could not parse test output. Ensure you are using Jest.',
171
+ };
172
+ }
173
+
174
+ if (verbose) {
175
+ logger(`Parsed results: ${testResults.passed}/${testResults.total} tests passing`);
176
+ }
177
+
178
+ // Check if .taf file exists
179
+ const tafPath = path.join(cwd, '.taf');
180
+ if (!fs.existsSync(tafPath)) {
181
+ return {
182
+ success: false,
183
+ testResults: {
184
+ total: testResults.total,
185
+ passed: testResults.passed,
186
+ failed: testResults.failed,
187
+ result: testResults.result,
188
+ },
189
+ tafUpdated: false,
190
+ error: 'No .taf file found. Run `faf taf init` to create one.',
191
+ };
192
+ }
193
+
194
+ // Update .taf file
195
+ const updated = await updateTafFile(tafPath, testResults);
196
+
197
+ if (updated) {
198
+ if (verbose) logger('โœ… .taf file updated successfully');
199
+
200
+ // Commit changes if enabled
201
+ if (autoCommit) {
202
+ await commitTafUpdate(cwd, commitMessage, verbose, logger);
203
+ if (verbose) logger('โœ… Changes committed to git');
204
+ }
205
+
206
+ return {
207
+ success: true,
208
+ testResults: {
209
+ total: testResults.total,
210
+ passed: testResults.passed,
211
+ failed: testResults.failed,
212
+ result: testResults.result,
213
+ },
214
+ tafUpdated: true,
215
+ };
216
+ } else {
217
+ return {
218
+ success: false,
219
+ testResults: {
220
+ total: testResults.total,
221
+ passed: testResults.passed,
222
+ failed: testResults.failed,
223
+ result: testResults.result,
224
+ },
225
+ tafUpdated: false,
226
+ error: '.taf file was not updated',
227
+ };
228
+ }
229
+ } catch (error) {
230
+ return {
231
+ success: false,
232
+ tafUpdated: false,
233
+ error: error instanceof Error ? error.message : 'Unknown error occurred',
234
+ };
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Commit .taf file changes to git (platform-agnostic)
240
+ */
241
+ async function commitTafUpdate(cwd: string, message: string, verbose: boolean, logger: (msg: string) => void = console.log): Promise<void> {
242
+ try {
243
+ const execOptions: exec.ExecOptions = { cwd };
244
+
245
+ // Configure git if needed
246
+ await exec.exec('git', ['config', '--global', 'user.name', 'faf-taf-git[bot]'], execOptions);
247
+ await exec.exec('git', ['config', '--global', 'user.email', 'faf-taf-git[bot]@users.noreply.github.com'], execOptions);
248
+
249
+ // Stage .taf file
250
+ await exec.exec('git', ['add', '.taf'], execOptions);
251
+
252
+ // Check if there are changes to commit
253
+ let diffOutput = '';
254
+ const diffOptions: exec.ExecOptions = {
255
+ cwd,
256
+ listeners: {
257
+ stdout: (data: Buffer) => {
258
+ diffOutput += data.toString();
259
+ }
260
+ }
261
+ };
262
+ await exec.exec('git', ['diff', '--cached', '--name-only'], diffOptions);
263
+
264
+ if (diffOutput.trim().length > 0) {
265
+ await exec.exec('git', ['commit', '-m', message], execOptions);
266
+
267
+ // Try to push (might fail in some environments, that's ok)
268
+ try {
269
+ await exec.exec('git', ['push'], execOptions);
270
+ } catch (error) {
271
+ if (verbose) {
272
+ logger('Could not push changes (this is ok in some CI environments)');
273
+ }
274
+ }
275
+ } else {
276
+ if (verbose) logger('No changes to commit');
277
+ }
278
+ } catch (error) {
279
+ if (verbose) {
280
+ logger(`Error committing changes: ${error}`);
281
+ }
282
+ throw error;
283
+ }
284
+ }
285
+
286
+ /**
287
+ * CLI entry point - parse args and run
288
+ */
289
+ async function main() {
290
+ const args = process.argv.slice(2);
291
+
292
+ const options: CLIOptions = {
293
+ verbose: args.includes('--verbose') || args.includes('-v'),
294
+ };
295
+
296
+ // Parse command flag
297
+ const commandIndex = args.indexOf('--command');
298
+ if (commandIndex !== -1 && args[commandIndex + 1]) {
299
+ options.command = args[commandIndex + 1];
300
+ }
301
+
302
+ // Parse auto-commit flag
303
+ if (args.includes('--commit')) {
304
+ options.autoCommit = true;
305
+ }
306
+
307
+ // Parse commit message
308
+ const messageIndex = args.indexOf('--message');
309
+ if (messageIndex !== -1 && args[messageIndex + 1]) {
310
+ options.commitMessage = args[messageIndex + 1];
311
+ }
312
+
313
+ // Parse working directory
314
+ const cwdIndex = args.indexOf('--cwd');
315
+ if (cwdIndex !== -1 && args[cwdIndex + 1]) {
316
+ options.cwd = args[cwdIndex + 1];
317
+ }
318
+
319
+ // Show help
320
+ if (args.includes('--help') || args.includes('-h')) {
321
+ console.log(`
322
+ faf-taf-git - Platform-agnostic TAF updater
323
+
324
+ USAGE:
325
+ npx faf-taf-git [OPTIONS]
326
+
327
+ OPTIONS:
328
+ --command <cmd> Test command to run (default: npm test)
329
+ --commit Auto-commit .taf changes to git
330
+ --message <msg> Custom commit message
331
+ --cwd <dir> Working directory (default: current)
332
+ --verbose, -v Verbose output
333
+ --help, -h Show this help
334
+
335
+ EXAMPLES:
336
+ # Run tests and update .taf
337
+ npx faf-taf-git
338
+
339
+ # Custom test command
340
+ npx faf-taf-git --command "npm run test:unit"
341
+
342
+ # Auto-commit changes
343
+ npx faf-taf-git --commit
344
+
345
+ # Custom commit message
346
+ npx faf-taf-git --commit --message "test: update TAF"
347
+
348
+ # Verbose mode
349
+ npx faf-taf-git --verbose
350
+
351
+ PLATFORM SUPPORT:
352
+ โœ… GitHub Actions
353
+ โœ… GitLab CI
354
+ โœ… Bitbucket Pipelines
355
+ โœ… Jenkins
356
+ โœ… CircleCI
357
+ โœ… Local development
358
+ โœ… Any CI/CD that runs Node.js
359
+
360
+ LEARN MORE:
361
+ https://github.com/Wolfe-Jam/faf-taf-git
362
+ `);
363
+ process.exit(0);
364
+ }
365
+
366
+ // Run the tool
367
+ const result = await runTafGit(options);
368
+
369
+ if (result.success) {
370
+ if (result.testResults) {
371
+ console.log(`โœ… Tests: ${result.testResults.passed}/${result.testResults.total} passing`);
372
+ console.log(`โœ… Result: ${result.testResults.result}`);
373
+ }
374
+ if (result.tafUpdated) {
375
+ console.log('โœ… .taf file updated');
376
+ }
377
+ process.exit(0);
378
+ } else {
379
+ console.error(`โŒ Error: ${result.error}`);
380
+ if (result.testResults) {
381
+ console.log(`Tests: ${result.testResults.passed}/${result.testResults.total} passing`);
382
+ }
383
+ process.exit(1);
384
+ }
385
+ }
386
+
387
+ // Run CLI if called directly
388
+ if (require.main === module) {
389
+ main().catch((error) => {
390
+ console.error('Fatal error:', error);
391
+ process.exit(1);
392
+ });
393
+ }