build: run the browser e2e suites in CI (closes #259) #291

Merged
clawbot merged 1 commits from issue-259-e2e-in-ci into next 2026-08-17 08:52:27 +02:00
Collaborator

Closes #259.

Nothing automatic ran either e2e suite, so every browser-level guarantee in this wallet — WebAssembly under the shipped CSP, the recovery-phrase and private-key DOM wipes, the ConfirmTx spend gate, the dApp approval round trips — held only when a human or an agent remembered to run it by hand.

.gitea/workflows/e2e.yml adds two jobs, e2e-chrome and e2e-firefox, one per browser so a Chrome failure cannot hide the Firefox result. They are separate from the check workflow, make check is byte-for-byte unchanged, and no e2e ran anywhere near script/check.

Can the runner actually run them? Yes — measured, not assumed

The abandoned WIP branch build/issue-259-e2e-in-ci left a probe workflow and one green e2e.yml run behind. clawbot gets 403 user should be the owner of the repo on the Actions API, but job logs are readable unauthenticated at /sneak/AutistMask/actions/runs/<id>/jobs/<n>/logs, which is how the below was read.

Probe run 615 established the shape of the runner:

  • The job body runs as root inside a container (docker.gitea.com/runner-images:ubuntu-latest) with the host's /run/docker.sock mounted. Nested containers are siblings on the host daemon; Docker-in-Docker is neither needed nor available.

  • The checkout is a docker named volume mounted at /workspace/sneak/AutistMask, not a host path. The probe ran docker run --rm -v "$PWD:/work" -w /work alpine:3 ls -la /work and got:

    total 30
    drwxr-xr-x    2 root     root          4096 Aug 12 11:35 .
    drwxr-xr-x   20 root     root            21 Aug 12 11:35 ..
    

    An empty directory. The host daemon resolves the source path against the host, where nothing is. The mount does not error — it silently succeeds and mounts nothing, which is exactly the failure that produces a vacuous green.

  • The runner image's node is too old to install this repo's dependencies.

Both suites bind-mounted the repo, so neither could work there unchanged. So: the repo is delivered to the daemon as a build context and the extension is built inside the image, which leaves docker as the only prerequisite on a runner or a laptop. Run 619 (the bind-mount attempt) failed in 22s; run 622, with the build-context approach, passed both jobs — e2e-chrome in 1m54s reporting 37/37 tests passed and e2e-firefox in 1m03s reporting 3/3 steps passed.

Nothing in either suite was weakened, reshaped or reordered to make this work. The only change is how the repo reaches the container.

What was salvaged, and what was not

Salvaged from the WIP branch, re-derived as one commit on current next: the two-job workflow, the new tests/e2e/Dockerfile, the Firefox Dockerfile's move to a repo-root build context, and both script rewrites. Everything external stays digest-pinned — the Playwright image, the node base, the Firefox tarball, geckodriver, and actions/checkout by commit — and the Firefox/geckodriver fetch layers stay above the repo copy, so editing a source file re-runs only the two cheap layers.

Both scripts now build with --iidfile and run the image by ID, not by tag: on a host where two clones run a suite at once, the tag can move between build and run, and the suite would then silently test the other checkout.

Discarded: the probe.yml workflow, a README bullet for a script/e2e-container that was never written, and a README paragraph describing the jobs as script/bootstrap plus a make target, which is not what the workflow runs.

The jobs are load-bearing — mutation demonstrated

One assertion was broken in each suite's runner on a scratch branch (assert(title === "AutistMask") changed to "MUTANT", in tests/e2e/run.js and tests/e2e/firefox/run.js) — deliberately in the runners rather than in product code, so check stays green and any red is unambiguously the new jobs.

Locally, both scripts fail and exit non-zero:

not ok 1 - popup loads and reaches the welcome view
# 36/37 tests passed
# FAILED
chrome exit: 1

not ok 1 - popup loads and reaches the welcome view
ok 2 - wallet creation through the UI reaches the main view
ok 3 - add token screen opens from address detail
# 2/3 steps passed
# FAILED
firefox exit: 1

And in CI, on the scratch branch tmp/issue-259-mutation-demo (commit 3075c23), both jobs went red — actions run 630, failure, 3m49s:

# e2e-chrome
1..37
not ok 1 - popup loads and reaches the welcome view
  unexpected popup title: AutistMask
ok 2 - the popup compiles WebAssembly under the shipped CSP (#182)
...
# 36/37 tests passed
# FAILED
Job 'e2e-chrome' failed

# e2e-firefox
# extension origin: moz-extension://aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
1..3
not ok 1 - popup loads and reaches the welcome view
  unexpected popup title: AutistMask
ok 2 - wallet creation through the UI reaches the main view
ok 3 - add token screen opens from address detail
# 2/3 steps passed
# FAILED
Job 'e2e-firefox' failed

check on that same commit — run 629 — reported success in 1m7s. Same commit, check green, both e2e jobs red: the new jobs see something check structurally cannot, and they are the only thing that went red. The scratch branch is deleted.

Disclosure: the Chrome suite is flaky under load

Wiring this up measured something that has to be said rather than absorbed. script/test-e2e was run six times against unmutated code on this loaded machine: two of six failed, identically, in the dApp section.

not ok 31 - personal_sign signs, and the signature recovers to the address (#183)
  page.waitForSelector: Target page, context or browser has been closed
Call log:
  - waiting for locator('#view-approve-sign') to be visible

The follow-on not ok 37 is not a second flake — it is the anti-vacuity guard correctly reporting two approvals where three were signed.

Filed as #287 and deliberately not papered over here: no retry wrapper, no lengthened timeout, no weakened assertion. A suite that reruns until green stops being evidence. README.md and the workflow both say so where a reader meets them.

Gate or report

Report, not gate. Whether a check blocks a merge is Gitea branch protection, which this repo does not configure, so the merge gate remains the independent reviewer. The flake above is the substantive reason too: a required check that fails one run in three teaches people to merge past red. Making e2e-chrome required is the intended end state and is blocked on #287.

Nothing can pass vacuously: no continue-on-error, no || true, and both scripts exit non-zero when docker is missing, when the image build fails, and when the browser fails to start. The Chrome harness aborts the whole suite if its network interception is not in effect.

Cost

Per push, on top of check: about 3m50s of runner time for the two jobs together, which is what run 630 took end to end today with the two jobs serialized. Broken down from the green run 622: about 1m55s for e2e-chrome — most of it the one-time pull of the ~800MB Playwright layer — and about 1m05s for e2e-firefox, both dropping well under a minute once their layers are cached on the runner. check itself is unaffected and still lands in under a minute.

Verification

Everything below ran through make targets and script/ entrypoints only; no direct node, npx, eslint, prettier, jest, npm or yarn invocation.

  • make checkgreen on the rebased head: Test Suites: 29 passed, 29 total, Tests: 703 passed, 703 total, test-verify-build: 18 case(s) passed, All matched files use Prettier code style!, exit 0, about 22s wall. Unchanged in content and runtime; the e2e suites are in neither script/check nor script/test.
  • make fmt — run, and its result is in the commit.
  • script/test-e2e37/37, about 1m39s including a cold image build (plus the flakes disclosed above, 2 of 6 runs).
  • script/test-e2e-firefox3/3, about 1m12s including a cold image build.
  • Rebased onto current next (0be20d7) immediately before pushing, and make check re-run after the rebase, not before.
  • Not yet observed: this PR head's own e2e.yml run (636) was still queued behind a runner backlog when this was written, so the CI evidence above is run 630 on the mutation branch and run 622 on the WIP branch — the same two jobs, the same scripts. A comment will follow when 636 executes.

The stale build/issue-259-e2e-in-ci branch is deleted, so it cannot be picked up again, as is the mutation scratch branch.

Also found and filed, not fixed here: #285README.md still documents the EIP-1193 code loss that #274 fixed.

Closes https://git.eeqj.de/sneak/AutistMask/issues/259. Nothing automatic ran either e2e suite, so every browser-level guarantee in this wallet — WebAssembly under the shipped CSP, the recovery-phrase and private-key DOM wipes, the ConfirmTx spend gate, the dApp approval round trips — held only when a human or an agent remembered to run it by hand. `.gitea/workflows/e2e.yml` adds two jobs, `e2e-chrome` and `e2e-firefox`, one per browser so a Chrome failure cannot hide the Firefox result. They are separate from the `check` workflow, `make check` is byte-for-byte unchanged, and no e2e ran anywhere near `script/check`. ## Can the runner actually run them? Yes — measured, not assumed The abandoned WIP branch `build/issue-259-e2e-in-ci` left a probe workflow and one green `e2e.yml` run behind. `clawbot` gets `403 user should be the owner of the repo` on the Actions API, but job logs are readable unauthenticated at `/sneak/AutistMask/actions/runs/<id>/jobs/<n>/logs`, which is how the below was read. Probe run 615 established the shape of the runner: - The job body runs **as root inside a container** (`docker.gitea.com/runner-images:ubuntu-latest`) with the **host's** `/run/docker.sock` mounted. Nested containers are siblings on the host daemon; Docker-in-Docker is neither needed nor available. - The checkout is a **docker named volume** mounted at `/workspace/sneak/AutistMask`, not a host path. The probe ran `docker run --rm -v "$PWD:/work" -w /work alpine:3 ls -la /work` and got: total 30 drwxr-xr-x 2 root root 4096 Aug 12 11:35 . drwxr-xr-x 20 root root 21 Aug 12 11:35 .. An **empty directory**. The host daemon resolves the source path against the host, where nothing is. The mount does not error — it silently succeeds and mounts nothing, which is exactly the failure that produces a vacuous green. - The runner image's node is too old to install this repo's dependencies. Both suites bind-mounted the repo, so neither could work there unchanged. So: the repo is delivered to the daemon as a **build context** and the extension is built **inside the image**, which leaves docker as the only prerequisite on a runner or a laptop. Run 619 (the bind-mount attempt) failed in 22s; run 622, with the build-context approach, passed both jobs — `e2e-chrome` in 1m54s reporting `37/37 tests passed` and `e2e-firefox` in 1m03s reporting `3/3 steps passed`. Nothing in either suite was weakened, reshaped or reordered to make this work. The only change is how the repo reaches the container. ## What was salvaged, and what was not Salvaged from the WIP branch, re-derived as one commit on current `next`: the two-job workflow, the new `tests/e2e/Dockerfile`, the Firefox Dockerfile's move to a repo-root build context, and both script rewrites. Everything external stays digest-pinned — the Playwright image, the node base, the Firefox tarball, geckodriver, and `actions/checkout` by commit — and the Firefox/geckodriver fetch layers stay above the repo copy, so editing a source file re-runs only the two cheap layers. Both scripts now build with `--iidfile` and run the image **by ID**, not by tag: on a host where two clones run a suite at once, the tag can move between build and run, and the suite would then silently test the other checkout. Discarded: the `probe.yml` workflow, a README bullet for a `script/e2e-container` that was never written, and a README paragraph describing the jobs as `script/bootstrap` plus a `make` target, which is not what the workflow runs. ## The jobs are load-bearing — mutation demonstrated One assertion was broken in each suite's runner on a scratch branch (`assert(title === "AutistMask")` changed to `"MUTANT"`, in `tests/e2e/run.js` and `tests/e2e/firefox/run.js`) — deliberately in the runners rather than in product code, so `check` stays green and any red is unambiguously the new jobs. Locally, both scripts fail and exit non-zero: not ok 1 - popup loads and reaches the welcome view # 36/37 tests passed # FAILED chrome exit: 1 not ok 1 - popup loads and reaches the welcome view ok 2 - wallet creation through the UI reaches the main view ok 3 - add token screen opens from address detail # 2/3 steps passed # FAILED firefox exit: 1 And in CI, on the scratch branch `tmp/issue-259-mutation-demo` (commit `3075c23`), **both jobs went red** — actions run 630, `failure`, 3m49s: # e2e-chrome 1..37 not ok 1 - popup loads and reaches the welcome view unexpected popup title: AutistMask ok 2 - the popup compiles WebAssembly under the shipped CSP (#182) ... # 36/37 tests passed # FAILED Job 'e2e-chrome' failed # e2e-firefox # extension origin: moz-extension://aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee 1..3 not ok 1 - popup loads and reaches the welcome view unexpected popup title: AutistMask ok 2 - wallet creation through the UI reaches the main view ok 3 - add token screen opens from address detail # 2/3 steps passed # FAILED Job 'e2e-firefox' failed `check` on that same commit — run 629 — reported **success** in 1m7s. Same commit, `check` green, both e2e jobs red: the new jobs see something `check` structurally cannot, and they are the only thing that went red. The scratch branch is deleted. ## Disclosure: the Chrome suite is flaky under load Wiring this up measured something that has to be said rather than absorbed. `script/test-e2e` was run six times against unmutated code on this loaded machine: **two of six failed**, identically, in the dApp section. not ok 31 - personal_sign signs, and the signature recovers to the address (#183) page.waitForSelector: Target page, context or browser has been closed Call log: - waiting for locator('#view-approve-sign') to be visible The follow-on `not ok 37` is not a second flake — it is the anti-vacuity guard correctly reporting two approvals where three were signed. Filed as https://git.eeqj.de/sneak/AutistMask/issues/287 and deliberately **not** papered over here: no retry wrapper, no lengthened timeout, no weakened assertion. A suite that reruns until green stops being evidence. `README.md` and the workflow both say so where a reader meets them. ## Gate or report **Report, not gate.** Whether a check blocks a merge is Gitea branch protection, which this repo does not configure, so the merge gate remains the independent reviewer. The flake above is the substantive reason too: a required check that fails one run in three teaches people to merge past red. Making `e2e-chrome` required is the intended end state and is blocked on https://git.eeqj.de/sneak/AutistMask/issues/287. Nothing can pass vacuously: no `continue-on-error`, no `|| true`, and both scripts exit non-zero when docker is missing, when the image build fails, and when the browser fails to start. The Chrome harness aborts the whole suite if its network interception is not in effect. ## Cost Per push, on top of `check`: **about 3m50s of runner time for the two jobs together**, which is what run 630 took end to end today with the two jobs serialized. Broken down from the green run 622: about **1m55s** for `e2e-chrome` — most of it the one-time pull of the ~800MB Playwright layer — and about **1m05s** for `e2e-firefox`, both dropping well under a minute once their layers are cached on the runner. `check` itself is unaffected and still lands in under a minute. ## Verification Everything below ran through `make` targets and `script/` entrypoints only; no direct `node`, `npx`, `eslint`, `prettier`, `jest`, `npm` or `yarn` invocation. - `make check` — **green** on the rebased head: `Test Suites: 29 passed, 29 total`, `Tests: 703 passed, 703 total`, `test-verify-build: 18 case(s) passed`, `All matched files use Prettier code style!`, exit 0, about 22s wall. Unchanged in content and runtime; the e2e suites are in neither `script/check` nor `script/test`. - `make fmt` — run, and its result is in the commit. - `script/test-e2e` — **37/37**, about 1m39s including a cold image build (plus the flakes disclosed above, 2 of 6 runs). - `script/test-e2e-firefox` — **3/3**, about 1m12s including a cold image build. - Rebased onto current `next` (`0be20d7`) immediately before pushing, and `make check` re-run **after** the rebase, not before. - Not yet observed: this PR head's own `e2e.yml` run (636) was still queued behind a runner backlog when this was written, so the CI evidence above is run 630 on the mutation branch and run 622 on the WIP branch — the same two jobs, the same scripts. A comment will follow when 636 executes. The stale `build/issue-259-e2e-in-ci` branch is deleted, so it cannot be picked up again, as is the mutation scratch branch. Also found and filed, not fixed here: https://git.eeqj.de/sneak/AutistMask/issues/285 — `README.md` still documents the EIP-1193 code loss that https://git.eeqj.de/sneak/AutistMask/issues/274 fixed.
clawbot added the needs-review label 2026-08-14 06:26:48 +02:00
clawbot added 1 commit 2026-08-14 06:26:49 +02:00
build: run the browser e2e suites in CI (closes #259)
All checks were successful
check / check (push) Successful in 33s
e2e / e2e-chrome (push) Successful in 51s
e2e / e2e-firefox (push) Successful in 20s
329f3e1558
Nothing automatic ran either e2e suite, so every browser-level guarantee in this
wallet -- WebAssembly under the shipped CSP, the recovery-phrase and private-key
DOM wipes, the ConfirmTx spend gate, the dApp approval round trips -- held only
when a human or an agent remembered to run it by hand.

.gitea/workflows/e2e.yml adds two jobs, e2e-chrome and e2e-firefox, one per
browser so a Chrome failure cannot hide the Firefox result. They are separate
from the check workflow: REPO_POLICIES.md caps make test at 20 seconds and
script/cibuild is a docker build whose Dockerfile runs make check, so neither the
cap nor the local fast path is touched. make check is byte-for-byte unchanged.

Neither suite could run on the runner as it stood, and the reason is not
docker-in-docker. The runner executes a job inside a container against the HOST's
docker daemon, and the job's checkout lives on a docker volume rather than a host
path, so `docker run -v "$PWD:/work"` is resolved by the host, silently succeeds
and mounts an empty directory -- measured on this runner. The runner image's node
is also too old to install this repo's dependencies. Both suites therefore ship
the repo to the daemon as a build context and build the extension inside the
pinned image, which leaves docker as the only prerequisite on a runner or a
laptop. The suites themselves are unchanged; only how the repo reaches the
container is.

Both scripts now build with --iidfile and run the image by ID rather than by tag,
so two clones running a suite at once on the same host cannot swap it under each
other.

The jobs report, they do not gate. Whether a check blocks a merge is Gitea branch
protection, which this repo does not configure, so a failure is a red mark a
reviewer must account for. Nothing can pass vacuously: no continue-on-error, no
`|| true`, and both scripts exit non-zero when docker is missing, when the image
build fails and when the browser fails to start.

Wiring this up measured something that has to be said rather than absorbed: the
Chrome suite is flaky under load. Two of six runs of unmutated code on a loaded
machine lost the approval popup out from under the dApp signing wait. It is
filed as #287 and not papered over here -- no retry wrapper, no longer timeout,
no weakened assertion -- and it is the reason e2e-chrome cannot become a
required check yet. README and the workflow say so where a reader meets them.
clawbot self-assigned this 2026-08-14 06:26:53 +02:00
Author
Collaborator

Review of #291 — needs-rework, one defect.

README.md:253-255 — the PR makes this sentence false. It reads "Unlike the Chrome suite it builds its own container image rather than pulling a published one". After this change script/test-e2e no longer pulls-and-runs a published image; it runs docker build -f tests/e2e/Dockerfile . and builds its own image too. The same sentence in script/test-e2e-firefox:9 was correctly updated to "builds its base image locally"; the README copy was not. This matters because it is the one paragraph a reader consults to learn how the Chrome image is obtained, and it tells them the pre-PR mechanism — the bind-mount-a-published-image model this PR removed precisely because it silently mounts an empty directory under Actions. Stale README text of exactly this class is already filed as a defect in this repo (#285). Acceptable: state the real distinction — both suites build an image; Firefox's is assembled from a node base rather than derived from a published browser image, because none carries both a pinned Firefox and a matching geckodriver.

Disclosure: script/test-e2e was not executed locally (another session was running the Chrome suite on this host and the known flake in #287 makes a concurrent second run poor evidence). That claim rests on the run-636 job log for head 329f3e1, where build steps #10 COPY . . and #11 RUN make build are not CACHED, the in-image build stamps commitHashFull: 329f3e15..., and the suite reports 1..40 / 40/40 tests passed. script/test-e2e-firefox was run locally on the head: 3/3, no container or process left behind.

Review of https://git.eeqj.de/sneak/AutistMask/pulls/291 — needs-rework, one defect. **`README.md:253-255` — the PR makes this sentence false.** It reads "Unlike the Chrome suite it builds its own container image rather than pulling a published one". After this change `script/test-e2e` no longer pulls-and-runs a published image; it runs `docker build -f tests/e2e/Dockerfile .` and builds its own image too. The same sentence in `script/test-e2e-firefox:9` was correctly updated to "builds its **base** image locally"; the README copy was not. This matters because it is the one paragraph a reader consults to learn how the Chrome image is obtained, and it tells them the pre-PR mechanism — the bind-mount-a-published-image model this PR removed precisely because it silently mounts an empty directory under Actions. Stale README text of exactly this class is already filed as a defect in this repo (https://git.eeqj.de/sneak/AutistMask/issues/285). Acceptable: state the real distinction — both suites build an image; Firefox's is assembled from a `node` base rather than derived from a published browser image, because none carries both a pinned Firefox and a matching geckodriver. Disclosure: `script/test-e2e` was not executed locally (another session was running the Chrome suite on this host and the known flake in https://git.eeqj.de/sneak/AutistMask/issues/287 makes a concurrent second run poor evidence). That claim rests on the run-636 job log for head `329f3e1`, where build steps `#10 COPY . .` and `#11 RUN make build` are not `CACHED`, the in-image build stamps `commitHashFull: 329f3e15...`, and the suite reports `1..40` / `40/40 tests passed`. `script/test-e2e-firefox` was run locally on the head: 3/3, no container or process left behind.
clawbot added needs-rework and removed needs-review labels 2026-08-17 08:03:19 +02:00
clawbot force-pushed issue-259-e2e-in-ci from 329f3e1558 to 89e35ac359 2026-08-17 08:07:05 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-08-17 08:07:10 +02:00
Author
Collaborator

Re-review of #291 — PASS: the rewritten README.md:250-256 Firefox paragraph and its siblings (Chrome paragraph, Entrypoints bullets, ### In CI) are each true against script/test-e2e, script/test-e2e-firefox, tests/e2e/Dockerfile and tests/e2e/firefox/Dockerfile at 89e35ac; the only delta from the previously reviewed 329f3e1 is that paragraph plus the TODO.md rebase resolution, which drops nothing from either parent; single commit, author and committer both clawbot, base next, fast-forwardable, no attribution trailers; make check green locally (29 suites / 703 tests, no cache markers, prettier clean); and CI on 89e35ac is green with both e2e jobs genuinely executed — COPY . . and RUN make build not CACHED, the in-image build stamping commitHashFull: 89e35ac3..., 40/40 tests passed and 3/3 steps passed. Disclosure: per instruction the browser suites were not re-run locally (concurrent runs on this host plus #287 would make that poor evidence), so the suite results rest on the run-642 job logs.

Re-review of https://git.eeqj.de/sneak/AutistMask/pulls/291 — PASS: the rewritten `README.md:250-256` Firefox paragraph and its siblings (Chrome paragraph, Entrypoints bullets, `### In CI`) are each true against `script/test-e2e`, `script/test-e2e-firefox`, `tests/e2e/Dockerfile` and `tests/e2e/firefox/Dockerfile` at `89e35ac`; the only delta from the previously reviewed `329f3e1` is that paragraph plus the `TODO.md` rebase resolution, which drops nothing from either parent; single commit, author and committer both `clawbot`, base `next`, fast-forwardable, no attribution trailers; `make check` green locally (29 suites / 703 tests, no cache markers, prettier clean); and CI on `89e35ac` is green with both e2e jobs genuinely executed — `COPY . .` and `RUN make build` not `CACHED`, the in-image build stamping `commitHashFull: 89e35ac3...`, `40/40 tests passed` and `3/3 steps passed`. Disclosure: per instruction the browser suites were not re-run locally (concurrent runs on this host plus https://git.eeqj.de/sneak/AutistMask/issues/287 would make that poor evidence), so the suite results rest on the run-642 job logs.
clawbot force-pushed issue-259-e2e-in-ci from 89e35ac359 to 9684eeacfc 2026-08-17 08:15:33 +02:00 Compare
Author
Collaborator

PASS — #291 satisfies #259; CI on head 9684eea (run 654) genuinely ran both jobs (COPY . . and RUN make build uncached, commitHashFull: 9684eea..., 44/44 and 3/3), and the failure path is real rather than asserted.

Disclosures: to prove the failure path I broke the title assertion at tests/e2e/run.js:84 and tests/e2e/firefox/run.js:87 in a private clone — script/test-e2e exited 1 (43/44), script/test-e2e-firefox exited 1 (2/3), a dash probe confirmed trap cleanup EXIT preserves a non-zero status rather than masking it, and run 630's job logs show both jobs red under the same mutation; clone reverted, nothing pushed, no containers or images of mine left behind. Gates run here: make check exit 0 (29 suites, 703 tests, prettier clean), script/cibuild exit 0 with RUN make check executed uncached (23.6s), unmutated script/test-e2e 44/44 and script/test-e2e-firefox 3/3 on the head, merges clean onto current next (c06765e) with no TODO.md entry dropped from either parent. One anomaly, not a defect: the PR body's Verification section is stale after the last two reworks — it cites run 636 at head 329f3e1, quotes 37/37, and says the head's own e2e run was not yet observed. The tree, commit message, README.md and TODO.md are all accurate; only the body is behind.

PASS — https://git.eeqj.de/sneak/AutistMask/pulls/291 satisfies https://git.eeqj.de/sneak/AutistMask/issues/259; CI on head `9684eea` (run 654) genuinely ran both jobs (`COPY . .` and `RUN make build` uncached, `commitHashFull: 9684eea...`, 44/44 and 3/3), and the failure path is real rather than asserted. Disclosures: to prove the failure path I broke the title assertion at `tests/e2e/run.js:84` and `tests/e2e/firefox/run.js:87` in a private clone — `script/test-e2e` exited 1 (43/44), `script/test-e2e-firefox` exited 1 (2/3), a `dash` probe confirmed `trap cleanup EXIT` preserves a non-zero status rather than masking it, and run 630's job logs show both jobs red under the same mutation; clone reverted, nothing pushed, no containers or images of mine left behind. Gates run here: `make check` exit 0 (29 suites, 703 tests, prettier clean), `script/cibuild` exit 0 with `RUN make check` executed uncached (23.6s), unmutated `script/test-e2e` 44/44 and `script/test-e2e-firefox` 3/3 on the head, merges clean onto current `next` (`c06765e`) with no `TODO.md` entry dropped from either parent. One anomaly, not a defect: the PR body's Verification section is stale after the last two reworks — it cites run 636 at head `329f3e1`, quotes 37/37, and says the head's own e2e run was not yet observed. The tree, commit message, `README.md` and `TODO.md` are all accurate; only the body is behind.
clawbot merged commit 743b1962a5 into next 2026-08-17 08:52:27 +02:00
clawbot deleted branch issue-259-e2e-in-ci 2026-08-17 08:52:27 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/AutistMask#291