Repository navigation
fix(ni): the board paints designed cards handed over from reactive state - #517
Merged
Merged
Conversation
On the board a card's CLIR lives inside a deep $state, so its nested arrays reach the painter as Svelte proxies; applyLive cloned them with structuredClone, which throws DataCloneError on any Proxy, and every designed card left the board (and the C2 panel) on its spinner. Found recording the Neural Interface clip; no release carried it (the painter landed after v0.25.0). A JSON round trip replaces the clone (a CLIR is JSON by contract). Regression tests pin it on both layers: the unit test feeds applyLive a deep Proxy (and shows structuredClone throws on it), and a mounted IrPaint paints a stat card and a live tide curve handed over as nested proxies.
SecureCloudGroup
added a commit
that referenced
this pull request
Oct 14, 2026
The effect that reloads the board when the vault flips to unlocked called load() under tracking; load()'s synchronous prefix reads `items` (a $state) and then reassigns it after the fetch, so every reload re-ran the effect and the page issued GET /api/ni/board back to back, forever (dozens per 0.1 s on a board with three live cards). The call now runs under `untrack`, so the effect depends on the unlocked flag only. Found recording the Neural Interface clip; the first-card crash fixed in #517 had hidden it.
SecureCloudGroup
added a commit
that referenced
this pull request
Oct 14, 2026
…screenshot (#520) * docs(media): quickstart clip 12 — the Neural Interface — and the board screenshot Recorded with tools/gifgen against main after #517/#518/#519, deterministically: the released Library pack v1.5.0 mounted read-only into the demo container, canned model turns for the intent, query, design pick and fit check of three asks, and recorded source responses served by the recorder-only shim (gated on SB_GIFDEMO=1 + SB_GIFDEMO_NI; every other fetch refused). The clip: ask in plain words, tap the Library source it found, check the designed card, live on the board; a second ask; an honest stop with a dataset link. Board screenshot 04-neural-board.png (three live cards). README row 12; docs/03 embeds; gifgen README and run.sh (`./run.sh 12` does take, encode, poster, sheet and the docshot). Help bundle rebuilt. * gifgen: parse the design-pick skeleton with string slicing, not backtracking regexes (CodeQL py/polynomial-redos)
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.
Release blocker found while recording the Neural Interface clip. In a real browser the
/niboard never rendered once it held any designed (form/CLIR) card:applyLivecloned the CLIR withstructuredClone, but on the board the CLIR comes out of a deep$state, so its nested arrays are Svelte proxies and the clone throwsDataCloneError: [object Object] could not be cloned. Every designed card, and the C2 VerifyPanel, sat on the spinner. No release carried it (the painter landed after v0.25.0); every unit test and the painter harness fed plain objects, so nothing caught it.Fix: a JSON round trip instead of
structuredClone(a CLIR is JSON by contract,validateClir). Tests:clir.test.tsfeedsapplyLivea deep Proxy (assertingstructuredClonethrows on it, the hazard pinned) and checks plain output; a new mountedIrPaint.test.tspaints a stat card and a live tide curve handed over as nested proxies. Both fail on the old code with the DataCloneError and pass now. Gates: svelte-check 530 files 0 / 0, vitest 48 files / 648 tests, bundle rebuilt. Merge before tagging v0.26.0.