Repo-audit cleanup + remove legacy path/training + fix eject#122
Merged
Conversation
… docs) Acts on the verified findings in docs/proposals/repo-audit-2026-06.md. Tooling / deps / CI: - Remove stale committed package-lock.json (pnpm is the only PM) + gitignore it - Drop unused deps (@ai-sdk/openai-compatible, zod-to-json-schema); bump @types/node ^24 and eslint-config-next 16.1.6 to match the Node-24 runtime - Lighten pre-commit from full `pnpm check` (ran a whole next build) to lint-staged; add `typecheck` + `lint:fix` scripts; `test` -> `vitest run` - Add tsconfig.scripts.json so scripts/ is type-checked; repoint the capture scripts off the undeclared `playwright` import to @playwright/test - Add .nvmrc (24); delete the dead .buildkite pipeline (dup of GH Actions) - ci.yml: --frozen-lockfile, a concurrency group (auto-cancel superseded PR runs), typecheck in `check`, correct the false "production build" e2e comment CSS / styling: - Remove the blanket stylelint-disable that silently un-linted 59% of globals.css; fix the 11 real violations it hid (incl. a cyber-fixer font cascade trap), merging the duplicate [data-aesthetic] blocks - Theme-drive the vignette via --aesthetic-vignette-*; delete 10 dead @theme tokens; replace hardcoded amber glow with the accent var - Extend the palette parity test from 1 var to all 15 mirrored vars x 5 presets Atmosphere (roadmap Tier-1 #1): wire each preset's declared atmosphere.particle into overlay selection so worlds no longer all rain noir-blue — nostromo gets terminal grain, gothic gets drifting embers (new EmberOverlay), minimal none. Architecture: consolidate the duplicated JSON-Pointer setAtPath into one shared binding/pointer.ts (mutable + immutable); delete the dead SurfaceManager class (235 lines) + its 360-line test; fix the misleading "wraps" store comment. Tests: add useVideoGeneration.test.ts (race-supersede / poll-timeout), a downloadVideo failure-path test, a deterministic fetch stub in ChatSidebar tests, and drop the orphan Linux visual-snapshot baseline. Docs: 23 -> 24 component types, document the `video` type, fix the set_aesthetic union, add missing .env.example vars, de-precise stale test-count badges.
Make A2UI v0.9 the only rendering path and drop the export-only training feature. The model still emits "legacy-shaped" trees validated by a2uiInputSchema and flattened to the catalog by flattenLegacyToCatalog — that shared model-emission contract is kept; only the legacy *consumers* are removed. Legacy removal: - Delete the legacy A2UIRenderer + FormContext, EvidenceBoard, and the /api/chat route (tool-result protocol), with their tests. - Rewrite DetectiveWorkspace as v0.9-only: drop useChat / DefaultChatTransport, the tool-result useEffect, sendMessageWithContext, and every useV09 branch. The interrogation log is now hand-driven local state (the v0.9 stream is a one-shot SSE POST, not an SDK chat transport). - Remove the useA2UIv09 toggle end-to-end (Settings type, ChatSettingsPanel, ChatSidebar) and drop the now-unused @ai-sdk/react dependency. - /print now renders through flattenLegacyToCatalog + SurfaceRenderer instead of the deleted legacy renderer, so the print view keeps working. - Point the events e2e spec at /api/a2ui/stream (was **/api/chat). Training removal (it only captured + exported examples as JSON/JSONL; nothing was wired into generation): - Delete src/lib/training/**, TrainingDataPanel, and the trainingSlice. - Strip trainingExamples from the store (slice spread, PersistedState, partialize, type re-exports) and the dead training CRUD from indexeddb.ts. - Remove the DeskLayout Training button + panel + props. Eject data-source migration (required by the legacy removal — eject read the legacy `evidence` atom that only the legacy path populated, so it was already stale in v0.9 mode): the stream route now emits the resolved A2UI tree as a `source` SSE message, useA2UIStream forwards it via onSource, and the workspace mirrors it into `evidence` so Eject Mode exports exactly what was generated.
Review-and-fix pass on the export-to-code feature. - Add a `video` case to the exporter: a real source renders as a <video> player; a prompt-only node (on-demand footage) renders a labelled stub instead of silently vanishing into the unknown-type comment. - Make renderNode defensive: the JSON editor feeds raw, unvalidated trees, so a partial node (e.g. a list without items) no longer throws and crashes the whole Eject panel — it degrades to a comment and valid siblings still export. Also guard countStatefulNodes against malformed tabs/modal nodes. - Clamp heading levels to h1–h4 so an out-of-range editor value can't emit invalid <h7>/<h0> that breaks the Sandpack compile. - Drop an unused React import in SandpackPreview. - Add 14 tests: video (player + stub), slider, defensive malformed-input, and heading-level clamping.
The legacy useA2UIv09 toggle was removed, so the enableA2UIv09 helper's wait for the (now-deleted) 'Toggle A2UI v0.9 mode' button hung every caller until the 20-min job timeout. Make it a no-op (v0.9 is the only path) and rewrite chat.spec to assert the v0.9 surface renders instead of the legacy editor mirror. Verified: the 32 affected specs pass locally in ~1m.
Google's Imagen `:predict` backend intermittently returns 429 RESOURCE_EXHAUSTED
('temporarily out of capacity') even when the caller is well under quota — a
server-side condition independent of the Gemini-native image path. Previously
this dead-ended the image after ~3 minutes of in-SDK backoff on the same dead
endpoint (→ image 404).
Now: detect a 429/capacity error and fail over once to a sibling Google image
model on a DIFFERENT backend (Imagen generateImage <-> Gemini generateText),
which is the most likely way to recover. Per-endpoint retries are trimmed to 1
so failover is fast instead of burning minutes of backoff on the saturated one.
Non-capacity errors (400, etc.) do not fall back.
Refactors the per-model call into runImageModel(); adds isCapacityError() +
selectGoogleFallbackModel(); +3 tests.
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.
Summary
Three threads of work on the way to a leaner, v0.9-only codebase:
docs/proposals/repo-audit-2026-06.md(an 8-dimension adversarially-verified audit).Net: 65 files, +974 / −16,937 lines. Full
pnpm checkis green (prettier + eslint + stylelint + typecheck + 1,180 tests + production build).1. Audit cleanup (
chore)Tooling / deps / CI
package-lock.json(pnpm is the only PM) + gitignore it; drop unused deps (@ai-sdk/openai-compatible,zod-to-json-schema); bump@types/node^24 +eslint-config-next16.1.6 to match the Node-24 runtime.pnpm check(it ran a wholenext build) tolint-staged; addtypecheck+lint:fix;test→vitest run; type-checkscripts/viatsconfig.scripts.json; repoint the capture scripts off the undeclaredplaywrightimport..nvmrc(24); delete the dead.buildkitepipeline.ci.yml:--frozen-lockfile, a concurrency group (auto-cancel superseded PR runs), typecheck incheck, fix the false "production build" e2e comment.CSS — remove the blanket
stylelint-disablethat silently un-linted 59% ofglobals.css(then fix the 11 real violations it hid, incl. a cyber-fixer font cascade trap); theme-drive the vignette; delete 10 dead@themetokens; replace hardcoded amber glow with the accent var; extend the palette parity test from 1 var → all 15 mirrored vars × 5 presets.Atmosphere (roadmap Tier-1 #1) — wire each preset's declared
atmosphere.particleinto overlay selection so worlds no longer all rain noir-blue: nostromo → terminal grain, gothic → drifting embers (newEmberOverlay), minimal → none.Architecture / tests / docs — consolidate the duplicated JSON-Pointer
setAtPath; delete the deadSurfaceManagerclass (235 lines) + its 360-line test; adduseVideoGenerationtests (race/timeout) + adownloadVideofailure test; fix stale doc counts and the missingvideotype /set_aestheticunion.2. Remove legacy path + training (
refactor)A2UIRenderer+FormContext,EvidenceBoard, and/api/chat, with tests.DetectiveWorkspacev0.9-only: dropuseChat/DefaultChatTransport, the tool-result effect, and everyuseV09branch; the chat log is now hand-driven local state. Remove theuseA2UIv09toggle end-to-end and drop the unused@ai-sdk/reactdep./printnow renders throughflattenLegacyToCatalog+SurfaceRenderer(feature preserved).a2uiInputSchema, thegenerate_uitool,flattenLegacyToCatalog) — only the legacy consumers are gone.src/lib/training/**, the panel, the store slice + persist field, the dead indexeddb CRUD, and the DeskLayout button.3. Eject: review, fix, migrate (
fix)The review found eject was already silently broken in v0.9 mode — it read the legacy
evidenceatom that only the legacy path ever populated, so removing legacy would have stranded it. Fixes:A2UIInputtree (image prompts already → real URLs) as asourceSSE message →useA2UIStream.onSource→setEvidence. Eject now exports exactly what was generated, at higher fidelity than reverse-adapting the lossy catalog.videonodes silently vanished → now export as a<video>player (or a labelled stub for prompt-only nodes); malformed editor JSON crashed the whole panel → now degrades per-node; out-of-range heading levels emitted invalid<h7>/<h0>→ clamped to h1–h4.Test plan
pnpm checkgreen (1,180 unit tests + build)./print+ eject migrated to v0.9,source → onSource → setEvidence → EjectPanelwiring confirmed across all three layers.