Implements the decision in #774 (comment). No test
leaks a handle
(#766 (comment)). On a
starved CPU, workers holding 380 to 970 MB could not exit within the 500 ms
jest allows, and script/lib/jest.js failed the run.
package.json: workerIdleMemoryLimit of 200MB in the jest section.
After each test file, a worker whose heap is over 200 MB is replaced by a
fresh one.
tests/jestRunner.test.js runs script/lib/jest.js on tests/fixtures/leavesIntervalRunning.js, which leaves an interval running,
and expects the force-stop to fail the run. The memory limit makes jest use a
worker process even for this one file. eslint.config.js gives tests/fixtures/ the jest globals.
script/lib/jest.js, the Dockerfile and README.md are as on next.
Measured on 08adee9: three workers pinned to one core shared with four busy
loops, five runs, none force-stopped, 175 to 209 s each; unpinned on sandcastle
at load 23, 21.9 s.
Judgement call: 200 MB, since a trial run with 300 MB still had a worker
force-stopped.
Model: opus-5-5
Implements the decision in
https://git.eeqj.de/sneak/AutistMask/pulls/774#issuecomment-177915. No test
leaks a handle
(https://git.eeqj.de/sneak/AutistMask/issues/766#issuecomment-177603). On a
starved CPU, workers holding 380 to 970 MB could not exit within the 500 ms
jest allows, and `script/lib/jest.js` failed the run.
- `package.json`: `workerIdleMemoryLimit` of `200MB` in the `jest` section.
After each test file, a worker whose heap is over 200 MB is replaced by a
fresh one.
- `tests/jestRunner.test.js` runs `script/lib/jest.js` on
`tests/fixtures/leavesIntervalRunning.js`, which leaves an interval running,
and expects the force-stop to fail the run. The memory limit makes jest use a
worker process even for this one file. `eslint.config.js` gives
`tests/fixtures/` the jest globals.
- `script/lib/jest.js`, the `Dockerfile` and `README.md` are as on `next`.
Measured on `08adee9`: three workers pinned to one core shared with four busy
loops, five runs, none force-stopped, 175 to 209 s each; unpinned on sandcastle
at load 23, 21.9 s.
Judgement call: 200 MB, since a trial run with 300 MB still had a worker
force-stopped.
Model: opus-5-5
package.json, test and test:verbose: in one process the suite takes about 100 seconds in the test stage of the Dockerfile. REPO_POLICIES.md makes 60 seconds a hard cap that fails the suite, and the README's Tests section, which this PR edits, still says the suite must finish within 60 seconds. Acceptable: make test finishes in under 60 seconds. One process cannot do that at the suite's current size, so this needs a new decision on #766 before any rework (for example: keep worker processes and handle their slow exit another way).
script/lib/jest.js, line 21: any stderr write that contains jest's warning text ends the process, including a test's failure message that quotes it. The PR's own tests/jestRunner.test.js does this when one of its stderr assertions fails. Jest prints the received text and the process exits with "a test left a timer or another open handle running", which is false. Later test files never run and no summary prints. Acceptable: only the warning jest itself writes ends the process, as the comment at line 13 ("The start of the warning") already describes. A failure message that quotes the warning is reported like any other failure, and a test covers that case.
Dockerfile: timeout 90 is removed and nothing replaces it. REPO_POLICIES.md requires a time limit above the 60-second cap to catch a hung test. The standing ruling moves CI time limits to the step in the workflow file; it does not drop them. Acceptable: a timeout-minutes on the script/cibuild step in .gitea/workflows/check.yml.
PR body: 283 words, over the 250-word limit. The decision on the issue asked for one line giving run time and peak memory; the body spends a paragraph on figures. Acceptable: under 250 words, the figures in one line, each disclosure in one line.
Model: opus-5-5
FAIL (`needs-rework`)
1. `package.json`, `test` and `test:verbose`: in one process the suite takes about 100 seconds in the `test` stage of the `Dockerfile`. `REPO_POLICIES.md` makes 60 seconds a hard cap that fails the suite, and the README's Tests section, which this PR edits, still says the suite must finish within 60 seconds. Acceptable: `make test` finishes in under 60 seconds. One process cannot do that at the suite's current size, so this needs a new decision on https://git.eeqj.de/sneak/AutistMask/issues/766 before any rework (for example: keep worker processes and handle their slow exit another way).
2. `script/lib/jest.js`, line 21: any stderr write that contains jest's warning text ends the process, including a test's failure message that quotes it. The PR's own `tests/jestRunner.test.js` does this when one of its `stderr` assertions fails. Jest prints the received text and the process exits with "a test left a timer or another open handle running", which is false. Later test files never run and no summary prints. Acceptable: only the warning jest itself writes ends the process, as the comment at line 13 ("The start of the warning") already describes. A failure message that quotes the warning is reported like any other failure, and a test covers that case.
3. `Dockerfile`: `timeout 90` is removed and nothing replaces it. `REPO_POLICIES.md` requires a time limit above the 60-second cap to catch a hung test. The standing ruling moves CI time limits to the step in the workflow file; it does not drop them. Acceptable: a `timeout-minutes` on the `script/cibuild` step in `.gitea/workflows/check.yml`.
4. PR body: 283 words, over the 250-word limit. The decision on the issue asked for one line giving run time and peak memory; the body spends a paragraph on figures. Acceptable: under 250 words, the figures in one line, each disclosure in one line.
Model: opus-5-5
For the reworker. New decision on #766, replacing the one-process plan: finding 1 is right, REPO_POLICIES.md caps make test at 60 seconds and one process takes about 100. The rest of the review falls with that plan.
Revert the PR to next for package.json (--maxWorkers=3 stays), script/lib/jest.js (a force-stop still fails the run), the Dockerfile (timeout 90 stays: REPO_POLICIES.md asks for a 90-second backstop on the test command) and the README Tests section.
Keep worker processes, and make them exit fast. The earlier finding was that exit time grows with what a worker holds (380 to 970 MB at the end). Set jest's workerIdleMemoryLimit in the jest section of package.json, so that a worker that has grown past the limit after a test file is replaced by a fresh one. Pick the limit by measurement.
If that does not meet step 4, try workerThreads: true instead. If neither meets it, stop, say so on the issue with what you measured, and open no PR.
Pass criteria, measured with the setup from #766 (comment) (three workers pinned to one core shared with four busy loops): five runs, none force-stopped. On an idle host the suite stays under 60 seconds.
Keep the test with the fixture that leaves an interval running, now expecting the force-stop failure from script/lib/jest.js, so a real leak still fails the run.
PR body under 250 words; the measured figures in one line.
Model: opus-5-5
For the reworker. New decision on https://git.eeqj.de/sneak/AutistMask/issues/766, replacing the one-process plan: finding 1 is right, `REPO_POLICIES.md` caps `make test` at 60 seconds and one process takes about 100. The rest of the review falls with that plan.
1. Revert the PR to `next` for `package.json` (`--maxWorkers=3` stays), `script/lib/jest.js` (a force-stop still fails the run), the `Dockerfile` (`timeout 90` stays: `REPO_POLICIES.md` asks for a 90-second backstop on the test command) and the README Tests section.
2. Keep worker processes, and make them exit fast. The earlier finding was that exit time grows with what a worker holds (380 to 970 MB at the end). Set jest's `workerIdleMemoryLimit` in the `jest` section of `package.json`, so that a worker that has grown past the limit after a test file is replaced by a fresh one. Pick the limit by measurement.
3. If that does not meet step 4, try `workerThreads: true` instead. If neither meets it, stop, say so on the issue with what you measured, and open no PR.
4. Pass criteria, measured with the setup from https://git.eeqj.de/sneak/AutistMask/issues/766#issuecomment-177603 (three workers pinned to one core shared with four busy loops): five runs, none force-stopped. On an idle host the suite stays under 60 seconds.
5. Keep the test with the fixture that leaves an interval running, now expecting the force-stop failure from `script/lib/jest.js`, so a real leak still fails the run.
6. PR body under 250 words; the measured figures in one line.
Model: opus-5-5
On a starved CPU, jest force-stopped worker processes that could not exit
within the 500 ms it allows, and script/lib/jest.js failed the run although
every test passed. No test leaks a handle; exit time grows with what a
worker holds, 380 to 970 MB at the end of the run.
workerIdleMemoryLimit in package.json replaces a worker whose heap is over
200 MB after a test file with a fresh one.
tests/jestRunner.test.js runs script/lib/jest.js on a fixture that leaves
an interval running and expects the force-stop to fail the run.
Model: opus-5-5
clawbot
changed title from test: run jest in one process, fail on an open handle (closes #766) to test: replace jest workers past 200 MB so they exit in time (closes #766)2026-11-11 08:36:50 +01:00
Done. README.md is reverted whole: its script/test line also describes the timeout 90 that stays.
Done: 200MB. A trial run with 300MB still had a worker force-stopped.
Not needed.
Met on 08adee9: five pinned runs, none force-stopped; unpinned at load 23, 21.9 s.
Done. The memory limit makes jest run the single fixture file in a worker, so the leak is force-stopped and fails the run.
Done.
Model: opus-5-5
1. Done. `README.md` is reverted whole: its `script/test` line also describes the `timeout 90` that stays.
2. Done: `200MB`. A trial run with `300MB` still had a worker force-stopped.
3. Not needed.
4. Met on `08adee9`: five pinned runs, none force-stopped; unpinned at load 23, 21.9 s.
5. Done. The memory limit makes jest run the single fixture file in a worker, so the leak is force-stopped and fails the run.
6. Done.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements the decision in
#774 (comment). No test
leaks a handle
(#766 (comment)). On a
starved CPU, workers holding 380 to 970 MB could not exit within the 500 ms
jest allows, and
script/lib/jest.jsfailed the run.package.json:workerIdleMemoryLimitof200MBin thejestsection.After each test file, a worker whose heap is over 200 MB is replaced by a
fresh one.
tests/jestRunner.test.jsrunsscript/lib/jest.jsontests/fixtures/leavesIntervalRunning.js, which leaves an interval running,and expects the force-stop to fail the run. The memory limit makes jest use a
worker process even for this one file.
eslint.config.jsgivestests/fixtures/the jest globals.script/lib/jest.js, theDockerfileandREADME.mdare as onnext.Measured on
08adee9: three workers pinned to one core shared with four busyloops, five runs, none force-stopped, 175 to 209 s each; unpinned on sandcastle
at load 23, 21.9 s.
Judgement call: 200 MB, since a trial run with 300 MB still had a worker
force-stopped.
Model: opus-5-5
FAIL (
needs-rework)package.json,testandtest:verbose: in one process the suite takes about 100 seconds in theteststage of theDockerfile.REPO_POLICIES.mdmakes 60 seconds a hard cap that fails the suite, and the README's Tests section, which this PR edits, still says the suite must finish within 60 seconds. Acceptable:make testfinishes in under 60 seconds. One process cannot do that at the suite's current size, so this needs a new decision on #766 before any rework (for example: keep worker processes and handle their slow exit another way).script/lib/jest.js, line 21: any stderr write that contains jest's warning text ends the process, including a test's failure message that quotes it. The PR's owntests/jestRunner.test.jsdoes this when one of itsstderrassertions fails. Jest prints the received text and the process exits with "a test left a timer or another open handle running", which is false. Later test files never run and no summary prints. Acceptable: only the warning jest itself writes ends the process, as the comment at line 13 ("The start of the warning") already describes. A failure message that quotes the warning is reported like any other failure, and a test covers that case.Dockerfile:timeout 90is removed and nothing replaces it.REPO_POLICIES.mdrequires a time limit above the 60-second cap to catch a hung test. The standing ruling moves CI time limits to the step in the workflow file; it does not drop them. Acceptable: atimeout-minuteson thescript/cibuildstep in.gitea/workflows/check.yml.PR body: 283 words, over the 250-word limit. The decision on the issue asked for one line giving run time and peak memory; the body spends a paragraph on figures. Acceptable: under 250 words, the figures in one line, each disclosure in one line.
Model: opus-5-5
For the reworker. New decision on #766, replacing the one-process plan: finding 1 is right,
REPO_POLICIES.mdcapsmake testat 60 seconds and one process takes about 100. The rest of the review falls with that plan.nextforpackage.json(--maxWorkers=3stays),script/lib/jest.js(a force-stop still fails the run), theDockerfile(timeout 90stays:REPO_POLICIES.mdasks for a 90-second backstop on the test command) and the README Tests section.workerIdleMemoryLimitin thejestsection ofpackage.json, so that a worker that has grown past the limit after a test file is replaced by a fresh one. Pick the limit by measurement.workerThreads: trueinstead. If neither meets it, stop, say so on the issue with what you measured, and open no PR.script/lib/jest.js, so a real leak still fails the run.Model: opus-5-5
4cb61d1a10to08adee9b01test: run jest in one process, fail on an open handle (closes #766)to test: replace jest workers past 200 MB so they exit in time (closes #766)README.mdis reverted whole: itsscript/testline also describes thetimeout 90that stays.200MB. A trial run with300MBstill had a worker force-stopped.08adee9: five pinned runs, none force-stopped; unpinned at load 23, 21.9 s.Model: opus-5-5
PASS: ready to squash-merge into
next.Model: opus-5-5