Repository navigation
A Vite context's build retires with its last open environment build - #395
Merged
Merged
Conversation
A custom buildApp builds a shared plugin's environments in parallel, and #380 retired the Session and engine in the first environment's closeBundle: the other environments then transformed without them and failed the build ("v2 transform before analyze — engine instance not initialized"). The context now tracks the environments whose build started and has not closed, and retires its build when the set empties. A set, not a count: Vite closes a failed environment's build twice and, in dev, closes environments whose build never started. Probe (run-and-discard): build --watch pairs each rebuild's buildStart with its closeBundle; a failing environment still rejects the build; sequential builds and dev close as before. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
A real Vite createBuilder over the dev-server fixture builds client and SSR in parallel through a custom buildApp, with SSR transforms delayed so the client closes first; SSR output must be extracted. Red on main 26a2b51 (macOS): the build fails with "v2 transform before analyze". Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
… under one name
spike-codex: the name-keyed set conflated distinct active builds. A
builder reused right after a rejected parallel buildApp let the old SSR
build's late closeBundle empty 'ssr' under the new SSR build; two
distinct environments named alike let the first close retire the engine
under the second (both loud, 'engine instance not initialized'). The
context now maps each open build's name to its environment and, in
buildStart, refuses a second build of an active environment ('a previous
build of environment ssr is still running on this plugin instance') and a
second environment under an active name. Only the environment that
opened an entry removes it, so a refused build's closeBundle never
retires the running one.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
- 'a second build of a running environment is refused, naming it': the builder reused straight after a parallel buildApp whose client failed while SSR still ran. - 'two environments under one name are refused, naming it': buildApp builds the client environment and a distinct twin named client in parallel. Both red at 3adeb4e. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
The pushed head failed lint (anti-slop no-object-parameters): the open builds took a broad `object`. They now take a BuildingEnvironment (Vite's environment, or the context's single stand-in for a host without environments). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…buildEnd spike-codex: a refused build owned the active generation's end. Its closeBundle removed the original's entry, so the reused builder's second client retired the engine under the original SSR build, which rejected. Hook contexts are new objects per call (no per-attempt token), but Vite ends every build exactly once in buildEnd, failed ones included, while closeBundle can run twice. So a buildStart for an environment whose build is open (the same object or one named alike) now waits for that build's end and then opens its own generation, and buildEnd ends only the generation its environment opened; the last to end retires the Session and engine. No refusal is left, so no stray end exists. A dev server ends only the environments that started. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…built in turn - 'a builder reused while an earlier build still runs builds after it': spike-codex's witness awaiting all four build promises; only the planned client failure rejects, the original SSR build fulfils. - 'two environments under one name build one after the other': the twin waits for the client and both build. Both red at 53d81d2. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
codecaaron
added a commit
that referenced
this pull request
Oct 11, 2026
…buildEnd spike-codex (P1, silent): a refused build owned the active generation's end. Under a builder reused after a failed parallel buildApp, the second client's buildEnd disposed the shared session directory before the original SSR build ended, which then fulfilled with animus.css referencing ./assets/badge.*.svg and no SVG emitted. As in vite-plugin (#395): a buildStart for an environment whose build is open (the same object, or one named alike) waits for that build's end, then opens its own generation; buildEnd, which runs once per build, ends only the generation its environment opened; the last to end disposes the session directory and releases the claim. No refusal is left, so no stray end. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
codecaaron
marked this pull request as draft
October 11, 2026 21:57
Owner
Author
|
Parked by root under the stopping rule after the final round. spike-codex confirmed the reused-builder findings closed (all four builds settle correctly; the original SSR keeps its assets), but the serialise shape introduces a circular wait: a plugin whose transform awaits a nested build of the same environment hangs, because the nested buildStart awaits the outer build's buildEnd (vite-plugin context.ts:517-521 / unplugin core.ts:529-537). The earlier refusal heads fail that case loudly instead. Owner decision pending: ship this head with the nested-build case as a stated limit, ship the refusal head, or leave parallel buildApp unsupported (main fails it loudly). 🤖 Generated with Claude Code |
codecaaron
marked this pull request as ready for review
October 11, 2026 23:17
# Conflicts: # packages/vite-plugin/src/build-start.ts
codecaaron
added a commit
that referenced
this pull request
Oct 12, 2026
Session C. #395 (vite-plugin) and #402 (unplugin) each tracked open environment builds with the same algorithm: open by name after any open build of that name ends, end only the entry this environment opened, and retire the shared build with the last. extract/session's EnvironmentBuilds now holds it once, with the single environment a host without environments builds as; both plugins delete their copy. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pre-release blocker (teardown audit gap D): a Vite custom
buildAppthat builds a shared plugin's environments in parallel failed the build. #380 retires the context's Session and engine incloseBundle, and the first environment to close did so while the others still transformed: "[animus-extract] Failed to transform src/Sentinel.ts: v2 transform before analyze — engine instance not initialized". Unreleased (#346 and #380 postdate v0.1.25).Fix
The context tracks the environments whose build started and has not closed (
openBuildinbuildStart,closeBuildincloseBundle) and retires its build only when that set empties. A set rather than a count, because the hook pairing is not one-to-one (probe below).Root's three checks (run-and-discard probe, real Vite 8.2.2, macOS)
vite build --watchbuildStart clientthencloseBundle clientbuildStart client,buildStart ssr,closeBundle client,closeBundle ssr×2buildStart clientonly; at closecloseBundle ssr,closeBundle clientSequential and parallel builds (sharedPlugins on and off) produce identical CSS and SSR/client output, with no raw builder code; with the fix, the slow-SSR parallel build matches them.
Review round (spike-codex P2 at 3adeb4e)
A name-keyed set conflated distinct active builds: a builder reused right after a rejected parallel
buildApp(the old SSR build's late close emptiedssrunder the new one), and two distinct environments named alike (the first close retired the engine under the second). Both were loud. The context now maps each open build's name to its environment and refuses, inbuildStart, a second build of an active environment (a previous build of environment ssr is still running on this plugin instance) and a second environment under an active name; only the environment that opened an entry removes it (bffeeee, 53d81d2). Rows (8674dc4), red at 3adeb4e: 'a second build of a running environment is refused, naming it' and 'two environments under one name are refused, naming it'.Last round (spike-codex: a refused build owned the active generation's end)
Hook contexts are new objects per call, so they carry no per-attempt token; but Vite ends every build exactly once in
buildEnd, failed ones included, whilecloseBundlecan run twice for a failed build (probe). So the refusal is gone: abuildStartfor an environment whose build is open (the same object, or one named alike) waits for that build's end and then opens its own generation, andbuildEndends only the generation its environment opened; the last to end retires the Session and engine (c3e3fca). A dev server's close callsbuildEndonly for environments that started. Rows (5abde23), red at 53d81d2: 'a builder reused while an earlier build still runs builds after it' (awaits all four builds: only the planned client failure rejects; the original SSR fulfils) and 'two environments under one name build one after the other'.Witness
tests/dev-server/build-app.test.ts› the first environment to close leaves the others their Session: a realcreateBuilderwith client and SSR in parallel and SSR transforms delayed; red on main 26a2b51 (the error above), green here.Checks
macOS at 53d81d2: Vite suite 229/229, lint and fmt clean. Linux CI: runs 38174475316 (3adeb4e), 38175931696 (53d81d2) and 38177357515 (5abde23), every job green.
🤖 Generated with Claude Code