← Commit history

Placement-invariant spec: one enforcement function, many triggers — from John's stranded agenda-monday window (user taskbar click activated a window parked 32000px off-screen). Next-session implementation spec plus the queued serialization and reparent items.

John Lauer ·9d38e8f0cc ·3mo ago ·parent 919185a
1 file changed +36
PLACEMENT-INVARIANT.mdadded+36
@@ -0,0 +1,36 @@+# The window-placement invariant (next-session spec, from John's 2026-07-26 stranding)++## The incident+`agenda-monday` was alive and healthy but parked at -32768,-32768 (the background-by-default+park). John clicked its taskbar button; Windows activated a window 32,000px outside every+monitor; it looked dead. Every backgrounded pup window carries this trap today.++## The invariant (one sentence)+A pup window is EITHER background-and-parked OR foreground-and-on-screen — never+foreground/user-activated while off-screen, and never on-screen while claiming to be parked.++## The process: ONE enforcement function, MANY triggers+Write a single `enforcePlacement(session, sessionId, cause)` that reads the real OS rect ++foreground state and repairs violations (slide on-screen if user-activated; re-park if a+background window drifted on-screen half-visible). Then call it from every layer:++1. **User-activation watcher (the big missing catch):** poll `osGetForegroundWindow()` every+   ~2s against parked sessions' HWNDs. A parked window that BECAME foreground = the user+   clicked its taskbar button = auto-slide on-screen. This makes plain left-click Just Work.+2. **Every reveal path:** raise_os_window, foreground:true opens, wiki_set_view's+   `bringToFront` on the unchanged-view branch (AUDIT: today it foregrounds without+   un-parking — same trap), focus_window from the jump-list header.+3. **Recovery:** after bridge restart, re-assert placement for every recovered session+   (windows survive restarts since 1.9.122, so stale park state now persists too).+4. **The periodic sweep:** the same maintenance loop that reaps orphans asserts the+   invariant and repairs violations.+5. **Visibility:** every auto-repair goes through `recordCleanup()` (the report-once queue)+   so the next AI caller and eventually John SEE that a window was rescued, per his design.+6. **Verb responses:** open/list responses should carry `parked: true|false` so AIs stop+   guessing where a window physically is.++## Also queued next session+- **#16 per-session serialization:** a slow `page.goto` queues eval/screenshot/list behind+  it → everything times out → "pup looks frozen". Navigation must not block reads.+- **Console-free reparent (parked):** 1.9.131 measurements — manual Start-Process launches+  fine, bridge-composed arg list does not. Diff the two command lines, re-land.