fix(settle): arm the dismissal confirmation on the producer's presented-surface fact
Closes #3470. Builds on #3522 (merged).
Summary
The iOS 1.5 s dismissal confirmation (#1831) now reads the producer's presented-surface fact (#3565):
absentrules it out: nothing was presented, so a tab switch or push keeps the plain window.presentedarms it, even on a rootless first capture.unknown, or no fact, keeps the parent's arming, so the fact can only narrow the guard.
A stored tree outdated by a later side effect drops its fact, so an absent read taken before a sheet opened cannot disarm that sheet's dismissal. Help text updated. 10 files.
Validation
927d2ce57, iPhone 17 Pro sim, RN lab Release build (the dev client's floating button makes every screen unknown, per #3578).
| Route, 4 reps | Baseline | waitedMs | Late diff snapshot -i |
|---|---|---|---|
| (a) selector press close | presented, 4 nodes | 1694–1887 | empty |
(b) snapshot, then @ref close | presented, 6 nodes | 1824–1857 | empty |
(c) back --settle, Contacts New Contact sheet | presented, 70 nodes | 1784–1801 | empty |
(d) same sheet, press x y close | presented, 70 nodes | 2524–2865 | empty |
| (e) selector tab switch | absent | 627–778 | empty |
Tab switch, same device and route: | base 40d868233 1829–1872 ms | head 627–778 ms |.
A full-screen modal reads unknown, so it keeps the confirmation. Each fact branch has a unit or daemon case that fails under mutation.
pnpm check:affected --run --base origin/main at fea0bb95a (rebased on main after #3522 merged): all runnable checks passed, 535 test files, 4,060 tests, Fallow clean on 10 files, under the host lock. The device runs above were taken at 927d2ce57. Since then the only change is help text, and the rebase onto #3522's squash is identical in content.
🤖 Generated with Claude Code