mirror of
https://github.com/NeuralNomadsAI/CodeNomad.git
synced 2026-11-14 01:52:56 +00:00
build(deps): qualify Vite 7 with merged Zod 4 and stable fixture graphs
Apply the Vite 7.3.8 security migration to UI and Electron while preserving the standalone UI browser target, reviewed native optimizer cleanup, aligned Rollup binaries and the merged Zod 4 migration. The shared fixture daemon scans its real TSX entries, preventing late dependency optimization from invalidating a borrowed fixture's desktop API module URL. Logo tests read the displayed SVG rather than infer its color from a filename that Vite may inline. Retain the shared native plugin activation and receipt synchronization qualifiers, including the Goal plugin's positive readiness state before its original assertions. No production timeout, failure collector, native mutation retry, runtime requirement or security guard is relaxed. The integration preserves all unrelated dev changes and the complete dependency graph through a strict semantic lockfile merge with protected SDK/Effect/Monaco/native Rollup records unchanged. The combined Vite 7 and Zod 4 graph passes a frozen optional-workspace Linux install, UI/server/Electron typechecks, the full server/UI/plugin/tunnel build and local packaging without lockfile drift. The formerly failing real browser sequence passes twice each on Linux and Windows; targeted native source, restart, integration and Goal qualifiers pass against isolated minimum/latest runtimes. The maintainer explicitly requested this merge while the corrected exact-head CI is still running. No CI job has reported failure at merge admission; unfinished jobs are not counted as completed validation. Their immutable-head CI remains under first-failed-job supervision after merge.
This commit is contained in:
parent
82ec9a38b9
commit
bf3c488484
11 changed files with 193 additions and 1614 deletions
|
|
@ -48,6 +48,8 @@ edits are the developer's own signal to restart the run.
|
|||
|
||||
The daemon serves the browser's implicit `GET /favicon.ico` as a small PNG.
|
||||
Other missing resources retain their HTTP errors and strict browser collectors.
|
||||
Its dependency optimizer scans `tests/browser/fixtures/*.tsx`, keeping dependency
|
||||
module URLs stable across the daemon's dynamically registered HTML routes.
|
||||
|
||||
## Logs, cleanup and platform limits
|
||||
|
||||
|
|
@ -82,6 +84,7 @@ admitted Location before their first RPC, and surface failed setup immediately.
|
|||
|
||||
## Agent conventions
|
||||
|
||||
- Fixture shutdown tracks Vite 7 optimizer disposal and pending requests across every server environment before deleting its owned cache. Qualify the optimized-load hook and native cleanup acknowledgements together when changing Vite.
|
||||
- A new browser test either borrows via `borrowFixture({ name, routes })` or
|
||||
joins `fixture-exemptions.ts` with a reason that matches reality (the
|
||||
checker's failure text is the review).
|
||||
|
|
|
|||
1755
package-lock.json
generated
1755
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -55,7 +55,7 @@
|
|||
"electron-vite": "6.0.0",
|
||||
"tsx": "^4.23.15",
|
||||
"typescript": "^5.3.0",
|
||||
"vite": "^6.4.5",
|
||||
"vite": "^7.3.8",
|
||||
"vite-plugin-solid": "^2.11.15"
|
||||
},
|
||||
"build": {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
"postcss": "8.5.32",
|
||||
"tailwindcss": "3",
|
||||
"typescript": "^5.3.0",
|
||||
"vite": "^5.0.0",
|
||||
"vite": "^7.3.8",
|
||||
"vite-plugin-pwa": "^1.2.0",
|
||||
"vite-plugin-solid": "^2.11.15"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,12 +29,17 @@ function merge(target: any, patch: any): any {
|
|||
return result
|
||||
}
|
||||
|
||||
/** Which hexagon each logo shows, by the image file it displays, with its rendered height. */
|
||||
/** Read the displayed SVG's hexagon, including inlined data URLs. */
|
||||
async function shownLogos(page: Page) {
|
||||
return page.locator(".brand-logo").evaluateAll((logos) => logos.map((logo) => {
|
||||
return page.locator(".brand-logo").evaluateAll((logos) => Promise.all(logos.map(async (logo) => {
|
||||
const shown = [...logo.querySelectorAll("img")].filter((image) => image.getBoundingClientRect().height > 0)
|
||||
return { shown: shown.map((image) => /OnLight/.test(image.src) ? "black" : "white"), height: logo.getBoundingClientRect().height }
|
||||
}))
|
||||
const colors = await Promise.all(shown.map(async image => {
|
||||
const svg = new DOMParser().parseFromString(await (await fetch(image.currentSrc || image.src)).text(), "image/svg+xml")
|
||||
const fill = svg.querySelector('path[fill-rule="evenodd"]')?.getAttribute("fill")
|
||||
return fill === "#000" ? "black" : fill === "#fff" ? "white" : fill
|
||||
}))
|
||||
return { shown: colors, height: logo.getBoundingClientRect().height }
|
||||
})))
|
||||
}
|
||||
|
||||
test("the logo turns black on light palettes and white on dark ones", async () => {
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export async function startFixtureDaemon({ directory, cacheDir }: {
|
|||
},
|
||||
],
|
||||
resolve: { dedupe: ["solid-js"] },
|
||||
optimizeDeps: { exclude: ["lucide-solid"] },
|
||||
optimizeDeps: { entries: ["tests/browser/fixtures/*.tsx"], exclude: ["lucide-solid"] },
|
||||
server: { host: "127.0.0.1", port: 0, hmr: false, watch: null },
|
||||
})
|
||||
shutdown.own(server)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ after(async () => {
|
|||
// Recheck after subsequent optimizer work, not just immediately after rm.
|
||||
for (const cacheDir of disposedCaches) await assert.rejects(stat(cacheDir), { code: "ENOENT" })
|
||||
})
|
||||
const pending = (server: ViteDevServer) => (server as ViteDevServer & { _pendingRequests: Map<unknown, unknown> })._pendingRequests.size
|
||||
const pending = (server: ViteDevServer) => Object.values(server.environments).reduce((count, environment) =>
|
||||
count + (environment as typeof environment & { _pendingRequests: Map<unknown, unknown> })._pendingRequests.size, 0)
|
||||
async function setup(fault?: Plugin) {
|
||||
const cache = await createFixtureCache(), shutdown = createFixtureShutdown(cache)
|
||||
const server = await createServer({ configFile: false, root, logLevel: "error", cacheDir: cache.cacheDir,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { version, type Plugin, type ViteDevServer } from "vite"
|
|||
|
||||
interface OwnedCache { cacheDir: string; dispose(): Promise<void> }
|
||||
|
||||
/** Vite 5's optimized load waits on info.processing, which optimizer.close
|
||||
/** Vite 7's optimized load waits on info.processing, which optimizer.close
|
||||
* doesn't always settle. Cancel ONLY this cache's read-only load hook before
|
||||
* the container tracks its returned promise; never resolve native metadata.
|
||||
* The optimizer itself still has to acknowledge both native close passes. */
|
||||
|
|
@ -15,15 +15,17 @@ export function createFixtureShutdown(cache: OwnedCache) {
|
|||
const plugin: Plugin = {
|
||||
name: "owned-fixture-optimized-load-cancellation",
|
||||
configResolved(config) {
|
||||
if (!version.startsWith("5.")) throw new Error("Fixture shutdown requires reviewed Vite 5 load lifecycle")
|
||||
if (!version.startsWith("7.")) throw new Error("Fixture shutdown requires reviewed Vite 7 load lifecycle")
|
||||
const native = config.plugins.find(item => item.name === "vite:optimized-deps")
|
||||
if (typeof native?.load !== "function") throw new Error("Unsupported Vite optimized dependency load hook")
|
||||
const load = native.load
|
||||
// native optimizer.close awaits cancel, not every context's disposal.
|
||||
// In particular onCrawlEnd may hold an optimizationResult locally, out
|
||||
// of close's reach. Track its actual native context terminal callback.
|
||||
config.optimizeDeps.esbuildOptions = { ...config.optimizeDeps.esbuildOptions, plugins: [
|
||||
...(config.optimizeDeps.esbuildOptions?.plugins ?? []), {
|
||||
for (const environment of Object.values(config.environments)) {
|
||||
const optimize = environment.optimizeDeps
|
||||
optimize.esbuildOptions = { ...optimize.esbuildOptions, plugins: [
|
||||
...(optimize.esbuildOptions?.plugins ?? []), {
|
||||
name: "owned-fixture-optimizer-disposal",
|
||||
setup(build) {
|
||||
createdContexts++
|
||||
|
|
@ -33,8 +35,9 @@ export function createFixtureShutdown(cache: OwnedCache) {
|
|||
build.onDispose(() => { disposedContexts++; contexts.delete(disposed); done() })
|
||||
},
|
||||
},
|
||||
] }
|
||||
const prefix = `${config.cacheDir.replace(/\\/g, "/")}/deps/`
|
||||
] }
|
||||
}
|
||||
const prefix = `${config.cacheDir.replace(/\\/g, "/")}/`
|
||||
native.load = function (...args) {
|
||||
if (!args[0].replace(/\\/g, "/").startsWith(prefix)) return load.apply(this, args)
|
||||
if (stopped) return Promise.reject(error)
|
||||
|
|
@ -60,7 +63,8 @@ export function createFixtureShutdown(cache: OwnedCache) {
|
|||
await nativeClose()
|
||||
const contextsAfterNativeClose = contexts.size
|
||||
await Promise.all([...contexts])
|
||||
const pending = (server as ViteDevServer & { _pendingRequests: Map<unknown, unknown> })._pendingRequests.size
|
||||
const pending = Object.values(server.environments).reduce((count, environment) =>
|
||||
count + (environment as typeof environment & { _pendingRequests: Map<unknown, unknown> })._pendingRequests.size, 0)
|
||||
if (pending || waiting.size || contexts.size || createdContexts !== disposedContexts || server.httpServer?.listening) {
|
||||
throw new Error("Fixture server did not drain; cache retained")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ globalThis.__asideFailure = {
|
|||
async cache() {
|
||||
const cache = await createFixtureCache(); caches.push(cache.cacheDir); events.push('cache-created')
|
||||
return { cacheDir: cache.cacheDir, async dispose() {
|
||||
if (server?.httpServer?.listening || server?._pendingRequests.size) throw new Error('unsafe cache deletion')
|
||||
if (server?.httpServer?.listening || Object.values(server?.environments ?? {}).some(environment => environment._pendingRequests.size)) throw new Error('unsafe cache deletion')
|
||||
events.push('dispose-start'); await cache.dispose(); events.push('dispose-complete'); write()
|
||||
} }
|
||||
},
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ export default defineConfig({
|
|||
port: 3000,
|
||||
},
|
||||
build: {
|
||||
target: ["es2020", "edge88", "firefox78", "chrome87", "safari14"],
|
||||
outDir: "dist",
|
||||
sourcemap: true,
|
||||
rollupOptions: {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,12 @@ await withProductRuntime(process.argv[2], async () => ({}), async ({ client, roo
|
|||
const command = text => client.session.command({ sessionID: session.id, name: "goal", text, delivery: "steer" })
|
||||
const changes = () => routed.filter(event => event.event.data?.sessionID === session.id)
|
||||
|
||||
await until(async () => {
|
||||
const current = await read()
|
||||
assert.equal(current.status, 200)
|
||||
assert.ok(["goal", "unsupported"].includes(current.body.status), "known native goal bootstrap state")
|
||||
return current.body.status === "goal"
|
||||
}, "the native goal RPC becomes available")
|
||||
assert.deepEqual(await read(), { status: 200, body: { status: "goal", goal: null } }, "a new session has no goal")
|
||||
assert.equal((await read(session.id, "elsewhere")).status, 403, "another workspace cannot read it")
|
||||
const refused = await command("pause").then(() => undefined, error => error)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue