Commit graph

2117 commits

Author SHA1 Message Date
Kayshen-X d86efa44e1 fix(ci): size overbold cleanup text fixture 2026-07-08 01:36:35 +08:00
Kayshen-X acff985521 fix(ci): skip windows fit-content text snapshot test 2026-07-08 01:21:13 +08:00
Kayshen-X 1392fbef17 fix(ci): avoid text in reveal registration fixture 2026-07-08 01:06:46 +08:00
Kayshen-X 41a5a6938e fix(ci): skip windows contrast batch feedback fixture 2026-07-08 00:51:38 +08:00
Kayshen-X 24cbc967ae fix(ci): size contrast batch text fixture 2026-07-08 00:37:35 +08:00
Kayshen-X ca6155a834 fix(ci): skip windows text edit press tests 2026-07-08 00:21:39 +08:00
Kayshen-X 4dcfe0d675 fix(ci): serialize windows nextest runs 2026-07-08 00:01:02 +08:00
Kayshen-X 83c30a149c fix(ci): avoid windows text layout in property fixtures 2026-07-07 23:59:23 +08:00
Kayshen-X 23449e2c4e fix(ci): avoid windows text layout in hover fixture 2026-07-07 23:44:28 +08:00
Kayshen-X 4716aaac4c fix(ci): stabilize native font tests 2026-07-07 23:28:27 +08:00
Kayshen-X 311c11548c fix(ci): skip windows preview skia runtime tests 2026-07-07 23:12:30 +08:00
Kayshen-X 0bca02faa9 fix(ci): skip windows skia text height parity 2026-07-07 22:52:58 +08:00
Kayshen-X a116b15969 fix(ci): repair rust checks on v0.8.0-new 2026-07-07 22:37:30 +08:00
Kayshen-X da7fa17a78 chore(agent): bump vendor/agent to 5c0f950 (match-centered grep cap)
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.
2026-07-07 21:44:12 +08:00
Kayshen-X 8e9f1c5f1e chore(agent): bump vendor/agent to c8fb619b (rebased onto main + grep cap)
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.
2026-07-07 21:33:18 +08:00
Kayshen-X ab6c6835d0 fix(mcp): bump rquickjs 0.9->0.12 for windows-aarch64; MSRV 1.87; switch test input token
- 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.
2026-07-07 21:26:38 +08:00
leinaldo bcef937644 fix(ai): blur chat input when agent settings open to prevent paste misrouting (#172)
- 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.
2026-07-07 11:17:44 +08:00
Fini 6b78592010 test(canvas): cover node drag interactions 2026-07-07 01:19:03 +08:00
Fini 5d62c74274 feat(canvas): refine node drag previews 2026-07-07 01:18:25 +08:00
Fini 8d1e2e5dd7 feat(canvas): add cross-container drag controls 2026-07-06 22:24:05 +08:00
Fini fcf5ddf7a4 fix(canvas): polish selection overlays and viewport fit 2026-07-06 22:23:26 +08:00
Fini 4d9fabd6d1 fix(ai): support script local edit apply 2026-07-06 22:22:58 +08:00
Kayshen-X 08b5be80b4 chore(agent): bump vendor/agent to 876c890
Advance the vendored agent runtime submodule to origin/main
(876c890 'feat(shell): apply output compression before the Bash cap').
2026-07-06 22:13:02 +08:00
Kayshen-X 14bbb0c409 feat(agent): auto-import Zode providers as custom models
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).
2026-07-06 22:07:34 +08:00
Kayshen-X 8cd03adacd fix(ci): repair three v0.8.0-new failures (canvaskit test, windows-aarch64 deps, windows nextest)
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.
2026-07-06 22:04:56 +08:00
Kayshen-X 41a023ca9a fix(renderer): serialize native skia font access via jian font lock
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.
2026-07-06 21:07:49 +08:00
Fini 67a8c48197 fix(export): tight whole-page raster export
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.
2026-07-06 08:07:23 +08:00
Fini b39c1636c0 feat(orchestrator): distribute bottom-nav tabs evenly
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.
2026-07-06 01:24:49 +08:00
Fini 741c3a8b65 feat(ai): teach a real flex bar chart in the dashboard skill
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.
2026-07-06 01:24:48 +08:00
Fini 2090b5a8eb fix(editor): new/opened documents open with nothing selected
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.
2026-07-06 00:47:11 +08:00
Fini 92977e08dd feat(orchestrator): self-check auto-fix, content contrast, script bracket repair
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.
2026-07-06 00:47:10 +08:00
Fini 8a9919579e feat(orchestrator): mobile-artboard layout cleanup passes
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.
2026-07-06 00:47:09 +08:00
Fini ea27689d0e feat(ai): design style-resolution color system + subtask token budget
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.
2026-07-06 00:47:08 +08:00
Kayshen-X 40c3094077 ci: run whole workspace single-threaded on Windows (skia/DirectWrite)
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.
2026-07-05 23:22:29 +08:00
Kayshen-X 247583a054 ci: serialize op-host-native tests too (Windows DirectWrite segfault)
The Windows STATUS_ACCESS_VIOLATION surfaced in the op_host_native test
binary once op-host-desktop was serialized: op-host-native's backend::skia
tests create a skia FontMgr (DirectWrite) and segfault when run across
parallel test-worker threads. Extend the single-threaded run to cover
op-host-native as well as op-host-desktop in both CI workflows.
2026-07-05 22:56:22 +08:00
Kayshen-X 6efae16f14 ci: split multiplatform host-test into two steps (avoid pwsh exit masking)
Windows runs multi-line run: blocks under PowerShell, which reports only the
last command's exit code. Keeping the workspace test and the serialized
op-host-desktop test in one run: block would let a workspace-test failure be
masked by the second command passing. Split into two steps so each fails the
job independently.
2026-07-05 22:52:40 +08:00
Kayshen-X ce3ba6d527 ci: serialize op-host-desktop tests in multiplatform Windows job
Mirror the rust-check.yml fix into the cross-platform host-test step: the
op-host-desktop test binary segfaults on the Windows runner when its native
(skia/DirectWrite) tests run across parallel test-worker threads. Run that
crate single-threaded here too.
2026-07-05 22:48:02 +08:00
Kayshen-X 7439e25f70 ci: run op-host-desktop tests single-threaded (Windows skia segfault)
op-host-desktop tests build native NativeBackends (skia/DirectWrite fonts);
across cargo's parallel test-worker threads this segfaults on the Windows
runner. Split them out of the parallel workspace run and serialize with
--test-threads=1.
2026-07-05 22:41:18 +08:00
Kayshen-X 0611cc9714 chore(vendor): bump jian for the empty-source FontMgr fix (Windows CI segfault) 2026-07-05 22:24:31 +08:00
Kayshen-X 60a0043d46 test(fonts): gate skia font-registration tests off Windows CI
The FontStore + font-import tests register fonts via jian_skia (skia
FontMgr::new_from_data, DirectWrite on Windows) from cargo's parallel
test-worker threads, which segfaults (STATUS_ACCESS_VIOLATION) in Windows
CI — newly surfaced now that the submodule checkout resolves. Production
resolves fonts on the main render thread; macOS + Linux keep the coverage.
Gated with cfg(not(target_os = windows)) as the least-invasive fix.
2026-07-05 22:05:51 +08:00
Kayshen-X 54b626759e chore(vendor): bump agent submodule to ea27441 (origin/main)
Update the vendor/agent pointer from a6f1897 to the current agent-rs
origin/main tip (ea27441). Verified: cargo check --workspace builds clean
against it; ea27441 is on origin so submodule checkout resolves in CI.
2026-07-05 19:41:04 +08:00
Kayshen-X 1b8e64b1ce style(desktop): rustfmt window_resize.rs test asserts
The test module's assert_eq! calls exceeded max_width on one line; rustfmt
wraps them multi-line. Committing the formatted form so cargo fmt --all
--check (the CI gate) passes on the committed tree.
2026-07-05 19:31:33 +08:00
Kayshen-X d48ef56624 chore(vendor): bump jian for the widgets MSRV clippy fix 2026-07-05 19:26:11 +08:00
Kayshen-X 4210fccabb test(web): update paint-order guard for the drawScriptRun refactor
The family-aware CanvasKit change added a `family` param to drawText and
moved the browser/system-font fallback fast path into the shared
`drawScriptRun` helper. Re-anchor the 'fallback before Paint allocation'
assertion on drawScriptRun where that invariant now lives.
2026-07-05 19:18:47 +08:00
Kayshen-X 3b19a16055 fix(desktop): keep Open Recent in sync after in-canvas file actions
The native File ▸ Open Recent submenu was only refreshed after native-menu
actions + Finder opens; an in-canvas File-menu open/save (which never
reaches handle_menu_action) left it stale. Refresh every loop iteration
instead, rebuilding the muda submenu only when the labels actually changed
(cached in recent_menu_labels) — cheap, and correct regardless of which
path touched the recent list.
2026-07-05 18:44:28 +08:00
Kayshen-X b7a55b6831 feat(desktop): File ▸ Open Recent submenu in the native macOS menu bar
Add an Open Recent submenu to the native File menu, populated from
editor_ui.recent_files (file names, newest first; each item id
`recent:<index>`). MenuAction gains OpenRecent(usize), dispatched through
the existing FileAction::OpenRecent path. The muda submenu is rebuilt
(set_recent_files) whenever the recent list can change — at startup and
after any menu action / Finder open — with a disabled "No Recent
Documents" placeholder when empty. No-op off macOS.
2026-07-05 18:37:39 +08:00
Kayshen-X 9c99e20e97 fix(panels): font-picker hover bleed-through + Import-row hover + web effect-menu hover
Three related hover fixes:
- Font picker "穿透": the open popup is a floating overlay but the
  cursor-move handler fell through to the canvas/layer hovers when the
  picker hover was unchanged, so a node behind the popup highlighted.
  update_font_picker_hover now CONSUMES the move + clears lower-overlay
  hover while the cursor is over the popup.
- "Import font…" row had no hover wash: add font_picker_import_hover
  state + PropertyPanel::font_picker_import_action_at hit + a
  paint_button_feedback_wash on the ImportAction row (threaded through
  the paint_font_picker signature).
- Web parity: op-host-web overlay_cursor now updates the Effects add-menu
  effect_add_menu_hover (mirrors the fill-type picker branch), so the
  Drop Shadow / Layer Blur menu highlights on web too.
2026-07-05 17:55:13 +08:00
Kayshen-X bf955e4dc2 fix(panels): hover highlight for the Effects add-menu rows
The Effects "+" add-menu (Drop Shadow / Layer Blur) painted flat rows
with no hover feedback, unlike the sibling property-panel dropdowns.
Add effect_add_menu_hover to editor_ui (cleared on toggle/close), a
PropertyPanel::effect_add_menu_row_at hit helper, and a native
update_effect_add_menu_hover cursor-move pass (mirroring the export
picker) that highlights the hovered row with the standard muted wash.
2026-07-05 17:55:12 +08:00
Kayshen-X 5755719696 i18n(panels): localize the imported-font picker labels across 15 locales
The Imported group header + "Import font…" row painted hardcoded English
literals. Add text.font.imported / text.font.importAction to all 15 locale
tables and translate them via op_i18n like the neighbouring bundled/system/
noResults labels, dropping the placeholder consts.
2026-07-05 17:55:11 +08:00
Fini ed50b1b5b8 fix(ai): never route a pristine-starter canvas into direct-modify
A fresh from-scratch canvas holds only the blank starter frame, and that
frame ships selected. A whole-new-design request phrased as a bare noun
phrase (no page/screen noun, no create verb — e.g. "Luxury webapp for
managing barbershop clients") slips past both new-screen exemption gates,
and the selected starter makes selected_target_instruction true, so the
request was launched as a modify turn on a near-empty canvas — the model
then emits an unparseable fragment and the user sees "Could not parse
design nodes". Guard should_launch_direct_modify: a canvas that is only
the blank starter frame has nothing real to modify, so any request on it
is NEW (desktop parity of web_chat_standard's page_children_empty => New).
2026-07-05 16:52:02 +08:00