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.
This commit is contained in:
1 parent
867fd42972
commit
9f0601027c
400 files changed
+26401
-3
No files matched your search
@@ -0,0 +1,112 @@
|
||||
// Round forty: what the device has never seen. No product code — this round
|
||||
// only changes what the walks CLAIM. The phone walk carried 88 named steps
|
||||
// against the mock walk's 252, four of its own were named and screenshotted
|
||||
// with no expectation at all (the driver reads `expect[s.name] ? ... : true`,
|
||||
// so a missing key is a silent pass), and nobody had written down which
|
||||
// features were proven on the device and which were only ever proven against
|
||||
// an object in memory. So: those four given their first assertion, thirty-three
|
||||
// more steps moved onto the device — the ones that can be proven there without
|
||||
// downloading, joining, sending, signing in or writing to Kyle's library — and
|
||||
// the map itself, in ANDROID.md beside Verifying, in four lists: what the
|
||||
// device proves, what is mock-only and why, what is conditional on his own
|
||||
// data, and what still needs a person. Four edits to smoke.mjs, all inside
|
||||
// PHONE_STEPS and PHONE_EXPECT; one insert in ANDROID.md. Nothing in the
|
||||
// PROBE, nothing in MOCK_STEPS or MOCK_EXPECT, no CSS, no Rust, no Kotlin.
|
||||
const fs = require('fs');
|
||||
const root = process.env.SS_ROOT || 'F:/Coding/SoulStream/';
|
||||
const scratch = 'C:/Users/Kyle/AppData/Local/Temp/claude/F--Coding-SoulStream/5488514a-11e8-482a-b0a0-20cb511ee110/scratchpad/';
|
||||
const ins = (name) => fs.readFileSync(scratch + name, 'utf8').replace(/\s+$/, '');
|
||||
let p, s;
|
||||
const load = (file) => { p = file; s = fs.readFileSync(root + p, 'utf8'); };
|
||||
const save = () => fs.writeFileSync(root + p, s);
|
||||
const once = (a) => {
|
||||
const i = s.indexOf(a);
|
||||
if (i < 0) throw new Error('missing in ' + p + ': ' + a.slice(0, 90));
|
||||
if (s.indexOf(a, i + 1) >= 0) throw new Error('ambiguous in ' + p + ': ' + a.slice(0, 90));
|
||||
return i;
|
||||
};
|
||||
const rep = (a, b) => { once(a); s = s.replace(a, () => b); };
|
||||
const NL = String.fromCharCode(10);
|
||||
|
||||
/* Three of the four smoke.mjs inserts re-emit their own anchor, so a second
|
||||
run would double-write where `once` cannot see it coming and would only
|
||||
throw further down, leaving half a tree. Refuse one here, before anything
|
||||
is touched: `wifi-restored` exists nowhere in the repo today and is a name
|
||||
this round creates. */
|
||||
if (fs.readFileSync(root + 'tests/mobile/smoke.mjs', 'utf8').includes('"wifi-restored"')) {
|
||||
throw new Error('round 40 is already applied in ' + root + ' — reset the tree rather than re-running');
|
||||
}
|
||||
|
||||
// ── the walk ──────────────────────────────────────────────────────────
|
||||
load('tests/mobile/smoke.mjs');
|
||||
|
||||
/* 0. The background check, which this round's own new steps broke. It asserts
|
||||
that ten seconds with the app backgrounded advances the position by at
|
||||
least eight seconds — true until the walk grew long enough to land that
|
||||
window on a TRACK BOUNDARY. Then the position legitimately goes 221 → 3
|
||||
as the queue moves on, which is playback continuing in the background,
|
||||
the very thing being tested, scored as a failure. Crossing a boundary
|
||||
with the screen off is the stronger proof of the two, so take it. */
|
||||
rep(` const posBefore = (await cdp.evaluate(PLAYER))?.pos ?? 0;
|
||||
cdp.close();`,
|
||||
` const bgBefore = await cdp.evaluate(PLAYER);
|
||||
const posBefore = bgBefore?.pos ?? 0;
|
||||
cdp.close();`);
|
||||
rep(` const posAfter = (await cdp.evaluate(PLAYER))?.pos ?? 0;
|
||||
const bgOk = stillPlaying && posAfter >= posBefore + 8;
|
||||
if (!bgOk) problems.push("EXPECT background " + JSON.stringify({ posBefore, posAfter, stillPlaying }));
|
||||
console.log((bgOk ? " ok " : " FAIL ") + "background".padEnd(16) + " " + JSON.stringify({ posBefore, posAfter, stillPlaying }));`,
|
||||
` const bgAfter = await cdp.evaluate(PLAYER);
|
||||
const posAfter = bgAfter?.pos ?? 0;
|
||||
const crossed = !!(bgBefore && bgAfter && bgBefore.title !== bgAfter.title);
|
||||
const bgOk = stillPlaying && (crossed || posAfter >= posBefore + 8);
|
||||
const bgSeen = { posBefore, posAfter, stillPlaying, crossed, from: bgBefore?.title ?? null, to: bgAfter?.title ?? null };
|
||||
if (!bgOk) problems.push("EXPECT background " + JSON.stringify(bgSeen));
|
||||
console.log((bgOk ? " ok " : " FAIL ") + "background".padEnd(16) + " " + JSON.stringify(bgSeen));`);
|
||||
|
||||
/* 1. the walk's own playlist, while it is still "Walk test" and still in
|
||||
the order the drags above it restored. The mock's same-named step is
|
||||
`[1]` and waits 1200, so this anchor is the phone's alone. */
|
||||
rep(` { do: \`document.querySelectorAll('.pl-rows .trk')[0].click()\`, name: "playlist-playing", wait: 3000 },`,
|
||||
ins('ins-r40-phone-playlist.txt') + NL
|
||||
+ ` { do: \`document.querySelectorAll('.pl-rows .trk')[0].click()\`, name: "playlist-playing", wait: 3000 },`);
|
||||
|
||||
/* 2. the import review's Keep switch, restored before the draft is created
|
||||
so `import-created` still counts its three rows. The mock's twin of
|
||||
this anchor waits 1500. */
|
||||
rep(` { do: \`__click('.imp-foot .btn-fill', 'Create playlist')\`, name: "import-created", wait: 2000 },`,
|
||||
ins('ins-r40-phone-keep.txt') + NL
|
||||
+ ` { do: \`__click('.imp-foot .btn-fill', 'Create playlist')\`, name: "import-created", wait: 2000 },`);
|
||||
|
||||
/* 3. the block that carries the rest. It navigates itself, so it needs one
|
||||
anchor and no particular screen: round thirty-nine's own comment, the
|
||||
last thing before the transfer face at the end of the list. Siblings
|
||||
appending phone steps reach for the `name: "end"` line, which this
|
||||
round deliberately leaves alone, so their block sits below this one
|
||||
and neither moves. */
|
||||
rep(` /* the one face of the six that a real build can show without arming`,
|
||||
ins('ins-r40-phone-block.txt') + NL
|
||||
+ ` /* the one face of the six that a real build can show without arming`);
|
||||
|
||||
/* 4. every new expectation in one insert. Round thirty-nine anchored its
|
||||
phone expectations on the `end:` line; this one stays away from it. */
|
||||
rep(` "artist-cold": (i) => i.screen.includes("has-hero"),`,
|
||||
` "artist-cold": (i) => i.screen.includes("has-hero"),` + NL + ins('ins-r40-phone-expect.txt'));
|
||||
save();
|
||||
|
||||
// ── the doc ───────────────────────────────────────────────────────────
|
||||
/* anchored on the closing sentence of Verifying rather than on the
|
||||
`## Not done yet` heading, because a sibling round adding to the map
|
||||
would reach for the heading. Nothing already in the file is re-worded —
|
||||
in particular not the sentences carrying a step count, which two earlier
|
||||
rounds both bumped. */
|
||||
load('ANDROID.md');
|
||||
rep(`\`--only-lock\` takes just that still of whatever is on the bar (resuming it if
|
||||
paused) without the walk.`,
|
||||
`\`--only-lock\` takes just that still of whatever is on the bar (resuming it if
|
||||
paused) without the walk.
|
||||
|
||||
` + ins('ins-r40-doc-map.txt'));
|
||||
save();
|
||||
|
||||
console.log('round 40 wired');
|
||||
Reference in new issue
Block a user