Commit graph

1568 commits

Author SHA1 Message Date
Kayshen-X 2dece21dfd docs(editor): update widget primitive list 2026-06-14 00:56:20 +08:00
Kayshen-X 382d2d0a87 chore(vendor): bump jian for widget review fixes 2026-06-14 00:56:19 +08:00
Kayshen-X 989dd916d9 chore(editor): drop unused dropdown sample superseded by jian-widgets Select 2026-06-14 00:56:18 +08:00
Kayshen-X d226da454b chore(vendor): bump jian for dialog primitive 2026-06-14 00:56:17 +08:00
Kayshen-X f2c6ced236 chore(vendor): bump jian for switch primitive 2026-06-14 00:56:16 +08:00
Kayshen-X 281698d95a chore(vendor): bump jian for scroll area primitive 2026-06-14 00:56:15 +08:00
Kayshen-X 8d73345cfe chore(vendor): bump jian for menu widget primitive 2026-06-14 00:56:14 +08:00
Kayshen-X 9734c1f73a chore(vendor): bump jian for select widget primitive 2026-06-14 00:56:13 +08:00
Kayshen-X 82b07847a4 chore(vendor): bump jian for text area widget view 2026-06-14 00:56:12 +08:00
Kayshen-X 5cb9d36ec5 chore(vendor): bump jian for text input widget view 2026-06-14 00:56:11 +08:00
Kayshen-X 949cb5a4b1 chore(vendor): bump jian for widget button primitive 2026-06-14 00:56:10 +08:00
Kayshen-X 9dce2957e6 chore(vendor): bump jian for shared widget tokens 2026-06-14 00:56:09 +08:00
Kayshen-X 42de84c917 refactor(editor): re-export painter contract from jian-widgets 2026-06-14 00:56:08 +08:00
Kayshen-X 0daca70f74 chore(vendor): bump jian for select-all arrow fix 2026-06-14 00:56:07 +08:00
Kayshen-X 46822b1ff5 chore(vendor): bump jian for text_input + scroll modules 2026-06-14 00:56:06 +08:00
Kayshen-X bfc8d1676b refactor(editor): unify Color::with_alpha and Color::to_jian 2026-06-14 00:56:05 +08:00
Kayshen-X d64d4a2dc4 refactor(editor): add Rect::contains, drop local rect_contains copies 2026-06-14 00:56:04 +08:00
Fini 5ba0fb62cb feat(mcp): default v1 element theme to system (spec D2)
Flip the manifest repair-layer default for v1 element kinds from
`light` to `system`, so weak-model designs adapt to the document's
light/dark axis instead of baking light-mode hex. Both prerequisites
are now in place: the orchestrator seeds the 56-token semantic palette
at run start (`-*` refs resolve at paint via scene_vars) and
every v1 builder emits numeric gap/padding in system mode. Explicit
`theme=light|dark` still wins.

ab-v9.3 validation (52 prompts × 4 arms, theme=system default):
- Rendering: 0 dangling $color-* refs across all 208 .op; 207/208
  carry the seeded palette + Mode:[Light,Dark] axis. The D2 grey-ref
  risk does not materialize at corpus scale.
- Structural inertness: theme is injected post-model by repair_args
  and only selects fills; role inference + the contrast post-pass are
  already $ref-aware (role_post_pass resolves a ref to None and skips).
  M3/M5 cannot move on the flip — glm's 15 M3 misses are 100%
  missing-role (model output), theme-independent.
- No collapse: M3 ark 81% / glm 71% / DS 85% / m3-think 94%, 0-1
  garbage per arm. Per-arm deltas vs ab-v9.2 are cross-codebase
  (Kayshen's d31734e2 edited the manifest skill + builders between
  runs) + sampling, NOT the theme flip.
2026-06-14 00:56:03 +08:00
Fini aa25cc2a7e fix(editor-ui): variables-panel wheel scroll + preset toggle test
Two failures surfaced once the casement build blocker cleared and the
`cargo test --workspace` step finally ran on v0.8.0-new:

- wheel_over_panel_scrolls_rows_and_clamps: `over_topmost_panel` ran
  first in apply_wheel and lists the variables panel, so a wheel over
  the panel was swallowed (returned true) WITHOUT ever reaching
  try_scroll_variables_panel — rows never advanced. Move the variables
  scroll handler ahead of the topmost-panel guard; it already swallows
  the wheel over its own rect, so the canvas-zoom guard still holds.

- variables_panel_preset_button_toggles_menu: the second press used a
  +58 y-offset that lands in the open dropdown's SaveCurrent row, which
  intentionally focuses the name input and keeps the popover open (TS
  parity, see anchor_press_does_not_double_toggle). Re-press the button
  itself (+22) so the test exercises the toggle it is named for.

op-host-native lib: 296 passed / 0 failed.
2026-06-13 21:07:24 +08:00
Kayshen-X 4dee479c6b chore: snapshot WIP across editor-core, editor-ui, hosts, mcp, ai-skills
Working-tree snapshot spanning op-editor-core (components, path_edit,
ref_resolve, text_edit, instance_override, image_panel), op-editor-ui
widgets (chat panel, variables, property fill, canvas overlays, ime),
op-host-desktop (chat backends, export, kit_persistence), op-host-native
(font picker, frame backend, pen press), op-mcp (batch_program), AI-skills
prompts, and regenerated shadcn-kit / iconify catalog assets.
2026-06-13 17:59:54 +08:00
Fini ebcb85a569 fix(mcp): emit numeric gap/padding in system-mode builders
theme=system audit (D2 prerequisite): the schema accepts $spacing-*
expression refs in gap/padding, but both Rust layout paths zero them
out — jian-core container_to_style and op-pen-loader gap_value fall
through Expression to 0 — so a ref collapses the layout instead of
resolving. Exactly three emission sites existed: modal_shell's card
padding ($spacing-5) and gap ($spacing-3), and toast's pill gap
($spacing-2). Emit the palette-equal numbers (24/12/8) in every mode,
same pattern as the numeric font-size toast fix (011f4104). A new
catalog-wide invariant test builds all kinds with theme=system and
rejects any expression gap/padding, so future ports can't reintroduce
the class. Color $refs are unaffected — scene_vars resolves fill and
stroke refs at paint.
2026-06-13 01:05:46 +08:00
Fini 05e1e4e2d8 feat(ai): route element manifest by model family (M4)
Replace the global OPENPENCIL_MANIFEST env gate with per-model routing:
manifest defaults ON for the families that cleared the ab-v9.2 KPI gate
(minimax 92% / ark-code 92% / glm 98% / deepseek 83%, all >=70%) and
stays OFF for models without benchmark data — the catalog is a floor
for weak models, not a ceiling for strong ones. The env var remains a
both-ways override (1/true/on forces on, 0/false/off forces off) so
op-smoke benchmarks and rollback keep their one-knob workflow.

Also plumb the selected built-in agent's model id into DesignRequest:
the production chat path always sent model:None, which routed every
model to Full-tier prompts and dead-armed both this gate and the M3
thinking policy outside op-smoke. Live-verified: glm-5.1 with no env
set engages the manifest protocol purely via routing.
2026-06-13 00:52:26 +08:00
Fini a9b0e729fd feat(ai): seed semantic palette at orchestration start
Port the TS applySemanticPalette 56-token palette (22 themed light/dark
colors on a Mode axis, 6 chart singles, 28 numerics) and wake the
dormant variables.rs seeding path. Merge semantics differ from TS:
editor-core set_variables_bulk extends (incoming wins) while TS keeps
existing values, so the snapshot computes the missing set first and
seeds only absent tokens via one MergeThemePreset; rollback removes
exactly the created names/axes when no content survives. Live-smoke
verified: generated .op carries the 56 vars + Mode axis and $color-*
refs resolve at paint.
2026-06-13 00:35:35 +08:00
Fini 9ffaf5980c fix(ai): admit painted childless frames as blank-check content
A childless Frame with explicit stroke or fill is pixel-equivalent to a
childless Rectangle, which the blank check already admits. otp_input's
empty stroked digit slots made perfect manifests read as blank
scaffolding -> retry ladder -> raw fallback degradation (ark emitted
flawless otp manifests twice and got rejected both times). Also
serialize the OPENPENCIL_MANIFEST env tests behind a shared lock --
parallel set/remove races only surfaced in full-suite runs.
2026-06-13 00:35:34 +08:00
Fini fa4130c133 feat(ai): deterministic element-kind hints for manifest sub-agents
ab-v9.1 misses were attention failures, not vocabulary failures: kinds
named literally in the brief (toolbar 5/10) still got hand-composed,
while anti-pattern-named kinds rarely missed. Token-match the subtask
label+elements text (plus the whole brief for single-section plans)
against the catalog, expand via a data-grounded synonym table, and
inject up to 6 nominations as an ELEMENT HINTS block with composite-
first and no-hand-compose rules. ab-v9.2 matrix: 51 FAIL->PASS vs 4
noise-shaped regressions; all four arms >=83% M3-pass, M5 adoption 96%.
2026-06-13 00:35:33 +08:00
Fini 461b77a054 fix(ai): manifest catalog recency placement + composite coverage teaching
Full-tier prompts run ~8k tokens and deepseek kept hand-rolling past a
top-of-prompt element catalog (ab-v9 58% vs Basic-tier 85%). Pull the
element-manifest skill out of priority order and append it last, right
above the output contract, so recency keeps the catalog in attention.
The skill's COVERAGE section now also teaches composite-first checking
instead of only naming examples.
2026-06-13 00:35:32 +08:00
Fini e7ae700678 feat(ai): keep MiniMax-M3 reasoning on design subtasks
M3 with thinking disabled drops to M2.7-level element adoption; route
design sub-agent calls through Adaptive thinking with a 16384 budget
for the M3 family while other built-in models keep Disabled+8192.
Validated by the ab-v9.2 matrix (m3-think arm 92% M3-pass).
2026-06-13 00:35:31 +08:00
Kayshen-X 9fd78d2d8a fix(editor-ui): resolve conflict markers swept into the chat panel during the rebase
The background fmt commit captured the editor-ui pick's conflicted state
mid-rebase; both sides kept (ab-v9 concurrency-chip spacing + tests_paint
module, batch tests_transcript module + footer tests), paint helpers
promoted for cross-module reuse.
2026-06-12 23:36:36 +08:00
Kayshen-X 14482a5d86 feat(variables): panel UX, variant-column color editing, theme presets, web mirror
#18 per-row management (resize edges, search with source indices, scroll
clamp, row overflow menu with delete+undo, inline hex cells), #19 variant-
column-targeted color/boolean writes (setValueForTheme parity, picker
seeds from the clicked column), #20 theme presets (.optheme io, app-level
persistence, shared preset menu), #21 full web host mirror (floating
panel replaces the read-only rail; keyboard/scroll/resize/blur routing).
Fixes the stale right-rail assertions in toolbar_panel_actions test.
Absorbs and completes the concurrent actor's variables-panel WIP.
2026-06-12 23:28:11 +08:00
Kayshen-X 3418fe60af fix(web): route iconify body parse through the widget_host boundary seam
check-widget-boundary.sh F4 forbids op_editor_ui::widgets references
outside widget_host.rs + siblings; the remote-icon fetcher now calls the
new icon_ingest wrapper instead of icon_catalog directly.
2026-06-12 23:28:10 +08:00
Kayshen-X 4c7a2a52a1 chore(build): release packaging scripts, wasm bundle gate with codegen, workspace docs + lockfile 2026-06-12 23:28:09 +08:00
Kayshen-X 036222645c feat(renderer): styled text runs, clip-content threading, image payload fields in the loader 2026-06-12 23:28:08 +08:00
Kayshen-X 3759331f79 chore(i18n): locale keys for pickers, image section, kit + preset surfaces 2026-06-12 23:28:07 +08:00
Kayshen-X 55982477fd feat(cli): codegen commands wired to real tools, status pid, web start json 2026-06-12 23:28:06 +08:00
Kayshen-X d7a079e64d feat(codegen): stored-zip encoder + cancel/page-generation hardening
Dependency-free STORED zip for the web bundle path; pipeline cancel +
whole-page input fallback verified surfaces.
2026-06-12 23:28:05 +08:00
Kayshen-X 296ccb3e31 feat(mcp): DSL programs, codegen workflow, debug screenshot, output-shape parity
batch_design multi-line program executor (per-line best-effort, TS quirks
verbatim, alias-table slash paths), codegen plan/submit/assemble/clean
tools + plan store, debug screenshot args, snapshot_layout/batch_get
shapes, refine postProcess in design_content.
2026-06-12 23:28:04 +08:00
Kayshen-X a30206222b feat(web): daemon-backed chat/codegen/live-sync, a11y mirror, kit browser, bundle export
Real chat streaming (echo stub retired; production bundle now builds with
codegen), live_sync glue for browser<->daemon<->MCP, codegen panel actions,
structure-bundle zip (stored-zip encoder), iconify web search, component
browser dispatch, accessibility DOM mirror v1, IME + clipboard paths.
2026-06-12 23:28:03 +08:00
Kayshen-X 4bd439a007 feat(desktop): chat transports, discovery, intent routing, IME, export painter, host pumps
OpenCode SSE transport rewrite, Codex/Gemini subprocess quirks port, Claude
token streaming + image prompts, chat intent classify/modify routing, model
discovery + provider probes, image search/generate hosts, kit io +
persistence, theme preset host, live screenshot + scene-painter export
unification, raster size caps, IME cursor-area anchoring, web canvas
server seams.
2026-06-12 23:28:02 +08:00
Kayshen-X cdfb7d9596 feat(ai): provider trait + ACP session options batch
Copilot binary constants fix, ACP NewSessionOptions (mcpServers + system
prompt meta), attachment fields on the chat turn surface.
2026-06-12 23:26:39 +08:00
Kayshen-X 994b55f928 feat(native): host dispatch batch — pen/path press, IME routing, panel dispatchers, font enumeration
pen_press + path-edit dispatch, ime.rs preedit/commit routing with chat
anchor, font_picker/image_panel/kit dispatch modules, panel-history undo
coverage tests, geometry split (settings-hover sibling), corner-radius
image clipping + skia text italic caches. variables_panel_* excluded
(concurrent WIP).
2026-06-12 23:26:38 +08:00
Kayshen-X c5b72ddffc feat(editor-ui): canvas + panel widget batch for TS parity
Path-edit overlays + anchor context menu, styled text runs/justify painter,
clipContent clipping, remote-image registry + rounded placeholders, font
family picker, image node section (search/generate popovers), component
browser kit strip/picker, IME preedit overlay, chat attachments UI, kit
management surfaces, preset menu widget. Includes the workspace fmt sweep.
2026-06-12 23:26:37 +08:00
Kayshen-X da3b029bc7 feat(editor): TS-parity engine batch — refine passes, atomic command batch, path editing, paste anchoring, IME state, kit model, web-sync seam
Render-time $variable/ref resolution, design-refine deterministic passes,
EditorCommand::Batch with document-only allowlist + snapshot rollback,
pen/bezier path_edit model, TS paste anchoring (container/sibling/instance
quirk), ime_state for native preedit, uikit kit-file plumbing, web_sync
protocol core. Child coords are parent-relative: translate_subtree now
shifts the root only.
2026-06-12 23:25:38 +08:00
Fini 2cd197a7ec test(ai): ab-v9 manifest matrix harness
scripts/ab-v9/run_matrix.py runs the ab-v3 corpus (52 prompts) through
the full Rust orchestrator per provider (op-smoke headless,
OPENPENCIL_MANIFEST=1) and scores M3 expected-shape (required roles in
the saved .op tree) + M5 element selection, appending rows per cell for
crash-safe resume. Keys come from env only (MM_KEY/ARK_KEY/DS_KEY).

op-smoke grows OPENPENCIL_SMOKE_KEEP_THINKING=1 to keep MiniMax
reasoning ON: ab-v9 showed M3-nothink emits lazy minimal manifests
(17%, ~10s answers) while M3-with-thinking lands 60% with composite
tied-best at ~110s — the MiniMax production routing target.
2026-06-10 21:04:07 +08:00
Fini 4bbf6b0883 feat(ai): element manifest pipeline for the built-in agent
Weak models stop tool-calling 188 element schemas and instead emit a
JSONL element manifest — one {"el":"stat_card",...} declaration per
line. Nesting uses manifest-local line numbers ("in"), node ids are
system-assigned (the id-hallucination class disappears at the protocol
level), and a repairing argument layer replaces strict rejection:
enum synonyms, schema-driven placeholders for missing required params,
plain-string-to-JSON shape coercion, and a bounded second-chance retry
when a builder names its missing arg. Raw PenNode lines stay available
as an escape hatch and raw frames can serve as "in" containers.

- op-mcp: element_manifest.rs — build_element facade over
  semantic_alias_node, kind normalization (prefers theme-aware _v1,
  light default until palette seeding lands), schema-generated prompt
  catalog; every known kind builds from empty args (the never-reject
  guarantee, covered by a 94-kind fixture test)
- op-orchestrator: manifest.rs parser (line-tolerant, id injection for
  raw subtrees, depth-clamped sections) wired into run_subtask behind
  OPENPENCIL_MANIFEST=1; retry ladder falls back to the raw-JSONL path
- op-ai-skills: element-manifest skill (priority 0, replaces the
  jsonl-format skills when active) with anti-hand-roll teaching;
  build.rs adds rerun-if-changed so include_dir! sees new skill files
- subagent.rs: childless rectangles count as content — skeleton-screen
  designs no longer reject as blank

ab-v9 (52-prompt corpus, full orchestration): ark-code-latest and
glm-5.1 hit 85% expected-shape success vs the 58% tool-calling
baseline, at 5-8k prompt tokens per call vs ~19.9k.
2026-06-10 21:03:46 +08:00
Fini 20a50eb70b fix(mcp): emit numeric font size in system-mode toast
add_toast_v1's system branch put the $type-body-size token ref into
fontSize, a strict f64 schema slot — every system-themed toast failed
PenNode deserialization. Emit 14 in every mode (the ref resolves to the
same default at render time; see the fidelity caveat on
build_modal_shell). gap keeps its $spacing-2 ref — that slot accepts
expressions.
2026-06-10 21:02:53 +08:00
Fini 6f2eefed5e refactor(editor): split chat panel paint tests under the 800-line cap
ai_chat_panel/tests.rs had grown to 960 lines. Move the paint-assertion
tests + the recording PanelPaintBackend into a tests_paint.rs sibling
(369 lines), leaving layout/hit-test in tests.rs (599 lines); shared
helpers stay in tests.rs as pub(super).
2026-06-10 21:02:42 +08:00
Fini 79f2a13ae1 fix(editor): restore chat toolbar chrome polish
- run the divider above the input across the full panel width
- paint the built-in model key with the real lucide Key glyph instead
  of a hand-rolled ring+shaft approximation
- concurrency chip rests as a faint ghost at 1x and gets a
  primary-tinted chip when the agent team is staffed, keeping the
  footer hover + cycle wiring
- attach/send are ghost icons; send fades to muted-foreground/30 when
  there is nothing to send

Re-lands 94b9aa1b (dropped during a re-batch) merged with the
agent-team footer layout.
2026-06-10 21:02:21 +08:00
Fini 09e1f5f606 fix(editor): clear agent indicators the instant a design turn stops
Stopping a turn or starting a new chat drops the DesignSession, but the
canvas indicators only cleared when the worker thread next touched its
channel and unwound — which lags seconds behind when the worker is
mid-LLM-call. The breathing borders lingered on a canvas the user had
already moved on from.

Give the host (which owns the turn lifecycle) the indicator epoch:
DesignSession::start mints it (clearing the prior turn at once) and the
session's Drop ends it immediately via end_if_epoch. The worker registers
under the same epoch via Orchestrator::with_indicator_epoch; headless and
test callers pass none and the concurrent path mints its own, so run()'s
signature and the DesignRequest construction sites are untouched.

end_if_epoch clears AND retires the epoch (vs clear_if_epoch which only
clears), so a worker still in its add_frame loop when the turn is stopped
can't re-populate the set under the now-stale epoch. It's epoch-scoped, so
a newer turn that already began is left untouched.
2026-06-10 11:18:38 +08:00
Kayshen-X 56e55f1159 fix(ai): align chat input hit testing with painted text 2026-06-10 00:08:04 +08:00
Kayshen-X 86cb4c3fb8 chore(editor): checkpoint chrome WIP + web picker select-all wiring
Snapshots the full working tree: web select-all picker wiring
(op-host-web) plus in-progress chrome work (chat input rework,
agent settings, codegen panel, variables modal, toolbar actions,
model discovery).
2026-06-09 23:27:39 +08:00