Files
software-mansion__argent/scripts/e2e-full/phases/40-chromium.sh
filip131311 b232114422 docs: audit every comment in src against the code it describes (#931)
Audits every comment in `src/` and `scripts/` against the code it
describes.

**462 files, 57 commits, net −8,194 lines.** Comment text only — the
whole branch is code-identical to `main`.

## Method

One subagent per file, strictly sequential. Scope was `src/` +
`scripts/` (459 files); three more files were added at the end because
they carried dead references of the same kind — two test headers citing
design docs that do not exist, and `publish-npm.yml` citing a retired
workflow. Each agent verified every comment — line, block, JSDoc, file
header, trailing — against the surrounding code and the rest of the
repo, following identifiers, paths, tool ids, config keys, env vars and
issue links to see whether they still exist and still behave as
described. Rules:

- **A false or misleading comment is deleted, not reworded.** If a claim
could not be confirmed by reading the source, it went. That is why the
deletion count is so much larger than the rewrite count.
- Survivors are cut to the shortest form carrying something the code
does not already say. Restatement, preamble, hedging, changelog prose
and ASCII banners are gone; the non-obvious *why* stays.
- Preserved byte-identical: license headers, pragmas and directives
(`@ts-*`, `eslint-disable`, shebangs, `/// <reference>`), JSDoc tag
tokens, everything inside a string or template literal, and the sole
comment inside an otherwise empty block (ESLint `no-empty` counts a
comment-bearing block as non-empty).

## Verification

Every file passed two independent gates before being recorded as done:

1. `comments-only` — the required check.
2. A second comment-stripping comparator with a proper mode stack,
written for this pass because `comments-only`'s flat scanner desyncs on
nested template literals and quote-bearing regex literals and then
reports comment lines as code changes. Two files hit that false FAIL
(`utils/android-profiler/pipeline/index.ts`,
`scripts/extract-tools.mjs`); in both the "changed code" it printed was
literally `//` lines, and the second checker confirmed the code was
byte-identical.

After the last file, all 462 changed files were re-checked against
`main` with the same comparator, rather than trusting any agent's
self-report. **459 code-identical; 2 are non-code (`.svg`, `.md`); 1
intentional.**

The intentional one is `packages/argent/scripts/bundle-tools.cjs`: the
changed template literal *is* the comment header of the file it
generates, `packages/native-devtools-android/src/bundled-meta.ts`.
Fixing only the generated file would have been reverted by the next
build, so the generator changed too — and it has been verified to
reproduce the committed generated file byte-for-byte.

## Representative false claims removed

Not wording nits — statements a reader would have acted on:

- **Reversed directions.** `proxyStart`'s JSDoc had the tunnel backwards
(it is a reverse tunnel: the host binds first and the simulator dials
in). A `paste()` doc had the pasteboard copy direction reversed.
- **Contradicted by the code below it.** A timeout budget multiplied by
three where the probes run concurrently — the same comment said so six
lines later. A "warn once" that warns on every call. A "binary search"
that is a linear scan.
- **Named things that do not exist.** A `vega-fast-cli` binary, a
`finish-recording.ts`, a `publish-next.yml` workflow, two
`profiler-react19-*.md` design docs, a `DebuggerTarget.ts`, a commit
hash git does not know, two tool ids, an `ensureEnv` cycle.
- **Wrong by construction.** "Welford accumulators" across four files
where the code keeps naive `n`/`sum`/`sumSq`; `sum`/`sumSq` documented
over `actualDuration` when reduce sums `selfDuration`; a strict-mode
halving written `n/2` where the code ceils; field docs listing enum
values the producers never emit.
- **Guarantees the code does not make.** A validation matrix claiming to
cover "EVERY tool" that skips flagless ones; a Pareto cutoff that
`slice(0, 20)` makes inert; an idempotence claim where the real rule is
at-or-ahead; a capability note describing a clean 400 the shape-based
device resolver can never produce.
- **Unverifiable assertions** about prebuilt binaries, external CLIs and
the cloud SDK — deleted rather than kept as folklore, since nothing in
the repo can confirm them.
- **Stale numbers**: invented Android tool versions, hard-coded tool
counts and description lengths that had drifted.

## Review

A Fable agent reviewed both halves adversarially for over-deletion,
misread code, `no-empty` hazards and byte-identity violations.
Second-half verdict: **SHIP**, with two one-line restores, both applied
in the final commit — the `npm view ""` rationale behind a blank-token
guard, and the note that `argent-mcp` keeps a copy of
`SECRET_PLACEHOLDER_MARKER` it cannot import.

## Code issues surfaced but deliberately not fixed

This pass changes comments only. Eight genuine findings are logged for a
follow-up:

1. `telemetry/src/consent.ts` — a non-ENOENT read error returns null and
falls through to the default-on path, so file errors *can* silently flip
telemetry on.
2. `chromium-server/navigation.ts` — `navigate()` is reachable from
`POST /api/navigate` with only a `typeof === "string"` check; open-url's
schema is a bare `z.string()`, so the "already validated by zod" premise
never held.
3. `http.ts` — `constantTimeEqual` returns early on a length mismatch,
so the auth token's length is observable.
4. `describe/index.ts:~114` — the ios-remote branch passes `{ isTvOs:
false }` unconditionally, so a remote tvOS simulator takes the iOS
ax-service path, though `isRemoteTvOsSimulator` exists and shake/paste
do use it.
5. `devices/boot-device.ts` — `-crash-report-mode never` is passed
unconditionally *and* appended again by the feature-detecting path, so
every emulator spawn passes it twice.
6. `react-profiler/pipeline/04-rank.ts` — `PARETO_THRESHOLD_PCT` is
dead: `slice(0, 20)` always wins.
7. `reaped-sessions.ts` — a user-facing hint string tells the agent that
`react-profiler-start { force: true }` disposes the debugger and
profiler session; it does not. Left byte-identical because it is a
string literal, not a comment.
8. `utils/simctl-backend.ts` — `localSimctl` is exported with no
importers anywhere.

## Docs

No documentation change is needed: this pass touches only source
comments, and no user-facing capability, tool, CLI flag, config key or
flow-file behaviour changed.

---------

Co-authored-by: filip131311 <f.kaminski2000@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 12:16:20 +02:00

190 lines
9.4 KiB
Bash

#!/usr/bin/env bash
# Phase 4 — Chromium / Electron tier (Linux + macOS).
#
# Generates a minimal Electron app and boots it through boot-device
# (electronAppPath). Electron is an argent optionalDependency, installed by
# run-e2e only when the chromium or rn phase is selected. resolveLauncher()
# prefers <app>/node_modules/.bin/electron, so the bundled binary is symlinked
# in. Needs a display on Linux.
_find_electron() {
find "$E2E_PREFIX" "$E2E_UNPACKED/.." -path '*/.bin/electron' 2>/dev/null | head -1
}
# Loads over http, not file://, so localStorage/sessionStorage have a storable
# origin — file:// origins are opaque and throw.
_gen_electron_app() { # electron-bin http-port -> echoes app dir
local ebin="$1" httpport="$2" dir="$E2E_WORK/electron-app"
mkdir -p "$dir/node_modules/.bin"
ln -sf "$ebin" "$dir/node_modules/.bin/electron"
cat > "$dir/package.json" <<'JSON'
{ "name": "argent-e2e-electron", "version": "0.0.0", "private": true, "main": "main.js" }
JSON
cat > "$dir/main.js" <<JS
const { app, BrowserWindow } = require("electron");
app.commandLine.appendSwitch("disable-gpu");
function createWindow() {
const win = new BrowserWindow({ width: 1024, height: 768, show: true,
webPreferences: { contextIsolation: true, nodeIntegration: false } });
win.loadURL("http://127.0.0.1:${httpport}/index.html");
}
app.whenReady().then(createWindow);
app.on("window-all-closed", () => app.quit());
JS
# Random noise keeps the PNG large and incompressible, above the screenshot
# size floor; the button and input sit at known positions for the gestures.
cat > "$dir/index.html" <<'HTML'
<!doctype html><html><head><meta charset="utf-8"><style>
html,body{margin:0;height:100%;overflow:auto}
#c{position:fixed;inset:0;z-index:0}
#b{position:absolute;left:45%;top:46%;width:10%;height:8%;font-size:20px;z-index:1}
#i{position:absolute;left:40%;top:60%;width:20%;z-index:1}
</style></head><body>
<canvas id="c" width="1024" height="768"></canvas>
<button id="b" onclick="this.textContent='tapped'">Tap me</button>
<input id="i" placeholder="type here"/>
<div id="scrollpad" style="height:3000px"></div>
<script>
const cv = document.getElementById('c'), x = cv.getContext('2d');
const img = x.createImageData(cv.width, cv.height), d = img.data;
for (let i = 0; i < d.length; i += 4) { d[i]=Math.random()*255; d[i+1]=Math.random()*255; d[i+2]=Math.random()*255; d[i+3]=255; }
x.putImageData(img, 0, 0);
</script>
</body></html>
HTML
printf '%s\n' "$dir"
}
run_phase() {
local P=chromium
ensure_server || { skip "$P" tier all "tool-server unavailable"; return 0; }
# Display gate (Linux; macOS always has one). A merely installed xvfb-run does
# not count — nothing wraps the Electron spawn in it, so run the whole harness
# under `xvfb-run` instead. A set-but-unreachable DISPLAY (e.g. a session
# switch left it pointing at a server this process has no cookie for) shows up
# only as an opaque CDP readiness timeout, hence the probe.
if [ "$E2E_OS" = "linux" ]; then
if [ -z "${DISPLAY:-}" ]; then
skip "$P" tier all "no DISPLAY on Linux (re-run the harness under xvfb-run)"; return 0
fi
if command -v xdpyinfo >/dev/null 2>&1; then
xdpyinfo >/dev/null 2>&1 || { skip "$P" tier all "DISPLAY=$DISPLAY set but not reachable (xdpyinfo failed)"; return 0; }
elif command -v xset >/dev/null 2>&1; then
xset -q >/dev/null 2>&1 || { skip "$P" tier all "DISPLAY=$DISPLAY set but not reachable (xset failed)"; return 0; }
else
info "no xdpyinfo/xset: DISPLAY=$DISPLAY assumed usable, unverified"
fi
fi
local ebin; ebin="$(_find_electron)"
if [ -z "$ebin" ] || [ ! -e "$ebin" ]; then
skip "$P" tier all "electron not installed (run without --skip-install and with chromium selected)"; return 0
fi
local httpport; httpport="$(python3 -c 'import socket;s=socket.socket();s.bind(("127.0.0.1",0));print(s.getsockname()[1]);s.close()')"
local appdir; appdir="$(_gen_electron_app "$ebin" "$httpport")"
# Serve the fixture so the renderer has a real http origin (for storage).
( cd "$appdir" && exec python3 -m http.server "$httpport" --bind 127.0.0.1 ) >/dev/null 2>&1 &
export E2E_HTTP_PID=$!
local port; port="$(python3 -c 'import socket;s=socket.socket();s.bind(("127.0.0.1",0));print(s.getsockname()[1]);s.close()')"
sleep 1
# --no-sandbox: Electron's sandbox is unusable under many CI/root Linux setups.
run_tool boot-device "{\"electronAppPath\":\"$appdir\",\"electronPort\":$port,\"electronArgs\":[\"--no-sandbox\",\"--disable-gpu\"]}"
if [ "$RT_RC" -ne 0 ] || ! printf '%s' "$RT_JSON" | jq -e '.booted==true' >/dev/null 2>&1; then
fail "$P" boot-device boot "$(rt_detail 180)"
skip "$P" tier remaining "electron did not boot"; return 0
fi
local DEV; DEV="$(printf '%s' "$RT_JSON" | jq -r '.id // .udid // .serial // empty')"
[ -z "$DEV" ] && DEV="chromium-cdp-$port"
export E2E_ELECTRON_PID="$(printf '%s' "$RT_JSON" | jq -r '.pid // empty')"
export E2E_ELECTRON_PORT="$port"
pass "$P" boot-device boot "electron $DEV (port $port)"
assert_true "$P" list-devices present "{}" "(any(.devices[]?; (.id//.udid//.serial)==\"$DEV\"))"
if capture_screenshot "$DEV" "$E2E_WORK/chromium-shot.png"; then
pass "$P" screenshot shot "${SHOT_SIZE}B"
else
fail "$P" screenshot shot "size=${SHOT_SIZE:-0} rc=${SHOT_RC:-?} (blank framebuffer?)"
fi
assert_field "$P" describe describe "{\"udid\":\"$DEV\"}" '(.description|length>0)' 'true'
assert_true "$P" gesture-tap tap "{\"udid\":\"$DEV\",\"x\":0.5,\"y\":0.5}" '.tapped'
assert_true "$P" gesture-scroll scroll "{\"udid\":\"$DEV\",\"x\":0.5,\"y\":0.5,\"deltaY\":0.5}" '.scrolled'
assert_true "$P" gesture-drag drag "{\"udid\":\"$DEV\",\"fromX\":0.4,\"fromY\":0.4,\"toX\":0.6,\"toY\":0.6}" '.dragged'
assert_ok "$P" keyboard text "{\"udid\":\"$DEV\",\"text\":\"hello chromium\"}"
# Stay on the http origin: the storage cases below need a storable one.
assert_true "$P" open-url url "{\"udid\":\"$DEV\",\"url\":\"http://127.0.0.1:$httpport/index.html\"}" '.opened'
# Electron has no browser-level target creation, so `new` comes back
# "Not supported"; tolerate that.
assert_ok "$P" chromium-tabs list "{\"udid\":\"$DEV\",\"action\":\"list\"}"
run_tool chromium-tabs "{\"udid\":\"$DEV\",\"action\":\"new\",\"url\":\"about:blank\",\"label\":\"e2e-tab\"}"
if [ "$RT_RC" -eq 0 ]; then
pass "$P" chromium-tabs new
assert_ok "$P" chromium-tabs select "{\"udid\":\"$DEV\",\"action\":\"select\",\"tab\":\"e2e-tab\"}"
assert_ok "$P" chromium-tabs close "{\"udid\":\"$DEV\",\"action\":\"close\",\"tab\":\"e2e-tab\"}"
else
case "$RT_OUT" in
*"Not supported"*|*"not supported"*)
skip "$P" chromium-tabs new "single-window Electron: tab creation not supported" ;;
*) fail "$P" chromium-tabs new "$(rt_detail 140)" ;;
esac
skip "$P" chromium-tabs select "no extra tab to select"
skip "$P" chromium-tabs close "no extra tab to close"
fi
assert_ok "$P" chromium-cookies set "{\"udid\":\"$DEV\",\"action\":\"set\",\"name\":\"e2e\",\"value\":\"1\",\"url\":\"https://example.com\"}"
assert_ok "$P" chromium-cookies get "{\"udid\":\"$DEV\",\"action\":\"get\"}"
assert_ok "$P" chromium-cookies delete "{\"udid\":\"$DEV\",\"action\":\"delete\",\"name\":\"e2e\",\"url\":\"https://example.com\"}"
assert_ok "$P" chromium-cookies clear "{\"udid\":\"$DEV\",\"action\":\"clear\"}"
local store
for store in local session; do
assert_ok "$P" chromium-storage "set-$store" "{\"udid\":\"$DEV\",\"store\":\"$store\",\"action\":\"set\",\"key\":\"e2e\",\"value\":\"v\"}"
assert_ok "$P" chromium-storage "get-$store" "{\"udid\":\"$DEV\",\"store\":\"$store\",\"action\":\"get\",\"key\":\"e2e\"}"
assert_ok "$P" chromium-storage "remove-$store" "{\"udid\":\"$DEV\",\"store\":\"$store\",\"action\":\"remove\",\"key\":\"e2e\"}"
assert_ok "$P" chromium-storage "clear-$store" "{\"udid\":\"$DEV\",\"store\":\"$store\",\"action\":\"clear\"}"
done
if [ -n "${E2E_ELECTRON_PID:-}" ] && kill -0 "$E2E_ELECTRON_PID" 2>/dev/null; then
kill "$E2E_ELECTRON_PID" 2>/dev/null || true
else
# Fall back to the CDP port's listener. The port is matched as the whole
# last field and the pid taken from that same line: ":$port" as a substring
# also hits ":${port}9", and a stray pid may be another user's process.
local pid; pid="$(python3 -c "
import re, subprocess
port = '$port'
pid = ''
try:
out = subprocess.run(['ss', '-ltnp'], capture_output=True, text=True).stdout
for line in out.splitlines():
f = line.split()
if len(f) < 5 or f[3].rsplit(':', 1)[-1] != port:
continue
m = re.search(r'pid=(\\d+)', line)
if m:
pid = m.group(1)
break
except Exception:
pass
print(pid)" 2>/dev/null)"
[ -n "$pid" ] && kill "$pid" 2>/dev/null || true
fi
[ -n "${E2E_HTTP_PID:-}" ] && kill "$E2E_HTTP_PID" 2>/dev/null || true
# Electron takes a moment to go down after SIGTERM, and this case is the run's
# only record that the tier left nothing behind — so poll, don't assert.
local waited=0
while [ -n "${E2E_ELECTRON_PID:-}" ] && kill -0 "$E2E_ELECTRON_PID" 2>/dev/null && [ "$waited" -lt 5 ]; do
sleep 1; waited=$((waited + 1))
done
if [ -n "${E2E_ELECTRON_PID:-}" ] && kill -0 "$E2E_ELECTRON_PID" 2>/dev/null; then
kill -9 "$E2E_ELECTRON_PID" 2>/dev/null || true
fail "$P" teardown electron-stopped "pid $E2E_ELECTRON_PID survived SIGTERM for ${waited}s"
else
pass "$P" teardown electron-stopped
fi
}