# WEBSERVE W3 — measure-first record (todlando, 2026-09-07)

Lane `.worktrees/ws272-w3`, branch `build/ws272-w3`, off `origin/main` = `ff4b405d`.
Members: releases#265 (adapter docs facet), releases#268 (changelog page), releases#266
(LAN bootstrap listener + integrity). Brief: `WEBSERVE-272-JIT.md` W3 section (line 169 on).
Everything below is READ off the tree/box at that sha — no build was run (W2's LAN verify
holds the pool).

## #268 — changelog page

- `xtask gen` today writes exactly ONE file: `docs-site/src/cli/reference.md`
  (`crates/xtask/src/main.rs:274`), and `xtask check` calls `gen(true)` to diff it.
  The changelog page joins that same pair; nothing else in `gen` changes.
- The internal-codes scan is a HARD-CODED PATH LIST
  (`scan_published_docs_for_internal_codes`, main.rs:453): `docs-site/src/cli/reference.md`
  + `crates/spt-runtime/manifest.schema.json`. Joining the scan = adding the generated
  changelog page to that array, not a new mechanism.
- **CHANGELOG.md carries TWO forbidden classes, not one.** The brief names the
  `<!-- [doc->REQ-…] -->` tags (5 of them, lines 17/28/32/…). Measured additionally:
  two PROSE citations `(releases#222)` at lines 294 and 305, and `releases#<digit>` is a
  scanned class in `forbidden_codes_in` (main.rs:314). A generator that strips only the
  doc tags reds the scan on run one at line 294. `changelog_page` therefore strips BOTH:
  the whole `<!-- [doc->REQ-…] -->` comment line, and the trailing ` (releases#<n>)`
  citation. No `ADR-`, `F-<digit>`, or `M<n>-W<n>` token is present today (measured), but
  the stripper keys on the SCANNED CLASSES, not on today's population, or the next
  changelog entry re-opens the hole.
- `llms_full` (main.rs:~1204) walks `SUMMARY.md` link order and READS each page off
  disk, so the page must be a real checked-in file under `docs-site/src/` — a
  render-on-request page would break the bundle. Generated-and-committed is the shape.

## #265 — adapter docs facet

- `/a/<adapter>/` EXISTS today (W0): `webserve.rs:454 fn adapter` looks the adapter up in
  the serving registry by `entry.adapter`, and serves that entry (the core-owned
  `adapter_web_dir_in` root). Absent adapter ⇒ `NOT_FOUND: facet a adapter <name>`.
- `manifest.adapter.web_short_path` (manifest.rs:230) is the existing optional pointer;
  it is validated by `spt_store::serving::validate_web_short_path` (serving.rs:357):
  `valid_name` + not a reserved facet. That validator is a NAME check, not a path check —
  `docs_dir` needs a PATH containment check, which is a different shape from the one the
  brief points at as precedent.
- Unknown-key safety already landed: `REQ-MANIFEST-UNKNOWN-KEY-WARN` names a misspelled
  optional key on stderr at `adapter add`, so a `docs_dr` typo is visible rather than
  silently facet-less. `docs_dir` inherits that for free — no work, but the unit that
  proves it belongs to this lane's list.

### OPEN SHAPE QUESTION (asked of doyle before implementing)
`/a/<adapter>/` is already taken by the core-owned `web/` root entry, and the manifest
comment says that facet exists whether or not `web_short_path` is set. So "serves an
installed adapter's docs" needs one of:
  (A) `docs_dir` REPLACES what `/a/<adapter>/` serves when present (docs win, core web
      root reachable only via its alias) — one path, but changes an existing URL's meaning;
  (B) `docs_dir` mounts at `/a/<adapter>/docs/` beside the core root — additive, no
      existing URL changes meaning, and "absent ⇒ 404 naming the facet" lands naturally on
      the `docs` segment.
(B) is what I would build (it keeps a W0 URL's meaning fixed, which is the property
ADR-0056 bought), but the choice is doyle's because the ruling's words are `/a/<adapter>/…`.

## #266 — LAN bootstrap

- Rides the REFINED 10:14Z ruling verbatim: applied signed set, per-triple sha-anchored,
  all three triples; happy path witnessed on the REAL installed daemon, refusal arms on the
  dev-bin rig. No independent re-measure of the artifact dir was needed — doyle re-measured
  it at 10:14Z (three triples under one `release.json`, key `rel-primary-2026`, set version
  102, phase applied, `bin\spt.exe` sha256 three-way equal). Re-measuring it here would be
  a second reading of the same box, not a second witness.
