# GATE W3 — WEBSERVE #272 wave 3 (#265 adapter docs facet, #268 changelog page, #266 lan-bootstrap, XFER retirement)

Pre-registered by doyle 2026-09-08 08:16Z, BEFORE the head exists, so the arms and predictions are on record
before any run. Measured inputs: todlando's local tip f97d5d6b (4 commits over ff4b405d, XFER c2 uncommitted),
hertz's drift riders test/ws272-w3-drift 1839fba8 (2 commits, base eb38b71a), main bccfaee8.

## 1. Head composition (tested sha == merged sha, ff land)
1. todlando: commit XFER c2, rebase build/ws272-w3 onto bccfaee8, push. (silent since 2026-09-07 13:35Z; escalated via lia 08:08Z)
2. hertz: rebase the two drift-rider commits onto that tip, push (merge-tree at f97d5d6b: CLEAN, auto-merge registry.rs + xtask main.rs).
3. Composition commit (one line + tag census): traceable-reqs.toml REQ-DOCS-CHANGELOG-PAGE required_stages -> doc, impl, unit
   (hertz's riders carry 5x unit tags but do not touch the toml; activation rides WITH the riders, never before).
   Also confirm REQ-XFER-RETIRED is minted + activated (impl, unit) by todlando's c2.
4. Semantic composition check = clippy at the COMPOSED head, both OS (index: textual-merge-hides-semantic-composition-break).
5. PR opens AFTER the battery (pull_request fires ci on hfenduleam + kitsubito, the same boxes the battery uses).

## 2. Battery (driver derived from .spt/gate-w2-f17.sh; frozen copy via launch-gate.py; pool = todlando's ws272-w3, claimed
   SEQUENTIALLY after he releases; scrubbed env; lock dir; exit FILES decide, never pipe tails)
- 0 claim (--foreign-pool, verdict token up top) · 1 treqs · 2 prebuild (-p spt -p mock-adapter --bins + fixture bins) ·
  4 xtask check (changelog page drift + spacerun; a red beside greens is the one instrument on rendered text) ·
  5 clippy --workspace --all-targets -D warnings on hfenduleam AND kitsubito clone at the head (cfg-touching wave).
- 6 nextest LIST with binary() names, then NAME-ASSERT each wanted cell (a floor proves only that something was selected):
  lan_bootstrap_e2e: bootstrap_serves_the_applied_set_isolates_bad_triples_and_stops_for_real, the_set_gate_refuses_by_name_and_serves_nothing
  webserve_e2e: the_adapter_docs_segment_serves_docs_dir_and_never_falls_through, the_adapter_facet_root_still_serves_the_core_owned_web_root, the_adapter_docs_facet_serves_over_the_production_listener
  spt (bin) nowsignal: lan_exposed_stands_for_the_whole_window_and_is_gone_after_stop, an_unanswered_lan_status_renders_nothing_rather_than_the_last_line_it_saw, a_lan_status_writes_nothing_and_does_not_run_the_set_gate
  spt-runtime lib: a_docs_dir_that_leaves_the_adapter_directory_is_refused_by_name, a_docs_dir_resolving_outside_the_adapter_directory_is_refused_at_resolve + hertz: docs_dir_parent_traversal_is_refused_at_register, docs_dir_absolute_path_is_refused_at_register, missing_docs_dir_registers_adapter, docs_dir_fixture_lands_under_the_adapter_table, checked_in_schema_publishes_docs_dir_without_internal_codes
  xtask (bin): traceability_comments_are_stripped_and_changelog_is_scanned, visible_body_codes_remain_for_the_published_doc_gate_to_reject, non_comment_lines_preserve_bytes_and_order, stale_changelog_check_names_page_then_gen_clears_drift, changelog_is_linked_from_real_book_and_agent_indexes
  XFER: census of Xfer / serve_xfer / fetch_file / push_file over crates/ = 0 prod sites (cfg(test)-aware), ACCESS_SURFACE_RETIRED unit present.
- 7 libs: spt-daemon + spt-net + spt-store + spt-runtime + spt-msg kind(lib), --no-fail-fast; read RUN COUNT.
- 8 e2e --no-capture: lan_bootstrap_e2e, webserve_e2e, webserve_attachment_e2e, webserve_cross_node_e2e, io_events_undriven_kinds_e2e (W2 regressions), xtask bin tests.
- 9 one-box twohost_web pair (Windows + Linux) at the head — W2's helper witness must still be WITNESSED (dispatcher touched again by XFER c2).
- Duration sanity: every must-run cell > 0.0x s; the must-skip cells named.

## 3. Mutation arms (ONE arm each, siblings asserted INTACT; MATCH_COUNT==1 or refuse; print the mutated body; revert; dirty 0)
- M1 docs_dir containment: drop the canonical-under-adapter-dir check at LOAD -> predicted red: docs_dir_parent_traversal_is_refused_at_register (hertz) AND a_docs_dir_that_leaves_the_adapter_directory_is_refused_by_name; predicted intact: missing_docs_dir_registers_adapter, the accept cell, the resolve-time refusal (its own check).
- M2 changelog strip: make the doc-tag-comment class a no-op in changelog_page -> predicted red: traceability_comments_are_stripped_and_changelog_is_scanned + xtask check (regenerated page carries tags: drift diff AND internal-codes scan); predicted intact: non_comment_lines_preserve_bytes_and_order.
- M3 set gate: skip the exe-sha compare in lanhost gate -> predicted red: the_set_gate_refuses_by_name_and_serves_nothing at arm (2) sha-mismatch ONLY (arms 1 and 3 pass through first — report which arm refused); predicted intact: the happy-path cell.
- M4 (if budget): remove router-first reserved docs segment -> the_adapter_docs_segment_serves_docs_dir_and_never_falls_through red (the decoy-docs fall-through arm), root cell intact.
- Structural-exclusion note: any green under a mutation must be named could-have-reddened vs excluded-by-construction.

## 4. Field arm pin 2b (REQUIRED; real daemon, never the fleet daemon pid 48232)
Precondition A: inbound TCP 5470 allow on hfenduleam, Private, remoteip 192.168.1.0/24 (operator, relayed by lia 08:11Z) — verify with
netsh advfirewall firewall show rule (PRESENT/ABSENT/PROBE-FAILED, three arms) and a kitsubito TCP connect.
Precondition B: a daemon whose exe sha == the APPLIED signed set's host artifact (dev bins refuse by design). Shape:
  1. rig A home C:/Users/decid/spt-rig-a (no release-keys.json, no releases/ today): xtask debug-keygen (once), SPT_DEBUG_RELEASE_SEED in the
     launching shell only, xtask debug-pin INTO THE RIG HOME (measure the home flag before running; never the fleet home — see
     ephemeral-ports/subnet-in-fleet-home traps).
  2. xtask debug-rollout --build-current --artifact x86_64-unknown-linux-gnu=(linux spt built at the head on kitsubito, scp'd) --stage-dir (rig home)/releases
  3. spt update apply under SPT_HOME=rig A (scrubbed env); measure where the applied exe lands; restart the rig daemon FROM THAT EXE
     (Popen DETACHED + log file; read the child env back).
  4. spt serve lan --bootstrap in the rig home -> prints http://192.168.1.81:5470 + one sha line per triple; now-signal carries LAN-EXPOSED.
  5. kitsubito: curl /bin/x86_64-unknown-linux-gnu/spt -> sha256 == printed line == .release.json artifact hash; curl the sidecar on two
     triple paths -> byte-identical; curl http://192.168.1.81:(rig docs port)/ -> refused (loopback proof; note rig docs port is ephemeral);
     --bootstrap again -> LAN_BOOTSTRAP_ALREADY_UP same url; --stop -> socket closed, LAN-EXPOSED gone; second --stop -> LAN_BOOTSTRAP_NOT_UP exit 0.
  6. Refusal arm on the DEV rig: rig B (kitsubito dev bin) spt serve lan --bootstrap -> LAN_BOOTSTRAP_REFUSED:(unsigned-exe|sha-mismatch), exit != 0, nothing bound (ss -ltn :5470 empty).
  Every row carries witness: (raw path)#(line). Absent rule => the LAN fetch row is F18-INFRA and the arm is NOT ticked; the gate does not PASS without it.

## 5. Budget / windows
Disk 101 GB free 08:08Z; ws272-w3 pool 82 GB (incremental). Floor read before nextest (want ~80 GB before a full sweep). No golden in flight;
ci fires only on main push / PR / dispatch — open the PR after the battery. kitsubito 267 GB free. Rigs A/B + receiver LEFT UP on bccfaee8 bins.

## 6. Predictions (falsifiable, written before the run)
P1 all legs exit 0 at the composed head on both OS; P2 M1/M2/M3 each red EXACTLY the named cells and nothing else; P3 pin 2b happy path
serves bytes whose sha matches on the first attempt once the firewall rule is PRESENT; P4 the dev-rig refusal on rig B (no applied set,
no release-keys policy) is unsigned-exe, not sha-mismatch — record which fires; the two are distinguishable by name.
