## What this clears
All **17 failures** in `settings-mobile.test.tsx` — the second-largest
block in the dashboard `app:backfill 3/4` shard after the
TaskDetailModal file (#2885), and the **same root cause**.
## Probed, not assumed
Every failure read `expected null to be truthy`, which looks like the
modal never rendered:
```
PROBE container.settings-layout=false document.settings-layout=true
document.modal=true bodyLen=36637
```
`SettingsModal` mounts through `createPortal`, so its subtree hangs off
`document.body`, not the container `render()` returns. The markup is
there; the container-rooted lookup cannot see it.
## Nine of these assertions could never have failed
They are **absence** checks:
```ts
expect(container.querySelector(".settings-scope-banner")).toBeNull();
expect(container.querySelector("#settings-mobile-section")).toBeNull();
```
`container` is empty for this component no matter what, so these passed
on an **empty root** rather than on absence — they would have kept
passing if the element appeared. Converting them makes them mean what
they say. All nine still pass, so they were correct, just unproven.
## Two rounds of my own errors, both caught by measuring
1. A blanket `container` → `document` replace also rewrote
`renderResult.container.querySelector` into `renderResult.document...` —
**not a thing**. That broke the two *"embedded Settings surface"* star
tests. Because the embedded surface is genuinely not portalled, this
first read as *"embedded needs container"*. It doesn't; the JS was
simply invalid.
2. Fixed by restoring those seven, then converting them to **bare
`document`** once I confirmed each test unmounts its surface before
rendering the next (`modalRender.unmount()` precedes the embedded
render), so a document-rooted query cannot match a stale instance.
**Verified no regressions rather than assuming** — diffed the
failing-test list before and after: 13 fixed / 0 new, then the remaining
4 fixed. Every failure in the final state was already failing at the
start.
## Evidence
| | result |
|---|---|
| the file | **41/41** (was 17 failed) |
| shard `3/4` | **55 → 38** with this change alone |
| mutation: rename `.settings-layout` in `SettingsModal` | **1 failed**
|
`pnpm lint` clean. Test-only; `SettingsModal.tsx` restored clean.
## Together with #2885#2885 clears the TaskDetailModal file (30). Both are the same
portal/query-root defect in different files, and both were sitting
behind `app:app` in the runner's fail-fast — which is why they went
unnoticed. Shard `3/4` should land at **~8** with both applied.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>