The hover dashed outline painted at page level from the unrotated
doc-space bounds, so a rotated frame (and any element inside one)
showed an axis-aligned outline detached from its rendered geometry.
Accumulate the root-to-node flip/rotation chain during the scene
paint walk and replay it around the dashed rect so the outline lands
exactly where the node renders. Hit-testing already handled ancestor
rotation, so trigger area and visual now agree.
`with_decorations(false)` strips the native frame entirely on Windows,
so DWM painted the borderless window as a flat rectangle with sharp
corners instead of the Windows 11 look. Opt back into
`CornerPreference::Round` and a hairline border matching the dark
chrome via casement's `WindowAttributesExtWindows`.
Introduce the ZSeven-W product family (zode, agent-rs, jian, noema)
with a new Ecosystem section across all 15 locales, and reframe jian
from 'widget/render/event toolkit' to 'GPU-Skia UI framework' in the
Tech Stack table, Ecosystem table, and Project Structure tree.
Chrome text rendered blurry on Retina: all chrome/canvas text goes
through the offscreen 2D-canvas raster path (drawBrowserText), which
rasterized glyphs at CSS (1x) resolution. Those bitmaps are then drawn
onto the CanvasKit surface while a scale(dpr, dpr) transform is active,
magnifying them dpr-x — half-resolution on 2x displays.
Supersample the offscreen text canvas by the device pixel ratio and
composite it back at 1/dpr so glyphs land at native device resolution.
Thread the real dpr from Rust (CanvasKitBackend::new + resize_for_display)
into the bridge via a new setDpr method; cache key includes dpr and
stale bitmaps are dropped on dpr change.
Advance past c8fb619b (head/tail grep cap that could hide a match in a
long line) to origin/main, which centers the per-line cap on the match
plus repairs feature gates/advisories.
Advance the submodule past the pre-rebase 876c890 (no longer on any
remote branch) to origin/main, which carries the ripgrep/compression
series rebased onto main plus the grep per-line output cap.
- rquickjs 0.9->0.12 (op-mcp): 0.12 ships aarch64-pc-windows-msvc bindings
(0.9 doesn't), so the native-only script feature builds on windows-arm64
with full parity (as Zode's zode-core already uses 0.12). Clean drop-in;
25 script_runner tests pass. Reverts the earlier per-target gating.
- Workspace MSRV 1.85->1.87 (rquickjs 0.12's floor; pinned toolchain is 1.94).
- agent_settings switch test: assert theme.input (the token the off-track
paints) now the light theme gives input its own value distinct from border.
- Call blur_input when agent settings panel opens (shortcut + click)
on both native and web hosts, so chat.focused becomes false.
- Guard agent_settings focus check with agent_settings_open in
input_active() to prevent stale focus from claiming keyboard.
- Reorder handle_cmd_paste to check non-chat inputs first, with an
additional !chat.focused guard.
Read `~/.zode/config.json` on startup (native/daemon) and merge every
Zode `(provider, model)` pair into agent_settings.builtin_agents as a
BuiltinAgentConfig, so providers already configured in the Zode CLI show
up as OpenPencil custom models without re-entering keys. Anthropic vs
OpenAI-compat is chosen by the provider `type`; one custom model per
model id (provider name qualified by model when a provider has several).
Best-effort + idempotent: missing/malformed file is a silent no-op, and
add_builtin_agent_config backend-dedupes so re-running each launch adds
nothing new. Imported agents are tracked in imported_agent_ids and
excluded from settings.json persistence — Zode's config stays the single
source of truth and its API keys are never silently duplicated onto a
second on-disk location (they're re-imported every launch).
Three independent CI failures, none caused by the font-lock push:
1. CanvasKit web-host test variables_panel_open_does_not_paint_legacy_modal
false-tripped: its '> half viewport' heuristic was a proxy for 'no
full-viewport modal', but only passed because the property panel used
to narrow the canvas and clamp the floating VariablesPanel below
half-width. The nothing-selected-by-default change collapsed the
property panel, widening the canvas so the legitimate 820x480 panel
paints unclamped. There is no legacy modal. Retarget the assertion at
a near full-viewport round fill and positively assert the panel paints.
2. windows-aarch64 cross-check failed: op-host-services + op-orchestrator
pulled op-mcp's native-only 'script' feature unconditionally, dragging
in rquickjs-sys which ships no bindings for aarch64-pc-windows-msvc.
Enable 'script' per-target (off on that unshipped check-only arch).
3. Windows workspace tests segfaulted single-threaded (before the first
test prints, under --test-threads=1) — an intra-test race a thread
flag can't serialize. Switch the Windows runner to cargo-nextest (one
process per test) so the crash is isolated + named; doctests run
separately.
Windows CI segfaulted (STATUS_ACCESS_VIOLATION 0xc0000005) because the
design worker thread runs SkiaMeasure layout concurrently with the UI
thread paint/measure, and skia Windows FontMgr (DirectWrite) is not
thread-safe. Wrap NativeBackend::{new,draw_text,enumerate_system_font_families}
in jian_skia::with_font_lock and bump vendor/jian to the commit adding
that global reentrant lock.
Also un-gate chat_intent_host_tests on Windows (the lock makes its
intra-test worker/UI concurrency safe) and harden the flaky
explicit_family_typeface_lookup_is_cached test with a
retry-until-clean-window against concurrent generation bumps.
Whole-page PNG/raster export added a 16px transparent margin around the
content union, so the exported image did not fill to its content (a
transparent border on all sides). Drop MARGIN to 0 for a tight export;
update the test expectations to the no-margin coordinates.
A recursive cleanup pass detects a horizontal row of >=3 vertical
icon+label tabs (a bottom nav bar, incl. a nested tab container) and makes
each tab fill_container + the row space_between, so tabs spread the full
width instead of bunching to one side and overflowing off-screen.
Replace the empty dashed-placeholder plot-area guidance (which left charts
blank) with a simple real bar chart via flexbox (layout=horizontal,
alignItems=end, value-proportional bar heights) instead of the layout=none
manual positioning the model mis-computes. Also add donut/ring concentric-
stacking guidance.