diff --git a/docs/DOC-IR-SPIDER-CONVERGENCE-PLAN.md b/docs/DOC-IR-SPIDER-CONVERGENCE-PLAN.md
index 33e7a9e..e5a3d89 100644
--- a/docs/DOC-IR-SPIDER-CONVERGENCE-PLAN.md
+++ b/docs/DOC-IR-SPIDER-CONVERGENCE-PLAN.md
@@ -33,21 +33,36 @@ Kopfzeile/Fußzeile/main positions the amendment's A3 template projects —
the web *self-labels* what OCR must *infer*. Same regions, two
acquisition modes, one IR.
-## P1. Access preflight (blocking facts to verify, first spider-enabled session)
-
-`AdaWorldAPI/spider` was NOT readable from this session (repo-access gate).
-Before W3 is scoped in detail, a session with spider access verifies:
-
-- **PF-1** fork exists, default branch, divergence from upstream
- `spider-rs/spider`.
-- **PF-2** page output surface (assumed from upstream: `Website` crawl →
- per-page HTML string + URL + headers; a headless-chrome feature exists
- for rendered layout). Verify names/features before writing the seam.
-- **PF-3** whether rendered layout coordinates are obtainable (headless
- feature) or whether W3 ships DOM-order pseudo-geometry first (see W3
- fallback — the plan works either way).
-- **PF-4** workspace layout: where a harvest crate lands in the fork
- (sibling crate, mirroring how `ruff_*_spo` crates live in the ruff fork).
+## P1. Access preflight — VERIFIED against source (2026-07-13, this session)
+
+`AdaWorldAPI/spider` is not readable via GitHub-MCP (repo-access gate) but
+clones fine over the local git proxy (same transport as MedCare-rs). Cloned
+to `/home/user/spider`; all four PF facts verified against the Rust source
+(the fork's own `.claude`/`CLAUDE.md` are stale upstream boilerplate and were
+NOT used — the seam is grounded in code):
+
+- **PF-1 ✓** Fork of `spider-rs/spider`, default branch `main` @ v2.52.9,
+ exactly ONE AdaWorldAPI commit over upstream: `8df3a1b3` *"Add pluggable
+ in-process HttpFetchEngine seam (#403)"* — the fork already thinks in
+ swappable seams (same shape as `DocRenderer` / OGAR producer seams),
+ lowering the risk of wiring a doc-IR producer. Otherwise virgin.
+- **PF-2 ✓** Page output surface: `spider::page::Page` exposes `get_html()`
+ (String) + `get_url()` + `get_bytes()` + status/headers + optional
+ `screenshot_bytes`. That is the W3 producer input.
+- **PF-3 ✓ (upgraded from "unknown" to "feasible-later")** Per-element
+ geometry is NOT exposed as page output, BUT the CDP primitive is used
+ throughout the `chrome` feature path — `bounding_box()` on element handles
+ (`features/solvers.rs`) and `getBoundingClientRect()` in injected JS
+ (`features/webdriver.rs`, `chrome_common.rs`). So rendered-coordinate rails
+ are a KNOWN-FEASIBLE later increment (a CDP/JS pass over the region
+ landmarks reusing that in-repo primitive), not speculative. W3 v1 ships
+ DOM-order pseudo-geometry (below); rendered rails are the increment.
+- **PF-4 ✓** Harvest crate `spider_doc_ir` lands as a workspace sibling next
+ to **`spider_agent_html`** — which is NOT an empty field: it already ships
+ `clean_html_with_profile` / `smart_clean_html` / `CleaningIntent` /
+ `HtmlCleaningProfile{Raw,Default,Aggressive,Slim,Minimal,Auto}` with
+ `from_content_analysis` — a content-relevance layer the region harvest
+ builds ON, not around.
## P2. Wave plan
@@ -86,14 +101,36 @@ gains a dep on `ogar-doc-ir`; `ogar-doc-ir` never depends back.
### W3 — spider-fork producer (`spider_doc_ir` harvest crate, in the fork)
-DOM → doc IR: HTML5 landmarks → region kinds; DOM order → reading order;
-`
` → cell grids; microdata/schema.org → typed fields; rendered
-layout coords → rails when PF-3 confirms the headless path, else
-**DOM-order pseudo-geometry** (top-to-bottom rail assignment) as the
-honest v1 — provenance lane marks which geometry mode produced the rails.
-Fixture-driven tests on committed HTML files; no live crawling in CI.
-Lives in the spider fork (PF-4), mirroring `ruff_*_spo`-in-ruff; depends
-on `ogar-doc-ir` via git dep floating on main (D-NEVER-PIN-BUMP).
+**Grounded in the verified surface (PF-2/3/4).** `spider_agent_html` parses
+with **`lol_html`** (Cloudflare's streaming CSS-selector rewriter — no
+random-access DOM tree), and that is a *gift* for region harvesting, not a
+constraint:
+
+- **HTML5 landmarks are CSS selectors → lol_html element handlers.**
+ `header`→Header, `main`/`article`→Main, `footer`→Footer, `nav`→furniture,
+ `table`→Table (with nested `tr`/`td`/`th` handlers → cell grids),
+ `figure`/`img`→Figure. The harvest is a rewriter with one handler per
+ landmark selector, emitting `ogar-doc-ir` region nodes as the stream
+ passes.
+- **Reading order is free.** lol_html is forward-only streaming = document
+ order = the reading-order the IR needs (and the temporal stream DeepNSM
+ consumes). No sort, no tree walk.
+- **DOM-order pseudo-geometry is free.** The streaming index → u8 rail
+ (top-to-bottom) IS the v1 spatial rail — lol_html gives no layout, but
+ document order is exactly the honest v1 the amendment specified. Rendered
+ rects (PF-3, the `bounding_box()` path) are the later increment; the
+ provenance lane marks which geometry mode produced the rails.
+- **Furniture/boilerplate discrimination is half-done.** Reuse
+ `HtmlCleaningProfile::from_content_analysis` / `CleaningIntent` to mark
+ which regions are content vs chrome — the "detect page furniture" concern
+ (header/footer/nav) the OCR side infers, the web side already scores.
+- **Typed fields:** microdata / schema.org / `` → typed-field nodes
+ (the DOM analogue of OCR's `harvest_profile`).
+
+Crate: `spider_doc_ir`, sibling to `spider_agent_html`, deps = `lol_html`
+(already in the workspace) + `ogar-doc-ir` (git dep floating on main,
+D-NEVER-PIN-BUMP). Fixture-driven tests on committed HTML files; no live
+crawling in CI (P4). Mirrors `ruff_*_spo`-in-ruff.
### W4 — `ogar-doc` (persistence + template + renderer trait)
@@ -152,3 +189,113 @@ producers exist and BEFORE W4 persists anything** — persisting a
tesseract-shaped subtree and discovering the divergence later would bake
the bias into stored data. Merge-order discipline per house rule:
OGAR-side crates first, fork-side producers second, in lockstep.
+
+## P6. The `ogar-doc-ir` type surface (the concrete contract W0 verifies)
+
+Per the operator protocol (spec detailed enough that the council VERIFIES,
+not redesigns), the W1 crate's surface in concrete form. Types only; no
+minting, no canon change — the council ratifies THIS shape, then W1 codes it.
+serde-only crate. **Canon-critical:** the spatial rail is `u8:u8` — **two
+separate bytes, never widened to u16** (P0 GUID canon) — and IS the `X:Y`
+reading of the 4+12 facet payload when a region persists as a node (W4).
+
+```rust
+/// Perceptual-IR version marker. `from_json` refuses any other value
+/// (I-LEGACY-API-FEATURE-GATED: a v2 reshape is a NEW marker, never silent).
+pub const DOC_IR_VERSION: &str = "doc.v1";
+
+/// Which retina produced this document. Confidence semantics differ per
+/// source, so they never share a float (OCR recognition ≠ crawl trust).
+#[non_exhaustive]
+pub enum Provenance { Ocr, Dom }
+
+/// One spatial coordinate on the unit-square tile — ONE byte per axis.
+/// A page/viewport is a 256×256 tile (P0 "256×256 centroid tile"); this
+/// is the "2D focus of attention" address. NEVER a u16.
+pub struct Rail { pub x: u8, pub y: u8 }
+
+/// A region's box: two rails (top-left, bottom-right) = 4 bytes = two of
+/// the six `u8:u8` pairs of the 12-byte facet register.
+pub struct BBoxRail { pub tl: Rail, pub br: Rail }
+
+/// How the rails were derived — kept in the provenance lane so a consumer
+/// never mistakes document-order placement for measured geometry.
+#[non_exhaustive]
+pub enum Geometry {
+ /// Measured layout (OCR pixel bbox / DOM `getBoundingClientRect`).
+ Rendered,
+ /// Reading-order placement (lol_html stream index / OCR line order).
+ DomOrder,
+}
+
+/// The CLOSED region-kind vocabulary. `from_json` HARD-FAILS on any kind
+/// outside this set (mirrors `ruff_spo_triplet::from_ndjson`'s closed
+/// predicate gate) — the single rule that keeps the IR source-agnostic
+/// instead of drifting into a tesseract-shaped or DOM-shaped grab-bag.
+#[non_exhaustive]
+pub enum RegionKind {
+ Header, // OCR page-furniture top / HTML
+ Footer, // OCR page-furniture bottom / HTML