Skip to content

Release 0.3.7: unblock the release gate and fix a worker freeze - #599

Merged
jonit-dev merged 8 commits into
mainfrom
develop
Nov 1, 2026
Merged

jonit-dev merged 8 commits into
mainfrom
develop

Conversation

@jonit-dev

@jonit-dev jonit-dev commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

What is this PR about?

The second attempt to release 0.3.7. It carries #595's content plus five fixes for what blocked the release after #595 merged.

Why does it matter?

The release could not pass at 5b72e5aeb. Main CI went green only after a --failed retry, and after such a retry GitHub answers 502 for that run's job list at per_page=100. The release gate reads that list from the tag's own commit, so no retry could clear it. Nothing was published: npm is still 0.3.6.

Done

  • 3f38446b0: job lists are read in pages of 10. Live read of the blocked run: 93 of 93 jobs, all gate-required jobs success.
  • fc26c3650: a game could freeze on worker.terminate(). A wake consumed before the worker's blocking wait left the main thread joined forever. Seen on macOS. Deterministic red-green test, 25 Linux stress runs with 0 hangs. macOS is unverified until this board runs.
  • c96dc2074: a --failed retry of an integration or native leg can now qualify. Unit specs and an independent review only. No live multi-attempt run yet.
  • 68129365c: the auto-batch settling walk no longer counts against the game in the bridge census (the collectathon flake).
  • 044a5cd34: the Windows starter check gets 600 s for 300 software frames (frame 293 at the 300 s cut).

Local gates on this head: typecheck, lint and budgets exit 0, and workflow specs pass 791 of 791.

Still open

  • template-nonvisual (shooter) debug-restart flake (advance over 20 s on software rendering) has no fix here.
  • The tag run itself has not run the page-size fix yet. It runs after this merge.

… too

b0e1b9e covered only legs outside the joins. A red leg inside a join reruns that join, whose
listing then holds GitHub's copies of every carried leg: new id, later run_attempt, same start, end
and runner (PR #595 run 41262008820: 124718810548 -> 124750441136). The integration check read those
copies as "ran again in a later attempt", and the native check demanded one attempt on every
receipt, so both still failed and only a whole rerun qualified.

mergeAttemptListings keeps the first record of a job that the same start, end and runner show to be
a copy, so a carried leg still matches its receipt and a real rerun still counts as a rerun. Native
judges each leg by its latest attempt, its receipt must name that attempt, and completion downloads
the receipts of every attempt in the run.

Red: the carried-leg case failed CI_NATIVE_JOB_IDENTITY, and the integration listing without the
merge fails "ran again in a later attempt". A latest-attempt red and a real rerun stay rejected. The
chain case for a stale job listing still rejects, now under BUILD_IDENTITY. Unit specs only: no live
multi-attempt run has exercised this yet.
PR #595 push run 41279573156 template-nonvisual (collectathon), green on PR run 41279577367 at the
same SHA: the walk landed on a bridge census frame in collectathon-collect, and its
__attributeNames re-reads (599 of 1085) pushed TN_BRIDGE_WARNING to 0.029 against the 1/50 limit.
It runs only while the scene settles, so it is not the game's steady cost. It now runs under the
observer mark, as de9e266 did for the reveal measurement. The merge and every game read stay
billed. Projected share with the reads removed: about 0.013 (486 reads at 3.99 us on a 151 ms frame).

Red: no children read saw the mark. Green: auto-batch, startup-offscreen-bytes, bridge-reads specs.
…ds a worker

Main CI run 41288322050, macOS desktop core: the native loading proof stopped answering at the
frame after the worker posted its result (TN_PLAYTEST_OPERATION_TIMEOUT, 45 s). A worker loop checks
its queue, pumps microtasks, then blocks in waitForTask(). The pump can consume the V8WakeTask that
terminate() or postMessage() posted after the check. The wait then has no task, and terminate()
joins that worker forever on the main thread, so the game freezes. The race is older than 0.3.6.

wakeTaskWait() now sets a flag before it posts, and waitForTask() returns at once if the flag is
set. The waker changes its state first and the worker rechecks it after the return, so clearing the
flag loses nothing. An extra loop pass is harmless.

Red: js-engine-contract "a wake consumed before the wait stranded the wait" (deterministic). Green:
that test, worker-production exit 0 with 12 contracts, 25 stress runs with 0 hangs on Linux. macOS,
where the hang was seen, is unverified until CI runs this.
…e frames

Native evidence run 41288321973, Windows desktop core: verify-starter-desktop ended with ETIMEDOUT
at 300 s on frame 293 of 300. Microsoft Basic Render Driver drew 1.3 s a frame there and 0.6 s on PR
run 41279577367 at the same tree, so the budget sat on the runner's speed, not on the game. The
verifier keeps TN_STARTER_TIMEOUT_MS for this case. The frame count, markers and screenshot checks
are unchanged, and a real hang stays bounded. Workflow specs: 790 of 790 pass. Not run on Windows.
Tag run 41299952917 failed twice in the gates job with `gh: Server Error (HTTP 502)`. After a
--failed rerun, GitHub answers 502 at 10.6 s for `jobs?filter=latest&per_page=100` on that run (run
41288322050 attempt 3: 9 of 9 reads, while status pages were green), so a --failed rerun that
qualified main could then block the release. ci-attempt-receipts.mjs already read with per_page=10
for this reason, and these paginated reads did not.

Red: the structure spec names the two native-release.yml lines. Green: that spec and the workflow
specs. Live: per_page=10 read that same run in 10 pages, 93 of 93 jobs, total_count equal, every
gate-required job success. The tag run itself has not run this yet.
3f38446 changed native-release.yml to per_page=10 and this fixture still
required per_page=100, so six release gate tests exited 64 in test-native.
PR run 41302359332 failed shooter debug-restart when the census landed on the
restart frame: 77,840 redundant reads from Play.enter, 16 ms of a frame of
seconds, judged as 16% of the 98 ms median. A scene rebuild reads a lot once.
A steady waster's frame is as long as its median, so the next census names it.
@jonit-dev
jonit-dev merged commit 57bc89e into main Nov 1, 2026
207 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant