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.
A fresh starter canvas and a just-opened .op no longer ship the root
frame pre-selected, which both reads cleaner and stops a stray selection
from mis-routing a whole-screen design request into modify.
Turn the product-row-overflow self-check from reject-and-retry into
accept-and-auto-fix (fixed-width cards -> fill_container, gap 12), and
skip clipContent scroll rows entirely. Extend the contrast fixer to any
container with a resolvable solid background (not just buttons) so light
text on a light chip flips to a legible foreground. Add a JS bracket
auto-repair in the script runner so a model's missing closing brace no
longer fails the whole subtask.
Geometry-driven post-passes on generated mobile screens: equalize
side-by-side card heights, collapse a bloating fill_container content
section on a fixed-height artboard, pad a clipping horizontal scroll row
so child strokes aren't shaved on any side, expand a collapsed absolute
(layout:none) image wrapper to its image height, and collapse nested
double horizontal padding. Wired into run_cleanup_passes + loop_finalize.
get_guidelines(category=style) returns a resolved style from an own-built
catalog (7 styles x 7 palettes) with OKLCH-based contrast validation, baked
into the design pipeline (loop prompt + orchestrator subagent instruction).
Also raise the per-subtask output budget 8000 -> 12000 so image-rich
data-list sections stop truncating mid-script.
The STATUS_ACCESS_VIOLATION is not confined to op-host-native/-desktop: any
crate whose tests reach a skia FontMgr (DirectWrite) via NativeBackend or
SkiaMeasure crashes when that test binary runs across parallel worker threads
(op-host-services surfaced next). Excluding crates one-by-one doesn't
converge. Instead run the entire workspace with --test-threads=1 on Windows
only; each binary is serialized (cross-process concurrency is safe), covering
every skia-touching crate at once. macOS / Linux stay parallel.