fix: repin the engine for the grid track sizing hang, and 0.8.4 - #157
Merged
Conversation
added 11 commits
August 16, 2026 13:17
The suite failed 65 tests across 11 files on a clean master. The cause was not the app code: package.json asked for ^2.2.2 and bun.lock resolved 2.2.2, but node_modules held 1.3.1, a major version behind. v1 exports Modal, Toggle and EmptyState where v2 exports Dialog, Switch and Empty, so three of the twelve components this app imports did not exist at runtime. CloseConfirm and WelcomeFlow crashed reading a property of an undefined Dialog, and the other 47 failures were the 5s timeout that follows when a component never renders and findByRole never resolves. Move to 2.5.0, published and the version the owner asked for. No source change was needed, which is the evidence the migration itself was sound: 563 tests pass, 56 of 56 files, and tsc is clean. Suite time drops from 117s to 18s now that nothing waits on a component that cannot mount.
`stable` could not build. The rust gate ran clippy and the tests under `--all-features`, and this workspace is one where that flag cannot be used: `blitz-runtime` and `webview-runtime` are mutually exclusive, and `main.rs` turns enabling both into a compile error naming them. The gate therefore failed before linting anything, so no delivery bundle could be produced. Name the runtime that ships instead, with the inspector `stable` already builds the binary against, which keeps the gate checking the code that actually goes out.
The git workflow section still said the file is tracked, carries the macOS link flag and the usvg patch, and that its working copy should equal its commit. None of that has been true since e8c30f4: the patch had already moved to the root manifest, that commit moved the linker flag into apps/gui/build.rs, and the file was deleted. `.cargo/` now holds only the gitignored local-renderer.toml. An agent reading the old text goes looking for a tracked file that is not there, and the natural repair is to recreate it, which is precisely the arrangement the rest of the section exists to prevent.
…ly it `flex items-center gap-2` was written out at 17 call sites, the most repeated layout signature in the app. The library's own recipe maps `gap="sm"` to `gap-2` and `align="center"` to `items-center`, and its base class is nothing but `display: flex`, so `<Flex align="center" gap="sm">` emits the same three classes on the same `div`. The rendering is unchanged by construction. Only this exact signature. The neighbouring ones are deliberately left alone: `flex items-center gap-2 pt-0.5` and `flex items-baseline gap-2` carry padding and alignment the recipe has no parameter for, and inventing one to absorb them would move a decision out of the call site that reads it.
… colour
Two 2.x-era breakages found by driving the shipping Blitz build.
Paste: the renderer dispatches no `paste` event to JS at all, and answers the
chord itself only for a focused native text input. Anything else reached no
handler in either language, so pasting did nothing. Cmd/Ctrl+V is now served
next to Copy, which was already here for the same reason. It writes through
the field and dispatches `input`, because a controlled Solid field takes its
value from a signal that only that event updates: without it the character
count, the autosize and the submitted text all keep the pre-paste value.
`execCommand("paste")` is deliberately not a fallback; scripted reads are
refused everywhere, so a refusal is the real answer and the field is left be.
The colour wheel: 2.x gives `.radio__control` its own
`background-color: var(--color-base-100)`, and the petal's colour is the
indicator *inside* that control. The fill is painted over it, so all 31 petals
render as identical empty circles. The override list already restated margin,
size, border width and border colour for this control; it never had to restate
the background, because the v1 control had no fill. Measured on the real
renderer: the petals were always the right size in the right circle, which is
why this reads as a colour bug rather than a layout one.
Dragging the glass sliders blanked the window. The cause is the one the GlassAxis comment already describes: every persisted step is a `set_settings` round trip costing 5-6ms on the window thread, and enough of them in a row starve paint. Traced on the owner's live session while they reproduced it, frames kept advancing (50243 -> 50317) while missed refreshes went 46 -> 73 and fps halved, and the profile log held 7,838 of those writes. A 180ms debounce was standing in for the event that means "the knob was released", because the pinned 1.3.1 had none. A debounce is not that event: it fires whenever the pointer pauses, so a slow drag is still a stream of writes. 2.x carries `onChangeEnd`, and both call sites said in comments that they were waiting for it, so `onChange` now paints and `onChangeEnd` persists. The three cost-warning tests drove half an interaction: `keyDown` with no `keyUp`, `pointerDown` with no `pointerUp`. That passed against a timer, which needs no release, and could not pass against the real event. They now finish the gesture, which is also what a user does. The library raises `onChangeEnd` from `keyup` and `blur`, so holding an arrow key repeats the preview without repeating the write.
…ll are Two places said the shipping renderer cannot carry a blur. It can: vello gained a real backdrop pass, `record_backdrop` with a blur sigma and an expansion rect, and ce156b0 recorded that landing without revising the section that contradicts it or the CSS comment repeating the same claim. What actually keeps glass off is a pair of deliberate switches: the window config carries no `transparent: true`, so `WINDOW_GLASS_ENABLED` stays false and the effect view is never attached. They move together or not at all, because an `NSGlassEffectView` over an opaque window flattens the whole app under one colour, which is the thing that flag was added to prevent. Stated as a table of three gates, with the two that are shut named by file and line, so the next person reads a switch to open rather than a renderer to rewrite.
Glass is meant to be core, so it should be the library's primitive rather than a set of axes this app invented. It already is: 2.5.0 ships `styles/glass.ts`, which derives twenty-five `--glass-*` tokens from `blur`, `refraction` and `depth`, and its own doc comment credits the consulting.parcle.ai tuning surface the owner pointed at. The port upstream was already done; what was missing was a consumer. So `applyTheme` now calls `applyGlassTokens` and Settings gains those three sliders, with `GLASS_LIMITS` and `GLASS_DEFAULTS` supplying their ranges and defaults so nothing is restated here and a retune upstream arrives for free. The preview re-derives the whole set from the other two axes on every change: three of the tokens are read by component CSS without a fallback, and an undefined custom property drops the declaration rather than falling back, so a partial set is a panel with no background at all. `.az-glass` is what makes any of it visible. Nothing in this app rendered `material="glass"`, so tokens alone would have been three controls that move nothing, which is exactly what the comment they replace warned about. It carries the same fallbacks, the same no-nested-blur rule and the same reduced-transparency and unsupported-backdrop paths the library uses, and it replaces the opaque fill rather than layering over it, because a backdrop filter behind an opaque background blurs nothing. The old axes stay. They style AgencyZero's own hue-ladder panel, which is a different question from how a glass surface refracts, and both now reach the chrome through one Panel. Two comments claiming CSS could not drive blur on either shipping renderer are gone: vello's backdrop pass landed, and `blitz-paint` converts and forwards the filter, so the chain is whole from stylesheet to scene.
…did not The document planned both halves and its status section only ever described the window one. In-app glass is now live through the library's tokens and needed no window transparency at all, which is worth stating next to the two switches that are still shut, so the next reader does not open them expecting to be turning glass on for the first time.
`.az-glass` asked for `--glass-app-surface-opacity` and `--glass-app-border-opacity`. Those belong to the older parcle vocabulary; the library's own producer emits twenty-four tokens and neither is among them, so both reads fell to their fallbacks and the refraction axis moved nothing on a panel's fill or edge. The names that carry the same two values are `--glass-background-opacity` and `--glass-border-opacity`, which is what `Card.css` reads for its own glass material. Checked the whole block against the producer's output rather than the two that were wrong: all eight tokens now resolve.
A table in a transcript could wedge the app permanently. ps-taffy's `distribute_space_up_to_limits` kept a track counted as growable while `property + increase < limit`, but sized the iteration from `limit - property - increase`, and f32 rounding lets the first be true while the second is exactly zero. The increase came out as zero, the guard below it rejected every track, and nothing changed, so the next iteration recomputed the same values forever. Layout runs on the main thread, so this presented as a beachball rather than a slow frame, and it survived SIGTERM: the handler drains the tables from a signal thread, but the exit that follows goes through the event loop the loop was holding. Reopening the app restored the same transcript and wedged again. The composer reads `scrollHeight` on every keystroke, which resolves the whole document, so any table on screen made a single keypress enough to trigger it. Chain: ps-taffy 4355471d, ps-blitz b82e649d, tauri-runtime-blitz 9edbec23. All the ps-blitz pins move together, since cargo treats one git source at two revisions as two crates and the shared traits then exist twice. apps/blitz-preview keeps the old pin. It is a separate workspace whose lock cannot be regenerated: it patches blitz-dom to ~/code/blitz-rust, which does not exist, so its pins were already unbuildable before this change.
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.
A table in a transcript could wedge the app permanently. This repins the engine chain onto the fix and bumps to 0.8.4 so a package can ship.
What was happening
ps-taffy'sdistribute_space_up_to_limitskept a track counted as growable whileproperty + increase < limit, but sized each iteration fromlimit - property - increase. f32 rounding lets the first be true while the second is exactly0.0. The increase then came out zero, theincrease > 0.0guard rejected every track, nothing changed, and the next iteration recomputed identical values. A fixed point, so it never recovered.Two things made it present as badly as it did:
SIGTERM received; draining the tables and exiting, but the exit that follows goes through the event loop the layout loop is holding. The store was always flushed; the process just never left.Reopening did not help, because boot restored the same transcript and wedged again on the same table.
The composer reads
scrollHeighton every keystroke, and the comment atComposer.tsx:650already records that this resolves the whole document. So with any table on screen, one keypress was enough.Chain
4355471db82e649d9edbec23All ps-blitz pins move together across
apps/guiandcrates/blitz-bench. Cargo treats one git source at two revisions as two distinct crates, so the shared traits would exist twice.scripts/check-one-rev-per-git-source.shpasses.Not included
apps/blitz-previewkeeps the old pin. It is a separate workspace and its lock cannot be regenerated: it patchesblitz-domto~/code/blitz-rust, which does not exist on this machine, socargo updatethere fails before reaching the pin. That rot predates this change and wants its own fix.Verification
cargo check --workspacepasses in ps-blitz and tauri-runtime-blitz against the new revs. ps-taffy's full suite is green, including 5541 generated layout fixtures, plus a regression test built from the exact column sizes that hung this app. The experimental bundle is building against this branch now, and I will confirm the app opens the offending transcript before this merges.