ADR-0003 · Rendered blocks carry the ids the service computes from source
Status: Accepted, 2026-10-10.
Context
Comments, redlines and changed-since marks must find the same block in the page
that the service diffs in the Markdown source. The comments component invented
dom:<tag>:<n> ids that matched nothing on the server.
Decision
parseDocumentBlocks in the package-root semantic.js is the single block
model. A remark plugin stamps data-redline-block with its ids on rendered
headings, paragraphs, list items and code blocks; the integration enables it
with blocks: true on a unified() Markdown processor.
Why
One implementation run in three places (service, page, tests) cannot drift. Matching by start line with a fingerprint fallback, never reusing an id, keeps duplicate paragraphs distinct.
Consequences
Astro 7’s default Sätteri processor runs no remark plugins, so a site must use
unified() (the integration warns otherwise). Pages rendered outside Astro,
such as kb-package fragments, have no block ids yet (TD-002).
Evidence
4c78769, 856049e, d28a3be; test/remark-blocks.test.js, test/semantic.test.js.
Revisit when
The harvester renders blocks at publish (TD-002), or a second Markdown processor needs block ids.