Train BM4 #810

Closed
kayg wants to merge 0 commits from train/2026-11-01-bm4 into dev
Owner

Train BM4 into dev. Head 9b623c8d on base dev 133cf2c2. Not ready to merge: 2 first-run failures (below).

Included (first-parent order)

  • #779 infra/nix-devshell c61c91d3
  • #787 perf/vm-setup 8c066c73
  • #780 ops/preview-dev02 89438634
  • #782 feat/dav-app-passwords a59f782e

Not included: #756 (BM1), see the comment.

Results (first run, no retries)

  • Rust workspace tests: pass (WORKSPACE_TESTS_EXIT=0, dev-01 ~/bm4-dev01-rust-final.log)
  • Bundle budgets: pass, first_js 237.2/240 KB, all_js 310.1/315 KB (~/bm4-dev01-bundle-final.log)
  • Playwright chromium (dev-01, full suite, 2010 tests): 1250 passed, 1 failed, 755 skipped, 4 did not run. Exit 1.
  • Playwright webkit (dev-02, full suite, 1989 tests): 1223 passed, 1 failed, 765 skipped. Exit 1.
  • Flaky: none reported by Playwright.

Failures

  1. [passkeys] e2e/passkeys.spec.ts:52 list, add, rename and remove passkeys... Clicking "Add a passkey" leaves 1 row, expected 2 (line 83). The 4 "did not run" follow it.
    Diagnostic (single spec, once each): passes on origin/dev 133cf2c2, fails on the train build. Looks like a regression from #782 (v9 migration adds assertion_at, so sessions not made by a sign-in assertion no longer count as fresh). Not confirmed by a code read.
  2. [webkit-390] e2e/swipe-rows.spec.ts:621 swiped plain row keeps its colour (light, photo, Rosewood). Card transform stayed 0, expected < -33.
    Diagnostic (single spec, once each): passes on origin/dev and passes on the train build. Load-sensitive in the full run; not a train regression as far as one run shows.

🤖 Generated with Claude Code

Train BM4 into dev. Head `9b623c8d` on base dev `133cf2c2`. **Not ready to merge: 2 first-run failures (below).** ## Included (first-parent order) - #779 infra/nix-devshell `c61c91d3` - #787 perf/vm-setup `8c066c73` - #780 ops/preview-dev02 `89438634` - #782 feat/dav-app-passwords `a59f782e` Not included: #756 (BM1), see the comment. ## Results (first run, no retries) - Rust workspace tests: pass (WORKSPACE_TESTS_EXIT=0, dev-01 `~/bm4-dev01-rust-final.log`) - Bundle budgets: pass, first_js 237.2/240 KB, all_js 310.1/315 KB (`~/bm4-dev01-bundle-final.log`) - Playwright chromium (dev-01, full suite, 2010 tests): 1250 passed, 1 failed, 755 skipped, 4 did not run. Exit 1. - Playwright webkit (dev-02, full suite, 1989 tests): 1223 passed, 1 failed, 765 skipped. Exit 1. - Flaky: none reported by Playwright. ## Failures 1. `[passkeys] e2e/passkeys.spec.ts:52` list, add, rename and remove passkeys... Clicking "Add a passkey" leaves 1 row, expected 2 (line 83). The 4 "did not run" follow it. Diagnostic (single spec, once each): passes on origin/dev `133cf2c2`, fails on the train build. Looks like a regression from #782 (v9 migration adds `assertion_at`, so sessions not made by a sign-in assertion no longer count as fresh). Not confirmed by a code read. 2. `[webkit-390] e2e/swipe-rows.spec.ts:621` swiped plain row keeps its colour (light, photo, Rosewood). Card transform stayed 0, expected < -33. Diagnostic (single spec, once each): passes on origin/dev and passes on the train build. Load-sensitive in the full run; not a train regression as far as one run shows. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
kayg added 24 commits 2026-10-31 20:15:22 +00:00
flake: Mesa EGL for WebKit on Linux
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
c61c91d39f
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xi6YxsuZ7m2ESGC7aS91AN
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xi6YxsuZ7m2ESGC7aS91AN
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xi6YxsuZ7m2ESGC7aS91AN
preview: serve on port 80 (NetBird ACL allows only 80/443), / redirects to review.html
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
8943863489
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xi6YxsuZ7m2ESGC7aS91AN
web: regenerate action types
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
70ccd57cb9
Fail-closed DAV URL user check, credential-first throttling, step-up for
minting, bounded cache with 503 on database errors, and small hardening.
perf: how to run measurements on the perf VMs
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
8c066c7353
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xi6YxsuZ7m2ESGC7aS91AN
Merge PR #782 feat/dav-app-passwords
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
9b623c8de1
Author
Owner

Why #756 (BM1) is not in this train: it is open and not merged into dev. It is a 30-file product/UI train (bundle trim, phone frost cards, Trash read-only and bulk Undo), not docs or harness. A test merge into this train conflicts in apps/web/src/lib/editing.svelte.ts, crates/fsio/src/swap.rs and a modify/delete on apps/web/src/lib/lazy.ts. It needs a rebase before any later train. This train is unchanged.

Diagnostic runs were done on dev-02: origin/dev in worktree bm4-diag-dev, train in bm4-gates. Each spec ran once.

Why #756 (BM1) is not in this train: it is open and not merged into dev. It is a 30-file product/UI train (bundle trim, phone frost cards, Trash read-only and bulk Undo), not docs or harness. A test merge into this train conflicts in `apps/web/src/lib/editing.svelte.ts`, `crates/fsio/src/swap.rs` and a modify/delete on `apps/web/src/lib/lazy.ts`. It needs a rebase before any later train. This train is unchanged. Diagnostic runs were done on dev-02: origin/dev in worktree `bm4-diag-dev`, train in `bm4-gates`. Each spec ran once.
Author
Owner

BM4 passkey regression fixed and targeted gates passed

Feature #782: 850e604774 (feat/dav-app-passwords). Rebuilt train #810: 29175e3782 (train/2026-11-01-bm4), including the updated feature branch. Both pushed. No merge into dev and no full train run started.

Cause and behavior

Confirmed by reading setup redemption and reproducing e2e/passkeys.spec.ts on the original BM4 build: after Add a passkey, the list stayed at one row. Setup verified a registration but created its session with no assertion_at. The new Rust setup-add regression also failed before the fix.

A completed registration now records assertion_at in the redemption transaction. Add-start, add-finish and remove require recent browser/native passkey proof. Stale/missing proof returns a distinct 403 passkey_reverification_required with “Verify with your passkey to continue.” Settings offers a passkey check, then retries the operation. Cancellation keeps the session and offers another try. Re-check requires the current account's passkey; another account's key cannot replace the session.

App-password minting keeps its sign-in-only rule. Additive auth.db v10 records registration_session so registration proof alone cannot mint. Existing v9 proof timestamps are preserved and old sessions are not assigned new proof. Recovery/invite redemption also performs registration in this implementation, so its completed ceremony counts for passkey management; sessions with no ceremony do not. Rust tests cover setup, recovery, invite, missing/stale proof, sign-in, mint restrictions, current-account re-check, and migration.

Verification

On calternal-dev-01-compute02, Nix dev shell, through ~/bin/slot bash ~/bm4-passkey-train-gates.sh, worktree ~/Developer/Worktrees/bm4-passkey-web. Log: ~/bm4-passkey-train.log, ending BM4_PASSKEY_TRAIN_EXIT=0. VM worktree is clean at the train head above. Rust sources were unchanged by the last merge, which only switched the e2e timestamp helper to Nix's sqlite3.

All passed:

cargo fmt --all -- --check
cargo test -j4 -p calternal-core -p calternal-auth -p calternal-server --no-fail-fast
cargo test -j4 -p calternal contract
cargo clippy -j4 -p calternal-core -p calternal-auth -p calternal-server --all-targets -- -D warnings
cargo build -j4 -p calternal
bun install --frozen-lockfile
# from apps/web:
bun run check
CALTERNAL_BIN=/home/claude/Developer/Worktrees/bm4-gates/target/debug/calternal bunx playwright test e2e/passkeys.spec.ts e2e/passkeys-ui.spec.ts --project=passkeys --project=chromium-1440 --project=webkit-1440 --workers=1

Browser result: 5 passed, zero retries. Chromium exercised real setup/add/rename/remove, stale removal with cancellation and retry, and stale add with verification followed by successful registration. Chromium/WebKit UI tests cover the stale-session prompt and a failed re-check with another attempt. WebKit has no virtual WebAuthn authenticator, so the real ceremony remains in the Chromium passkeys project. Svelte check: 0 errors, 14 warnings in 8 existing files; clippy clean.

One earlier feature-suite run failed counter_concurrent_mutations_drift_and_restart (16577 vs 16440). The final rebuilt-train suite passed it. No quota code changed. Existing ignored performance tests remain ignored. The full train rerun, including the previously reported WebKit swipe case, is left to the orchestrator.

## BM4 passkey regression fixed and targeted gates passed Feature #782: **850e6047740974a7c0b31ce874da1bf14c8f5807** (`feat/dav-app-passwords`). Rebuilt train #810: **29175e37829bf54038d9c8660252044904abdfce** (`train/2026-11-01-bm4`), including the updated feature branch. Both pushed. No merge into dev and no full train run started. ### Cause and behavior Confirmed by reading setup redemption and reproducing `e2e/passkeys.spec.ts` on the original BM4 build: after Add a passkey, the list stayed at one row. Setup verified a registration but created its session with no assertion_at. The new Rust setup-add regression also failed before the fix. A completed registration now records assertion_at in the redemption transaction. Add-start, add-finish and remove require recent browser/native passkey proof. Stale/missing proof returns a distinct 403 `passkey_reverification_required` with “Verify with your passkey to continue.” Settings offers a passkey check, then retries the operation. Cancellation keeps the session and offers another try. Re-check requires the current account's passkey; another account's key cannot replace the session. App-password minting keeps its sign-in-only rule. Additive auth.db v10 records registration_session so registration proof alone cannot mint. Existing v9 proof timestamps are preserved and old sessions are not assigned new proof. Recovery/invite redemption also performs registration in this implementation, so its completed ceremony counts for passkey management; sessions with no ceremony do not. Rust tests cover setup, recovery, invite, missing/stale proof, sign-in, mint restrictions, current-account re-check, and migration. ### Verification On **calternal-dev-01-compute02**, Nix dev shell, through `~/bin/slot bash ~/bm4-passkey-train-gates.sh`, worktree `~/Developer/Worktrees/bm4-passkey-web`. Log: **~/bm4-passkey-train.log**, ending **BM4_PASSKEY_TRAIN_EXIT=0**. VM worktree is clean at the train head above. Rust sources were unchanged by the last merge, which only switched the e2e timestamp helper to Nix's sqlite3. All passed: ```sh cargo fmt --all -- --check cargo test -j4 -p calternal-core -p calternal-auth -p calternal-server --no-fail-fast cargo test -j4 -p calternal contract cargo clippy -j4 -p calternal-core -p calternal-auth -p calternal-server --all-targets -- -D warnings cargo build -j4 -p calternal bun install --frozen-lockfile # from apps/web: bun run check CALTERNAL_BIN=/home/claude/Developer/Worktrees/bm4-gates/target/debug/calternal bunx playwright test e2e/passkeys.spec.ts e2e/passkeys-ui.spec.ts --project=passkeys --project=chromium-1440 --project=webkit-1440 --workers=1 ``` Browser result: **5 passed**, zero retries. Chromium exercised real setup/add/rename/remove, stale removal with cancellation and retry, and stale add with verification followed by successful registration. Chromium/WebKit UI tests cover the stale-session prompt and a failed re-check with another attempt. WebKit has no virtual WebAuthn authenticator, so the real ceremony remains in the Chromium `passkeys` project. Svelte check: 0 errors, 14 warnings in 8 existing files; clippy clean. One earlier feature-suite run failed `counter_concurrent_mutations_drift_and_restart` (16577 vs 16440). The final rebuilt-train suite passed it. No quota code changed. Existing ignored performance tests remain ignored. The full train rerun, including the previously reported WebKit swipe case, is left to the orchestrator.
Author
Owner

BM4 first-run rerun on 833c3aac

Merged current origin/dev (a55521f94ef7337f0793037ae2cb2c27266d5720, including #811 and the case-path guard) into train/2026-11-01-bm4 with --no-ff. No conflicts. Pushed 833c3aaccb4e0039505c32109018a13c71032000. This PR remains open and was not merged.

Rust and web gates on dev-01

Gate Command Result
fmt cargo fmt --all -- --check pass
clippy cargo clippy -j4 --workspace --locked --all-targets -- -D warnings pass
workspace tests cargo test -j4 --workspace --locked pass, exit 0
case paths node ci/check-case-paths.mjs pass
web build bun run build from apps/web pass
bundle budget bun scripts/bundle-size.mjs --json plus 240/315 KiB checks pass

First-paint JS: 243,078 bytes (237.381/240 KiB). All JS: 317,912 bytes (310.461/315 KiB). The previously intermittent counter_concurrent_mutations_drift_and_restart test passed on its first run.

Playwright first-run counts

Both full-suite runs used CI=1, --retries=0, and --workers=1. Chromium ran on dev-01 with playwright.bm4-chromium.config.ts; WebKit ran on dev-02 with --no-deps, after the separate admin-setup prelude.

Half Project Passed Failed Flaky Skipped
Chromium chromium-1440 386 0 0 586
Chromium chromium-390 821 0 0 151
Chromium flow 1 0 0 0
Chromium passkeys 1 0 0 0
Chromium admin-setup 1 0 0 0
Chromium admin-chromium-1440 12 0 0 9
Chromium admin-chromium-390 12 0 0 9
Chromium prefs-chromium 7 0 0 0
Chromium contrast 9 0 0 0
Chromium sidebar-band-chromium 3 0 0 0
Chromium throttled-1440 2 0 0 0
Chromium throttled-390 2 0 0 0
WebKit webkit-1440 381 0 0 591
WebKit webkit-390 820 0 0 152
WebKit admin-webkit-1440 0 9 0 9
WebKit admin-webkit-390 0 9 0 9
WebKit prefs-webkit 3 0 0 4
WebKit sidebar-band-webkit 3 0 0 0

Chromium total: 1,257 passed, 0 failed, 0 flaky, 755 skipped; exit 0. WebKit suite total: 1,207 passed, 18 failed, 0 flaky, 765 skipped; exit 1. The separate WebKit-side admin-setup prelude passed 1 test.

WebKit failures and origin/dev diagnostic

The 18 failures are the same 9 cases in each admin WebKit project:

  • e2e/admin.spec.ts:13, :30, :42, :64, :109, :128
  • e2e/admin-contrast.spec.ts:54 (light and dark)
  • e2e/sheet-geometry.spec.ts:222

Evidence: the expected People or Groups heading was not found within 5 seconds after navigation. I ran those three specs once on origin/dev at a55521f94ef7337f0793037ae2cb2c27266d5720, with the same admin-setup prelude, projects, no retries, and one worker. The diagnostic reproduced all 9 failures in each admin WebKit project, so these failures also occur on current dev.

Logs:

  • dev-01 gates: ~/bm4-20261101-dev01-gates.log
  • Chromium: ~/bm4-20261101-chromium.log
  • WebKit: ~/bm4-20261101-webkit.log
  • origin/dev diagnostic: ~/bm4-20261101-origin-dev-admin-diag.log
## BM4 first-run rerun on `833c3aac` Merged current `origin/dev` (`a55521f94ef7337f0793037ae2cb2c27266d5720`, including #811 and the case-path guard) into `train/2026-11-01-bm4` with `--no-ff`. No conflicts. Pushed `833c3aaccb4e0039505c32109018a13c71032000`. This PR remains open and was not merged. ### Rust and web gates on dev-01 | Gate | Command | Result | | --- | --- | --- | | fmt | `cargo fmt --all -- --check` | pass | | clippy | `cargo clippy -j4 --workspace --locked --all-targets -- -D warnings` | pass | | workspace tests | `cargo test -j4 --workspace --locked` | pass, exit 0 | | case paths | `node ci/check-case-paths.mjs` | pass | | web build | `bun run build` from `apps/web` | pass | | bundle budget | `bun scripts/bundle-size.mjs --json` plus 240/315 KiB checks | pass | First-paint JS: 243,078 bytes (237.381/240 KiB). All JS: 317,912 bytes (310.461/315 KiB). The previously intermittent `counter_concurrent_mutations_drift_and_restart` test passed on its first run. ### Playwright first-run counts Both full-suite runs used `CI=1`, `--retries=0`, and `--workers=1`. Chromium ran on dev-01 with `playwright.bm4-chromium.config.ts`; WebKit ran on dev-02 with `--no-deps`, after the separate `admin-setup` prelude. | Half | Project | Passed | Failed | Flaky | Skipped | | --- | --- | ---: | ---: | ---: | ---: | | Chromium | chromium-1440 | 386 | 0 | 0 | 586 | | Chromium | chromium-390 | 821 | 0 | 0 | 151 | | Chromium | flow | 1 | 0 | 0 | 0 | | Chromium | passkeys | 1 | 0 | 0 | 0 | | Chromium | admin-setup | 1 | 0 | 0 | 0 | | Chromium | admin-chromium-1440 | 12 | 0 | 0 | 9 | | Chromium | admin-chromium-390 | 12 | 0 | 0 | 9 | | Chromium | prefs-chromium | 7 | 0 | 0 | 0 | | Chromium | contrast | 9 | 0 | 0 | 0 | | Chromium | sidebar-band-chromium | 3 | 0 | 0 | 0 | | Chromium | throttled-1440 | 2 | 0 | 0 | 0 | | Chromium | throttled-390 | 2 | 0 | 0 | 0 | | WebKit | webkit-1440 | 381 | 0 | 0 | 591 | | WebKit | webkit-390 | 820 | 0 | 0 | 152 | | WebKit | admin-webkit-1440 | 0 | 9 | 0 | 9 | | WebKit | admin-webkit-390 | 0 | 9 | 0 | 9 | | WebKit | prefs-webkit | 3 | 0 | 0 | 4 | | WebKit | sidebar-band-webkit | 3 | 0 | 0 | 0 | Chromium total: 1,257 passed, 0 failed, 0 flaky, 755 skipped; exit 0. WebKit suite total: 1,207 passed, 18 failed, 0 flaky, 765 skipped; exit 1. The separate WebKit-side `admin-setup` prelude passed 1 test. ### WebKit failures and origin/dev diagnostic The 18 failures are the same 9 cases in each admin WebKit project: - `e2e/admin.spec.ts:13`, `:30`, `:42`, `:64`, `:109`, `:128` - `e2e/admin-contrast.spec.ts:54` (light and dark) - `e2e/sheet-geometry.spec.ts:222` Evidence: the expected `People` or `Groups` heading was not found within 5 seconds after navigation. I ran those three specs once on `origin/dev` at `a55521f94ef7337f0793037ae2cb2c27266d5720`, with the same admin-setup prelude, projects, no retries, and one worker. The diagnostic reproduced all 9 failures in each admin WebKit project, so these failures also occur on current dev. Logs: - dev-01 gates: `~/bm4-20261101-dev01-gates.log` - Chromium: `~/bm4-20261101-chromium.log` - WebKit: `~/bm4-20261101-webkit.log` - origin/dev diagnostic: `~/bm4-20261101-origin-dev-admin-diag.log`
Author
Owner

Corrected WebKit run on 833c3aaccb4e

Configuration correction

The earlier WebKit run executed admin-setup separately from the WebKit projects; the WebKit invocation used --no-deps. Each Playwright invocation loads a fresh config, creates new E2E_ADM_DATA and E2E_ADM_STATE paths, and starts fresh web servers. These paths are under os.tmpdir(): calternal-adm-*/data and calternal-adm-state-*/admin.json. admin-setup reads the first admin token from E2E_ADM_DATA/token.txt, completes passkey sign-in, and writes the session to E2E_ADM_STATE. The admin WebKit projects depend on admin-setup and load that state. The second invocation therefore used a new server and state path without running setup. The earlier origin/dev diagnostic used the same split pattern, so it did not distinguish a train issue from this setup issue.

Corrected invocation

Ran on dev-02 via ~/bin/slot in nix develop, with CI=1, --workers=1, and --retries=0:

CI=1 CALTERNAL_BIN=/home/cua/Developer/Worktrees/bm4-gates/target/debug/calternal bunx playwright test --config=playwright.webkit-only.config.ts --project=admin-setup --project=webkit-1440 --project=webkit-390 --project=admin-webkit-1440 --project=admin-webkit-390 --project=prefs-webkit --project=sidebar-band-webkit --workers=1 --retries=0

The wrapper retained the admin-setup dependency and removed only the Chromium prerequisites for prefs-webkit and sidebar-band-webkit. No --no-deps was used.

The unit received SIGTERM (exit 143) at 1840/1991, before the admin setup and admin projects ran. The log ends in webkit-390 at e2e/tint.spec.ts:313. No final Playwright per-project summary was emitted.

Project Result
webkit-1440 Project phase completed; final pass/fail counts were not emitted before interruption.
webkit-390 Interrupted at overall case 1840/1991; no final project summary.
admin-setup Not reached.
admin-webkit-1440 Not reached.
admin-webkit-390 Not reached.
prefs-webkit Not reached.
sidebar-band-webkit Not reached.

Conclusion: this corrected run is inconclusive about the admin WebKit failures because it stopped before those projects. The split-invocation results do not establish whether the failures reproduce on origin/dev. No rerun was started.

## Corrected WebKit run on `833c3aaccb4e` ### Configuration correction The earlier WebKit run executed `admin-setup` separately from the WebKit projects; the WebKit invocation used `--no-deps`. Each Playwright invocation loads a fresh config, creates new `E2E_ADM_DATA` and `E2E_ADM_STATE` paths, and starts fresh web servers. These paths are under `os.tmpdir()`: `calternal-adm-*/data` and `calternal-adm-state-*/admin.json`. `admin-setup` reads the first admin token from `E2E_ADM_DATA/token.txt`, completes passkey sign-in, and writes the session to `E2E_ADM_STATE`. The admin WebKit projects depend on `admin-setup` and load that state. The second invocation therefore used a new server and state path without running setup. The earlier `origin/dev` diagnostic used the same split pattern, so it did not distinguish a train issue from this setup issue. ### Corrected invocation Ran on dev-02 via `~/bin/slot` in `nix develop`, with `CI=1`, `--workers=1`, and `--retries=0`: ```sh CI=1 CALTERNAL_BIN=/home/cua/Developer/Worktrees/bm4-gates/target/debug/calternal bunx playwright test --config=playwright.webkit-only.config.ts --project=admin-setup --project=webkit-1440 --project=webkit-390 --project=admin-webkit-1440 --project=admin-webkit-390 --project=prefs-webkit --project=sidebar-band-webkit --workers=1 --retries=0 ``` The wrapper retained the `admin-setup` dependency and removed only the Chromium prerequisites for `prefs-webkit` and `sidebar-band-webkit`. No `--no-deps` was used. The unit received SIGTERM (exit 143) at `1840/1991`, before the admin setup and admin projects ran. The log ends in `webkit-390` at `e2e/tint.spec.ts:313`. No final Playwright per-project summary was emitted. | Project | Result | | --- | --- | | `webkit-1440` | Project phase completed; final pass/fail counts were not emitted before interruption. | | `webkit-390` | Interrupted at overall case 1840/1991; no final project summary. | | `admin-setup` | Not reached. | | `admin-webkit-1440` | Not reached. | | `admin-webkit-390` | Not reached. | | `prefs-webkit` | Not reached. | | `sidebar-band-webkit` | Not reached. | Conclusion: this corrected run is inconclusive about the admin WebKit failures because it stopped before those projects. The split-invocation results do not establish whether the failures reproduce on `origin/dev`. No rerun was started.
Author
Owner

dev-01: complete first WebKit run

verdict: WebKit half not green. the admin setup correction worked: admin-setup and both admin WebKit projects passed. the full invocation completed normally, with 1,224 passed, 2 failed, 765 skipped, no retries, no flaky tests, and no tests left unrun. exit 1; no outside signal or rerun.

host: claude@calternal-dev-01-compute02, via NetBird SSH. train head: 833c3aaccb4e0039505c32109018a13c71032000. debug build completed successfully in the train's Nix devshell via ~/bin/slot cargo build --locked -j4 -p calternal. dependencies installed with ~/bin/slot bun install --frozen-lockfile.

project passed failed skipped
webkit-1440 380 1 591
webkit-390 819 1 152
admin-setup 1 0 0
admin-webkit-1440 9 0 9
admin-webkit-390 9 0 9
prefs-webkit 3 0 4
sidebar-band-webkit 3 0 0
total 1224 2 765

exact invocation

one script: /home/claude/bm4-webkit-dev01.sh, invoked once in train mode:

systemd-run --user --unit=bm4-webkit-dev01 --collect -p RuntimeMaxSec=10800 bash -c "cd /home/claude/Developer/Worktrees/bm4-gates && /nix/var/nix/profiles/default/bin/nix develop -c bash /home/claude/bm4-webkit-dev01.sh train > /home/claude/bm4-webkit-dev01.log 2>&1"

inside that Nix shell, from /home/claude/Developer/Worktrees/bm4-gates/apps/web:

/home/claude/bin/slot env CI=1 CALTERNAL_BIN=/home/claude/Developer/Worktrees/bm4-gates/target/debug/calternal PLAYWRIGHT_JSON_OUTPUT_NAME=/home/claude/bm4-webkit-dev01/train.json bunx playwright test --config=playwright.bm4-webkit.config.ts --project=webkit-1440 --project=webkit-390 --project=admin-setup --project=admin-webkit-1440 --project=admin-webkit-390 --project=prefs-webkit --project=sidebar-band-webkit --workers=1 --retries=0 --reporter=line,json

the wrapper imports the unmodified playwright.config.ts, selects the seven projects above, and filters each project's dependencies to those seven names. this preserves admin-setup for both admin projects while removing only the Chromium prerequisite chains for prefs and sidebar. no --no-deps, no separate setup invocation.

failures and origin/dev comparison

  1. [webkit-1440] e2e/composer-tasks.spec.ts:43, “Enter makes a tracked task line in the journal with a link to its note; Undo takes both back”. first error line: Error: expect(received).toContain(expected) // indexOf. the snippet assertion at line 63 timed out after 25,000 ms: expected call plumberculng, received an empty string. does not reproduce on origin/dev in the one spec run: the matching test passed, and all 3 tests in this project passed.
  2. [webkit-390] e2e/composer-tasks.spec.ts:43, same test. first error line: Error: expect(received).toContain(expected) // indexOf. the same line-63 assertion timed out after 25,000 ms: expected call plumberxm7kb, received the earlier desktop test's call plumberculng. does not reproduce on origin/dev in the one spec run: the matching test passed, and all 3 tests in this project passed.

comparison baseline was fetched origin/dev at a55521f94ef7337f0793037ae2cb2c27266d5720, built in Nix with the same debug build command, in detached worktree /home/claude/Developer/Worktrees/bm4-webkit-dev01-baseline. the train invocation had already ended before the baseline build. one invocation selected only the failing spec and both failing projects, with no retries. 6 passed, exit 0. this isolated comparison does not establish the cause of the full-suite failures or prove a train regression.

baseline used the same script in baseline mode under bm4-webkit-dev01-baseline.service. exact Playwright command from its apps/web directory (the shared Cargo target directory held the freshly built baseline binary):

/home/claude/bin/slot env CI=1 CALTERNAL_BIN=/home/claude/Developer/Worktrees/bm4-gates/target/debug/calternal PLAYWRIGHT_JSON_OUTPUT_NAME=/home/claude/bm4-webkit-dev01/baseline-1.json bunx playwright test composer-tasks.spec.ts --config=playwright.bm4-webkit.config.ts --project=webkit-1440 --project=webkit-390 --workers=1 --retries=0 --reporter=line,json

logs on dev-01: /home/claude/bm4-webkit-dev01.log, /home/claude/bm4-webkit-dev01-baseline.log. JSON reports and per-project summaries: /home/claude/bm4-webkit-dev01/. no merge performed.

## dev-01: complete first WebKit run **verdict: WebKit half not green.** the admin setup correction worked: `admin-setup` and both admin WebKit projects passed. the full invocation completed normally, with **1,224 passed, 2 failed, 765 skipped**, no retries, no flaky tests, and no tests left unrun. exit 1; no outside signal or rerun. host: `claude@calternal-dev-01-compute02`, via NetBird SSH. train head: `833c3aaccb4e0039505c32109018a13c71032000`. debug build completed successfully in the train's Nix devshell via `~/bin/slot cargo build --locked -j4 -p calternal`. dependencies installed with `~/bin/slot bun install --frozen-lockfile`. | project | passed | failed | skipped | | --- | ---: | ---: | ---: | | webkit-1440 | 380 | 1 | 591 | | webkit-390 | 819 | 1 | 152 | | admin-setup | 1 | 0 | 0 | | admin-webkit-1440 | 9 | 0 | 9 | | admin-webkit-390 | 9 | 0 | 9 | | prefs-webkit | 3 | 0 | 4 | | sidebar-band-webkit | 3 | 0 | 0 | | **total** | **1224** | **2** | **765** | ### exact invocation one script: `/home/claude/bm4-webkit-dev01.sh`, invoked once in train mode: ```sh systemd-run --user --unit=bm4-webkit-dev01 --collect -p RuntimeMaxSec=10800 bash -c "cd /home/claude/Developer/Worktrees/bm4-gates && /nix/var/nix/profiles/default/bin/nix develop -c bash /home/claude/bm4-webkit-dev01.sh train > /home/claude/bm4-webkit-dev01.log 2>&1" ``` inside that Nix shell, from `/home/claude/Developer/Worktrees/bm4-gates/apps/web`: ```sh /home/claude/bin/slot env CI=1 CALTERNAL_BIN=/home/claude/Developer/Worktrees/bm4-gates/target/debug/calternal PLAYWRIGHT_JSON_OUTPUT_NAME=/home/claude/bm4-webkit-dev01/train.json bunx playwright test --config=playwright.bm4-webkit.config.ts --project=webkit-1440 --project=webkit-390 --project=admin-setup --project=admin-webkit-1440 --project=admin-webkit-390 --project=prefs-webkit --project=sidebar-band-webkit --workers=1 --retries=0 --reporter=line,json ``` the wrapper imports the unmodified `playwright.config.ts`, selects the seven projects above, and filters each project's dependencies to those seven names. this preserves `admin-setup` for both admin projects while removing only the Chromium prerequisite chains for prefs and sidebar. no `--no-deps`, no separate setup invocation. ### failures and origin/dev comparison 1. **`[webkit-1440] e2e/composer-tasks.spec.ts:43`**, “Enter makes a tracked task line in the journal with a link to its note; Undo takes both back”. first error line: `Error: expect(received).toContain(expected) // indexOf`. the snippet assertion at line 63 timed out after 25,000 ms: expected `call plumberculng`, received an empty string. **does not reproduce on origin/dev in the one spec run**: the matching test passed, and all 3 tests in this project passed. 2. **`[webkit-390] e2e/composer-tasks.spec.ts:43`**, same test. first error line: `Error: expect(received).toContain(expected) // indexOf`. the same line-63 assertion timed out after 25,000 ms: expected `call plumberxm7kb`, received the earlier desktop test's `call plumberculng`. **does not reproduce on origin/dev in the one spec run**: the matching test passed, and all 3 tests in this project passed. comparison baseline was fetched `origin/dev` at `a55521f94ef7337f0793037ae2cb2c27266d5720`, built in Nix with the same debug build command, in detached worktree `/home/claude/Developer/Worktrees/bm4-webkit-dev01-baseline`. the train invocation had already ended before the baseline build. one invocation selected only the failing spec and both failing projects, with no retries. **6 passed, exit 0**. this isolated comparison does not establish the cause of the full-suite failures or prove a train regression. baseline used the same script in `baseline` mode under `bm4-webkit-dev01-baseline.service`. exact Playwright command from its `apps/web` directory (the shared Cargo target directory held the freshly built baseline binary): ```sh /home/claude/bin/slot env CI=1 CALTERNAL_BIN=/home/claude/Developer/Worktrees/bm4-gates/target/debug/calternal PLAYWRIGHT_JSON_OUTPUT_NAME=/home/claude/bm4-webkit-dev01/baseline-1.json bunx playwright test composer-tasks.spec.ts --config=playwright.bm4-webkit.config.ts --project=webkit-1440 --project=webkit-390 --workers=1 --retries=0 --reporter=line,json ``` logs on dev-01: `/home/claude/bm4-webkit-dev01.log`, `/home/claude/bm4-webkit-dev01-baseline.log`. JSON reports and per-project summaries: `/home/claude/bm4-webkit-dev01/`. no merge performed.
Author
Owner

BM4: composer-tasks WebKit failure, cause and fix

Cause: a test bug, not a train regression and not an app bug. composer-tasks.spec.ts:43 read the list snippet with daily.open {}, which is the server's UTC day. The rest of the test used the browser's zone (journal() passes tz). The full WebKit run started at 23:50 UTC. The webkit-1440 test started at 23:53 UTC, which is 00:53 CET. The task landed in the browser's day (Nov 1) and the snippet poll read the server's day (Oct 31), so it saw an empty note and timed out. That test failed before its Undo, so its line stayed first in Nov 1's note. webkit-390 ran at 01:00 UTC, when both days matched, and read that leftover line (hence the other test's name). The same code passes whenever it runs outside the hour after local midnight.

Evidence (dev-01, Nix devshell, ~/bin/slot, WebKit, CI=1 --workers=1 --retries=0):

  • Spec alone on train head 833c3aac, --repeat-each=20, both projects: 120 passed (so not a spec-alone fault).
  • All specs up to and including composer-tasks on webkit-1440: 23 passed (earlier neighbours don't cause it).
  • No train PR (#779, #787, #780, #782) touches the Composer, tasks or list-snippet code.
  • Old spec with TZ=America/Los_Angeles (browser day differs from server's UTC day): 4 failed, 8 passed (--repeat-each=2). New spec, same zone: 30 passed (--repeat-each=5).

Fix: 0cb78a2e, pushed to the train branch train/2026-11-01-bm4 (no responsible PR; the spec is from dev). The test now asks daily.open for the browser's today in both places (today(page) helper). Test-only, one file: apps/web/e2e/composer-tasks.spec.ts. No timeout was changed.

Gate: composer-open, composer-tasks, composer specs, webkit-1440 and webkit-390, --repeat-each=20: 600 passed, 0 failed, 0 flaky, exit 0, 44.8 min. Log: ~/bm4-ct-gate.log on dev-01.

Train head is now 0cb78a2eaa1e77cd8b9d2a4a02f052ae2af652d8. The rest of the 833c3aac full WebKit run was green (1222 other tests). A full-suite rerun on the new head was not done. Nothing merged.

## BM4: composer-tasks WebKit failure, cause and fix **Cause: a test bug, not a train regression and not an app bug.** `composer-tasks.spec.ts:43` read the list snippet with `daily.open {}`, which is the server's UTC day. The rest of the test used the browser's zone (`journal()` passes `tz`). The full WebKit run started at 23:50 UTC. The webkit-1440 test started at 23:53 UTC, which is 00:53 CET. The task landed in the browser's day (Nov 1) and the snippet poll read the server's day (Oct 31), so it saw an empty note and timed out. That test failed before its Undo, so its line stayed first in Nov 1's note. webkit-390 ran at 01:00 UTC, when both days matched, and read that leftover line (hence the other test's name). The same code passes whenever it runs outside the hour after local midnight. **Evidence** (dev-01, Nix devshell, `~/bin/slot`, WebKit, `CI=1 --workers=1 --retries=0`): - Spec alone on train head `833c3aac`, `--repeat-each=20`, both projects: 120 passed (so not a spec-alone fault). - All specs up to and including composer-tasks on webkit-1440: 23 passed (earlier neighbours don't cause it). - No train PR (#779, #787, #780, #782) touches the Composer, tasks or list-snippet code. - Old spec with `TZ=America/Los_Angeles` (browser day differs from server's UTC day): 4 failed, 8 passed (`--repeat-each=2`). New spec, same zone: 30 passed (`--repeat-each=5`). **Fix:** `0cb78a2e`, pushed to the **train branch** `train/2026-11-01-bm4` (no responsible PR; the spec is from dev). The test now asks `daily.open` for the browser's today in both places (`today(page)` helper). Test-only, one file: `apps/web/e2e/composer-tasks.spec.ts`. No timeout was changed. **Gate:** `composer-open`, `composer-tasks`, `composer` specs, webkit-1440 and webkit-390, `--repeat-each=20`: **600 passed, 0 failed, 0 flaky**, exit 0, 44.8 min. Log: `~/bm4-ct-gate.log` on dev-01. Train head is now `0cb78a2eaa1e77cd8b9d2a4a02f052ae2af652d8`. The rest of the 833c3aac full WebKit run was green (1222 other tests). A full-suite rerun on the new head was not done. Nothing merged.
Author
Owner

deployed BM4 to prod on 2026-11-01 at 13:04 IST via scripts/deploy-prod.sh --yes-prod, after its dry run. version 0.1.0 (unchanged app version string), git d0a2819ab2. no rollback or deploy retry.

image archive sha256: 66ef11196e8c411d77857be6109dce40c9f5758b9ea86831d962710e5ce3ed49 (118,227,968 bytes). built on dev-01 with Nix/slot, rootless Podman, clean source archive/umask 022 and unchanged deploy/Containerfile, docker format/no cache; sha256 matched after the documented relay to the control host. prod architecture checked first: x86_64. running/current/tag image ID matches 24c4e363534ea873309a0ac3b6e339a4e7e47083008863c022f1425556f0ec23.

migration: yes, additive auth.db v7 → v10: DAV scopes/triggers, assertion timestamps, registration-session tracking. deployed without --restore.

checks: /healthz 200/version 0.1.0; Podman healthy; unit active/0 restarts; first 120 seconds of container logs: 120 lines, 0 errors, 0 warnings. public app 200; Chromium renders #/signin, title Calternal, visible “Sign in with your passkey”; auth status 200. browser recorded one HTTP 401 console entry. shared browser unavailable due host libraries, so used existing Playwright in dev-01's Nix shell.

DAV smoke failed: unauthenticated PROPFIND https://calternal.cloud/dav/ returns 405, not 401, confirmed from dev-01 and control. #782 adds the auth gate but explicitly leaves DAV route mounting to D4; BM4 does not mount it. reporting this limitation, with no further prod changes.

backup: /srv/calternal-app/backup-pre-d0a2819a-20261101T073355247806641Z.tgz (mode 600, 12,544,087 bytes). all build/slot jobs stopped.

deployed BM4 to prod on 2026-11-01 at 13:04 IST via `scripts/deploy-prod.sh --yes-prod`, after its dry run. version **0.1.0** (unchanged app version string), git **d0a2819ab2d3e7eb49a82d2cf20d13f707fdc383**. no rollback or deploy retry. image archive sha256: `66ef11196e8c411d77857be6109dce40c9f5758b9ea86831d962710e5ce3ed49` (118,227,968 bytes). built on dev-01 with Nix/slot, rootless Podman, clean source archive/umask 022 and unchanged `deploy/Containerfile`, docker format/no cache; sha256 matched after the documented relay to the control host. prod architecture checked first: x86_64. running/current/tag image ID matches `24c4e363534ea873309a0ac3b6e339a4e7e47083008863c022f1425556f0ec23`. **migration: yes**, additive `auth.db` v7 → v10: DAV scopes/triggers, assertion timestamps, registration-session tracking. deployed without `--restore`. checks: `/healthz` 200/version 0.1.0; Podman healthy; unit active/0 restarts; first 120 seconds of container logs: 120 lines, **0 errors, 0 warnings**. public app 200; Chromium renders `#/signin`, title Calternal, visible “Sign in with your passkey”; auth status 200. browser recorded one HTTP 401 console entry. shared browser unavailable due host libraries, so used existing Playwright in dev-01's Nix shell. **DAV smoke failed:** unauthenticated `PROPFIND https://calternal.cloud/dav/` returns **405, not 401**, confirmed from dev-01 and control. #782 adds the auth gate but explicitly leaves DAV route mounting to D4; BM4 does not mount it. reporting this limitation, with no further prod changes. backup: `/srv/calternal-app/backup-pre-d0a2819a-20261101T073355247806641Z.tgz` (mode 600, 12,544,087 bytes). all build/slot jobs stopped.
Author
Owner

Closing: head 0cb78a2e is already in dev (reached via d0a2819a); nothing left to merge. Branch kept.

Closing: head 0cb78a2e is already in dev (reached via d0a2819a); nothing left to merge. Branch kept.
kayg closed this pull request 2026-11-04 13:04:44 +00:00
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!810
No description provided.