The navigator's counts test and the force job's grow and shrink tests stay inside their budgets on a loaded runner #133

Merged
agra merged 2 commits from task/3731-two-web-unit-tests-fail-sak-s-fast-gate into master 2026-10-24 20:41:02 +03:00
Owner

Tracker: #3731

Two web unit tests that npm run build runs failed sak's fast gate on a loaded runner, then passed on a retry with no change. This PR makes each test wait only for the state it checks. It changes test files only, and no golden under web/e2e.

What changes

NavigatorRoute.test.ts › "shows the counts of the loaded tracker". The test already polled for the counts with vi.waitFor, whose deadline is 1 s. That second also had to cover something the test does not check. NavigatorRoute.svelte imports ./navigator/Navigator.svelte lazily, so the first test to mount the route waits while vite transforms the navigator and about 25 modules under it. On a loaded host that alone takes more than a second, which is why only the file's first test failed: the second found the module cached. The test file now imports the navigator itself. The transform then happens while the file loads, a phase with no deadline, and the route's lazy import resolves from the module cache. The wait covers only the load and the render.

force.test.ts › "spaces the anchors after an in-session grow as a fresh layout of the grown set does". The test ran two 600-task force simulations to read anchors that layoutForce sets before it simulates anything. The grown set is now 120 tasks. That is still four times the first layout's 30, and no size clamp applies (spread clamps below 18 and above 800 tasks).

force.test.ts › "draws the kept tasks of an in-session shrink in with their anchors as a fresh layout does". This is the file's other 600-task test, and it took 4166 ms of its 5 s in job 81's release-step vitest. Its first layout is now 360 tasks, near the smallest that still fails both defects it pins.

The force tests still pin their defects

Each defect was put into force.ts and the file was run at the new sizes:

force.ts grow (120) shrink (360), offset ratio against its 1.1 bound
as it is passes passes, 1.020
kept anchors not rescaled (const rescale = 1) fails fails, 1.149
kept tasks not moved with their anchor (const at = kept) passes fails, 1.278

The rescale defect also fails the existing 36-over-30 test. A shrink from 240 misses the rescale defect (1.076), and one from 120 misses both, which is why the shrink keeps 360.

Fail before, pass after

Each arm is a git archive of web/ at base 13c9709 or head 33a7605, with the gate cache's node_modules. The whole vitest suite was run in each, in alternation, on m5 on 2026-10-24. Times are in ms. "Counts" is the navigator test (1000 ms waitFor deadline); "grow" and "shrink" are the force tests (5000 ms test timeout).

load arm runs failed counts grow shrink
another run's sx gate and probes, load 16–25 base 3 1 run: counts 1119 ✗, grow 5783 ✗ 674–1119 2171–5783 1043–2107
same head 3 0 121–245 539–1173 687–1468
18 yes loops, load 14–30 base 3 0 251–305 2892–3729 1668–2000
same head 3 0 91–98 334–368 772–929
36 yes loops, load 28–77 base 2 0 452–557 4330–4747 2248–2280
same head 2 0 93–98 439–617 1139–1370

The failing base run failed exactly the gate's two tests. Counts failed with AssertionError: expected undefined to be '3 tasks · 2 projects · 2 relations', and grow went past its 5000 ms timeout. Another base run passed at the edge: counts at 1001 ms, grow at 4890 ms. Run on their own in the checkout at the same load, the base's two files failed the counts test 2 times out of 2 (1131 ms in the timed one). The head's passed 3 times out of 3, at 110–203 ms.

Not changed: layer.test.ts › "keeps every size, alignment, and side inside the viewport gutter". It makes 41,472 placeLayer calls with 6 expects each, takes the same 0.6–2.5 s in both arms, and timed out once in job 81's release-step vitest. Making it cheaper means rewriting that matrix, which is a change of its own.

Gates at 33a7605

  • fast (gate run 295): passed. vitest 401/401, Duration 5.25 s.
  • full (gate run 298): failed, environmentally. Every step through the deploy contract passed, including tests/*.sx and the release step's second vitest run (401/401). The main Playwright config then failed at global setup with sak serve never answered on http://127.0.0.1:18987. At that moment the port was held by a sak serve --port 18987 from a Playwright run in another checkout on the runner host, started about two minutes earlier.
  • full (gate run 304): passed. The main Playwright config passed 740 tests in 3.4 min, and the runner config passed 10. Its first vitest run had a Duration of 19.74 s (environment 127 s), the same load as the task's failing runs (17–21 s), and passed 401/401. In that run grow took 518 ms, shrink 1276 ms and the whole navigator file 261 ms. In job 76, at a Duration of 18.30 s on the base, grow timed out at 5099 ms and counts took 1046 ms.
  • The flow's gate step, full (job 112, on s32): failed, environmentally. Its steps run in order and stop at the first failure, and it reached the last one: npm run build with vitest, tests/*.sx, the release step with its second vitest run and step9_release, and the deploy contract all passed, and the main Playwright config passed 740 tests. The runner config then failed at global setup with sak serve never answered on http://127.0.0.1:18988. On s32 that port is held by a sak serve left running by an earlier run, the fixed-port problem filed as #3776.
  • full (gate run 311): failed in tests/*.sx on one check of runner_core.sx, "a run whose stub harness waits silently on a gate longer than the idle timeout is not ended idle_timeout". The check gives its stub harness 500 ms to start sak-gate. Another project's full gate was running beside it at a one-minute load of about 11, and the run was killed idle_timeout before its gate started. This PR touches no runner/ or tests/ file.
  • full (gate run 312): passed every step. vitest passed 401/401 in both runs (Durations 4.17 s and 2.97 s), and so did tests/*.sx, release with step9_release, the deploy contract, the main Playwright config (740 passed, 1 skipped, 3.5 min) and the runner config (10 passed).
  • The flow's gate step, full (job 114, on m5): failed in the main Playwright config on two specs this PR does not touch, at a load average of about 30 (2 failed, 1 skipped, 738 passed, 8.8 min). accounts.spec.ts:535 › dark › "paints a sign-in that expired" missed its golden by 79 pixels. board.spec.ts:1315 › "320px app shell" timed out after 30 s on its Close menu click, which the open drawer intercepted. Both are filed as #3796. Every earlier step passed.
  • full (gate run 327, m5, load average 20–44): failed in tests/*.sx on two checks of runner_core.sx's idle-cap test: "what the harness says after SIGTERM lands on the stream" and "the process the harness started dies with its group, SIGTERM ignored". The test gives its stub harness a 300 ms idle cap. In that time the stub has to start its sleep, write sleep.pid and set its TERM trap. The run was claimed, started and killed idle_timeout within one second. Every other test file passed, and so did the steps before them, including vitest 401/401 at a suite Duration of 23.22 s. The gate stops at its first failed step, so it ran no Playwright. This intermittent runner_core failure under full is #3629. This PR touches no runner/, tests/ or src/ file.
  • tests/runner_core.sx run by hand at 33a7605 right after gate run 327, from a git archive arm with the gate cache's sx (16:45–16:51 EEST, load average 24–44): passed, 378 ok, RUNNER CORE OK, with both idle-cap checks ok.
  • The flow's gate step, full (job 119, on m5, 16:52–17:40 EEST, with another project's full gate beside it from 17:01): failed in the main Playwright config on one golden this PR does not touch (1 failed, 1 skipped, 739 passed, 5.8 min). accounts.spec.ts:535 › dark › "paints a sign-in waiting on its device code" missed its golden by 79 pixels. This is the same accounts sign-in flake as job 114's, filed as #3796. Every earlier step passed.
  • full (gate run 340, m5, 17:42–18:24 EEST): passed every step. vitest passed 401/401 in both runs (Durations 4.99 s and 12.49 s; in the second, force.test.ts took 2200 ms for its five tests and NavigatorRoute.test.ts 284 ms), and so did tests/*.sx, release with step9_release, the deploy contract, the main Playwright config (740 passed, 1 skipped, 4.1 min, every accounts sign-in golden included) and the runner config (10 passed).
  • The flow's gate step, full (job 123, on m5, 18:37–19:10 EEST, with another project's full gate beside it from 18:30 to 19:09): failed in tests/*.sx on one check of runner_core.sx (RUNNER CORE FAIL (1 checks)). The gate prints only the last 40 lines of a failing file's log, and its log directory is removed when the step ends, so the check's name was not kept. Every step before it passed, including vitest 401/401 (Duration 14.74 s; force.test.ts 1497 ms for its five tests, grow 383 ms; NavigatorRoute.test.ts 227 ms). This PR touches no runner/, tests/ or src/ file; runner_core's intermittent failure under full is #3629.
  • full (gate run 349, m5, 19:12–19:58 EEST, at a load average of 12–25 while another project's review ran many sx processes beside it): passed every step. vitest passed 401/401 in both runs (Durations 6.51 s and 10.08 s; force.test.ts took 969 ms and 1470 ms for its five tests, NavigatorRoute.test.ts 157 ms and 215 ms), and so did tests/*.sx (runner_core.sx 378 ok), release with step9_release, the deploy contract, the main Playwright config (740 passed, 1 skipped, 8.7 min) and the runner config (10 passed).

Master has since moved to 6f823cd (release 0.3.6: src/version.sx, README.md and two hand-over test constants). It touches no file this PR changes, and git merge-tree of the branch and master is clean.

Tracker: [#3731](https://sak.swipelab.com/tasks/3731) Two web unit tests that `npm run build` runs failed sak's `fast` gate on a loaded runner, then passed on a retry with no change. This PR makes each test wait only for the state it checks. It changes test files only, and no golden under `web/e2e`. ## What changes **`NavigatorRoute.test.ts` › "shows the counts of the loaded tracker".** The test already polled for the counts with `vi.waitFor`, whose deadline is 1 s. That second also had to cover something the test does not check. `NavigatorRoute.svelte` imports `./navigator/Navigator.svelte` lazily, so the first test to mount the route waits while vite transforms the navigator and about 25 modules under it. On a loaded host that alone takes more than a second, which is why only the file's first test failed: the second found the module cached. The test file now imports the navigator itself. The transform then happens while the file loads, a phase with no deadline, and the route's lazy import resolves from the module cache. The wait covers only the load and the render. **`force.test.ts` › "spaces the anchors after an in-session grow as a fresh layout of the grown set does".** The test ran two 600-task force simulations to read anchors that `layoutForce` sets before it simulates anything. The grown set is now 120 tasks. That is still four times the first layout's 30, and no size clamp applies (`spread` clamps below 18 and above 800 tasks). **`force.test.ts` › "draws the kept tasks of an in-session shrink in with their anchors as a fresh layout does".** This is the file's other 600-task test, and it took 4166 ms of its 5 s in job 81's release-step vitest. Its first layout is now 360 tasks, near the smallest that still fails both defects it pins. ## The force tests still pin their defects Each defect was put into `force.ts` and the file was run at the new sizes: | `force.ts` | grow (120) | shrink (360), offset ratio against its 1.1 bound | |---|---|---| | as it is | passes | passes, 1.020 | | kept anchors not rescaled (`const rescale = 1`) | fails | fails, 1.149 | | kept tasks not moved with their anchor (`const at = kept`) | passes | fails, 1.278 | The rescale defect also fails the existing 36-over-30 test. A shrink from 240 misses the rescale defect (1.076), and one from 120 misses both, which is why the shrink keeps 360. ## Fail before, pass after Each arm is a `git archive` of `web/` at base 13c9709 or head 33a7605, with the gate cache's `node_modules`. The whole vitest suite was run in each, in alternation, on m5 on 2026-10-24. Times are in ms. "Counts" is the navigator test (1000 ms `waitFor` deadline); "grow" and "shrink" are the force tests (5000 ms test timeout). | load | arm | runs | failed | counts | grow | shrink | |---|---|---|---|---|---|---| | another run's sx gate and probes, load 16–25 | base | 3 | 1 run: **counts 1119 ✗, grow 5783 ✗** | 674–1119 | 2171–5783 | 1043–2107 | | same | head | 3 | 0 | 121–245 | 539–1173 | 687–1468 | | 18 `yes` loops, load 14–30 | base | 3 | 0 | 251–305 | 2892–3729 | 1668–2000 | | same | head | 3 | 0 | 91–98 | 334–368 | 772–929 | | 36 `yes` loops, load 28–77 | base | 2 | 0 | 452–557 | 4330–4747 | 2248–2280 | | same | head | 2 | 0 | 93–98 | 439–617 | 1139–1370 | The failing base run failed exactly the gate's two tests. Counts failed with `AssertionError: expected undefined to be '3 tasks · 2 projects · 2 relations'`, and grow went past its 5000 ms timeout. Another base run passed at the edge: counts at 1001 ms, grow at 4890 ms. Run on their own in the checkout at the same load, the base's two files failed the counts test 2 times out of 2 (1131 ms in the timed one). The head's passed 3 times out of 3, at 110–203 ms. Not changed: `layer.test.ts` › "keeps every size, alignment, and side inside the viewport gutter". It makes 41,472 `placeLayer` calls with 6 `expect`s each, takes the same 0.6–2.5 s in both arms, and timed out once in job 81's release-step vitest. Making it cheaper means rewriting that matrix, which is a change of its own. ## Gates at 33a7605 - `fast` (gate run 295): passed. vitest 401/401, Duration 5.25 s. - `full` (gate run 298): failed, environmentally. Every step through the deploy contract passed, including `tests/*.sx` and the release step's second vitest run (401/401). The main Playwright config then failed at global setup with `sak serve never answered on http://127.0.0.1:18987`. At that moment the port was held by a `sak serve --port 18987` from a Playwright run in another checkout on the runner host, started about two minutes earlier. - `full` (gate run 304): passed. The main Playwright config passed 740 tests in 3.4 min, and the runner config passed 10. Its first vitest run had a Duration of 19.74 s (environment 127 s), the same load as the task's failing runs (17–21 s), and passed 401/401. In that run grow took 518 ms, shrink 1276 ms and the whole navigator file 261 ms. In job 76, at a Duration of 18.30 s on the base, grow timed out at 5099 ms and counts took 1046 ms. - The flow's gate step, `full` (job 112, on s32): failed, environmentally. Its steps run in order and stop at the first failure, and it reached the last one: `npm run build` with vitest, `tests/*.sx`, the release step with its second vitest run and `step9_release`, and the deploy contract all passed, and the main Playwright config passed 740 tests. The runner config then failed at global setup with `sak serve never answered on http://127.0.0.1:18988`. On s32 that port is held by a `sak serve` left running by an earlier run, the fixed-port problem filed as #3776. - `full` (gate run 311): failed in `tests/*.sx` on one check of `runner_core.sx`, "a run whose stub harness waits silently on a gate longer than the idle timeout is not ended idle_timeout". The check gives its stub harness 500 ms to start `sak-gate`. Another project's `full` gate was running beside it at a one-minute load of about 11, and the run was killed `idle_timeout` before its gate started. This PR touches no `runner/` or `tests/` file. - `full` (gate run 312): passed every step. vitest passed 401/401 in both runs (Durations 4.17 s and 2.97 s), and so did `tests/*.sx`, release with `step9_release`, the deploy contract, the main Playwright config (740 passed, 1 skipped, 3.5 min) and the runner config (10 passed). - The flow's gate step, `full` (job 114, on m5): failed in the main Playwright config on two specs this PR does not touch, at a load average of about 30 (2 failed, 1 skipped, 738 passed, 8.8 min). `accounts.spec.ts:535` › dark › "paints a sign-in that expired" missed its golden by 79 pixels. `board.spec.ts:1315` › "320px app shell" timed out after 30 s on its Close menu click, which the open drawer intercepted. Both are filed as #3796. Every earlier step passed. - `full` (gate run 327, m5, load average 20–44): failed in `tests/*.sx` on two checks of `runner_core.sx`'s idle-cap test: "what the harness says after SIGTERM lands on the stream" and "the process the harness started dies with its group, SIGTERM ignored". The test gives its stub harness a 300 ms idle cap. In that time the stub has to start its sleep, write `sleep.pid` and set its TERM trap. The run was claimed, started and killed `idle_timeout` within one second. Every other test file passed, and so did the steps before them, including vitest 401/401 at a suite Duration of 23.22 s. The gate stops at its first failed step, so it ran no Playwright. This intermittent runner_core failure under `full` is #3629. This PR touches no `runner/`, `tests/` or `src/` file. - `tests/runner_core.sx` run by hand at 33a7605 right after gate run 327, from a `git archive` arm with the gate cache's sx (16:45–16:51 EEST, load average 24–44): passed, 378 ok, `RUNNER CORE OK`, with both idle-cap checks ok. - The flow's gate step, `full` (job 119, on m5, 16:52–17:40 EEST, with another project's `full` gate beside it from 17:01): failed in the main Playwright config on one golden this PR does not touch (1 failed, 1 skipped, 739 passed, 5.8 min). `accounts.spec.ts:535` › dark › "paints a sign-in waiting on its device code" missed its golden by 79 pixels. This is the same accounts sign-in flake as job 114's, filed as #3796. Every earlier step passed. - `full` (gate run 340, m5, 17:42–18:24 EEST): passed every step. vitest passed 401/401 in both runs (Durations 4.99 s and 12.49 s; in the second, force.test.ts took 2200 ms for its five tests and NavigatorRoute.test.ts 284 ms), and so did `tests/*.sx`, release with `step9_release`, the deploy contract, the main Playwright config (740 passed, 1 skipped, 4.1 min, every accounts sign-in golden included) and the runner config (10 passed). - The flow's gate step, `full` (job 123, on m5, 18:37–19:10 EEST, with another project's `full` gate beside it from 18:30 to 19:09): failed in `tests/*.sx` on one check of `runner_core.sx` (`RUNNER CORE FAIL (1 checks)`). The gate prints only the last 40 lines of a failing file's log, and its log directory is removed when the step ends, so the check's name was not kept. Every step before it passed, including vitest 401/401 (Duration 14.74 s; force.test.ts 1497 ms for its five tests, grow 383 ms; NavigatorRoute.test.ts 227 ms). This PR touches no `runner/`, `tests/` or `src/` file; runner_core's intermittent failure under `full` is #3629. - `full` (gate run 349, m5, 19:12–19:58 EEST, at a load average of 12–25 while another project's review ran many sx processes beside it): passed every step. vitest passed 401/401 in both runs (Durations 6.51 s and 10.08 s; force.test.ts took 969 ms and 1470 ms for its five tests, NavigatorRoute.test.ts 157 ms and 215 ms), and so did `tests/*.sx` (`runner_core.sx` 378 ok), release with `step9_release`, the deploy contract, the main Playwright config (740 passed, 1 skipped, 8.7 min) and the runner config (10 passed). Master has since moved to 6f823cd (release 0.3.6: `src/version.sx`, `README.md` and two hand-over test constants). It touches no file this PR changes, and `git merge-tree` of the branch and master is clean.
agra changed title from The navigator's counts test and the galaxy grow test pass sak's fast gate on a loaded runner to The navigator's counts test and the force job's grow and shrink tests stay inside their budgets on a loaded runner 2026-10-24 12:18:01 +03:00
agra merged commit 8cda22fc33 into master 2026-10-24 20:41:02 +03:00
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
sx/sak!133
No description provided.