Files
SoulStream/handoff/rounds/ins-r41-steps.txt
T
KeelrLeek 9f0601027c android: the handoff — the pending rounds, the pipeline, and what is unverified
Everything written this session that has not been through the device: rounds 43
to 48 (each patch adversarially verified, 43's transient-notice expectation
fixed), a partial round 49, the pipeline scripts, the Android Auto design and
the icon comparison mock. Also the two harness changes that were never A/B'd —
adaptive waits, which may only shorten a declared wait and never lengthen it,
and a ship that runs the mock walk and the deploy at the same time. The A/B and
its 255-step baseline are in handoff/tools; main stays at what the phone has
actually walked.
2026-09-14 07:57:41 -05:00

161 lines
9.8 KiB
Plaintext

/* ── the long session ─────────────────────────────────────────────
Every walk before this one was minutes long. A phone runs the app
for hours, and nothing in the port had ever been looked at for a
leak. This block is both the instrument and the assertion.
The registry is installed by a STEP rather than through
Page.addScriptToEvaluateOnNewDocument, and that is load-bearing: the
first-run block above reloads three times and reattach() opens a NEW
DevTools session, so a script registered on the old one is gone for
the rest of the run. Installed from here it covers exactly the laps
the assertion is about, and the last step takes it out again. It
wraps addEventListener/removeEventListener (holding a WeakRef to
anything that is not window or document) and the four timer
functions, and it counts only what was registered AFTER it went in
and is still ATTACHED. Attached, because the naive counter — add
minus remove — climbs about twelve a lap in this app and none of it
is a leak: {#key nav.seq} replaces the .screen element on every
navigation and the old element's scroll handler goes with it. After
the install, because nothing can be registered before it: the
absolute count is therefore small (two after the whole walk, eight
from a settled boot) and only the DELTA across the laps is the
measurement. A listener or an interval stranded once a lap shows as
+9 in one and +9 in the other; it was driven to check.
Then two laps to warm, a reading latched into __ssBase, nine more
laps, and a second reading. A lap is the five tabs, the Library, a
record, Play, the mini bar, all three faces of the sheet, the artwork
viewer, a row's half sheet, the artist page (a catalog lookup) and
back — about five seconds each, and fifty in all. The lap count is
what makes the assertion sharp: a one-per-lap leak shows as +9
against a headroom of four, and trimming it to save time blunts the
only thing this block is for.
Nothing here reaches the network or the disk beyond what any other
mock step does, and the last step puts the Library back on whichever
section the walk left it on. */
{ do: `
window.__ssLibTab = (function () { try { return __ss.nav.stacks.library[0].c.tab || 'albums'; } catch (e) { return 'albums'; } })();
window.__ssLapN = 0;
window.__ssLap = function (n) {
var nap = function (ms) { return new Promise(function (r) { setTimeout(r, ms); }); };
var tap = function (sel, text) {
var all = document.querySelectorAll(sel);
for (var k = 0; k < all.length; k++) if (!text || (all[k].textContent || '').indexOf(text) >= 0) { all[k].click(); return true; }
return false;
};
/* the app's own back, never history.back(): walking off the
history mirror leaves file:// and the page is simply gone */
var peel = async function () {
for (var b = 0; b < 8; b++) {
var nv = __ss.nav;
if (!nv.timing && !nv.viewer && !nv.half && !nv.sheet && nv.stacks[nv.tab].length === 1) return;
__ss.back();
await nap(190);
}
};
return (async function () {
for (var i = 0; i < n; i++) {
/* the counter is global, not the loop's own: the laps
run in threes, and a lap that always opened the same
record would stop asking for anything new after the
first call and quietly measure nothing */
var which = window.__ssLapN++;
__ss.go('search'); await nap(90);
__ss.go('community'); await nap(90);
__ss.go('you'); await nap(90);
__ss.go('library'); await nap(200);
tap('.segtabs button', 'Albums'); await nap(260);
var rel = document.querySelectorAll('.grid2 .release');
if (rel.length) { rel[which % rel.length].click(); await nap(440); }
tap('.rec-acts .disc'); await nap(440);
tap('.mini'); await nap(380);
var fb = document.querySelectorAll('.fbtn');
for (var f = 0; f < fb.length; f++) { fb[f].click(); await nap(110); }
tap('.np-art'); await nap(240);
/* peeled one layer at a time and only if it opened: a
record with no cover never opens the viewer, and a
blind pair of backs would pop the album page instead
and take the rows below with it */
if (__ss.nav.viewer) { __ss.back(); await nap(220); }
if (__ss.nav.sheet) { __ss.back(); await nap(260); }
var trk = document.querySelector('.trk .r');
if (trk) { trk.click(); await nap(260); tap('.scrim'); await nap(220); }
tap('.rec-artist'); await nap(620);
await peel();
__ss.go('home'); await nap(160);
}
return n;
})();
};
(function () {
if (window.__ssCount) return 'already';
var recs = [], liveT = new Set(), liveI = new Set();
var ael = EventTarget.prototype.addEventListener, rel = EventTarget.prototype.removeEventListener;
EventTarget.prototype.addEventListener = function (t, f) {
try { recs.push({ t: t, f: f, w: (this === window || this === document) ? null : new WeakRef(this), dead: false }); } catch (e) {}
return ael.apply(this, arguments);
};
EventTarget.prototype.removeEventListener = function (t, f) {
try { for (var i = recs.length - 1; i >= 0; i--) if (!recs[i].dead && recs[i].t === t && recs[i].f === f) { recs[i].dead = true; break; } } catch (e) {}
return rel.apply(this, arguments);
};
var st = window.setTimeout, ct = window.clearTimeout, si = window.setInterval, ci = window.clearInterval;
window.setTimeout = function (fn, ms) {
var id, rest = [].slice.call(arguments, 2);
var w = typeof fn === 'function' ? function () { liveT.delete(id); return fn.apply(window, arguments); } : fn;
id = st.apply(window, [w, ms].concat(rest)); liveT.add(id); return id;
};
window.clearTimeout = function (id) { liveT.delete(id); return ct.call(window, id); };
window.setInterval = function () { var id = si.apply(window, arguments); liveI.add(id); return id; };
window.clearInterval = function (id) { liveI.delete(id); return ci.call(window, id); };
/* a listener is LIVE when its target is window, document, or an
element still in the tree; a timer is live until it fires or
is cleared */
window.__ssCount = function () {
var n = 0;
for (var i = 0; i < recs.length; i++) {
var r = recs[i];
if (r.dead) continue;
if (r.w === null) { n++; continue; }
var el = r.w.deref();
if (el && el.isConnected) n++;
}
return { listeners: n, timeouts: liveT.size, intervals: liveI.size };
};
/* and hands the page back exactly as it was found. A sibling
round appending after this block must not inherit a patched
EventTarget or a patched clock; __ssCount and __ssBase go
with them, so every later probe reads the -1 that means
'nothing has measured this' rather than a frozen number. */
window.__ssUninstall = function () {
EventTarget.prototype.addEventListener = ael;
EventTarget.prototype.removeEventListener = rel;
window.setTimeout = st; window.clearTimeout = ct;
window.setInterval = si; window.clearInterval = ci;
delete window.__ssCount; delete window.__ssBase; delete window.__ssUninstall;
return 'removed';
};
return 'installed';
})()
`, wait: 500 },
{ do: `__ssLap(2)`, name: "session-warm", wait: 1200 },
/* the baseline, taken after the warm laps have settled and their own
probe has run — __ssCensus is defined by the probe itself */
{ do: `window.__ssBase = window.__ssCensus(); true`, wait: 300 },
/* nine laps, in threes: cdp.send() gives a step forty-five seconds to
answer and a lap is about five, so one call of nine times out, the
walk records a failure it did not have, and the probe lands in the
middle of a lap instead of at Home */
{ do: `__ssLap(3)`, wait: 400 },
{ do: `__ssLap(3)`, wait: 400 },
{ do: `__ssLap(3)`, name: "session-late", wait: 1400 },
/* back to Home with nothing open, the Library on the section the walk
was using before this block, and the registry out of the page, so
whatever is appended after this finds the app — and the platform —
where the block above left them. This step's own probe therefore
reports -1 for every grew* field, which is the sentinel for
'nothing has latched a baseline': session-late is where the numbers
are. */
{ do: `__settle(); try { __ss.go('library'); __ss.patch({ tab: __ssLibTab }); __ss.go('home'); } catch (e) {} try { __ssUninstall(); } catch (e) {} true`, name: "session-clear", wait: 1000 },