pdfnative-mcp 1.6.0 ecosystem alignment + 1.7.0 conformity audit - #76
Merged
Conversation
…r, MCP 2026-07-28) Bump the ecosystem manifest (single source of truth) to pdfnative-mcp 1.6.0: version, pin ^1.7.0, toolCount 28 (+ add_ltv, timestamp_pdf, update_metadata, inspect_layout), six prompts, and the mcp-tool-count assertion canonical "28 tools". versions.js fallbacks follow (incl. the stale pdfnative 1.6.0 engine fallback, corrected to 1.7.0). The MCP guide gains four new tool sections, the 10-variable environment table with the operator network charter (TSA / OCSP / CRL egress class, SSRF guard), the six-prompt table, the v1.6.0 error codes, the 13 block kinds / layout / build-time encrypt / print production / honest PDF/A coverage on generate_basic_pdf, PAdES guidance on sign_pdf, and a "What's new in v1.6.0" release-history entry with the six migration notes. The stale claim that RFC 3161 validation was "not part of this server" is corrected — verify_pdf now validates /DocTimeStamp tokens. README, llms.txt (root + docs copy, byte-identical), AGENTS.md, ROADMAP.md, onboarding, architecture and agentic-workflows follow the manifest. Two pre-existing inconsistencies are fixed in passing: onboarding said "v1.4.0 ships 24 tools" and ROADMAP said "Built on pdfnative 1.6.0 as of v1.5.0". All MCP facts verified against the local D:/Github/pdfnative-mcp source (package.json, release-notes/v1.6.0.md, src/server.ts).
…and SEO The landing page #mcp section grows to 28 rows with the four v1.6.0 tools (add_ltv, timestamp_pdf, inspect_layout, update_metadata) and its JSON-LD node bumps softwareVersion to 1.6.0; the architecture SVG desc and MCP box now read "28 tools"; the guides/learn/playground index blurbs and the mcp.html guide shell follow. responsibility.html names the SDK v2 package (@modelcontextprotocol/server) that replaced @modelcontextprotocol/sdk. The MCP playground gains two runnable cards: update_metadata drives the real openPdf -> createModifier -> updateMetadata -> save incremental pipeline on a browser-built source PDF, and inspect_layout runs the real inspectDocumentLayout dry run and prints the pagination report in place (a new runJson card variant, since the tool produces no PDF by design). add_ltv and timestamp_pdf are documented as deliberately card-less: they need the operator-configured TSA / OCSP / CRL providers a browser page cannot supply. Coverage arithmetic is restated as eleven of 28 without a card. Stale card blurbs (five chart types, 24 lang codes, no listbox, pre-PAdES sign_pdf) are refreshed, and the intro no longer stops at v1.4.0. Cross-cutting guides: signatures.md documents the MCP PAdES ladder (sign_pdf -> add_ltv -> timestamp_pdf, verify_pdf ltv: true), pdfa.md adds the embedFonts / strict / includeDiagnostics honesty note with the known AcroForm /DR /Helv limitation, and ai-governance.md states the single permitted egress class mirrored from the pdfnative-mcp 1.6.0 charter. sitemap.xml lastmod moves to 2026-08-25 for the 13 touched pages, llms-full.txt is regenerated (never hand-edited), and the stale-token canary in tests/docs/verify-docs.test.ts follows the manifest canonical (28) so the perturbation test keeps testing a live value. verify:docs: 17 rules passed across 109 files; vitest docs suite: 18/18.
…-count canonical The served og-image.png had never been re-rasterised since the v1.4.0 docs audit: its git history stops at 52cbbdd while og-image.svg was edited later in f88c3b0, so every social card still advertised the pre-1.6.0 feature line. The SVG subtitle now names the 1.7.0 headliners (LTV Signatures, Print Production) alongside the engine constants, and the PNG was re-captured per the procedure in the SVG header comment: chrome --headless --disable-gpu --hide-scrollbars \ --window-size=1200,630 --screenshot=og-image.png og-image.svg Verified 1200x630 with the new line rendered. No conversion tooling is committed - the SVG header comment remains the documented procedure. charts.html was the only page referencing og-image without og:image:width/height; the pair is added, and its og:description now enumerates all nine chart kinds instead of seven labels. ecosystem.json: the test-count-homepage canonical read "665+ tests across 122 files" - a dropped leading 2 that made the substring assertion unable to catch the very drift it exists for. Corrected to "2665+"; verify:docs stays green (docs/index.html carries the full string).
…round truth A cross-verified conformity audit of the whole documentation surface found the errors that the 17 verify-docs rules do not cover - counters, versions and API claims living outside the rule corpus, plus engine-version prose. Counters and versions: AGENTS.md said 2664+ tests and ~241 sample PDFs (manifest: 2665 / 242); testing.instructions.md was frozen at "2396+ tests across 105 files" with 44 generator modules (2665+ / 122 / 48) and its test tree missed tests/docs, tests/tools and tests/visual; quality-gate.prompt.md expected 2396+; SECURITY.md still supported 1.6.x/1.5.x (now 1.7.x/1.6.x). Signature claims: SECURITY.md, ROADMAP.md and pdf-core.instructions.md described two selectable algorithms - v1.7.0 has four (rsa-sha256/384/512, ecdsa-sha256, src/crypto/cms.ts); compliance-audit.prompt.md audited only adbe.pkcs7.detached where the engine now also emits ETSI.CAdES.detached and ETSI.RFC3161. MIRROR_MAP no longer exists in the code - the shaping instructions now name BIDI_MIRRORING_PAIRS and its full 428-pair UCD table, plus the v1.7.0 I1/I2 conformance work. Engine-version over-propagation: cli.md, react.md, mcp.md's v1.5.0 history entry, README's CLI v1.3.0 / MCP v1.5.0 history lines and llms.txt claimed "built on pdfnative 1.7.0" for packages whose published manifests pin ^1.6.0 (CLI 1.3.0, React 1.1.0) or shipped on the 1.6 engine (MCP 1.5.0, per its own release notes). All now state 1.6.0 with the pin/semver-accepts nuance, matching versions.js and the manifest. Site: the no-JS Library badge fallback said v1.6.0; the charts cards, metas and playground badge were frozen at five kinds/v1.6.0 while the engine has nine since 1.7.0; two "nine types" enumerations listed seven labels (barH and stackedBarH restored, also in README and llms.txt); learn pages said 26 reference guides (28); ltv.md and responsibility.html mischaracterised pdfnative-cli verify (full cryptographic verification, OCSP/CRL only behind --revocation online, no TSA contact) - and the published grep proof on responsibility.html is rephrased now that the v1.7.0 provider interfaces carry @example JSDoc showing user-land fetch. llms.txt (root + docs copy, byte-identical) also gains the v1.6/v1.7 roadmap detail its "v1.0 -> v1.7" line promised.
…mitted The audit''s second class of findings: pages whose facts were not wrong but whose framing predated 1.7.0. The guide index cards and HTML shell metas for signatures (PAdES profile, RSA SHA-384/512, multiple signatures, listSignatures), colour emoji (sweep gradients, the 73 flag/ZWJ sequences, --sequences / --sequence-list), PDF/A (declaration guards, dropping the "v1.1.0" framing) and the CLI (all 17 commands, verify with RFC 3161 + OCSP/CRL) now describe the current release. The landing page gains the print-production sentence in the Rich Content card, print in the #library JSON-LD description, the emoji-sequences line in the scripts card, and print.html / ltv.html in the footer guide list. Four guides gain the 1.7.0 note their subject now requires: form-filling (AcroForm /Helv carries /ToUnicode in every mode - searchable form text, byte change on every form document), text-extraction (complete base-14 and form-field coverage), pdf-manipulation (page boxes and /UserUnit survive merge/split/extract), accessibility (PDF/A declaration guards). Agent instruction files catch up with the 1.7.0 API surface: api-design.instructions.md gains the LTV/PAdES, print-production and PDF/A-diagnostics export categories; pdfa-conformance.instructions.md gains the "Declaration guards (v1.7.0)" section AGENTS.md routes to; copilot-instructions.md names all nine playgrounds. The "built on pdfnative 1.6.0" phrasings introduced by the audit fixes are restated as "the pdfnative 1.6 engine (pins ^1.6.0, semver-accepts 1.7.0)" so the version-token rule keeps guarding real drift instead of being suppressed - the pin carries the exact floor. llms.txt (root + docs, byte-identical) follows, llms-full.txt is regenerated, and sitemap lastmod moves to 2026-08-25 for the newly touched pages. verify:docs 17 rules green; vitest docs suite 18/18.
…e index The 28 guide pages used to ship an empty <article> filled in by guide.js at runtime: any fetcher that does not execute JavaScript - most AI crawlers, social scrapers, curl - received the word "Loading..." instead of the guide, and the JSON-LD injected by the same script was equally invisible. scripts/build-guides.ts now renders each guide''s Markdown into its shell between guide:render markers, with deterministic GitHub-style heading ids plus visible anchor links (marked >= 5 stopped emitting heading ids, so in-page anchors had never actually existed), externalised links, and server-side TechArticle + BreadcrumbList JSON-LD (FAQPage for the FAQ) carrying dateModified from the manifest''s verifiedOn. marked@12.0.2 is pinned as an exact devDependency - the same version the pages load from the CDN. The new guide-render-sync rule rebuilds every shell in memory and fails CI when a committed render is stale, exactly as llms-sync polices llms-full.txt; the served site stays fully static. guide.js detects the pre-rendered article, skips the fetch, and keeps its old render path as a fallback; it now also adds copy buttons to every code block and a "Copy page as Markdown / View Markdown source" bar on both paths. Machine discoverability: llms.txt gains a "Machine-readable artefacts" section; robots.txt points AI pipelines at llms.txt and llms-full.txt; the sitemap lists the 28 raw .md URLs plus llms.txt and llms-full.txt; the major page heads declare rel="alternate" links to llms.txt; and the new generated docs/llms-index.json publishes per-guide HTML/Markdown URLs, titles, summaries, section anchors and exact byte / approximate token sizes (policed by llms-index-sync) - sizes live there rather than in llms.txt so no artefact embeds its own size. llms-full.txt now also embeds the README, the largest API reference in the repo and previously absent from the ingestible corpus. The docs test suite gains perturbation tests for both new rules (20/20), with the repo''s node_modules junction-linked into the sandbox so the generator''s marked import resolves there. Rule count 17 -> 19 updated in CONTRIBUTING and copilot-instructions. verify:docs: 19 rules green.
…rst guides The homepage demo becomes a split view: the example code runs as a real ES module through a Blob URL (its import-from-pdfnative lines are real, top-level await works natively, and errors carry genuine line numbers instead of the old new Function + import-stripping regex), downloadBlob is routed to an inline PDF preview iframe - the same Blob/object-URL pattern the React playground already used - and the first example renders automatically when the section scrolls into view, so a visitor sees a real PDF without clicking. Download becomes an explicit button, navigator.pdfViewerEnabled gates an honest no-inline-preview note for mobile browsers, and #preset=<id> permalinks restore and share the selected example. No new dependency, no code-encoding permalinks. docs/agent-brief.md is the new paste-into-context pack for coding agents: the core API table, the six verified pitfalls that produce wrong code (synchronous builder, top-level title, reserved /F1-/F2, registerFont-without-fontEntries, PDF/A claim in layout, and the pdfkit/jsPDF ghost APIs - named under explicit verify-docs:allow markers), the surface decision tree, and the generate-inspect-assert self-verification loop. Linked from llms.txt, llms-index.json, the sitemap, and a "Copy as prompt" button in the homepage MCP section. It joins the verify-docs corpus (110 files), so its counters and identifiers are policed like every other page. Six guides that opened without an answer-first summary (accessibility, architecture, pdfa, quickstart, signatures, troubleshooting) gain one, extractable by answer engines; signatures.md''s intro claim "both with SHA-256" is corrected (RSA gained SHA-384/512 in 1.7.0). The nine learn pages share a new learn/learn.css instead of nine duplicated inline style blocks. verify:docs 19 rules green; docs suite 20/20.
…i-exists Three machine-truth artefacts join the served surface, each policed by a sync rule cloned from the llms-sync pattern: - recipes/ - 14 standalone TypeScript recipes importing only from ''pdfnative'', each carrying @task/@surface/@since/@expect headers and executed in CI (tests/docs/recipes.test.ts, 16 tests: every @expect is asserted with the engine''s own readers - extractText, openPdf, listSignatures, inspectDocumentLayout). Deterministic output where the API allows (pinned creationDate/signingTime/modDate); signed-pades takes its signing material as a parameter and the test injects the existing mock PKI. vitest aliases pdfnative -> src/index.ts. Served concatenated as docs/llms-recipes.txt - the cheapest high-signal fetch for a coding agent, because the code it copies is proven in CI. - docs/assets/api.json (445 exports) - the public API surface derived mechanically from src/index.ts export statements with signatures and TSDoc summaries where extractable, null where not; the substitute for the gitignored dist/index.d.ts. Rule api-json-sync; npm run docs:api. - docs/data/surfaces.json + two new guides: choose (the library/CLI/ MCP/React decision tree with a 12-capability matrix, every MCP tool and CLI command name checked against ecosystem.json) and self-verify (the generate->inspect->assert->correct loop across all four surfaces, with the honest caveats: shared measurement code, structural PDF/UA, no cryptographic verifier in the engine). Guide count 28 -> 30 everywhere (manifest, TOC, ItemList, learn pages, sitemap incl. .md). The api-exists rule graduates from ~4 watched identifiers to the whole documented surface: any identifier written call-shaped at the start of an inline code span must exist in src/ (or scripts/), with markdown-vs-HTML span openers distinguished (a backtick in HTML is a JS template literal), companion-package guides scoped out (their APIs belong to their repos), import-example detection for companion names, and a small allow-list for platform/test globals and conventional-commit prefixes. The wider net immediately caught four genuinely rotten identifiers in the agent instruction files (_renderToc, _renderPageTemplate, _estimateTocHeight, and assertNotEncrypted - removed in 1.6.0 when encrypted sources became ingestible) - all corrected. llms.txt gains the recipes/api/surfaces artefact entries; rule count 19 -> 20 in CONTRIBUTING/copilot-instructions; perturbation tests added (docs suites 37/37 green; verify-docs 20 rules across 115 files).
…or-parity docs/playgrounds/inspect.html is the tenth playground: drop any PDF (or generate a sample in-page) and read a full report - version, page count, encryption, /Info, extracted text with runs, PDF/UA structural verdict, signature inventory, form fields - produced entirely in the tab via openPdf / extractText / validatePdfUA / listSignatures / readFormFields. The privacy claim is stated verifiably (all requests happen at page load, before any file is dropped; FileReader only) and every card carries its rs-verify source link plus the honest caveats: PDF/UA checks are structural, the signature card is an inventory not cryptographic verification, and listSignatures/validatePdfUA take no password. Full parity paid: switcher updated across all ten pages, playgrounds index card + ItemList (10) + "Nine" -> "Ten" prose, ecosystem derived.playgrounds, sitemap, homepage footer, learn pages. The homepage demo gains a JSON mode: a DocumentParams editor whose object is exactly what the library, pdfnative-cli render and the generate_basic_pdf MCP tool consume - with "Copy as CLI command" and "Copy as MCP call" buttons, and #doc= share links that encode DATA (deflate-raw via the native CompressionStream, base64url, defensively decoded against the 13-kind block union with a size cap - never code). Below the CI benchmark bars, "Run this benchmark in your browser" measures 100/500/1000 rows on the visitor''s own device with performance.now(), rendered under .bench-live-* classes so the bench-parity rule keeps guarding the committed reference figures, and framed honestly as indicative, not a benchmark. New verify-docs rule anchor-parity (21 rules): every internal link fragment must match an id in its pre-rendered target - internal-links deliberately ignored fragments, so deep links rotted invisibly. It immediately caught real rot: guide deep links written with GitHub''s double-hyphen slugs while the renderer collapsed whitespace (slugger aligned to the GitHub convention), and a tables.md link to a section that never existed. Perturbation test added; docs suites 38/38 green.
Above the "How It Compares" table, a small quiz derives its verdicts
from the table itself: tick what your project needs and the matching
rows highlight while a factual conclusion appears - including the cases
where another library is the better fit ("if reading and modifying
existing PDFs is your whole need, pdf-lib is a solid, widely used
choice"; "pdfkit, jsPDF and pdfmake also offer AES"). A comparison
that sometimes recommends the competitor is the only kind that is
believed - the direct translation of responsibility.html''s doctrine
into an interactive component. Rows are tagged data-cap; no data is
duplicated outside the table the caption already sources and dates.
docs/data/errors.json is the served registry of the engine''s diagnostic
codes (the three PDFA_* conformance guards from pdf-diagnostics.ts,
with severity, trigger, ISO clause, remedy, sink semantics), and the
new error-parity rule (22 rules total) checks it both ways: every
PDFA_* token in the docs must exist in the registry AND in src/, and
every registry entry must still be emitted by src/ - a registry entry
for a ghost code would teach agents an API that no longer exists. The
CLI''s E_* and the MCP codes stay in their own repositories by design,
noted in the registry''s $comment. Perturbation test added; docs suites
39/39; served-content smoke check: a guide fetched without JavaScript
carries its full article, TechArticle JSON-LD and heading anchors.
…w found
User-reported bugs, root-caused by a three-auditor review:
- Live benchmark crashed with "Cannot read properties of undefined
(reading ''length'')": makeParams omitted four required PdfParams fields
(infoItems/balanceText/countText/footerText - the engine boundary only
validates rows/headers). Params completed; errors now land in an
aria-live note instead of destroying the button label. The engine-side
boundary guard is deferred to an engine PR to keep this branch docs-only.
- "Copy link" half-hidden behind the PDF preview - three stacked causes:
.demo-actions had no flex-wrap; the demo container was 780px wide
(382px per split pane); and [hidden] was silently defeated by author
display rules (.btn{display:inline-flex}), so the Copy-as-CLI/MCP
buttons were visible in Code mode too. Fixed with a global
[hidden]{display:none!important}, flex-wrap, a full-width status line,
and an 1120px demo container.
- The re-encrypt example previewed an AES-256-protected PDF, cramming
the browser viewer''s password prompt into a half-width iframe. The
example now declares encryptedOutput: the preview is skipped for an
honest note (password: rotated, use Download), such presets never
auto-run, and a /Encrypt tail-sniff covers user-authored code.
Review blockers, worse than the reported bugs:
- The new Code/JSON mode buttons reused .tab-btn, and the homepage
tablist binds every .tab-btn on the page - clicking "JSON" emptied the
Examples section entirely and arrow keys jumped between the two groups.
The tablist is now scoped to #examples and the mode switch is a proper
aria-pressed button group (.demo-mode-btn).
- docs/assets/api.json attributed each module''s banner comment as the
summary of every export (leftmost-match regex): 77 distinct summaries
for 445 exports. A tempered regex now binds to the JSDoc immediately
above each declaration - 389 summaries, all distinct, verified.
- llms-index.json measured artefact sizes with statSync on the working
tree - CRLF-inflated on autocrlf Windows clones, making a pristine
checkout fail verify:docs. Sizes now come from the LF-normalised
content, the bytes GitHub Pages actually serves.
Also in this pass: the invoice recipe used the reserved /F1 fontRef its
own documentation forbids (now /F3 + lang); the exact test count is
re-measured at 2686 tests across 123 files and updated everywhere with
the test-count canonical (the old literal validated its own staleness);
README''s playground list gains inspect and says ten.
…1y, infra Front-end majors: the preview pane no longer reserves 320-420px when the iframe is hidden on mobile; inline preview is now an explicit opt-in on navigator.pdfViewerEnabled === true; guide copy buttons and heading anchors become visible with 24px targets on touch devices (opacity:0 hover-reveal is unusable there); the pre-rendered guide path enhances immediately and only the Prism highlight waits (kills a 2s layout shift); inspect.html''s theme toggle adopts app.js semantics (explicit light/dark - removing the attribute made "light" a no-op on dark-OS machines and the empty stored value leaked to every page); its status banners gain aria-live, theme-aware classes, and an honest tally when sections fail; mcp.html cards no longer force a horizontal scrollbar at 360px; the demo autorun is desktop-only; #doc= permalinks scroll to the demo and the autorun awaits their async decode; all four homepage copy affordances share one guarded copyText helper with an execCommand fallback for non-secure contexts. Minors: quiz grid and verdict aria-live; demo status aria-live; darker active mode-button background in dark theme (white on #3b82f6 was 3.7:1); guide copy buttons move into a positioned wrapper outside the scrollable pre (they scrolled away with wide code and polluted manual selection); rewriteImports handles multi-line and namespace imports and explains unsupported forms; inspect gains a document-level drop guard with a dragenter counter, a size warning above 25MB, yields between the five readers, and a capped /Info key column; a minimal @media print sheet (a PDF library''s docs should print); the #doc= inflater reads in chunks and aborts past the cap instead of materialising first; link block URLs from shared payloads are scheme-validated. Infrastructure: docs.yml triggers cover recipes/, bench/ and the two new generators; the JSON-LD injection uses a function replacer ($-safe); isMain is an exact-path check in all three generators (a substring match would let importers rewrite 30 shells as a side effect); ''run'' leaves the span-scan allow-list (nothing references it); error-parity gains the src->registry direction; one shared slugger feeds both heading ids and the llms index anchors; manifest-shape rejects unknown derived keys; the recipes count in tests reads the manifest instead of a literal; the sandbox path is quoted for shell:true; llms-recipes.txt leaves the scan corpus in favour of recipes/*.ts scanned directly (22 rules across 129 files); sitemap lastmod tolerates +1 day of timezone skew; arabic-rtl registers its font inside run() so importing the recipe has no global side effect. verify:docs green; docs suites 40/40.
… honest The extreme-scripts colour-emoji preset showed tofu for U+1F4E6 (package): verified against the bundled noto-color-emoji-data cmap, that codepoint is simply outside the curated 1167-glyph subset - a data-coverage limit, not a playground or engine bug - and it was the only character on the page not covered. Replaced with U+1F381 (gift), which is in the subset and keeps the "objects" theme. No engine or font-data change. PDF/A discoverability and honesty: the charts donut preset now says "PDF/A-2b tagged" in its label (it embeds Noto Sans, so its claim is the real thing), and the inspect playground''s generated sample - which claims PDF/A-2b while using unembedded base-14 text AND form fields under the claim - now says so in its own body text, naming the two documented engine limitations and pointing at veraPDF and the PDF/A guide. A deliberately non-conformant sample is a fine teaching aid; a silently non-conformant claim is not.
CodeQL flagged guide.js line 98: the data-md attribute value flows from getAttribute() into the source-bar link href (and into fetch() and the GitHub fallback URLs) without validation - a crafted `javascript:` value would become an executable link. The attribute is author-controlled static HTML in practice, but the hardening is one line: src must match a plain same-directory Markdown filename (^[A-Za-z0-9][A-Za-z0-9_-]*\.md$) or the renderer bails, which sanitises every downstream sink at once. All 30 committed shells pass the filter; node --check and verify:docs (22 rules / 129 files) stay green.
…M text CodeQL kept flagging js/xss-through-dom on the source-bar href: the query tracks getAttribute() values into href/fetch sinks and does not accept a regex test as a barrier, so validating the data-md string was not enough - the taint had to die at the root. The Markdown filename is now DERIVED from location.pathname (every guide pairs name.html with name.md) and filtered to a plain same-directory filename; data-md is demoted to an opt-in marker that must agree with the derived name but never flows into any sink. Behaviour is unchanged - the name.html/name.md pairing is the documented authoring convention (AGENTS.md) and all 30 committed shells satisfy it, verified. node --check and verify:docs (22 rules) green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Documentation PR — pdfnative-mcp 1.6.0 ecosystem alignment + 1.7.0 conformity audit
Title
docs: align documentation with pdfnative-mcp 1.6.0 (28 tools, PAdES ladder, MCP 2026-07-28) + full 1.7.0 conformity audit and Open Graph refreshSummary
This is a documentation-only branch. No
src/product changes, no version bump, no CI changes, no new dependency, no touched fonts or generators. (One docs-infrastructure test,tests/docs/verify-docs.test.ts, updates its hard-coded stale-token canary from the old canonical24 toolsto the new28 tools— a required consequence of the manifest bump, so the perturbation test keeps testing a live value.)Two workstreams:
A. MCP 1.6.0 alignment — the entire documentation surface follows the pdfnative-mcp 1.6.0 release (2026-08-23), along five axes:
docs/assets/ecosystem.jsonbumps pdfnative-mcp to 1.6.0 / pin^1.7.0/toolCount: 28(+add_ltv,timestamp_pdf,update_metadata,inspect_layout) / six prompts, and themcp-tool-countassertion canonical moves to"28 tools".versions.jsoffline fallbacks follow (incl. the stale pdfnative1.6.0engine fallback →1.7.0).generate_basic_pdf(13 block kinds, layout, build-timeencrypt, print production, honest PDF/A,creationDate), PAdES guidance onsign_pdf, and a "What's new in v1.6.0" release-history entry with the six migration notes. README,llms.txt(root +docs/copy, byte-identical), AGENTS.md, ROADMAP.md, onboarding, architecture and agentic-workflows follow.#mcpsection at 28 rows, JSON-LDsoftwareVersion: "1.6.0"on both the landing page#mcpnode and the playgroundaboutnode (the latter is a manual bump — no@id), guide/learn/playground blurbs,architecture.svgdesc + MCP box at "28 tools",ocsp/crlkeywords on the landing page,sitemap.xmllastmod2026-08-25 on the 13 touched pages,llms-full.txtregenerated vianpm run docs:llms.update_metadata(realopenPdf→createModifier→updateMetadata→saveincremental pipeline) andinspect_layout(realinspectDocumentLayoutdry run, printing the pagination JSON in place — a newrunJsoncard variant since the tool produces no PDF).add_ltv/timestamp_pdfare documented as deliberately card-less (operator-configured network providers a browser page cannot supply). Coverage restated as eleven of 28 tools without a card; stale card blurbs refreshed.onboarding.mdsaid "v1.4.0 ships 24 tools",ROADMAP.mdsaid "Built on pdfnative 1.6.0 as of v1.5.0", the playground intro stopped at v1.4.0; plus one stale claim in the MCP guide ("RFC 3161 timestamp validation is … not part of this server" — false since 1.6.0) and the renamed SDK package onresponsibility.html(@modelcontextprotocol/sdk→@modelcontextprotocol/server).B. 1.7.0 conformity audit — a cross-verified audit (two auditors + one verification pass) of every root doc and every
/docspage against pdfnative 1.7.0 and pdfnative-mcp 1.6.0 ground truth, catching what the 17 verify-docs rules do not cover:og-image.pnghad never been re-rasterised since the v1.4.0 docs audit (git history proof: PNG last touched at52cbbdd, SVG edited later inf88c3b0) — every social card still advertised the pre-1.6.0 feature line. The SVG subtitle now names the 1.7.0 headliners (LTV Signatures,Print Production) and the PNG was re-captured headless at 1200×630 per the procedure in the SVG header comment.playgrounds/charts.htmlwas the only page missingog:image:width/height— fixed..github/instructions|prompts(2396+/105→2665+/122, 44→48 generators); SECURITY.md supported-versions table (1.7.x/1.6.x) and signature algorithms (RSA SHA-256/384/512); the vanishedMIRROR_MAPsymbol replaced byBIDI_MIRRORING_PAIRS(428 UCD pairs); four selectable signature algorithms in ROADMAP/pdf-core instructions;ETSI.CAdES.detached/ETSI.RFC3161in the compliance-audit prompt; the no-JS Library badge (v1.6.0→v1.7.0); "26 reference guides"→28 on the learn pages; two "nine chart types" enumerations that listed seven labels;ltv.mdandresponsibility.htmlmischaracterisingpdfnative-cli verify(full cryptographic verification; OCSP/CRL only behind--revocation online; no TSA contact) and the now-broken grep proof (v1.7.0 provider JSDoc@exampleblocks); charts cards/metas frozen at five kinds/v1.6.0.^1.6.0; MCP 1.5.0 shipped on pdfnative 1.6 per its own release notes). Restated as "the pdfnative 1.6 engine (pins^1.6.0, semver-accepts 1.7.0)" — regex-safe for theversion-tokenrule without suppressing it.#libraryJSON-LD + footer links toprint.html/ltv.html) and the emoji-sequences line; four guides gain their 1.7.0 note (form-filling/ToUnicodebyte-change, text-extraction coverage, pdf-manipulation page-box survival, accessibility declaration guards);api-design/pdfa-conformance/copilotagent instruction files catch up with the 1.7.0 API surface.test-count-homepagecanonical read"665+ tests across 122 files"(dropped leading 2) — corrected so the assertion can catch the drift class it exists for.Deliberately not changed (audited and rejected):
comparison-2026-07-28.json(honest self-dated snapshot), the benchmarks date, "95%+ measured at v1.6.0" coverage statements (exact as written), a chart preset inapp.js(feature work), and the toolkit playground's 1.4.0→1.6.0 framing (describes its actual coverage).C. Adoption showcase (Waves 1+2 of the docs-evolution study) — a strategist/verifier study (2 analysts + 1 arbitration pass) of how /docs can drive organic adoption for humans AND AI agents, then implemented in full:
scripts/build-guides.tsnow bakes the rendered article + server-side TechArticle/BreadcrumbList (FAQPage for the FAQ) JSON-LD withdateModified, deterministic GitHub-convention heading ids and visible anchors (heading ids had never actually existed — marked ≥ 5 dropped them), policed by theguide-render-syncrule.guide.jskeeps runtime rendering as a fallback and adds copy buttons + a "Copy page as Markdown" bar.llms-index.json(per-page URLs/anchors/sizes),agent-brief.md(paste-into-context pack with the six verified pitfalls),assets/api.json(445 exports derived fromsrc/index.ts— the substitute for the gitignoredindex.d.ts),data/surfaces.json(capability × surface matrix),data/errors.json(engine diagnostic registry),llms-recipes.txt; llms.txt/robots/sitemap now reference all of it, incl. the 30 raw.mdURLs.recipes/— 14 standalone TypeScript recipes importing only frompdfnative, executed in CI with every@expectassertion verified by the engine's own readers (16 tests).DocumentParamsmode with "Copy as CLI command / MCP call", data-only#doc=share links (CompressionStream + defensive decode — never code), and a run-it-on-your-device benchmark under.bench-live-*classes.inspect.html— drop any PDF and read a full report (openPdf/extractText/validatePdfUA/listSignatures/readFormFields) entirely client-side, with the verifiable network claim and honest caveats; full parity paid (switchers ×10, ItemList, counters, sitemap).choose(surface decision tree + matrix) andself-verify(the generate→inspect→assert→correct loop) — guide count 28 → 30.guide-render-sync,llms-index-sync,api-json-sync,anchor-parity(which immediately caught really-broken deep links),error-parity— plus anapi-existsgraduated from ~4 watched identifiers to the whole documented surface (it caught four rotten internal names in the agent instruction files). Each new rule has a perturbation test.D. Triple review + fixes — three user-reported UI bugs plus a three-auditor review (factuality / front-end / engineering-CI) with an arbitration pass, all confirmed findings fixed:
PdfParamsfields (params completed; engine boundary guard deferred to an engine PR to keep this branch docs-only); "Copy link" was hidden behind the preview (three stacked causes: no flex-wrap, 382px panes, and[hidden]defeated by authordisplayrules — global[hidden]{display:none!important}added); the re-encrypt example previewed an encrypted PDF, cramming the viewer's password prompt into a half-width iframe (declarativeencryptedOutputflag → honest note + Download, excluded from autorun,/Encrypttail-sniff as safety net)..tab-btnand clicking "JSON" emptied the homepage Examples section (tablist scoped, mode switch is now anaria-pressedgroup);api.jsonattributed each module's banner comment as every export's summary — 77 distinct summaries for 445 exports (tempered regex → 389, all distinct);llms-index.jsonmeasured working-tree sizes (CRLF-inflated on Windows clones) — now LF-normalised content bytes.metadataalso takestrapped(v1.7.0); the invoice recipe used the reserved/F1its own docs forbid (→/F3); test count re-measured at 2686 tests / 123 files and updated everywhere incl. the self-validating canonical; README said "nine" playgrounds; missingsinceannotations added (validatePdfUA 1.3.0, addSignaturePlaceholder 1.2.0,<Chart>react 1.1.0);dateModifiedremoved from guide JSON-LD (a false date is worse than none — git dates are unavailable to the CI's shallow checkout); FAQPage now serialises table-only answers (25/25 questions); the "22 scripts with real OpenType shaping" phrasing tightened to the ten shaped scripts.#doc=inflation cap, link-URL scheme validation, drop-outside guard, dark-theme banners…).recipes/+ an "unperturbed sandbox is clean" control test (the negative tests were vacuous without it),docs.ymltriggers cover the new inputs, one shared slugger,error-paritythree-directional, exact-pathisMain,$-safe JSON-LD injection, unknown-derived-key guard, recipes scanned directly by the corpus (22 rules across 129 files). Docs suites 40/40.Ground-truth facts (verified)
All MCP facts were verified against the local
D:/Github/pdfnative-mcpsource (package.json, release-notes/v1.6.0.md, src/server.ts).pdfnative-mcp 1.6.0 (released 2026-08-23)
add_ltv(PAdES B-LT,/DSS+/VRI),timestamp_pdf(B-LTA,/DocTimeStamp),update_metadata(incremental/Info+ XMP),inspect_layout(pagination dry run) —src/server.tsTOOLS registry, 28 entries.pades_ladder,print_ready,reproducible_output,pdfa_validjoingovernance_contract,draft_issue_workflow—src/server.tsl.1236-1268.HTTP_TOKEN,MAX_INFLATE_BYTES,TSA_URL,TSA_AUTH,REVOCATION,NETWORK_ALLOWED_HOSTS,NETWORK_TIMEOUT_MSjoinOUTPUT_DIR,CACHE_DIR,PORT(plus the deprecatedPDFNATIVE_MPC_OUTPUT_DIRalias).pdfnative ^1.7.0(was^1.6.0); SDK@modelcontextprotocol/server ^2.0.0+zod ^4.2.0(still three runtime dependencies); Node ≥ 22; MCP spec 2026-07-28 with automatic 2025-era fallback.generate_basic_pdf; charts v2 (9 types); build-timeencrypton 7 document tools (keeps the AcroForm); print production (print,metadata,outputIntent); honest PDF/A (embedFonts/strict/includeDiagnostics); network charter: no egress by default, single permitted class = operator-configured TSA / OCSP / CRL, never a URL from a tool argument.redact_pdf, telemetry, per-page HTTP streaming.Terminology guard
requireInfiles bycanonical-present).langcodes (22 shaping scripts +latin+emoji+math); the engine canonical "22 scripts" is untouched (script-countassertion, expect 22). The server's own "24 scripts" phrasing is never quoted verbatim, to avoid colliding with that assertion.verify-docs:allow stale-token (historical: …)markers, per house style.Files touched (~45)
docs/assets/ecosystem.json(version bump +mcp-tool-countcanonical +test-count-homepagetypo),docs/assets/versions.js,tests/docs/verify-docs.test.ts(canary follows the canonical)docs/assets/og-image.svg,docs/assets/og-image.png(regenerated),docs/playgrounds/charts.htmldocs/guides/mcp.md,README.md,llms.txt,docs/llms.txt,AGENTS.md,ROADMAP.md,SECURITY.md,docs/guides/onboarding.md,docs/guides/architecture.md,docs/guides/agentic-workflows.md,docs/guides/cli.md,docs/guides/react.md,docs/guides/ltv.md.github/copilot-instructions.md,.github/instructions/{testing,pdf-core,text-shaping,api-design,pdfa-conformance}.instructions.md,.github/prompts/{quality-gate,compliance-audit}.prompt.mddocs/index.html,docs/guides/{mcp,index,charts,signatures,pdfa,cli,colour-emoji}.html,docs/learn/{index,08-next-steps}.html,docs/playgrounds/{index,charts}.html,docs/responsibility.html,docs/assets/architecture.svg,docs/sitemap.xml,docs/llms-full.txt(generated)docs/playgrounds/mcp.html(two new runnable cards + refreshed blurbs)docs/guides/{signatures,pdfa,ai-governance,form-filling,text-extraction,pdf-manipulation,accessibility}.mdChecklist
npm run verify:docspasses — 17 rules across 109 files, source of truth verified 2026-08-25npx vitest run tests/docs/verify-docs.test.ts— 18/18docs/llms-full.txtregenerated vianpm run docs:llms(never hand-edited)llms.txt≡docs/llms.txt(byte-identical,llms-sync)softwareVersionbumped in both blocks (landing#mcpviajsonld-version; playgroundaboutmanually)og-image.pngregenerated at 1200×630 from the updated SVG (headless Chromium screenshot, per the SVG header procedure; no tooling committed) and visually verifiedsitemap.xmllastmod= 2026-08-25 on touched pages only, never in the futuresrc/product change, nopackage.jsonchange, no workflow change, no new dependencynode --check(playground-syntax); CDN imports stay pinned topdfnative@1.7.0with SRI-pinned Prism