
Security News
Happy Birthday, Shai-Hulud
It has been one year since Shai-Hulud made its first appearance on npm.
faf-taf-git
Advanced tools
A Test Receipt Printer for git. Every CI run prints a receipt to .taf — append-only, timestamped, cannot be gamed. Proof over time.
Anyone can get green once. TAF proves it over time — an append-only Test Receipt on every CI run, git-anchored and cannot be gamed. Solid engineering shows in the timeline; everything else gets exposed.
TAF — Testing AI Format. Sibling of FAF, independent. The Test Receipt Printer for git.
Q: What does TAF do? A: It prints Receipts. Q: What sort of Receipts? A: Test Receipts. Q: Why do I need Test Receipts? A: Proof over time.
Bonus: Cannot be gamed.
TAF is a Receipt Printer for git. Every CI run prints a receipt to .taf. The receipts accumulate on a git branch. The history is append-only. The proof is permanent.
Works on any git repo. No FAF required. TAF is a standalone product — install the action, get receipts. FAF integration is one of TAF's use cases (see below), not a precondition.
npm: faf-taf-git · action: Wolfe-Jam/faf-taf-git
A Test Receipt Printer for git. Every CI run produces one receipt — timestamp, counts, result, trigger — appended to .taf on the taf-receipts branch. The timeline is the proof.
Example Test Receipt:
- timestamp: 2026-02-17T19:12:14.810Z
result: PASSED
tests:
total: 808
passed: 799
failed: 0
skipped: 9
trigger: github-actions
Every field maps to a real receipt: timestamp = receipt date, tests = itemized lines, result = total, trigger = cashier/register, run_id = receipt number, project = vendor, format_version = receipt template.
📄 Full receipt schema: RECEIPT-FORMAT.md — the pinned .taf format (fields, the cannot-be-gamed mechanism, where it fits vs JUnit/TAP/SLSA).
What you get:
For development teams who need:
.faf project DNA)Use cases:
Tests run, results disappear. No permanent record. No accountability.
Before:
✅ Tests passing (right now)
❓ Were they passing yesterday?
❓ When did that flaky test start failing?
❓ What's the trend over time?
After (with .taf):
✅ Tests passing (tracked in git)
✅ History shows: 99% pass rate over 30 days
✅ Flaky test identified: started failing Feb 10
✅ Trend: improving (was 85%, now 99%)
Git-native receipts. Every test run becomes a permanent, auditable record.
.taf is software accountability - proof that your code works, tracked over time, visible to everyone.
Works in ANY CI/CD environment that runs Node.js:
| Platform | Status | Example |
|---|---|---|
| GitHub Actions | ✅ Tested | See Quick Start |
| GitLab CI | ✅ Tested | npx faf-taf-git --commit |
| Jenkins | ✅ Compatible | sh 'npx faf-taf-git --commit' |
| CircleCI | ✅ Compatible | run: npx faf-taf-git --commit |
| Bitbucket Pipelines | ✅ Compatible | npx faf-taf-git --commit |
| Travis CI | ✅ Compatible | npx faf-taf-git --commit |
| Azure Pipelines | ✅ Compatible | npx faf-taf-git --commit |
| Local development | ✅ Works | npm test && npx faf-taf-git |
| Pre-commit hooks | ✅ Works | See Examples |
Architecture: Platform-agnostic core. No CI-specific dependencies. Pure functions.
Use faf-taf-git when you need:
Proof of testing over time
AI-augmented development
.faf format)Debugging flaky tests
Team accountability
Don't use when:
TAF works on any git repo. Adoption requires zero ecosystem buy-in — install the action, you get receipts. Below are the use cases TAF serves today and tomorrow:
| Use Case | What TAF gives you |
|---|---|
| Plain JS/TS projects | Receipt for every Jest or Vitest run, on every CI execution |
| Pytest projects | Receipt for every Python test run (pending pytest parser — v2.2 roadmap) |
| Open source maintainers | "This repo has 1,847 receipts going back 14 months, none missing" |
| Regulated industries (SOC 2, ISO, HIPAA) | Append-only longitudinal evidence — auditors get a tamper-evident timeline, not a snapshot |
| Supply-chain trust | "Prove these tests ran before this artifact shipped" |
| AI-agent verification | "Prove this agent's code passed tests consistently over the last 90 days" |
| Use Case | What TAF gives you |
|---|---|
| FAF-aware projects | Receipts include faf_score, faf_associated, faf_location — the receipt tells you not just did the tests pass, but what was the project's AI-readiness when they ran. Score trends over time become visible. |
| Full CAR Framework | TAF (Receipt) + WJTTC (Audit) + FAF (Claim) — closed-loop attestation: project DNA → testing audit → permanent receipt |
FAF is one tenant among many. TAF is the platform. The receipt printer doesn't care what kind of project prints to it.
Step 1: Create .taf file
npm install -g faf-cli
faf taf init
Step 2: Add to CI workflow
name: Tests
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
permissions:
contents: write # Required for auto-commit
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '24.x'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Run Tests and Capture Output
run: npm test 2>&1 | tee test-output.txt
- name: Generate TAF Receipt
uses: Wolfe-Jam/faf-taf-git@v2.3.0
with:
test-output-file: test-output.txt
auto-commit: 'true'
commit-message: 'chore(taf): update .taf receipt [skip ci]'
Step 3: Push and watch
.taf file updates with new entry# Run tests and update .taf
npm test 2>&1 | tee test-output.txt
npx faf-taf-git --file test-output.txt --commit
# Or in one command (legacy v1.x CLI)
npx faf-taf-git --command "npm test" --commit
test:
script:
- npm ci
- npm test 2>&1 | tee test-output.txt
- npx faf-taf-git --file test-output.txt --commit --message "ci: update .taf [skip ci]"
stage('Test') {
steps {
sh 'npm ci'
sh 'npm test 2>&1 | tee test-output.txt'
sh 'npx faf-taf-git --file test-output.txt --commit'
}
}
# Run tests and update .taf (no commit)
npm test 2>&1 | tee test-output.txt
npx faf-taf-git --file test-output.txt --verbose
# Pre-commit hook
#!/bin/bash
npm test 2>&1 | tee test-output.txt && npx faf-taf-git --file test-output.txt
Step 1: Run Tests Step 2: Generate Receipt
┌─────────────────────┐ ┌──────────────────────┐
│ npm test 2>&1 | │ │ faf-taf-git reads │
│ tee test-output.txt │───────▶│ test-output.txt and │
│ │ │ updates .taf file │
└─────────────────────┘ └──────────────────────┘
Why separate steps?
Process:
npm test 2>&1 | tee test-output.txt| Input | Description | Default | Required |
|---|---|---|---|
test-output-file | Path to file containing test output | - | ✅ Yes |
auto-commit | Automatically commit .taf updates | true | No |
commit-message | Custom commit message | chore(taf): update .taf receipt [skip ci] | No |
| Output | Description | Example |
|---|---|---|
result | Test result | PASSED, FAILED, IMPROVED, DEGRADED |
passed | Number of tests passed | 799 |
failed | Number of tests failed | 0 |
total | Total number of tests | 808 |
skipped | Number of skipped tests | 9 |
taf-updated | Whether .taf was updated | true or false |
npx faf-taf-git [options]
Options:
--file <path> Path to test output file (v2.0.0+)
--command <cmd> Test command to run (legacy v1.x)
--commit Auto-commit .taf changes
--message <msg> Custom commit message
--cwd <dir> Working directory
--verbose, -v Verbose output
--help, -h Show help
| Framework | Status | Notes |
|---|---|---|
| Jest | ✅ Fully supported | All output formats |
| Vitest | ✅ Fully supported | Including todo counts |
| Mocha | ⏳ Planned | - |
| Pytest | ⏳ Planned | - |
| Go test | ⏳ Planned | - |
| Rust cargo test | ⏳ Planned | - |
- name: Generate TAF Receipt
id: taf
uses: Wolfe-Jam/faf-taf-git@v2.3.0
with:
test-output-file: test-output.txt
- name: Check Results
run: |
echo "Result: ${{ steps.taf.outputs.result }}"
echo "Tests: ${{ steps.taf.outputs.passed }}/${{ steps.taf.outputs.total }} passing"
if [ "${{ steps.taf.outputs.result }}" == "DEGRADED" ]; then
echo "⚠️ Test quality degraded!"
exit 1
fi
version: 2.1
jobs:
test:
docker:
- image: node:20
steps:
- checkout
- run: npm ci
- run: npm test 2>&1 | tee test-output.txt
- run: npx faf-taf-git --file test-output.txt --commit
#!/bin/bash
# .git/hooks/pre-commit
# Run tests and capture output
npm test 2>&1 | tee test-output.txt
TEST_EXIT=$?
# Update .taf (don't commit yet - that's what the commit is for!)
npx faf-taf-git --file test-output.txt
# Exit with test status
exit $TEST_EXIT
Projects with .faf + repo + .taf are engineered to succeed:
.faf
(WHAT IT IS)
/ \
/ \
/ \
repo ←→ .taf
(IMPLEMENTATION) (PROOF IT WORKS)
Why this matters:
.faf to understand your project.taf to understand test qualitynpm run build
npm test
npm run package # Creates bundled dist/index.js
npm run build
node dist/cli.js --help
v2.0.0 is a breaking change - the architecture was redesigned for reliability.
v1.x (test-command):
- uses: Wolfe-Jam/faf-taf-git@v1
with:
test-command: npm test
v2.x (test-output-file):
- run: npm test 2>&1 | tee test-output.txt
- uses: Wolfe-Jam/faf-taf-git@v2.3.0
with:
test-output-file: test-output.txt
v1.x ran tests inside the action using @actions/exec. This caused:
v2.0.0 uses pre-capture pattern - separate test execution from receipt generation. This is:
test-output-file instead of test-commandnpm test 2>&1 | tee test-output.txt@v2.3.0See CHANGELOG.md for complete version history.
See CONTRIBUTING.md for development guidelines.
.faf files (one of TAF's use cases)| Format | IANA Status |
|---|---|
application/vnd.faf+yaml (FAF) | ✅ Registered |
application/vnd.fafm+yaml (VML) | 🟡 Under review |
application/vnd.taf+yaml (TAF) | ⏳ Queued |
.taf is filed entirely on its own merits — append-only test provenance, git-tracked, tamper-evident — independent of .faf's registration.
If faf-taf-git has been useful, consider starring the repo — it helps others find it.
MIT - FREE FOREVER
Software Accountability
This tool implements a paradigm shift:
Before: Tests run → results disappear → no permanent record
After: Tests run → .taf updated → git-tracked forever
.taf is about accountability. Proof that your code works. Tracked over time. Visible to everyone.
Built with championship standards. F1-inspired engineering. Methodically tested.
Platform-agnostic core. Works everywhere. Trust the format.
FAQs
A Test Receipt Printer for git. Every CI run prints a receipt to .taf — append-only, timestamped, cannot be gamed. Proof over time.
The npm package faf-taf-git receives a total of 131 weekly downloads. As such, faf-taf-git popularity was classified as not popular.
We found that faf-taf-git demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.