@afixt/ai-prefilter
v0.1.2
Published
Deterministic pre-filter layer for AI-assisted accessibility tests. Reduces LLM cost by answering what can be answered deterministically and routing only ambiguous cases to the AI proxy.
Readme
@afixt/ai-prefilter
Deterministic pre-filter layer for AI-assisted accessibility tests. Sits between
the test runner and the platform AI proxy, classifying aiRequest payloads
into:
- Decided verdicts — answered deterministically with no LLM call.
- Residual
aiRequest— the subset that still needs the model.
Purpose
AI-assisted accessibility tests (see
AFixt/afixt-tests issues labeled AI)
emit aiRequest objects describing what they need evaluated. Routing every
request to a vision or text LLM is expensive. This package applies cheap
deterministic analysis first and only escalates ambiguous cases.
Built to serve the Project Revenant platform invariant: AI/LLM calls route through the platform's AI proxy. This package does not call LLMs itself — it reduces the work the proxy receives.
Status
Phase 5 of the Revenant ROADMAP — AI-Assisted Detection. Prefilters implemented:
- Contrast (CSS-02) — deterministic WCAG 1.4.11 evaluation
- OCR (NON-TEXT-CONTENT-05/06/19) — Tesseract-based text-in-image detection
- Language detection (LANG-02) — franc-based language-mismatch detection
Install
npm install @afixt/ai-prefilterQuick start
import {
dispatch,
createRegistry,
contrastPrefilter,
memoryCache,
} from '@afixt/ai-prefilter';
const registry = createRegistry();
registry.register('CSS-02', contrastPrefilter);
const result = await dispatch(aiRequest, {
registry,
cache: memoryCache(),
});
// result.verdicts → elements decided deterministically
// result.residualAiRequest → what (if anything) still needs the modelDevelopment
This project follows the monorepo standards in the parent CLAUDE.md:
- TDD — write tests first, in batches of 2–3, verified to pass incrementally.
- Git Flow — feature branches from
develop, PR todevelop, release branches tomain. - Git hooks — Husky pre-commit (lint-staged +
tsc-files+ trufflehog) and pre-push (npm run check:all). Never bypass. - Coverage — ≥80% on new code.
Setup
First clone requires both Node deps and a few external binaries (semgrep, osv-scanner, trufflehog, lychee). The bootstrap script installs everything:
bash scripts/bootstrap.shIf you skip the script the Node side still works; CI enforces the external
scanners regardless, and pre-commit prints a warning when trufflehog is
missing rather than blocking.
Scripts
npm run dev # tsup --watch
npm run build # tsup → dist/ (dual CJS + ESM)
npm test # vitest run
npm run test:watch
npm run test:coverage
npm run typecheck
npm run lint # eslint (strict-type-checked + quality plugins)
npm run lint:fix
npm run format # prettier --write .
npm run format:check
npm run markdownlint
npm run dupes # jscpd duplicate-code detection
npm run links # lychee link check
npm run docs:api # TypeDoc → docs/api/
npm run size # size-limit budget check
npm run license:check # production-dep license allowlist
npm run license:report # CSV report → reports/licenses.csv
npm run security:audit # npm audit --omit=dev --audit-level=high
npm run security:osv # google/osv-scanner against package-lock.json
npm run security:semgrep
npm run security:secrets # trufflehog (verified-only)
npm run security # all four security scans in parallel
npm run check # lint + typecheck + markdownlint (fast)
npm run check:all # check + test + build + size + dupes + license + auditThe check:all script is what the pre-push hook runs and what CI mirrors, so
"passes locally" means "passes in CI".
Architecture Decisions
See docs/adr/ for the decisions that shaped this package's
tooling stack, rule tunings, and library-vs-app scope exclusions.
License
MIT
