29 KiB
P3 Interaction runtime: evidence log
Package card: PLAN §2.3 "P3 Interaction runtime". Contract: docs/phase2/contracts/interaction.md. Review: docs/phase2/wp/P3-review-R1.md.
Status
- Maintenance session 4 (2026-10-07 13:40-14:30 EDT, platform maintainer): REQ Coordinator->P3 (PLAN R2-8) done. P3-D4 is decided: §1.13's 0.8 s / 0.2 s are delays,
tipQuickstays off (S29) and stays a test switch, and IN-7 is scored by the amended criterion (PLAN §2.3 P3).contracts/interaction.md§0, §4.1 and §8 already cite R2-8 (no "pending"); REQ P3->V1 no longer asks fortipQuick. IN-7 by R2-8: the run the coordinator cited (s3k, 08:17, quiet device) meets every clause on both inputs (table below). Re-runs this session on the busy shared device (runner/tmp/lgs/p3/p3run.py, now also scoring R2-8,pass_r2_8_default): laser passes every clause in 3 of 4 runs (materialize start 836-839 ms; one at 846 ms); the pad path fails only "materialize starts 800 ± 40 ms" (3 valid runs): each time the samples stop for about 100 ms at the moment the tooltip shows (last sample at 790-797 ms, the next at 888-915 ms), so its first visible sample is 896-915 ms although the label timing puts the start at about 840 ms. Laser shows the same stall shorter (30-40 ms). Withwp.c1a,wp.c2b,c2bToggleoff for the step it is unchanged, so it is not another area's module. An isolated probe without the runner's per-framegetComputedStylesampling (Evidence "S4 probe") shows no frame gap when a tooltip appears, except once per window: the first show creates the window's tip node and style (30.7 ms synchronous, a 29-38 ms frame gap), later shows cost 1.3-1.8 ms with normal frames. Measured directly (the momentdata-stateturnsin, which starts the materialize, against the button'svgp_onfocus, one clock): 802, 803, 802 ms for the pad path, inside 800 ± 40. So the pad clause's miss in the runner is its own sampling cost while the thick-glass layer starts, not a late tooltip; the one-off first-show hitch is recorded, not changed (paid once per window and runtime install). IN-7 by R2-8: PASS (s3k on both inputs; this session laser on its own samples, pad by the direct start time and its own samples for every other clause; bar wrapper andm_mapTooltipsempty in every run). - Review R1 fixes done (session 3, 2026-10-07 07:32 to 08:25, Frame clock EDT, Steam build 11094443). All six findings are handled; see "Review R1" below. Every card test was re-run live on the final code: runs
s3ktos3n, 08:17 to 08:22, after the last sync at 08:16 and loaded with--reload. - M1 reached (2026-10-07). Contract written; modules
input,attention,states,tooltip(device/rt/04-input.jsto07-tooltip.js) load through P1's runtime behind flagwp.p3. - M3 reached, with one recorded deviation (re-verified 2026-10-07 08:22 on the final code). Every Build of the card is in.
- Pass in both input modes: IN-1 to IN-6, IN-8, IN-9, and the bar part of IN-7.
- Also pass: the extras IN-3b, IN-10 to IN-13, the leak test and the lazy-token test.
- IN-7 as written failed with the default timing (deviation P3-D4; decided in round R2, PLAN R2-8: the criterion is amended, see the maintenance note above). Measured on computed opacity, the label is at 0.07 at 900 ms, and the capsule is still at 1.0 250 ms after leaving. The cause: PLAN §1.13, D2 §11 and MO make 0.8 s and 0.2 s delays, which come before a 250 ms materialize and a 350 ms dematerialize.
- With flag
tipQuick(off by default), IN-7 passes as written on both inputs.
- What is live (behind
wp.p3):- input-mode signals on every popup, with
rt.input(mode,vrMode,state(),onChange,stub); - the global 80 ms laser dwell, and
rt.attend/rt.attention; - the light spot
--hx/--hy, and the classeslgs-pressed,lgs-focus-in,lgs-ring-checkandlgs-focus-disabled; - in-window tooltips (P4 thick glass, P5 materialize), the bar
ShowTooltip0.8 s wrapper, and flagtipQuick; rt.soundthrough Steam's bus, andrt.hapticas a dry run (S17).
- input-mode signals on every popup, with
- Remaining:
- (a) Done: the coordinator amended the card (R2-8);
tipQuickstays off. - (b) V1 decides whether
wp.p3is on by default (REQ below). - (c) M5 (V2 acceptance). After that, delete the prototype
device/proto/input_mode.js(PLAN §6). - Wearer-only items stay outside the card's tests: SteamVR's own grip mode toggle (
onChangereasonvr-mode/vr-overlay-focus, wired from source as in IM §2.1), and how a haptic feels. Haptics stay disarmed (S17).
- (a) Done: the coordinator amended the card (R2-8);
- How to re-run the tests:
- Runner:
<scratch>/p3/p3run.py, where scratch is this workflow's scratchpad. A copy lives at/tmp/lgs/p3/p3run.pyon the Frame until a reboot. - What a run does: it runs inside one
lab.Lockstep and turnswp.p3on throughrt.test.flags.push. It drops haptic, affordance and sound playback calls (IM §9). It drives the laser with CDPInput.dispatchMouseEventon the popup's own target. At the end it restores the pointer to (1400, 900), the pad source, the route and the interceptions. - Command:
sh run.sh NAME [--reload] [--media reduce] TESTS…, run from the scratch folder. It waits up to 240 s for the lab lock. - Tests:
in1 in2 in3 in3x in3b in4 in5 in6 in7 in8 in10 in11 in12 in13 idx selset shot.in9andleakrun outside the flag block. - Output: each
out_NAME.jsoncarriest0/t1(Frame clock) and the Steam build. - Offline checks:
node --expose-gc <scratch>/p3fix/offline.js. It covers fail-closed installs of all four modules, the chunk record, weak marks and lazy tokens.
- Runner:
Requests
- REQ P3->Coordinator: please rule on IN-7 (P3-D4).
- Coordinator (2026-10-07, round R2): your proposal adopted with tolerances from your own measurements: §1.13's delays stand; IN-7 now passes on "nothing before 760 ms; materialize starts 800 ± 40 ms; label ≥ 0.9 by 1100 ms; leave starts 200 ± 40 ms; label 0 by 460 ms, node hidden by 640 ms; a return within 200 ms keeps ≥ 0.9;
m_mapTooltipsempty" (PLAN §2.3 P3); C9 follows it;tipQuickstays off (S29) (PLAN §1.19 R2-8). Follow-up REQ Coordinator->P3 inwp/coordinator.md. - The conflict. The card says "None at 500 ms; the label at 900 ms; gone ≤ 250 ms after leaving". PLAN §1.13 ("0.8 s in and 0.2 s out") and D2 §11 ("After 0.8 s, materialize 250 ms | 0.2 s, dematerialize 350 ms", MO §4.17, Apple's WWDC24 sample) make both numbers delays. Under those, the label reaches 0.9 at about 1045 ms, and the capsule is gone about 565 ms after leaving (measured, Evidence IN-7).
- Proposal. Amend the IN-7 pass criterion to: "none at 500 ms; the materialize starts 800 ± 40 ms after attention; label ≥ 0.9 by 1080 ms; the leave starts 200 ± 40 ms after attention ends; the node is hidden by 600 ms;
m_mapTooltipsempty after cleanup". C4a's C9 (concepts/controls.md§18.2) repeats the card's numbers and needs the same amendment. - If you keep the card instead. Flag
tipQuickalready meets it (all checks pass, both inputs), and V1 can turn it on indefaults.json. The cost is laser jitter. A laser that leaves and returns within about 180 ms makes the capsule dip to about 0.6 instead of staying solid. If it returns later, the tooltip is gone and waits the full 0.55 s again.
- Coordinator (2026-10-07, round R2): your proposal adopted with tolerances from your own measurements: §1.13's delays stand; IN-7 now passes on "nothing before 760 ms; materialize starts 800 ± 40 ms; label ≥ 0.9 by 1100 ms; leave starts 200 ± 40 ms; label 0 by 460 ms, node hidden by 640 ms; a return within 200 ms keeps ≥ 0.9;
- REQ P3->C4a: FYI, no change in your files is requested. C9's timing ("its
aria-labelat 900 ms; gone ≤ 250 ms after leaving") inherits P3-D4. With the default timing it fails exactly as P3's IN-7 does, and with--flags wp.p3,tipQuickit passes. Please score C9 per the coordinator's ruling on REQ P3->Coordinator. - REQ P3->V1: please set
"wp.p3": trueindevice/defaults.jsononce you agree.- P3 is at M3 (evidence below). The R1 review's leak (F1) is fixed and verified live.
- Every T2/T3 consumer (
attentionindeps: C1a More circle and frozen target, C2a ramp, tooltips) staysblockedwhilewp.p3is off. With it off, CSS keeps the documented fallbacks (contracts/interaction.md §1.1). - (2026-10-07, session 4) No
tipQuick: PLAN R2-8 keeps it off (S29); only"wp.p3": trueis asked.
- REQ P3->P4: a
--lgs-shadow-5mmtoken (CTL §11: in-window tooltips sit at owner + 5 mm as a CSS shadow; by your rule y .4 px/mm, blur 1.2 px/mm:0 2px 6px rgb(0 0 0 / .30)).07-tooltip.jsalready readsvar(--lgs-shadow-5mm, 0 2px 6px rgb(0 0 0 / .30)). P4 (2026-10-07): done:--lgs-shadow-5mm: 0 2px 6px rgb(0 0 0 / .30)intheme/00-tokens.nowrap.css(live) and the kit; contracts/tokens.md §1.7.
Decisions taken without the user (PLAN §1.17 rule)
| # | Question | Decision (safe default) | Where |
|---|---|---|---|
| P3-D1 | (superseded by P3-D4, review R1 F2) IN-7 "gone ≤ 250 ms" vs PLAN §1.13 + MO | Was: IN-7 scored on the start of the leave. Withdrawn: IN-7 is now scored on computed opacity, and the conflict is recorded as a deviation (P3-D4) | — |
| P3-D2 | Lab tests by other packages use L.hover, which sends untrusted events and cannot set :hover |
Attention accepts untrusted hover by tracking the last mouseover target (trusted events keep the stricter :hover check). No change for real laser input |
05-attention.js, contract §2 |
| P3-D3 | Tooltip look source | P4's thick material and edge hook plus P5's lgs-mat-* keyframes (instead of private keyframes), zero-specificity so C3a/C1a can restyle |
07-tooltip.js |
| P3-D4 | IN-7 ("label at 900 ms; gone ≤ 250 ms after leaving") contradicts PLAN §1.13 / D2 §11 / MO §4.17 (0.8 s and 0.2 s are delays before a 250 ms materialize and a 350 ms dematerialize) | Default: PLAN §1 timing, because §1 decides conflicts and it matches Apple's sample. IN-7 as written is recorded as FAIL (deviation), and a coordinator ruling is requested. Flag tipQuick (off) implements the card's literal timing with tokens only: materialize starts at 550 ms (fully in at 800 ms), no leave grace, and the dematerialize runs on --lgs-d-reduce (180 ms). A return to the same owner during the leave brings the tooltip straight back (data-resume) |
07-tooltip.js, contract §0, §4.1 |
| P3-D5 | When does a laser leave start? | At the attended element's own mouseout (to an element outside it). It used to start at the next element's mouseover, which Steam's handlers held back by about 70 ms (measured: mouseout at 1273 ms, mouseover at 1342 ms). leaveMs: 0 now leaves in the same task instead of on a 0 ms timer, which Steam's D-pad work delayed by about 100 ms |
05-attention.js, contract §2.2 |
New strings
None. Tooltip text always comes from the owner (data-lgs-tip-text, aria-label, title). The test strings used by the runner ("Glass test tooltip", "Pad test tooltip", "Options", "Leak test", "Now tip") exist only inside the locked test step.
Review R1 (session 3)
| # | Finding | Fix | Evidence (live rows below) |
|---|---|---|---|
| F1 major | Detached-DOM leak: states.st.touched and attention.st.marked |
Both sets were removed. In 04, the sticky-marks registry is now weak (WeakMap element → classes, plus a WeakRef set used only for sweeps, pruned of collected elements and closed documents). The last pointer target, the spot host and the tooltip's last owner are WeakRefs. Removal sweeps every live window (classes, [style*="--hx"], .lgs-tip) and calls marks.sweep. The live leak test found a second leak, also fixed: if a feed attention was re-entered by the laser, it kept source: 'feed', so the laser's leave never ended it. That held the element and even showed its tooltip after the pointer had left. The input that enters last now owns the attention |
leak PASS (runs s3g 08:05 and s3k 08:17): control collected, and with P3 on the node is collected in all three variants. The reviewer's own harness (08:06) went from alive to collected. Offline: an 8 MB marked element is collected under --expose-gc |
| F2 major | IN-7 scored on DOM state, reported PASS | The runner now samples the computed opacity of the capsule and the label every frame. The leave sampler is armed in the page before the pointer moves, so there is no CDP round trip in the measurement. IN-7 is scored as written: default FAIL (deviation P3-D4), tipQuick PASS. M3 is qualified in the Status |
IN-7 row (s3k 08:18; also s3h 08:07) |
| F3 minor | input not fail-closed; same order in 05/06/07 |
Each module sets st.remove right after live = st, before its first subscription. In 04, every Steam subscription registers its undo the moment it is made, both in undo and with P1's tracked rt.cleanup (run once). All public members go through rt.expose, with plain assignment only as a fallback |
Offline (p3fix/offline.js): input throwing at each of 6 points (with and without P1's scope) leaves 0 subscriptions and 0 API members. attention, states and tooltip throwing late leave 0 listeners. The reviewer's failclosed.js reads 0 in all four cases, and node now exits (no leaked interval) |
| F4 minor | [Symbol(lgs-p3-input)] left in webpackChunksteamui |
Steam's require is taken once per page load and cached. The record is spliced out at once, and records left by earlier builds are cleaned | IN-9 (s3k): webpackChunksteamui.length 221 → 221 → 221, records of ours 0 (s3f: 177 → 177 → 177; s3h: 190 → 190 → 190) |
| F5 minor | Logged times did not match the artifacts; the shot predated the final code | Rows below are replaced with session-3 runs. Each time comes from the runner's own t0/t1 stamp (Frame clock). The live shot was re-taken with the final code (08:20) and the comparison rebuilt. Key numbers are copied into this log. The session-2 rows were removed. Their true file times (per the review) were r2a 05:15, r2b 05:16, r2c 05:20, r2d 05:21, r2e 05:24, r3a 05:29 and r3b 05:30, not the 05:27 to 06:07 logged |
this table; shots/p2_p3_tooltip_live.png, shots/p2_cmp_p3_tooltip.png (08:21) |
| F6 minor | %{Token} selectors resolved once at install |
rt.input.lazySel(list) is P3-internal and shared by 05/06/07. It resolves on use, drops unresolved parts, and retries at most once a second until every token resolves. Coverage: the ring, disabled, spot, press and spot-host selectors, rt.attend / rt.tooltip.register string targets, and dwellSelector. New diagnostics: rt.states.selectors(). New test hook: rt.input.test.index(fake), which affects P3 only |
idx and selset PASS (s3k; idx also s3f, s3h) |
| extra | IN-3 failed once in s3a (07:48): Steam swapped the card's child under a still pointer, and Chromium sent the new mouseover 422 ms late |
When the 80 ms dwell timer finds the old element no longer hovered, the card now under the laser (the document's :hover chain) inherits the dwell |
in3x 3/3 three times (s3b, s3h, s3k) |
Evidence
Common conditions. Steam build 11094443 and the final code, synced at 08:16 and loaded with --reload in s3k. Every row is one locked step (lab.Lock) with wp.p3 on through rt.test.flags.push, popped at the end. Steam's haptic and affordance calls and PlayAudioURL were intercepted and dropped, so nothing played and nothing pulsed; P3's own haptic calls were 0 in every run. Each step sent the pointer to (1400, 900), restored the pad source (padSource: 1) and restored the starting route. Outputs: <scratch>/p3/out_<run>.json, with times from the runner's t0–t1 (Frame clock, EDT). The main run is s3k: sh run.sh s3k --reload in9 leak idx selset in1 in2 in3x in3b in4 in5 in6 in7 in8 in10 in11 in12 in13, 08:17:29–08:19:19.
| Test | Run, time | Command | Result | Artifacts |
|---|---|---|---|---|
| offline | 08:16 | node --check device/rt/0[4-7]-*.js; python glass.py check-theme; node --expose-gc p3fix/offline.js; reviewer's p3rev/failclosed.js |
PASS. The bundler reports 45 files; fail-closed, chunk, weak-mark and lazy-token checks as in "Review R1" | p3fix/offline_out.json |
| IN-1 input classes on every popup | s3k |
in1: pad source first, CDP mouseMoved ×5 on main, then L.pad('down') |
PASS. All 9 live popups (VR, VRKeyboard, VRNotificationToasts, bar, barpopup, tooltip, volumelevel, floatingfooter, frame.menu) went pad → laser on the move and → pad on the press. onChange fired pad→laser and laser→pad (reason source) |
out_s3k.json |
| IN-2 input stub | s3m 08:20:34 |
sh run.sh s3m in2: from the live gamepad source; rt.input.stub('laser', {vrMode: 'laser'}), restore(), then P1's rt.test.input.set('laser') / set(null) |
PASS. Our classes went pad → laser → pad on all 9 popups at each step. NavigationSource.Value, IsInGamepadNav, the getter and both objects' own properties stayed identical. SteamVR's own mode was laser at the time (set outside this step), so the restored state is pad / laser. s3k failed only on the runner's old hard-coded gamepad; the runner now compares with the start state |
out_s3m.json |
| IN-3 dwell | s3k (also s3b 07:54 and s3h 08:07) |
in3x: in3 three times on /library/home (CDP hold on card 2, then a sweep over 5 cards at about 45 ms per card) |
PASS 3/3: .lgs-dwell at 80.5, 85.5 and 80.5 ms after the entering mouseover; 0 dwells in every sweep. Earlier runs gave 85.1 / 80.3 / 80.4 (s3b) and 83.6 / 80.3 / 80.3 (s3h) |
out_s3k.json |
| IN-3b lab hover (untrusted) | s3k |
in3b |
PASS: lgs-dwell and lgs-attend-80 set, then lgs-attend-300; current is the button; events enter,dwell,step300,leave; all cleared after the unhover |
out_s3k.json |
| IN-4 gamepad press | s3k |
in4 on /zoo/buttons (rt.states.test.feed, then one real L.pad('down') with a passive spy) |
PASS: lgs-pressed on A down, cleared 0 ms after the up, safety clear at 413 ms; B, D-pad and repeats ignored; preventDefault / stopPropagation never called; the real D-pad event (button 10) arrived un-prevented and set nothing |
out_s3k.json |
| IN-5 light spot | s3k |
in5 on /zoo/buttons |
PASS: --hx/--hy 25/50 %, 50/25 % and 75/75 %, written 1, 3 and 3 ms after each move; 0 writes while idle; 0 elements with --hx after the switch to pad |
out_s3k.json |
| IN-6 first focus frame | s3k |
in6 (P5's lgs-focus-in keyframe on .lgs-focus-in.gpfocus::after, 3 × D-pad) |
PASS 3/3: lgs-focus-in set in the vgp_onfocus task, before Steam's .gpfocus, and both present at the next frame; ::after 0.60 at t0 and 1.00 at 700 ms; class gone by 700 ms |
out_s3k.json |
| IN-7 tooltips (opacity-scored) | s3k |
in7. Laser: CDP hover on an icon-only 60 px test owner on /zoo/buttons; the leave goes to an empty page area inside the window, timed from the owner's own mouseout. Pad: a zoo button registered with force, timed from the real vgp_onfocus / vgp_onblur. Both run once in the default mode and once with tipQuick. Bar: CDP hover on the bar's "Launch Program" button |
Default: FAIL as written (P3-D4). "None at 500 ms" passes; "label at 900 ms" fails (0.066 laser, 0.077 pad); "gone ≤ 250 ms" fails (capsule 1.0, label 0.88 / 0.77). tipQuick: PASS as written on laser and pad. Bar: PASS: wrapper on, the entry has unDelayMS 800 and is not finished at 500 ms, finished at 900 ms; m_mapTooltips 0 after the pointer left. Timeline numbers in the next table |
out_s3k.json (also s3b–s3e 07:54–08:01, s3h 08:07) |
| S4 IN-7 by PLAN R2-8 | 2026-10-07 13:45, 14:06, 14:12, 14:21 (×2) EDT | cd /tmp/lgs/p3 && python3 -B p3run.py in7 in12 (runner now also scores R2-8: metrics.r2_8, pass_r2_8_default); the last run also with --flags wp.c1a=false,wp.c2b=false,c2bToggle=false |
Busy shared device (other agents' gates and native sessions between the runs). Laser (start / label 0.9 / leave / label 0 / hidden, ms): 846 / 1053 / 210 / 397 / 564 (start 6 ms over), 839 / 1091 / 208 / 396 / 563, 836 / 1054 / 209 / 396 / 552, 838 / 1054 / 212 / 399 / 555: every other clause and "no dip on return" pass in all runs. Pad (14:06, 14:21, 14:22): first visible sample 896, 915, 906 ms after a 98-103 ms frame gap that starts at 790-800 ms (the tooltip's show); label 0.9 at 1046-1053, leave 208-247, label 0 395-409, hidden 560-575: all pass but the start clause (one run's leave 247 ms, 7 ms over). Not counted: the 13:45 pad part (no tooltip and no gamepad attention events at all, like that run's in12: gamepad focus was not in the main window then) and the 14:12 run, which overlapped P8's own dm2 selftest (native mode started mid-run). Bar wrapper checks pass in every run; in12 errored twice on the zoo's button list (route left elsewhere by other agents), not counted |
/tmp/lgs/p3/out_s4*.json (RAM) |
| S4 pad materialize start, direct | 2026-10-07 14:41 EDT | glass.py js "<probe3>" --flags wp.p3 --mode pad on /zoo/buttons: a tooltip registered on a button (force); three times: focus away 0.7 s, then L.gpTakeEl(button) with a vgp_onfocus listener (SharedJSContext clock), 1.3 s, then rt.tooltip.state().shown[].shownAt (same clock: the moment the node turns in and its lgs-mat-glass-in starts) |
802, 803, 802 ms after the focus event: R2-8's "materialize starts 800 ± 40 ms" met on the pad path | console output |
| S4 probe: frames at the show | 2026-10-07 14:33, 14:36 EDT | glass.py js "<probe>" --flags wp.p3 on /zoo/buttons: rt.tooltip.show(btn) four times with rAF timing, plus a control mutation; then --mode pad with real gamepad attention (L.gpTakeEl) and a 1.3 s rAF gap log, with and without a registered tooltip, twice each |
show() synchronous cost 30.7 ms the first time in the window (node and style created), then 1.3-1.8 ms; frames after it 6-11 ms. Under attention: with a tooltip, gaps 38 ms at 799 ms and 29 ms at 857 ms on the first show, none on the second; without one, no gap (one unrelated 148 ms gap at 1183 ms). The runner's 100 ms pad gap is therefore not the tooltip's own cost; the first-show 30 ms is |
console output |
| IN-7 look | s3l 08:20 |
shot: rt.tooltip.show() on a 60 px test circle labelled "Options", over a game poster on /library/tab/AllGames; lab.capture('main') |
Thick-glass capsule 114 × 48 CSS px, 20 px Semibold, 12 px under its owner, no outline, E3 arc on the top edge; the poster shows through as blurred colour. It matches the mockup's "Options" capsule over a poster in size, weight, placement and material. The live capsule is lighter over this bright poster: worst label contrast 6.1 : 1 against the mockup's 8.3 : 1, both above 4.5 : 1 (P-39). Material density is P4's thick-glass token | shots/p2_p3_tooltip_live.png, shots/p2_cmp_p3_tooltip.png |
| IN-8 sounds (+ haptic dry run) | s3k |
in8 on /library/home |
PASS: activate → 21 (DefaultOk), and Steam's bus requested /sounds/deck_ui_default_activation.wav (intercepted); hover refused (null), 0 requests; 0 sound requests during a 5-card laser sweep; haptic plan {effect 3, available true, armed false, fired false}, 0 calls of ours |
out_s3k.json |
| IN-9 removal | s3k |
in9: counts, wp.p3 push, counts, pop, counts, sweep of every node of every popup |
PASS: navigationSource 10 → 11 → 10; vrNavigationType 1 → 2 → 1; MobX observers 16 → 17 → 16; popup created / destroyed 6 / 3 unchanged (P1's single pair); webpackChunksteamui 221 → 221 → 221 with 0 records of ours. Sweep: no P3 class, attribute, --hx/--hy, .lgs-tip or #lgs-tip-style; no P3 member on __LGS_RT; ShowTooltip is the prototype's again |
out_s3k.json (s3f, s3h: same) |
| leak (F1) | s3k (also s3g 08:05) |
leak. A node with an 8 MB payload is touched by the laser spot, dwell, an rt.attend registration, its tooltip, a synthetic A press (non-bubbling, our node only) and a pad focus / attention feed under the input stub. Then: (a) the pointer leaves the window and the page drops the node; (b) the node is dropped under a still pointer, then one move; (c) dropped with no further input. WeakRef, then CDP HeapProfiler.collectGarbage ×2 |
PASS: control (P3 off) collected; P3 on: (a), (b) and (c) collected, (c) even before any further input; marks.count() 0 afterwards. The first run (s3f 08:03) had (a) alive, which found the attention source bug fixed in "Review R1" F1 |
out_s3k.json, out_s3g.json, out_s3f.json; reviewer harness p3rev/out_s3_rev.json (08:06: withP3: collected) |
| lazy tokens (F6) | s3k |
idx: rt.states.selectors(); a fresh lazySel('%{FocusRing}, .p3t-x') under rt.input.test.index(fake index without FocusRing), then the real index again. selset: area setters with an unresolved token |
PASS: every states selector resolved; with the stand-in index, .p3t-x and resolved: false; still cached within 1 s; after 1.1 s ._1wPplsegQqCoe06wXPhzKT, .p3t-x and resolved: true. selset: an unresolved spotSelector / pressSelector falls back to the default list; a mixed one keeps its resolved parts |
out_s3k.json |
| IN-10 ring tag (CTL §4.5) | s3k |
in10 on /settings/notifications (44 check circles): L.gpTakeEl on a .DialogCheckbox, then on another Focusable |
PASS: focus in the checkbox, and its %{FocusRing} (40 px) carries lgs-ring-check; after the move no node keeps the class |
out_s3k.json |
| IN-11 disabled + focus (CTL §4.7) | s3k |
in11 on /zoo/buttons |
PASS: exactly the focused "Can't click me" button carries lgs-focus-disabled (P4's --lgs-dis = 1); removed after the move |
out_s3k.json |
| IN-12 attention, gamepad paths | s3k |
in12 on /zoo/buttons, focus by L.gpTakeEl only |
PASS: padImmediate fires enter, dwell, step400, step800 at once; a timed registration fires at 302 / 601 ms with source: 'pad'; away and back within 120 ms keeps it (hysteresis), while the leaveMs 0 one leaves and re-enters; leaving for 450 ms fires one leave and clears every class; current is the focused button; feed → enter:feed, dwell, leave; a padNow + above tooltip is in within 80 ms, above its owner, gone 650 ms after the blur |
out_s3k.json |
| IN-13 tooltip motion | s3k; s3n 08:22:20 (--media reduce) |
in13; sh run.sh s3n --media reduce in13 |
PASS: P5's lgs-mat-glass-in / lgs-mat-content-in at 250 ms and -out at 350 ms; nothing running 1.3 s after the leave; node hidden (P-52). Reduce Motion: all four at 180 ms, the glass animates opacity only, and the label keyframes are empty |
out_s3k.json, out_s3n.json |
| perf (idle cost) | 08:20:44–08:22:04 | python glass.py perf main --route /library/tab/AllGames --flags wp.p3, then the same without the flag |
Theme on: 53.4 fps with P3, 57.2 fps without; median 11.1 ms in both; 23 long frames in both. Theme off moved between 74.9 and 73.0 fps in the same runs. The difference is inside run-to-run noise. P3 does nothing per frame while the user is not pointing (listeners only; the spot writes at most once per frame while the laser moves, IN-5). The theme-on fps is lower than session 2's 71–77, for all three runs alike, so the theme has grown since. A first attempt at 08:11 ran during P10's native session and was discarded | console output |
IN-7 timelines (s3k, ms from attention start or end, computed opacity sampled every frame; "label" = capsule opacity × label opacity):
| Mode, input | Glass visible | Label 0.5 | Label 0.9 | At 900 ms (label) | Leave starts | Label gone | Capsule gone | Node hidden | At 250 ms after leave (capsule / label) |
|---|---|---|---|---|---|---|---|---|---|
| default, laser | 821 | 982 | 1048 | 0.066 | 233 | 420 | 588 | 588 | 1.0 / 0.88 |
| default, pad | 816 | 983 | 1049 | 0.077 | 223 | 416 | 568 | 581 | 1.0 / 0.77 |
tipQuick, laser |
564 | 730 | 796 | 1.0 | ≤ 106 (first sample) | 106 | 190 | 190 | hidden |
tipQuick, pad |
577 | 738 | 803 | 1.0 | ≤ 83 (first sample) | 210 | 223 | 223 | hidden |
- Repeatability.
s3h(08:07) gave the same picture: default laser 819 / 978 / 1045 / 0.068 / 213 / 400 / 566; default pad 818 / 986 / 1041 / 0.082 / 223 / 410 / 565;tipQuickcapsule gone at 186 ms (laser) and 209 ms (pad). - Laser jitter (the pointer leaves for about 100 ms and returns):
- Default: the tooltip never leaves. State is
inthroughout and the capsule stays at 1.0 (re-entrymouseoverat 200 ms ins3k, 189 ms ins3h). tipQuick: when the laser returns inside the 180 ms leave (176 ms ins3h), the capsule dips to 0.59 and is back at 1.0 75 ms after the return (data-resume). When it returns later (202 ms ins3k), the tooltip is already gone and needs the full 0.55 s again. That is the cost of having no grace, and why the default keeps PLAN §1's 0.2 s.
- Default: the tooltip never leaves. State is
- Earlier IN-7 runs found two timing faults, both fixed (P3-D5):
s3c(07:57): the laser leave started at 274 ms. Themouseoutcame at 1273 ms, but the new element'smouseovercame only at 1342 ms.s3c:tipQuickon the pad was gone at 294 ms, because the 0 ms leave timer ran after Steam's D-pad work.