TL;DR: The engines move to the public API. Turbo-Cat (the ~200-format knowledge base) and the bench engine join scoring and the 6Ws Interview as composed, single-source engines — every FAF MCP imports them through the bridge instead of carrying its own drifting copy. And a same-day patch proves the doctrine polices itself.
One Engine Each. Composed Everywhere.
Before this release, the real Turbo-Cat lived only inside the CLI — so each MCP server ran its own smaller, hand-maintained format map. Same for the bench engine. That's how drift happens: five copies, five trajectories, one truth slowly forking.
import {
turboCatScan, // ~200-format detection — per-format breakdown + stack signature
deriveQuestionSet, // the bench engine — your .faf is the answer key
publicQuestions, // questions WITHOUT the answer key (see below)
gradeAnswers, // mechanical grading — no judge, no rubric drift
buildReceipt, // the ✪ receipt — sha256, third-party re-derivable
} from 'faf-cli'; The servers don't adapt to these — they delete their local copies. Detection sourced-only and order-independent. Grading byte-identical across the CLI and every server. The ✪ receipt is now one convention across parity, trust, and bench: sha256 over a canonical projection, re-derivable by anyone.
The Answer Key Stays Locked
The bench export came with one integrity-critical clause: deriveQuestionSet returns the answer key (your .faf's values) so grading can be mechanical. A tool that printed that key would make the benchmark a lie. So the API makes the mistake unmakeable — publicQuestions(qset) is the only shape a "give me the questions" surface hands out. Version, hash, questions. Never answers.
The Same-Day Patch — Doctrine Policing Itself
Hours after 6.10.0 shipped, the first consumer caught something: Turbo-Cat's knowledge base asserted a full Chrome Extension stack — JavaScript, Chrome Web Store, the lot — from the filename manifest.json alone. But manifest.json is one of the most overloaded names in software: chrome extension, MCP bundle manifest, PWA, plain config. Asserting a stack from the name is a guess. Sourced-only forbids guessing. The release that shipped the doctrine was violating it.
TS project + an mcpb manifest.json
6.10.0: JavaScript · Chrome Extension ✗ guessed
6.10.1: TypeScript · (none) ✓ sourced v6.10.1 fixes it the right way: content decides, never the filename. Chrome asserts only when manifest_version is a number and a chrome field is present — real extensions still detect, v2 and v3. MCP manifests, PWAs, and anything ambiguous assert nothing. An honest empty beats a guessed stack.
That's the part worth reading twice: the consumer that caught it verified the fix independently before it shipped. Single-source engines mean one bug, one fix, every surface healed at once — that's the entire argument for composing.
Try It
Or bunx faf, or brew install faf-cli. Building on the formats? The engines are right there on the import.
The Numbers
- v6.10.0 + v6.10.1 — Released June 12, 2026
- 843 tests, 0 fail — 2,746 assertions
- 🏆 100% — Trophy score
- 4 composed engines — scoring · 6Ws Interview · Turbo-Cat · bench
- 23 new contract tests — populated-not-present · answer-key-not-leaked · content-not-filename
