Commit graph

116 commits

Author SHA1 Message Date
Fini 32192b9348 feat(orchestrator): geometry validation + layout repair passes
Resolve real layout geometry to correct table-column overflow and collapsed
fill-container heights, iterating until stable. Add whole-root passes: sidebar
app-shell reshape + content eviction + split-shell row layout, table column
gap/regroup, footer sink, surface discipline, scaffold padding. The design-loop
finalize backstop runs these once at loop end and injects background-contrasting
fills for fill-less text. run.rs: continue past a failed subtask and compute
zero-content before cleanup.
2026-07-02 21:21:44 +08:00
Fini 9e9cdec7cf feat(smoke): OPENPENCIL_SMOKE_PROGRAM mode runs a batch_design program headless
Reads a program file, runs it through op_mcp::batch_design_snapshot, applies, saves
the .op (postProcess off = raw structure) — the headless harness for benchmarking
the program-DSL path vs flat JSONL across weak models.
2026-07-02 21:21:41 +08:00
Fini cd2131ce28 feat(smoke): minimal scaffold seed for loop (OPENPENCIL_SMOKE_LOOP_SEED) reusing build_fallback_plan; data-gate harness for orchestrator-vs-loop migration 2026-07-02 21:21:28 +08:00
Fini 5b612ed6c6 feat(smoke): headless agentic-loop mode (OPENPENCIL_SMOKE_LOOP) + design-library loading for benchmarking 2026-07-02 21:21:18 +08:00
Kayshen-X a7d73ebb62 feat(ai): pencil-style agentic design tool-loop, multi-chat tabs, #27 panel restyle
Built-in design generation now runs as an agentic MCP tool-loop (reusing the
agent-rs BuiltInProvider), gated behind OPENPENCIL_DESIGN_AGENT_LOOP / the
Settings experimental toggle; the orchestrator stays the default.

- design-agent system prompt + in-process design toolset (parity-locked with
  the MCP surface) + flag-gated Intent::Design routing
- spawn_agents execution as sequential sub-loops + live creation-mode badges
  (per-agent glow + 'N/M designing...' header)
- new MCP tools: get_guidelines, ToolSearch, get_screenshot, get_editor_state,
  export_nodes, spawn_agents; style-guide local audit
- #27 AI panel restyle: rounded tool cards + green check-rings, gray user
  bubbles, model-pill bottom toolbar, header, empty-state pills, the
  PARALLEL AGENTS (agent_team_size) 1x-6x chip dropdown
- multi-chat tabs: ChatSessions model (Deref-to-active) + tab row UI
  (switch / close / + / Cmd+T) with each run bound to its tab

Large checkpoint commit spanning the working tree (Rust shell crates).
2026-07-02 21:21:06 +08:00
Kayshen-X 6a43c90774 build(ci): binaryen-tolerant wasm-opt flags + refresh cargo-deny advisories
The wasm bundle gates (tools/check-wasm-bundle.sh and
crates/op-web-sdk/tools/build-wasm.sh) hard-passed --enable-bulk-memory-opt
to wasm-opt, which older binaryen (the CI runner's apt package) does not
recognize, failing the WASM bundle build (#56) and op-web-sdk bundle
workflows at the size gate. Probe wasm-opt --help and keep only the feature
flags the installed binaryen advertises; on those older versions the single
--enable-bulk-memory already covers memory.copy/fill, so dropping the unknown
flag is safe. Local binaryen (v117+) keeps both.

cargo-deny advisories also failed: ttf-parser flagged unmaintained
(RUSTSEC-2026-0192, a transitive font-stack dep with no maintained
replacement) and memmap2 flagged unsound (RUSTSEC-2026-0186). Ignore the
former and bump memmap2 0.9.10 -> 0.9.11 (the patched release) for the
latter. advisories now pass.
2026-07-02 01:53:40 +08:00
Kayshen-X b1aebc3252 feat(ai): agentic design tool-loop, multi-chat tabs, #27 panel restyle
Built-in design generation now runs as an agentic MCP tool-loop (reusing the
agent-rs BuiltInProvider), gated behind OPENPENCIL_DESIGN_AGENT_LOOP / the
Settings experimental toggle; the orchestrator stays the default.

- design-agent system prompt + in-process design toolset (parity-locked with
  the MCP surface) + flag-gated Intent::Design routing
- spawn_agents execution as sequential sub-loops + live creation-mode badges
  (per-agent glow + 'N/M designing...' header)
- new MCP tools: get_guidelines, ToolSearch, get_screenshot, get_editor_state,
  export_nodes, spawn_agents; style-guide local audit
- #27 AI panel restyle: rounded tool cards + green check-rings, gray user
  bubbles, model-pill bottom toolbar, header, empty-state pills, the
  PARALLEL AGENTS (agent_team_size) 1x-6x chip dropdown
- multi-chat tabs: ChatSessions model (Deref-to-active) + tab row UI
  (switch / close / + / Cmd+T) with each run bound to its tab

Large checkpoint commit spanning the working tree (Rust shell crates).
2026-06-25 00:12:45 +08:00
Fini 169e6abed2 feat(orchestrator): tree-heuristics, palette-harmonize, post-pass refinements
Port the post-streaming tree-heuristics pass to Rust (tree_heuristics.rs):
- fill_card_leading_image_width: a card's leading header image spans the
  card width instead of leaving a white gap (160px image in a 252px card)
- fix_notification_badge_overlay: a badge authored as a flex sibling of an
  icon becomes a corner-overlay circle, not a square beside the icon
- active nav-tab pill, card image corner clip, invisible text-band fill,
  stacked-overlay-to-absolute, redundant colored wrapper strip

Add palette_harmonize.rs: retint the cool-slate neutral ramp toward the
page's temperature so a warm design no longer reads as off-palette gray.

Plus role-resolver / cleanup / scaffold / run refinements accumulated from
the glm-opus design-parity campaign.
2026-06-21 23:18:16 +08:00
Kayshen-X fef880b8a5 chore(lock): reconcile Cargo.lock with jian-scene dep edits
Add jian-scene; drop op-editor-ui from op-mcp/op-pen-loader — matches the
scene-unification Cargo.toml changes so the lock isn't stale.
2026-06-20 00:16:24 +08:00
Kayshen-X 88a571c028 refactor(host): rename op-web-daemon crate to op-host-services
The extracted headless crate is consumed by BOTH op-host-desktop (the GUI binary, for its
embedded --serve-web/MCP/chat/export) AND op-host-web-server — so 'web-daemon' was misleading.
Renamed crate dir + package + lib (op_web_daemon -> op_host_services) across all consumer files
(114 refs in 24 files) + the 4 Cargo.toml deps + Dockerfile/guard comments; identity docs
rewritten (it's the GUI-free host backend — daemon/MCP/AI/export/persistence — not web-specific).
No behavior change. (Lock renamed accordingly; the concurrent actor's op-host-web serde line excluded.)
2026-06-19 22:35:22 +08:00
Kayshen-X f198cdf76a feat(host): add headless op-host-web-server binary (Phase 6, Task 6.1)
A thin binary linking ONLY op-web-daemon — no winit/glutin/muda/accesskit-adapters/skia-GL.
Routes --serve-web/--mcp/--mcp-http argv to op_web_daemon::web_canvas_server::run_web_canvas +
op_web_daemon::mcp_serve::{run,run_http} (mirrors the desktop dispatcher, headless-only — no GUI
fallback). Added to root default-members. VERIFIED via cargo tree: 0 winit/glutin/casement/muda/
accesskit-adapters + skia-safe without gl (raster) — the web-server image now excludes all
desktop/GL code, answering the original question. (Lock also drops the actor-removed op-app crate.)
2026-06-19 22:09:58 +08:00
Kayshen-X 2ae343785b refactor(host): carve headless doc-io out of persistence into op-web-daemon (Phase 2, Task 2.3)
The host-free load/save core moves to op_web_daemon::doc_io: save_to_path,
load_editor_state, document_fingerprint, is_supported_document/_figma_import,
ActionOutcome, ErrorKind + the shared EditorState helpers (set_file_name_display,
preserve_app_preferences, active_page_bbox, sidecar_path). The rfd/winit dialog
flow (handle_open/save, run_action, show_error_dialog) stays in op-host-desktop
and imports them back. 23 external refs repointed; codex Issue-4 shared helpers
promoted to pub. Adds op-i18n for the dialog strings. op-web-daemon stays GL-free.
2026-06-19 19:57:28 +08:00
Kayshen-X 00526dec31 chore(host): lock op-host-desktop's op-web-daemon dependency
The web_static move (a0f37443) added op-web-daemon to op-host-desktop's
Cargo.toml but omitted the corresponding Cargo.lock entry (codex stop-review),
leaving the lock inconsistent with the manifest. Hunk-staged to add only
op-host-desktop's op-web-daemon dep line, excluding the concurrent actor's
in-flight op-web-sdk lock changes.
2026-06-19 18:46:01 +08:00
Kayshen-X 3872c90289 chore: refresh README crate table + lock op-web-daemon entry
Deferred from the prior commits (both were co-edited with the concurrent actor
at the time): README's stale crate list -> accurate op-* entry-crates table
(matching the cargo:wasm-check fix), and the op-web-daemon Cargo.lock package
entry (hunk-staged to exclude the concurrent op-web-sdk changes still in flight).
2026-06-19 18:29:41 +08:00
Kayshen-X 75ec668463 feat(sdk): add op-web-sdk read-only web viewer crate
Plan 1 of the web embedding SDK (TS-retirement Phase 2): a wasm Viewer that
parses a .op document, renders it read-only via CanvasKit by reusing
op-editor-ui's canvas_viewport, supports pan/zoom navigation, exposes
read-only JSON snapshots, and exports SVG. Type-gen reuses jian-ops-schema's
ts-rs export.

Additive: new crate plus surgical cold pub exposures (CanvasViewport::from_scene
in op-editor-ui; pub mod canvaskit + pub init_backend in op-host-web). No TS
deleted. 17 tests; wasm 2.2 MiB gzip (0 env.* imports); clippy -D warnings clean.
2026-06-19 17:52:12 +08:00
Kayshen-X 9a4dd34bf4 fix(ci): address rust check failures 2026-06-19 03:03:33 +08:00
Kayshen-X bd4c8d5935 fix(web): use browser fonts in canvaskit shell 2026-06-19 02:39:34 +08:00
Kayshen-X 0104c8bd61 feat(editor): a11y + single-instance + layer-panel Rust↔TS parity
Close the non-web-productionization gaps from the 2026-06-18 recheck:

- a11y (#67/#57): assemble each widget's access_node() into an
  accesskit::TreeUpdate (op-editor-ui/accessibility.rs); publish on
  desktop via accesskit_macos/_windows/_unix SubclassingAdapter off the
  raw window handle (op-host-desktop/a11y.rs, NOT accesskit_winit — the
  casement winit fork), and on web via a hidden ARIA DOM mirror
  (op-host-web/a11y_dom.rs); native/web region enumeration + action
  routing in op-host-{native,web}.
- single-instance (#51): fixed-loopback-port guard + second-launch file
  forwarding to the running window (op-host-desktop/single_instance.rs).
- layer panel: drop-into-container inserts at index 0 (#12a); container
  predicate widened to frame/group/rectangle/ref (#12b); Escape closes
  the context menu on both hosts (#14).
- distribution: Homebrew cask fix + op formula + install-op.sh, README
  CLI install, CI codesign/notarize/signtool scaffolding gated on secrets.

Codex-reviewed (1 BLOCKER + 3 CONCERNs resolved). main.rs, app_handler.rs,
canvaskit.rs and Cargo.lock are staged whole and carry some unrelated
in-progress WIP they're interleaved with.
2026-06-18 22:18:07 +08:00
Kayshen-X 227da7fa11 refactor(renderer): consolidate web shell on CanvasKit, retire skia path
Retire the from-scratch wasm32 skia raster web backend and the vendored
skia-safe fork now that CanvasKit is the sole web renderer.

- remove gl-webgl-shim + the `webgl` feature + backend/webgl.rs
- absorb chat streaming, live-sync, codegen, icon search, Figma/file IO,
  and system fonts into the `canvaskit` build via a backend-agnostic
  `RepaintContext` trait; wire them into `mount_ck` (chat send, image
  paste routing, window resize)
- delete the skia raster modules (backend/, a11y, shell_drop/resize,
  ime_target, boolean_ops, caret_pump, repaint_scheduler) + the skia
  `Inner` mount; op-host-web is now `web` (stub) + `canvaskit` only
- drop [patch.crates-io]; delete vendor/skia-safe-op + crates/wasm-libc-shim
  so skia-safe reverts to upstream crates.io 0.97.x (native unchanged,
  byte-identical; upstream has no wasm32-unknown-unknown target)
- switch the bundle gate (check-wasm-bundle.sh) to --features canvaskit

Also float new shapes above the frame (z-order), inset the shape-picker
selected-row highlight, and align the web file-menu hover without the
traffic-light inset.

Builds clean: canvaskit + web-stub (wasm32) + native desktop; bundle gate
passes (0 env.*, 4.5 MiB gzip).
2026-06-18 09:34:37 +08:00
Kayshen-X 05fedb1ec7 feat(editor): widget design-canvas visuals + jian-runtime preview mode
Render the 10-widget family as composite visuals on the design canvas
(op-pen-loader payload -> scene -> canvas_viewport_widget), and add a
Play/Stop canvas Preview mode that runs the jian runtime live via a
DrawOp -> Painter bridge (native host) with doc-invariant enter/exit.
The web Preview button is an honest no-op pending a web runtime owner.

Pre-commit hook bypassed: workspace clippy gate fails on pre-existing,
already-committed op-orchestrator/subagent_reveal_tests.rs (unrelated).
This change is rustfmt-clean and cargo check --workspace passes.
2026-06-14 23:46:58 +08:00
Kayshen-X 8f3d7588c0 chore(host-core): tighten feature boundaries 2026-06-14 12:18:51 +08:00
Kayshen-X 2a6d2191ef refactor(host-core): share codegen session core 2026-06-14 11:49:55 +08:00
Kayshen-X 478668dcbc refactor(host-core): share design actor core 2026-06-14 11:32:01 +08:00
Kayshen-X 207560b7a3 refactor(host-core): share codegen input state 2026-06-14 11:12:19 +08:00
Kayshen-X 941d51f805 feat(process): extract shared process io primitives 2026-06-14 10:54:26 +08:00
Kayshen-X 4d9b2d783d feat(rpc): extract shared JSON-RPC transport 2026-06-14 10:33:21 +08:00
Kayshen-X 811b02d155 feat(config): add shared OpenPencil config store 2026-06-14 10:17:22 +08:00
Kayshen-X f0a264e078 refactor(editor): migrate settings inputs to shared text state 2026-06-14 00:56:21 +08:00
Kayshen-X 42de84c917 refactor(editor): re-export painter contract from jian-widgets 2026-06-14 00:56:08 +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
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
Kayshen-X b6e6d1da7f feat(web): web codegen session driving CodegenPipeline [unverified] 2026-06-07 19:21:33 +08:00
Kayshen-X ec2ed2796d feat(web): AI-streaming foundation (rAF pump + XHR/SSE transport + clipboard/download) [unverified] 2026-06-07 19:21:32 +08:00
Kayshen-X 907190d341 feat(host): scaffold codegen_session + op-codegen ai dep 2026-06-07 19:21:25 +08:00
Kayshen-X 32aeb2737d feat(codegen): port codegen asset extraction 2026-06-07 14:55:25 +08:00
Fini 9af99ba62e feat(ai): infer semantic roles from node names (role-resolver I1)
First increment of the role-resolver port (spec
openpencil-docs/.../2026-06-06-role-resolver-rust-port.md). Port of
inferRoleFromName + the name-inference path of resolveNodeRole + the
resolveTreeRoles walk from role-resolver.ts.

New `role_infer` module: NAME_EXACT_MAP + NAME_PATTERN_MAP (regex) + the
container-suffix and role-part-word guards, plus the page-chrome-in-card guard
(a card's inner "Header" must not become a navbar) and the tiny-card guard
("Status Dot" must not become stat-card). Runs on each sub-agent subtree in
run_subtask BEFORE the fallback sizing normalize (semantic-before-fallback).

No role DEFAULTS injection yet (that is increment I2) — but setting `role`
already has effect: the existing cleanup passes (nav-surface repair, section
logic) key off node.role, so an inferred navbar/footer is now repaired the
same way an explicitly-tagged one is.

Adds the `regex` dep (already locked at 1.12.3). 12 tests cover the exact /
pattern maps, all guards, explicit-role-wins, and the tree walk.
2026-06-06 21:42:57 +08:00
Fini cd8837128b test(ai): add direct-client headless benchmark harness to op-smoke
op-smoke's QueryEngine path can't send MiniMax's `thinking:{type:
"disabled"}` field, so reasoning models (M3 etc.) thought themselves out
of the token budget and couldn't be benchmarked end-to-end. Add a
non-streaming DirectClient (OPENPENCIL_SMOKE_DIRECT=1) that posts
openai-compat directly and disables thinking at the wire for MiniMax —
or any endpoint via OPENPENCIL_SMOKE_DISABLE_THINKING=1 (Volcengine
honors the same param) — so the production thinking-disable path can be
exercised headless without a GUI.
2026-06-06 15:45:37 +08:00
Kayshen-X 561687de1b fix(mcp): resolve fit-content text bounds 2026-06-06 11:32:10 +08:00
Kayshen-X 54fb746881 feat(mcp): expand rust editor mcp surface 2026-06-05 22:19:08 +08:00
Fini b349b06f2a feat(ai): headless model-design benchmark harness
Adds a fully-headless pipeline to benchmark built-in-Agent design generation across models, with no GUI or live canvas.

op-smoke: OPENPENCIL_SMOKE_OUT saves the generated PenDocument to a .op; OPENPENCIL_SMOKE_DUMP dumps the raw LLM response for diagnosing weak-model JSON malformations. openpencil-desktop --render-shots FILE OUTDIR SCALE loads a .op, runs the jian layout pass, and exports one cropped PNG per top-level node via export_node_raster (skia CPU raster) for node-only benchmark screenshots.
2026-06-04 02:33:08 +08:00
Kayshen-X 0282283cb6 feat(editor): command-layer ops for MCP layered design
Add EditorCommand support powering the MCP layered-design workflow: authored-id subtree insertion for design skeletons, deterministic RefineDesign cleanup, plus batch-page and replace-node apply paths and an InsertSubtree page_id target. Includes command_apply/command_node wiring and tests.
2026-06-02 09:42:04 +08:00
Kayshen-X 68394826fe fix(cli): add figma import parity 2026-06-02 09:41:47 +08:00
Kayshen-X cb1cf55ae9 fix(mcp): add batch get parity 2026-06-02 09:41:39 +08:00
Kayshen-X 2469f424f0 fix(mcp): add design prompt parity 2026-06-02 09:41:36 +08:00
Kayshen-X e3ae058b29 fix(cli): align rust op with live mcp 2026-05-31 22:00:41 +08:00
Kayshen-X 43e6bedcfb fix(ci): vendor openssl for macos cross checks 2026-05-31 17:53:17 +08:00
Kayshen-X 22305a29d4 fix(ci): address native action failures 2026-05-31 17:30:30 +08:00
Kayshen-X 5974b2f55e fix(git): migrate repo operations to libgit2 2026-05-31 17:04:56 +08:00
Kayshen-X 19652f0724 feat(panels): improve native property controls and icons 2026-05-24 23:30:00 +08:00
Fini 1b103a017c Merge branch 'v0.8.0-new' of github.com:ZSeven-W/openpencil into v0.8.0-new 2026-05-24 19:45:55 +08:00