Timing-sensitive tests fail under VM load #31

Open
opened 2026-09-24 09:41:33 +00:00 by kayg · 28 comments
Owner

With about 10 parallel jobs (load5 around 15 to 18), tests that pass on a quiet machine fail:

  1. crates/engine/tests/integration.rs:481 stalled_pty_stdin_cannot_hold_exec_termination: session.close() exceeded its 4 s timeout on Podman. At low load it passed 3 of 3, reaping in 389 to 400 ms on Docker and 502 to 732 ms on Podman.
  2. A packages/stream Vitest case expected close code 4108 and received undefined (seen in the ui-apis fast gate). It passed at low load.

Fix: make these tests robust to scheduling delay without hiding real regressions. Use deterministic synchronization (wait on events, not wall-clock sleeps). Where a wall-clock bound is the product guarantee, measure it from the right start point and give it a stated tolerance for a loaded CI host, or move the timing assertion to bench. Also consider a scripts/verify guard that warns when load5 is above the core count.

With about 10 parallel jobs (load5 around 15 to 18), tests that pass on a quiet machine fail: 1. `crates/engine/tests/integration.rs:481` `stalled_pty_stdin_cannot_hold_exec_termination`: `session.close()` exceeded its 4 s timeout on Podman. At low load it passed 3 of 3, reaping in 389 to 400 ms on Docker and 502 to 732 ms on Podman. 2. A `packages/stream` Vitest case expected close code `4108` and received `undefined` (seen in the `ui-apis` fast gate). It passed at low load. Fix: make these tests robust to scheduling delay without hiding real regressions. Use deterministic synchronization (wait on events, not wall-clock sleeps). Where a wall-clock bound is the product guarantee, measure it from the right start point and give it a stated tolerance for a loaded CI host, or move the timing assertion to `bench`. Also consider a `scripts/verify` guard that warns when load5 is above the core count.
Author
Owner

Starting work on flaky-tests from base f1bedf994ce5399cf4b53ff0ca693ff0db4cfb9d.
Scope: test code and the load warning in scripts/verify. I am mapping existing timing-sensitive cases before establishing quiet and deliberate-load baselines.

Starting work on `flaky-tests` from base `f1bedf994ce5399cf4b53ff0ca693ff0db4cfb9d`. Scope: test code and the load warning in `scripts/verify`. I am mapping existing timing-sensitive cases before establishing quiet and deliberate-load baselines.
Author
Owner

Starting work on flaky-tests from base f1bedf994ce5399cf4b53ff0ca693ff0db4cfb9d.

Scope: test code and the load warning in scripts/verify. I am mapping existing timing-sensitive cases before establishing quiet and deliberate-load baselines.

Starting work on `flaky-tests` from base `f1bedf994ce5399cf4b53ff0ca693ff0db4cfb9d`. Scope: test code and the load warning in `scripts/verify`. I am mapping existing timing-sensitive cases before establishing quiet and deliberate-load baselines.
Author
Owner

Baseline setup evidence: launching fast and integration simultaneously caused both infraternal_ensure_js_dependencies calls to run bun install against this checkout's shared node_modules; they failed with EEXIST while linking packages before any tests ran. I am sequencing the gates under one continuous stress-ng --cpu 8 run. The separate debug build also exited because embedded web assets had not yet been built.

Baseline setup evidence: launching `fast` and `integration` simultaneously caused both `infraternal_ensure_js_dependencies` calls to run `bun install` against this checkout's shared `node_modules`; they failed with `EEXIST` while linking packages before any tests ran. I am sequencing the gates under one continuous `stress-ng --cpu 8` run. The separate debug build also exited because embedded web assets had not yet been built.
Author
Owner

Loaded baseline evidence: under stress-ng --cpu 8 --cpu-load 100, scripts/verify fast passed the Cargo workspace tests, web and UI Vitest, and typechecks, then stream Vitest failed client_protocol_failures.test.ts → closes 1008 when the peer exceeds the 400-control-frame burst: it expected 1008 and got undefined (line 302). The test sends 401 PING frames while the implementation's 200/s token bucket uses real performance.now(); this run's test body took 22 ms, enough for tokens to refill during the synchronous loop. The adjacent browser-policy case expects 4108 from the same burst path and has the same timing assumption.

Loaded baseline evidence: under `stress-ng --cpu 8 --cpu-load 100`, `scripts/verify fast` passed the Cargo workspace tests, web and UI Vitest, and typechecks, then stream Vitest failed `client_protocol_failures.test.ts` → `closes 1008 when the peer exceeds the 400-control-frame burst`: it expected 1008 and got `undefined` (line 302). The test sends 401 PING frames while the implementation's 200/s token bucket uses real `performance.now()`; this run's test body took 22 ms, enough for tokens to refill during the synchronous loop. The adjacent browser-policy case expects 4108 from the same burst path and has the same timing assumption.
Author
Owner

The two stream burst tests now pin performance.now() at 0 while delivering their 401 PING frames, so scheduler delays cannot refill the burst bucket during the modeled same-instant input. The focused test file passed under the same stress workers: Test Files 1 passed (1); Tests 49 passed (49). I also added a non-failing scripts/verify warning when /proc/loadavg load5 exceeds the online CPU count; it prints both values.

The two stream burst tests now pin `performance.now()` at 0 while delivering their 401 PING frames, so scheduler delays cannot refill the burst bucket during the modeled same-instant input. The focused test file passed under the same stress workers: `Test Files 1 passed (1); Tests 49 passed (49)`. I also added a non-failing `scripts/verify` warning when `/proc/loadavg` load5 exceeds the online CPU count; it prints both values.
Author
Owner

The first loaded integration run completed every integration step successfully, including Docker/Podman engine adapters, stream regressions, CLI/MCP, and real sshd. The script then exited 1 in the new warning helper with load5: unbound variable under set -u. I initialized both local values explicitly and am rerunning the helper and gate.

The first loaded `integration` run completed every integration step successfully, including Docker/Podman engine adapters, stream regressions, CLI/MCP, and real sshd. The script then exited 1 in the new warning helper with `load5: unbound variable` under `set -u`. I initialized both local values explicitly and am rerunning the helper and gate.
Author
Owner

Loaded integration run 1 found another test timing assumption in crates/server/tests/stream_regressions.rs::every_grant_shrink_closes_logs_and_persistent_exec_on_both_engines. At load5 13.99, Docker's transient grant shrink observed 4 log DATA frames before CLOSE; Podman's observed 0 and failed the assertion that every run must have a log frame arrive after the SQLite commit. The product behavior assertion still passed for Podman: both CLOSE frames arrived in 66.7 ms, below the 1 s contract. I am changing the test to wait for an actual log DATA event before mutating grants and to keep the 1 s close and DATA-before-CLOSE assertions.

Loaded integration run 1 found another test timing assumption in `crates/server/tests/stream_regressions.rs::every_grant_shrink_closes_logs_and_persistent_exec_on_both_engines`. At load5 13.99, Docker's transient grant shrink observed 4 log DATA frames before CLOSE; Podman's observed 0 and failed the assertion that every run must have a log frame arrive after the SQLite commit. The product behavior assertion still passed for Podman: both CLOSE frames arrived in 66.7 ms, below the 1 s contract. I am changing the test to wait for an actual log DATA event before mutating grants and to keep the 1 s close and DATA-before-CLOSE assertions.
Author
Owner

The first focused rerun of the grant-shrink test after adding the log-event wait passed all Docker causes and Podman's first two causes, then panicked because shrink_open_reply saw the WebSocket end while waiting for an OPEN reply (Option::unwrap() at the helper). It did not capture a CLOSE code or payload. I am improving the test's failure diagnostic and repeating before deciding whether this is a product bug or another harness race.

The first focused rerun of the grant-shrink test after adding the log-event wait passed all Docker causes and Podman's first two causes, then panicked because `shrink_open_reply` saw the WebSocket end while waiting for an OPEN reply (`Option::unwrap()` at the helper). It did not capture a CLOSE code or payload. I am improving the test's failure diagnostic and repeating before deciding whether this is a product bug or another harness race.
Author
Owner

The next focused run under eight stress workers passed Docker and the first seven Podman grant-shrink causes. It then failed starting the final Podman token_expired case: the WebSocket closed with 4003 token expired or revoked before the logs OPEN reply. Several preceding Podman process-reap checks took 1.5–3.7 s under this load. I am checking whether the test's shared token lifetime expires naturally before that final case.

The next focused run under eight stress workers passed Docker and the first seven Podman grant-shrink causes. It then failed starting the final Podman `token_expired` case: the WebSocket closed with 4003 `token expired or revoked` before the logs OPEN reply. Several preceding Podman process-reap checks took 1.5–3.7 s under this load. I am checking whether the test's shared token lifetime expires naturally before that final case.
Author
Owner

Follow-up on the intermittent 4003: SqliteStorage::issue_test_token sets a 15-minute expiry; the focused matrix completes in under 2 minutes, so natural expiry does not explain the early close. The next focused run, with runtime/cause context, passed both engines through the final token_expired case (68 ms CLOSE). I have not confirmed a product bug; the full integration repetitions will exercise this again.

Follow-up on the intermittent 4003: `SqliteStorage::issue_test_token` sets a 15-minute expiry; the focused matrix completes in under 2 minutes, so natural expiry does not explain the early close. The next focused run, with runtime/cause context, passed both engines through the final `token_expired` case (68 ms CLOSE). I have not confirmed a product bug; the full integration repetitions will exercise this again.
Author
Owner

Loaded integration repetition 1 reached the real server stream regressions but failed authorization_loss_terminates_stalled_stdin_on_both_engines: Podman emitted CLOSE-forbidden at 47.624097 ms, then the test failed podman termination completion was not audited at crates/server/tests/stream_regressions.rs:833. The newly adjusted grant-shrink matrix passed on Docker and Podman in the same run; its transient stream saw 3 Docker and 10 Podman DATA frames after commit. Investigating whether the audit assertion races asynchronous completion or indicates a product bug; no product changes made.

Loaded integration repetition 1 reached the real server stream regressions but failed `authorization_loss_terminates_stalled_stdin_on_both_engines`: Podman emitted CLOSE-forbidden at 47.624097 ms, then the test failed `podman termination completion was not audited` at `crates/server/tests/stream_regressions.rs:833`. The newly adjusted grant-shrink matrix passed on Docker and Podman in the same run; its transient stream saw 3 Docker and 10 Podman DATA frames after commit. Investigating whether the audit assertion races asynchronous completion or indicates a product bug; no product changes made.
Author
Owner

The focused rerun of authorization_loss_terminates_stalled_stdin_on_both_engines passed once under continued host load: cargo test: 1 passed, 15 filtered out (1 suite, 20.77s). This does not establish whether the first Podman audit miss was a delayed completion or a product failure; the test now prints all termination audit rows if it recurs.

The focused rerun of `authorization_loss_terminates_stalled_stdin_on_both_engines` passed once under continued host load: `cargo test: 1 passed, 15 filtered out (1 suite, 20.77s)`. This does not establish whether the first Podman audit miss was a delayed completion or a product failure; the test now prints all termination audit rows if it recurs.
Author
Owner

After adding audit-row diagnostics (keeping the assertion intact), the first post-diagnostic loaded scripts/verify integration repetition passed every step. It emitted WARN load5=8.78 exceeds online CPU count=8; timing-sensitive checks may be delayed; the stream regression suite passed on Docker and Podman, including the stalled-stdin audit case. The earlier single Podman audit miss has not reproduced in three focused repetitions or this full run. Log: /tmp/flaky-tests-20260924-loaded-integration-final-1.log.

After adding audit-row diagnostics (keeping the assertion intact), the first post-diagnostic loaded `scripts/verify integration` repetition passed every step. It emitted `WARN load5=8.78 exceeds online CPU count=8; timing-sensitive checks may be delayed`; the stream regression suite passed on Docker and Podman, including the stalled-stdin audit case. The earlier single Podman audit miss has not reproduced in three focused repetitions or this full run. Log: `/tmp/flaky-tests-20260924-loaded-integration-final-1.log`.
Author
Owner

Finished job #31 on branch flaky-tests, based on f1bedf994ce5399cf4b53ff0ca693ff0db4cfb9d.

Head: 5c0c0dd2861c895531489ace82780dbbd01147e8 (not pushed).

Changes:

  • Stabilized the two 401-PING stream burst tests by freezing performance.now() during the burst, so the token bucket cannot refill while the test loop runs.
  • Stabilized the grant-shrink regression setup by waiting for an actual log DATA event before mutating grants. Removed the assertion that a new DATA frame must arrive in the short commit-to-CLOSE window; retained the under-1-second CLOSE bound and DATA-before-CLOSE ordering for any frames that arrive. Added runtime/cause details to OPEN/CLOSE failures.
  • Kept the stalled-stdin termination completion-audit assertion and added audit-row details if it fails.
  • Added a non-failing scripts/verify warning when load5 exceeds online CPU count.

Verification:

  • After the final test changes, scripts/verify fast passed three consecutive times under the same stress-ng --cpu 8 --cpu-load 10 run. Gate-start load5 warnings were 10.87, 9.25, and 10.55 on 8 CPUs. Logs: /tmp/flaky-tests-20260924-loaded-fast-final-{1,2,3}.log.
  • scripts/verify integration passed three consecutive times under the same stress profile. Logs: /tmp/flaky-tests-20260924-loaded-integration-final-{1,2,3}.log.
  • Quiet scripts/verify fast and scripts/verify integration also passed after stress-ng stopped and other builds cleared. Logs: /tmp/flaky-tests-20260924-quiet-fast.log and /tmp/flaky-tests-20260924-quiet-integration.log.
  • Focused authorization_loss_terminates_stalled_stdin_on_both_engines passed three consecutive loaded repetitions: 20.77 s, 15.74 s, and 14.56 s.

One earlier loaded full integration attempt failed because Podman sent forbidden CLOSE in 47.6 ms and the test then did not observe an accepted/forbidden termination audit within 2 seconds. I added audit-row diagnostics without weakening that assertion. It passed in the three focused repetitions, all three later loaded integration gates, and the quiet integration gate. I found no confirmed product bug and changed no product code. The earlier isolated WebSocket CLOSE 4003 before OPEN also did not recur in the later matrix runs.

Representative loaded gate output, verbatim:

WARN load5=10.55 exceeds online CPU count=8; timing-sensitive checks may be delayed
PASS fast: migrations are append-only
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
WARN load5=8.78 exceeds online CPU count=8; timing-sensitive checks may be delayed
PASS integration: JavaScript dependencies
PASS integration: build web app
PASS integration: build release binary
PASS integration: real HTTP behavior
PASS integration: Docker socket _ping
PASS integration: rootless Podman socket _ping
PASS integration: engine adapters against Docker and Podman
PASS integration: TypeScript stream client against Docker and Podman
PASS integration: stream authorization and CLOSE regressions against Docker
PASS integration: persistent PTY termination preempts blocked send
PASS integration: resource HTTP API against Docker and rootless Podman
PASS integration: compiled CLI and MCP against real server and engines
PASS integration: SSH contract against real sshd

Quiet gate output, verbatim:

PASS fast: migrations are append-only
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
PASS integration: JavaScript dependencies
PASS integration: build web app
PASS integration: build release binary
PASS integration: real HTTP behavior
PASS integration: Docker socket _ping
PASS integration: rootless Podman socket _ping
PASS integration: engine adapters against Docker and Podman
PASS integration: TypeScript stream client against Docker and Podman
PASS integration: stream authorization and CLOSE regressions against Docker
PASS integration: persistent PTY termination preempts blocked send
PASS integration: resource HTTP API against Docker and rootless Podman
PASS integration: compiled CLI and MCP against real server and engines
PASS integration: SSH contract against real sshd
Finished job #31 on branch `flaky-tests`, based on `f1bedf994ce5399cf4b53ff0ca693ff0db4cfb9d`. Head: `5c0c0dd2861c895531489ace82780dbbd01147e8` (not pushed). Changes: - Stabilized the two 401-PING stream burst tests by freezing `performance.now()` during the burst, so the token bucket cannot refill while the test loop runs. - Stabilized the grant-shrink regression setup by waiting for an actual log DATA event before mutating grants. Removed the assertion that a new DATA frame must arrive in the short commit-to-CLOSE window; retained the under-1-second CLOSE bound and DATA-before-CLOSE ordering for any frames that arrive. Added runtime/cause details to OPEN/CLOSE failures. - Kept the stalled-stdin termination completion-audit assertion and added audit-row details if it fails. - Added a non-failing `scripts/verify` warning when load5 exceeds online CPU count. Verification: - After the final test changes, `scripts/verify fast` passed three consecutive times under the same `stress-ng --cpu 8 --cpu-load 10` run. Gate-start load5 warnings were 10.87, 9.25, and 10.55 on 8 CPUs. Logs: `/tmp/flaky-tests-20260924-loaded-fast-final-{1,2,3}.log`. - `scripts/verify integration` passed three consecutive times under the same stress profile. Logs: `/tmp/flaky-tests-20260924-loaded-integration-final-{1,2,3}.log`. - Quiet `scripts/verify fast` and `scripts/verify integration` also passed after stress-ng stopped and other builds cleared. Logs: `/tmp/flaky-tests-20260924-quiet-fast.log` and `/tmp/flaky-tests-20260924-quiet-integration.log`. - Focused `authorization_loss_terminates_stalled_stdin_on_both_engines` passed three consecutive loaded repetitions: 20.77 s, 15.74 s, and 14.56 s. One earlier loaded full integration attempt failed because Podman sent forbidden CLOSE in 47.6 ms and the test then did not observe an accepted/forbidden termination audit within 2 seconds. I added audit-row diagnostics without weakening that assertion. It passed in the three focused repetitions, all three later loaded integration gates, and the quiet integration gate. I found no confirmed product bug and changed no product code. The earlier isolated WebSocket CLOSE 4003 before OPEN also did not recur in the later matrix runs. Representative loaded gate output, verbatim: ```text WARN load5=10.55 exceeds online CPU count=8; timing-sensitive checks may be delayed PASS fast: migrations are append-only PASS fast: JavaScript dependencies PASS fast: build web app PASS fast: cargo fmt --check PASS fast: cargo clippy PASS fast: cargo test PASS fast: svelte-check PASS fast: UI package svelte-check PASS fast: stream package typecheck PASS fast: Vitest PASS fast: UI package Vitest PASS fast: stream package Vitest PASS fast: OpenAPI and TypeScript client drift PASS fast: terminal TypeScript PASS fast: terminal Vitest ``` ```text WARN load5=8.78 exceeds online CPU count=8; timing-sensitive checks may be delayed PASS integration: JavaScript dependencies PASS integration: build web app PASS integration: build release binary PASS integration: real HTTP behavior PASS integration: Docker socket _ping PASS integration: rootless Podman socket _ping PASS integration: engine adapters against Docker and Podman PASS integration: TypeScript stream client against Docker and Podman PASS integration: stream authorization and CLOSE regressions against Docker PASS integration: persistent PTY termination preempts blocked send PASS integration: resource HTTP API against Docker and rootless Podman PASS integration: compiled CLI and MCP against real server and engines PASS integration: SSH contract against real sshd ``` Quiet gate output, verbatim: ```text PASS fast: migrations are append-only PASS fast: JavaScript dependencies PASS fast: build web app PASS fast: cargo fmt --check PASS fast: cargo clippy PASS fast: cargo test PASS fast: svelte-check PASS fast: UI package svelte-check PASS fast: stream package typecheck PASS fast: Vitest PASS fast: UI package Vitest PASS fast: stream package Vitest PASS fast: OpenAPI and TypeScript client drift PASS fast: terminal TypeScript PASS fast: terminal Vitest ``` ```text PASS integration: JavaScript dependencies PASS integration: build web app PASS integration: build release binary PASS integration: real HTTP behavior PASS integration: Docker socket _ping PASS integration: rootless Podman socket _ping PASS integration: engine adapters against Docker and Podman PASS integration: TypeScript stream client against Docker and Podman PASS integration: stream authorization and CLOSE regressions against Docker PASS integration: persistent PTY termination preempts blocked send PASS integration: resource HTTP API against Docker and rootless Podman PASS integration: compiled CLI and MCP against real server and engines PASS integration: SSH contract against real sshd ```
Author
Owner

Starting independent review on branch flaky-tests, head 5c0c0dd2861c895531489ace82780dbbd01147e8, against requested base f1bedf9. I’m reviewing the test-strength changes and verify warning, then will run the changed tests and scratch fault checks as requested.

Starting independent review on branch `flaky-tests`, head `5c0c0dd2861c895531489ace82780dbbd01147e8`, against requested base `f1bedf9`. I’m reviewing the test-strength changes and verify warning, then will run the changed tests and scratch fault checks as requested.
Author
Owner

Independent review — branch flaky-tests, head 5c0c0dd2861c895531489ace82780dbbd01147e8, base f1bedf9.

Findings:

  • later — In every_grant_shrink_closes_logs_and_persistent_exec_on_both_engines, the queued_logs_after_commit > 0 assertion is removed. The new event wait proves an actual logs DATA reached the client before the transient shrink. The test still requires forbidden CLOSE on both channels, the one-second deadline measured from the shrinking commit, no same-channel DATA after CLOSE, and no same-channel frames during the 100 ms post-CLOSE drain. This removes a scheduling-dependent workload observation and leaves less direct evidence that a log frame was in flight at the commit boundary. Consider deterministic queue-barrier coverage later if that race needs explicit integration coverage. The §2.3 close/fence checks and §3.10 1008/4108 checks remain asserted.

No blocks-merge findings.

Test review:

  • freezeControlClock() fixes performance.now() for the two 401-frame tests; their 4108 and 1008 expectations are unchanged. No timeout, sleep, skip, or retry change was added in Vitest.
  • The new log event wait is 10 seconds; its comment states that the fixture emits every 200 ms. This is setup synchronization. A 10× slowdown in fixture emission (2 seconds) would still pass this wait; the one-second revocation CLOSE deadline is separate and unchanged. shrink_open_reply remains at 5 seconds. No new conditional skip or retry was added.
  • The load warning ran under bash -euo pipefail. Its normal branch returned 0; exercising the overload branch with load 99 / 8 CPUs printed the warning and returned 0; a failed awk lookup also returned 0. scripts/verify fast passed.

Verification:

  • Quiet host: load5 was 2.60 before Vitest and 2.70 before the Rust grant-shrink matrix (required threshold: below 6).
  • Current stream Vitest: 49 passed. Current ignored real-engine regressions: authorization_loss_terminates_stalled_stdin_on_both_engines passed; every_grant_shrink_closes_logs_and_persistent_exec_on_both_engines passed against Docker and rootless Podman (48.30 s).
  • Scratch-only fault injection delayed server-side client CLOSE by 2 seconds. The current grant-shrink test failed at docker role_change CLOSE exceeded one second (2.43 s). After restoring the Rust and TypeScript test files from f1bedf9, the old grant-shrink assertion set failed at the same one-second CLOSE deadline (2.21 s); the old stream Vitest file passed 49 tests.
  • Main worktree remains clean; the scratch worktree was removed. No commit was made.

scripts/verify fast output:

PASS fast: migrations are append-only
PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: stream package typecheck
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: stream package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS fast: terminal TypeScript
PASS fast: terminal Vitest
Independent review — branch `flaky-tests`, head `5c0c0dd2861c895531489ace82780dbbd01147e8`, base `f1bedf9`. Findings: - **later** — In `every_grant_shrink_closes_logs_and_persistent_exec_on_both_engines`, the `queued_logs_after_commit > 0` assertion is removed. The new event wait proves an actual logs `DATA` reached the client before the transient shrink. The test still requires `forbidden` CLOSE on both channels, the one-second deadline measured from the shrinking commit, no same-channel DATA after CLOSE, and no same-channel frames during the 100 ms post-CLOSE drain. This removes a scheduling-dependent workload observation and leaves less direct evidence that a log frame was in flight at the commit boundary. Consider deterministic queue-barrier coverage later if that race needs explicit integration coverage. The §2.3 close/fence checks and §3.10 `1008`/`4108` checks remain asserted. No blocks-merge findings. Test review: - `freezeControlClock()` fixes `performance.now()` for the two 401-frame tests; their `4108` and `1008` expectations are unchanged. No timeout, sleep, skip, or retry change was added in Vitest. - The new log event wait is 10 seconds; its comment states that the fixture emits every 200 ms. This is setup synchronization. A 10× slowdown in fixture emission (2 seconds) would still pass this wait; the one-second revocation CLOSE deadline is separate and unchanged. `shrink_open_reply` remains at 5 seconds. No new conditional skip or retry was added. - The load warning ran under `bash -euo pipefail`. Its normal branch returned 0; exercising the overload branch with load 99 / 8 CPUs printed the warning and returned 0; a failed `awk` lookup also returned 0. `scripts/verify fast` passed. Verification: - Quiet host: load5 was 2.60 before Vitest and 2.70 before the Rust grant-shrink matrix (required threshold: below 6). - Current stream Vitest: 49 passed. Current ignored real-engine regressions: `authorization_loss_terminates_stalled_stdin_on_both_engines` passed; `every_grant_shrink_closes_logs_and_persistent_exec_on_both_engines` passed against Docker and rootless Podman (48.30 s). - Scratch-only fault injection delayed server-side client CLOSE by 2 seconds. The current grant-shrink test failed at `docker role_change CLOSE exceeded one second` (2.43 s). After restoring the Rust and TypeScript test files from `f1bedf9`, the old grant-shrink assertion set failed at the same one-second CLOSE deadline (2.21 s); the old stream Vitest file passed 49 tests. - Main worktree remains clean; the scratch worktree was removed. No commit was made. `scripts/verify fast` output: ```text PASS fast: migrations are append-only PASS fast: JavaScript dependencies PASS fast: build web app PASS fast: cargo fmt --check PASS fast: cargo clippy PASS fast: cargo test PASS fast: svelte-check PASS fast: UI package svelte-check PASS fast: stream package typecheck PASS fast: Vitest PASS fast: UI package Vitest PASS fast: stream package Vitest PASS fast: OpenAPI and TypeScript client drift PASS fast: terminal TypeScript PASS fast: terminal Vitest ```
Author
Owner

Another load-sensitive flake: steady_state_framing_does_not_allocate_per_chunk failed in verify fast at load5 6.23 during verify-11c. The direct rerun passed. Label: later.

Another load-sensitive flake: `steady_state_framing_does_not_allocate_per_chunk` failed in `verify fast` at load5 6.23 during verify-11c. The direct rerun passed. Label: later.
Author
Owner

Starting fix-scroll-wait on branch ws-close-reply, base head 2fae616b9f06ceed40d8cd270b58a6a3402799ec. Scope: make the production browser smoke wait for the filtered container row to be fully visible after DataTable scrolling, then reproduce under CPU load and run the requested fast gate.

Starting fix-scroll-wait on branch `ws-close-reply`, base head `2fae616b9f06ceed40d8cd270b58a6a3402799ec`. Scope: make the production browser smoke wait for the filtered container row to be fully visible after DataTable scrolling, then reproduce under CPU load and run the requested `fast` gate.
Author
Owner

The supplied gate log records WARN load5=11.43 exceeds online CPU count=8; the production browser smoke then fails in findContainerRow with container row did not scroll into view. The existing geometry poll has a 200 ms timeout and 20 ms interval. I am preparing the requested stress-ng reproduction; the shared VM is still above the documented load threshold for starting a release build.

The supplied gate log records `WARN load5=11.43 exceeds online CPU count=8`; the production browser smoke then fails in `findContainerRow` with `container row did not scroll into view`. The existing geometry poll has a 200 ms timeout and 20 ms interval. I am preparing the requested stress-ng reproduction; the shared VM is still above the documented load threshold for starting a release build.
Author
Owner

Implementation decision: retain the existing scroll adjustment and full-row containment predicate, and change only the polling window from 200 ms / 20 ms to 5 s / 50 ms. This gives the virtualized layout time to settle under VM load without accepting a partially visible row. The original script is saved outside the worktree so the before-change reproduction can run later against the matching release binary.

Implementation decision: retain the existing scroll adjustment and full-row containment predicate, and change only the polling window from 200 ms / 20 ms to 5 s / 50 ms. This gives the virtualized layout time to settle under VM load without accepting a partially visible row. The original script is saved outside the worktree so the before-change reproduction can run later against the matching release binary.
Author
Owner

The source change is ready, but verification is temporarily blocked by shared-host admission: /proc/loadavg has remained around 35–40 and a separate cargo build --release -p infraternal is active in install-timeline-ui. The worktree job rules require waiting for load below 10 before starting a heavy build. I will resume the baseline, five post-change smoke runs and fast when the host clears.

The source change is ready, but verification is temporarily blocked by shared-host admission: `/proc/loadavg` has remained around 35–40 and a separate `cargo build --release -p infraternal` is active in `install-timeline-ui`. The worktree job rules require waiting for load below 10 before starting a heavy build. I will resume the baseline, five post-change smoke runs and `fast` when the host clears.
Author
Owner

Follow-up admission snapshot: both external release builds have ended, but /proc/loadavg is now 42.80 34.88 30.90; Rust builds and browser processes remain active. No smoke suite has been started from this worktree. I am continuing to wait for load below 10 and browser-suite serialization.

Follow-up admission snapshot: both external release builds have ended, but `/proc/loadavg` is now `42.80 34.88 30.90`; Rust builds and browser processes remain active. No smoke suite has been started from this worktree. I am continuing to wait for load below 10 and browser-suite serialization.
Author
Owner

To avoid another release compile on the loaded host, I will run the browser smoke against the cached release binary built at 1dd62b854fbdedadd9611c07b5bf19cd067cf9ae. The source diff from the task base is limited to crates/server/src/stream.rs and its regression test; the container route, DataTable and browser-check source are unchanged. The smoke checks stream/channel retirement but does not assert the WebSocket close-reply frame itself. I will include this binary head in the result.

To avoid another release compile on the loaded host, I will run the browser smoke against the cached release binary built at `1dd62b854fbdedadd9611c07b5bf19cd067cf9ae`. The source diff from the task base is limited to `crates/server/src/stream.rs` and its regression test; the container route, DataTable and browser-check source are unchanged. The smoke checks stream/channel retirement but does not assert the WebSocket close-reply frame itself. I will include this binary head in the result.
Author
Owner

Before-change reproduction: nix run nixpkgs#stress-ng -- --cpu 16 started stress-ng 0.22.00 with 16 CPU workers. Browser smoke run fix-scroll-before-1 against the cached release binary failed in findContainerRow at line 2528 with container row did not scroll into view; the assertion still had { timeout: 200, interval: 20 }. The failure occurred after the auth and sidebar persistence flows passed. The test's source was restored to the committed version afterward.

Before-change reproduction: `nix run nixpkgs#stress-ng -- --cpu 16` started stress-ng 0.22.00 with 16 CPU workers. Browser smoke run `fix-scroll-before-1` against the cached release binary failed in `findContainerRow` at line 2528 with `container row did not scroll into view`; the assertion still had `{ timeout: 200, interval: 20 }`. The failure occurred after the auth and sidebar persistence flows passed. The test's source was restored to the committed version afterward.
Author
Owner

After-change reproduction: while the same nix run nixpkgs#stress-ng -- --cpu 16 process ran for 16 minutes, the updated browser smoke passed five sequential runs (fix-scroll-after-1 through fix-scroll-after-5). Each ended with POST_CHANGE_SMOKE_PASS; each reached SIDEBAR_CONTAINERS repetition=1/1 GET /api/v1/containers status=200. Stress-ng reported 16 CPU workers passed, 0 failed. The browser script requires full-row containment and now polls for 5 s at 50 ms intervals. These runs used the cached release binary at base 1dd62b854fbdedadd9611c07b5bf19cd067cf9ae as recorded above. The requested fast gate remains pending shared-host load admission.

After-change reproduction: while the same `nix run nixpkgs#stress-ng -- --cpu 16` process ran for 16 minutes, the updated browser smoke passed five sequential runs (`fix-scroll-after-1` through `fix-scroll-after-5`). Each ended with `POST_CHANGE_SMOKE_PASS`; each reached `SIDEBAR_CONTAINERS repetition=1/1 GET /api/v1/containers status=200`. Stress-ng reported 16 CPU workers passed, 0 failed. The browser script requires full-row containment and now polls for 5 s at 50 ms intervals. These runs used the cached release binary at base `1dd62b854fbdedadd9611c07b5bf19cd067cf9ae` as recorded above. The requested fast gate remains pending shared-host load admission.
Author
Owner

Finished fix-scroll-wait.

  • Branch: ws-close-reply
  • Base: 2fae616b9f06ceed40d8cd270b58a6a3402799ec
  • Head: e10cb37d52e1980cd82a3b0b2a8bd8ae931dd532
  • Change: keep the full-row geometry predicate and extend the poll from 200 ms / 20 ms to 5 s / 50 ms.
  • Before: under nix run nixpkgs#stress-ng -- --cpu 16, fix-scroll-before-1 failed at findContainerRow with container row did not scroll into view.
  • After: five sequential smoke runs (fix-scroll-after-1 through fix-scroll-after-5) passed under 16 CPU workers. Stress-ng reported 16 passed, 0 failed.
  • Browser smoke release binary: base 1dd62b854fbdedadd9611c07b5bf19cd067cf9ae, whose only source difference from the task base is server WebSocket close-reply handling. Container UI, DataTable, API and browser-check code are identical.

Fast gate output:

WARN load5=14.47 exceeds online CPU count=8; timing-sensitive checks may be delayed
PASS fast: migrations are append-only (0.244s)
PASS fast: workspace package dependencies (0.335s)
PASS fast: gate target-directory and launch diagnostics tests (0.322s)
PASS fast: JavaScript dependencies (0.206s)
PASS fast: advisory review policy tests (0.215s)
PASS fast: supply-chain checks (6.659s)
PASS fast: build web app (17.046s)
PASS fast: cargo fmt --check (2.231s)
PASS fast: cargo clippy (204.978s)
PASS fast: cargo test (344.892s)
PASS fast: svelte-check (31.542s)
PASS fast: UI package svelte-check (9.505s)
PASS fast: stream package typecheck (8.428s)
PASS fast: Vitest (13.762s)
PASS fast: UI package Vitest (17.185s)
PASS fast: stream package Vitest (3.442s)
PASS fast: OpenAPI and TypeScript client drift (170.754s)
PASS fast: terminal TypeScript (9.148s)
PASS fast: terminal Vitest (3.780s)
Gate: fast
Stages: 19
Total: 844.674s

The pre-existing THIRD_PARTY_NOTICES.md worktree modification remains unstaged and unchanged.

Finished `fix-scroll-wait`. - Branch: `ws-close-reply` - Base: `2fae616b9f06ceed40d8cd270b58a6a3402799ec` - Head: `e10cb37d52e1980cd82a3b0b2a8bd8ae931dd532` - Change: keep the full-row geometry predicate and extend the poll from 200 ms / 20 ms to 5 s / 50 ms. - Before: under `nix run nixpkgs#stress-ng -- --cpu 16`, `fix-scroll-before-1` failed at `findContainerRow` with `container row did not scroll into view`. - After: five sequential smoke runs (`fix-scroll-after-1` through `fix-scroll-after-5`) passed under 16 CPU workers. Stress-ng reported 16 passed, 0 failed. - Browser smoke release binary: base `1dd62b854fbdedadd9611c07b5bf19cd067cf9ae`, whose only source difference from the task base is server WebSocket close-reply handling. Container UI, DataTable, API and browser-check code are identical. Fast gate output: ```text WARN load5=14.47 exceeds online CPU count=8; timing-sensitive checks may be delayed PASS fast: migrations are append-only (0.244s) PASS fast: workspace package dependencies (0.335s) PASS fast: gate target-directory and launch diagnostics tests (0.322s) PASS fast: JavaScript dependencies (0.206s) PASS fast: advisory review policy tests (0.215s) PASS fast: supply-chain checks (6.659s) PASS fast: build web app (17.046s) PASS fast: cargo fmt --check (2.231s) PASS fast: cargo clippy (204.978s) PASS fast: cargo test (344.892s) PASS fast: svelte-check (31.542s) PASS fast: UI package svelte-check (9.505s) PASS fast: stream package typecheck (8.428s) PASS fast: Vitest (13.762s) PASS fast: UI package Vitest (17.185s) PASS fast: stream package Vitest (3.442s) PASS fast: OpenAPI and TypeScript client drift (170.754s) PASS fast: terminal TypeScript (9.148s) PASS fast: terminal Vitest (3.780s) Gate: fast Stages: 19 Total: 844.674s ``` The pre-existing `THIRD_PARTY_NOTICES.md` worktree modification remains unstaged and unchanged.
Author
Owner

Architecture-review evidence (2026-10-04; source report reviewed d1eefa9, current checkout is 0b4fc37):

  • The report counted 282 recent commits touching scripts/browser-check.mjs (24.8% of all recent commits), with 208 changing only that file. This is churn, not a measured failure rate.
  • The browser geometry check once used a 200 ms window; it was raised to 5 s while retaining containment checks. Stream regression tests still have 100 ms sleeps at crates/server/tests/stream_regressions.rs:597,978,1149.
  • The report also records steady_state_framing_does_not_allocate_per_chunk failing under load and passing on retry. Keep the allocation bound; isolate its measurement phase/thread instead of loosening it.
  • It recommends readiness events or barriers for the highest-repeat races and 20 targeted repetitions plus the real gate, as required by PLAN step 7.

These are audit findings, not new reproductions. Source: arch-review 2026-10-04; /mnt/hdd/infraternal/jobs/arch-review/report.md.

Architecture-review evidence (2026-10-04; source report reviewed d1eefa9, current checkout is 0b4fc37): - The report counted 282 recent commits touching `scripts/browser-check.mjs` (24.8% of all recent commits), with 208 changing only that file. This is churn, not a measured failure rate. - The browser geometry check once used a 200 ms window; it was raised to 5 s while retaining containment checks. Stream regression tests still have 100 ms sleeps at `crates/server/tests/stream_regressions.rs:597,978,1149`. - The report also records `steady_state_framing_does_not_allocate_per_chunk` failing under load and passing on retry. Keep the allocation bound; isolate its measurement phase/thread instead of loosening it. - It recommends readiness events or barriers for the highest-repeat races and 20 targeted repetitions plus the real gate, as required by PLAN step 7. These are audit findings, not new reproductions. Source: arch-review 2026-10-04; /mnt/hdd/infraternal/jobs/arch-review/report.md.
Author
Owner

One more timing-sensitive class from the architecture review (historical evidence only; not reproduced by this review):

The report groups commits 7d4a71d, 665407c, 7014255 and 1a8755d under runtime starvation from probes/subprocesses. Its recommendation is to keep blocking work off the async executor and wait for observed process state. This belongs with the existing loaded-VM timing issue: use controlled readiness/state evidence, keep deadlines for detecting a hung fixture, and retain real integration gates.

Source: arch-review 2026-10-04; /mnt/hdd/infraternal/jobs/arch-review/report.md.

One more timing-sensitive class from the architecture review (historical evidence only; not reproduced by this review): The report groups commits `7d4a71d`, `665407c`, `7014255` and `1a8755d` under runtime starvation from probes/subprocesses. Its recommendation is to keep blocking work off the async executor and wait for observed process state. This belongs with the existing loaded-VM timing issue: use controlled readiness/state evidence, keep deadlines for detecting a hung fixture, and retain real integration gates. Source: arch-review 2026-10-04; /mnt/hdd/infraternal/jobs/arch-review/report.md.
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
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/infraternal-v0#31
No description provided.