Every milestone ends with the corpus regression green, an accessibility
pass on the application itself, and an entry here — including what is
still missing.
1.2.0 — Batch processing, and the claims trimmed to what ships
· milestone M7
Batch and folder processing
taggart check and taggart fix now take several paths, or a directory, with -r to descend into it.
With more than one input every artefact path becomes a directory: -o, --report-json and --report-pdf each write one file per input, named from the source. Two inputs called report.pdf in different folders produce report.pdf and report-2.pdf rather than one overwriting the other.
A file that fails does not end the run. A backlog is the situation batch exists for, and a backlog always contains something corrupt. Each failure is reported on its own line and the remaining files are still processed; the worst exit code across the batch is what you get back.
The appearance gate runs per file, and a file whose rendering changed is called out rather than buried — it is the one result that must not ship quietly.
Extension matching is case-folded, because a backlog assembled from Windows machines is full of .PDF.
Custom report branding and shared check profiles were listed as current features. Neither is built. Both now use the line the Team plan was already using honestly for SSO: on the roadmap, not shipped.
Alt-text generation was described in both privacy policies, on the download page, in the home FAQ, in a guide and on a reference page as a shipped feature with three privacy modes including a bundled local model. None of it exists — figure-alt-text refuses to write a value it was not given, which is the correct behaviour and a better privacy story than the one being claimed. A privacy policy is the worst place to describe the data handling of a feature that is not there.
Fixed
The subscription webhook returned 500 on every event. stripe-python returns typed resources whose .get() raises rather than behaving like a mapping, so a customer could have paid and had no subscription recorded. Found by firing real events at the deployed endpoint.
The Stripe setup script duplicated products when run twice in quick succession: it looked them up through the search index, which is eventually consistent.
APP_URL pointed at a hostname that does not resolve. It builds Stripe’s success_url and return_url, so a paying customer would have been redirected nowhere.
1.1.0 — Reference library, and two build gates
· milestone M6
A content release, plus the accessibility work the site and application owed their own subject.
Reference and guides
Five right-to-left failure conditions now have written pages, completing the TG-RTL set: text stored in visual order, missing per-run language, mixed-direction runs, left-to-right column order in a right-to-left document, and misplaced punctuation.
Twenty-seven guides. New this release: checking a PDF free, Word, PowerPoint, Google Docs, LaTeX, scanned documents, Arabic, headings and bookmarks, links and annotations, artifacts and decorative content, titles and metadata, form field naming, colour contrast, tagging an untagged PDF, choosing a screen reader, reviewing remediation someone else delivered, what a remediation deliverable should contain, a checklist that marks each item machine-checkable or human judgement, and PDFs on a website.
Two more Hebrew pages, written rather than translated: checking a PDF free, and producing an accessible PDF from Word. A Hebrew privacy policy naming חוק הגנת הפרטיות and the EU transfer position.
The remediation panel says what it can and cannot do
The Fix panel listed every non-mechanical fix as a checkbox, including thirteen the engine refuses without a per-element approval — ticking one produced an error rather than a fix.
Three groups now. Mechanical fixes in one batch with one undo. Fixes a checkbox genuinely settles, each with a hint written for that fix. And the rest, listed with the reason they are a judgement per element, and a route into the guided review queue. Font embedding says plainly that Taggart will not substitute a font program, because doing so would change the rendered page.
The conformance claim moved to its own card. It had been inside the decisions card, so a document whose only fixes were mechanical could never write the identifier.
Accessibility of the tools themselves
The application had role="tabpanel" on its <main>, which replaced the main landmark rather than adding to it — so the application had no main landmark and all of its content sat outside every landmark. It had no h1. The rendered-page viewport scrolled and could not take focus, which fails 2.1.1. One panel heading skipped a level, which is the condition the application itself reports as 14-003.
Seven tabs, zero axe violations. On the site, 104 pages, zero.
Two gates that run after every site build
Most of this site is generated from the rule file, but only conditions a human has verified get a page — so cross-references to the rest were linking to pages that did not exist. Ninety of them.
check-links.mjs resolves every internal link against what the build actually produced, including the absolute self-references in canonical, hreflang and og:image — which is how a missing social image turned up. A rehype plugin degrades a link to an unwritten condition into plain text, so the prose stays as written and every link turns itself back on the day its page ships.
check-contrast.mjs fails the build if any syntax-highlight colour drops below 4.5:1 against its background. The theme in use paints one token at 3.49:1 on white.
Still the same
167 engine tests, appearance gate at 1.000000 across the corpus, and no claim anywhere that a document is legally compliant.
1.0.0 — First release: check engine, remediation and the RTL engine
· milestone M1–M5
The first public release. Everything below is shipping, not planned.
Check engine
The full Matterhorn Protocol 1.1 rule set — 31 checkpoints, every failure condition — mapped to PDF/UA-1 clauses and WCAG 2.1 AA success criteria in a single shared rule file that drives the engine, the reports and this website.
Every machine-checkable condition the object model can decide, plus heuristics for the human-judgement conditions where a signal genuinely exists.
Three validation profiles: PDF/UA-1, WCAG 2.1 Level AA and IS 5568.
Severity model: blocker for machine-checkable failures, warning where a heuristic says a human will reject it, manual for genuine judgement calls. Nothing is ever auto-passed.
Right-to-left engine
Visual-order detection for Hebrew and Arabic, by comparing the order glyphs are painted in against their positions on the page, corroborated by Hebrew final-letter morphology.
Logical-order repair through /ActualText, leaving the content stream untouched.
Per-run /Lang tagging, in both directions — Hebrew runs in an English document and English runs in a Hebrew one.
Right-to-left aware column and reading-order evaluation.
Remediation
Mechanical fixes applied in bulk with a diff and a single undo.
Semantic fixes — headings, lists, alt text, artifacting — proposed and held for approval rather than applied unattended.
Appearance gate: every remediated file is re-rendered against the original and compared page by page at structural similarity ≥ 0.999. A file that fails is discarded rather than returned. It measures 1.000000 across the test corpus.
Taggart refuses to write a PDF/UA conformance claim its own re-validation cannot confirm.
Reading-order editor
Numbered badges drawn on the rendered page from the real structure tree.
Selection linked between the tree and the page in both directions.
Alt plus arrow keys to reorder from the keyboard, with an undo stack that spans a batch.
A real ARIA tree with roving tabindex, because shipping an inaccessible accessibility tool would be indefensible.
Reports
Remediation report in PDF and JSON: findings, fixes, accepted items with justifications, remaining issues, every human decision with an actor and a timestamp, the tool version, and the SHA-256 of both files.
The PDF report is itself tagged, titled, language-tagged and sets DisplayDocTitle.
Known limits
Batch and folder processing, and the CLI for CI pipelines, are in the Pro tier but not yet in the web application.
Font-program internals (conditions 31-011 to 31-026) are reported from the object model; the checks that require parsing the embedded font binary are marked partial in the rule file and say so in the report.
No OCR. Taggart detects that a document needs it and points at ocrmypdf rather than building a worse one.