Commit graph

1913 commits

Author SHA1 Message Date
Fini cc2846d618 feat(orchestrator): force-include component-composition teaching when library present + el:ref/type:ref protocol-branched manifest 2026-07-02 21:21:24 +08:00
Fini 03d7c9b437 feat(mcp): el:ref component-instance kind in Element-Manifest IR (manifest-arm composition → PenNode::Ref) 2026-07-02 21:21:23 +08:00
Fini 0c2fdf8650 feat(loader): merge library masters onto separate Components page (avoids active-page pollution / dashboard scaffold collision) 2026-07-02 21:21:22 +08:00
Fini a67723fbc4 feat(editor-core): append_components_page_masters — design-kit masters on a hidden Components page, active design page stays clean 2026-07-02 21:21:21 +08:00
Fini 77f60a4efb fix(editor-core): ref slot-children fallback — instance inline children fill empty-master shells (Pencil slot-component pattern)
Pencil's slot-component pattern uses an empty styled master (slot:[...] + zero children)
with the instance supplying content via its own inline children. expand_ref only
populated children from the master, dropping instance content → empty shell → blank
white circle in converted templates. Now falls back to instance children (remapped)
when the master has none. Fixes converted-template stat-card rendering + composed-ref
content. +2 ref_resolve tests +1 variables_resolve nested-token regression guard.
2026-07-02 21:21:20 +08:00
Fini 72dbf535d5 chore(editor-ui): chat panel + checklist working-tree progress (WIP) 2026-07-02 21:21:19 +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
Fini 7b1307d72e feat(ai-skills): integrate harvested Pencil guide depth (web-app/mobile/landing/slides/dashboard/design-system) + component-composition + shader-fill teaching 2026-07-02 21:21:17 +08:00
Fini c80f43dbf5 feat(desktop): chat-session loop bridge (finalize/spawn) + smoke library load + image downscale 2026-07-02 21:21:16 +08:00
Fini ed8f763af4 feat(host): agentic-loop screenshot/finalize/spawn bridge + real vision providers + smoke library env 2026-07-02 21:21:15 +08:00
Fini 31ca7c1168 feat(orchestrator): loop-finalize backstop + concurrent spawn-agents + vision validation providers + component-manifest prompt 2026-07-02 21:21:14 +08:00
Fini 89fbee2095 feat(editor-core): mesh/shader fill state + ref id-remap + chat-session state 2026-07-02 21:21:13 +08:00
Fini 41f46ff0d2 feat(mcp): batch_design ref-node emission + full PenFill passthrough + set_node_stroke_side_width tool + get_editor_state 2026-07-02 21:21:12 +08:00
Fini 8adb09220c fix(lint): typography detector adjustment 2026-07-02 21:21:11 +08:00
Fini e6c14f9550 feat(render): skia mesh-gradient via draw_vertices + SkSL shader paint (shader_cache) 2026-07-02 21:21:10 +08:00
Fini bf4a741d8e feat(loader): mesh/shader fills + .pen→.op legacy normalize hardening + pen2op bin + design-library merge
Bumps jian submodule for mesh-gradient/shader PenFill variants. normalize_legacy_doc
gains 8 .pen-compat repairs (stroke-fill string, gradient fill, icon/prompt nodes,
$ref cornerRadius, single-object fill). New pen2op bin converts Pencil .pen→.op.
library.rs merges a .lib.op's reusable masters+variables into a working doc.
2026-07-02 21:21:09 +08:00
Kayshen-X 89e5699e69 fix(ai): chat panel hover/close/send-slot refinements (#41/#42/#43)
- #41: collapse chevron renders through IconButton so it shows the ghost
  button-hover wash instead of only swapping the icon color
- #42: send/stop share one circle slot (toggle in place); footer cluster
  sits snug with no reserved stop gap; hit-test routes streaming->stop else send
- #43: example cards stay clickable without a connected model (clicking one
  fills the input; sending still requires a model)
- tab close glyph shows only while the tab is hovered (inset still reserved
  on the active tab so the title doesn't reflow)
2026-07-02 21:21:08 +08:00
Kayshen-X fc58a4601d chore: bump jian submodule (node promotion for batch_design) 2026-07-02 21:21:07 +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 2ccb063b28 feat(ai): drain the generation overlay gracefully when a design turn ends
On natural completion the design-turn teardown now calls
agent_indicators::finish_if_epoch instead of end_if_epoch: the already
queued reveals keep playing at the queue cadence and the whole overlay
(cursor + borders) clears itself once the last one lands, so the tail of
a slow 160ms stream is no longer snapped away mid-reveal.

A user stop / abort still tears down immediately via end_if_epoch, so a
cancelled generation does not keep animating. Wired across the
orchestrator run guard, the web design session, the host-core
DesignSession drop, and the desktop sub-agent / design-loop teardown.

Updates the desktop lifecycle tests to match: the frame-clear test now
drives past the drain window before asserting the overlay cleared, and a
shared registry test-lock serializes reveal-streaming turns against the
exact animation-deadline assertion (the registry is process-global).
2026-07-02 21:21:05 +08:00
Kayshen-X 05986b1eab feat(canvas): animate AI design generation with an agent pointer cursor
Each agent gets an arrow cursor that flies between the nodes it places
along the reveal schedule, arriving as each node scale-pops in; the
element currently being placed carries a breathing border. Replaces the
old dashed-border reveal fade (canvas_agent_overlay removed).

Reveal cadence is slowed to a uniform 160ms queue and retained for the
whole run, so the cursor parks on the last placement between streamed
chunks instead of fading out. Splits agent_indicators tests into a
sibling file to stay under the 800-line cap.
2026-07-02 21:02:27 +08:00
Kayshen-X ad52b1386b ci(wasm): install pinned modern binaryen instead of apt v108
The WASM bundle build (#56) and op-web-sdk bundle workflows install binaryen
via apt, which on the ubuntu runner is v108 (2022) — too old for rustc 1.94's
wasm feature set. It lacks the --enable-bulk-memory-opt flag (the original
'Unknown option' failure) AND cannot validate the memory.copy/fill opcodes
rustc now emits, so wasm-opt rejects the bundle with 'all used features should
be allowed'. Download a pinned binaryen version_123 release (matches the local
dev toolchain) and prepend it to PATH. Verified locally: the full
check-wasm-bundle.sh pipeline passes with binaryen 123 against a fresh
rustc-1.94 wasm build.
2026-07-02 02:05:42 +08:00
Kayshen-X 09f2f55f6b fix(ci): rustfmt, clippy -D warnings, and stale test fixes for green rust-check
The rust-check workflow's cargo fmt --all -- --check failed on 108
line-wrap drifts under the pinned 1.94 rustfmt; running cargo fmt --all
clears them. With fmt fixed, the downstream steps (never reached in CI
before) surfaced accumulated lint + test debt from the recent chat-panel
(#41/#42/#43), agentic-design tool-loop, and multi-chat-tab work:

- clippy -D warnings: question_mark, field_reassign_with_default (test-only,
  false positives on DerefMut writes), dead_code, double_ended_iterator_last,
  doc_overindented_list_items, module_inception, single_match, nonminimal_bool,
  sliced_string_as_bytes — fixed via clippy's own mechanical rewrites or
  narrowly-scoped #[allow] on test items.
- op-editor-ui: the no-model quick-action-card test asserted pre-#43 behavior
  (pills are now clickable regardless of model); re-point it at the Example hit.
- op-host-native (gl-host) + op-host-web (canvaskit) widget_host tests: 10
  stale UI/layout/behavior expectations — footer gained a palette icon
  (attach shifted), quick-action pills are full-width stacked, the speed chip
  opens the Parallel-Agents picker (#32), applying a single-root-frame design
  swaps the empty starter frame (command_root_replace) so the child count is
  unchanged, a CJK prompt wraps to two lines, the toolbar grew under the
  bottom-left chat panel, and the canvas Preview button is behind the
  experimental-features opt-in. All test-only; the two bug-suspect cases (CJK
  selection, design-apply count) were confirmed intended behavior.
- op-host-web canvaskit test helper returned ChatState where the .chat field
  is now ChatSessions (multi-tab); return the container and let DerefMut carry
  callers.

No production behavior changed.
2026-07-02 01:54:05 +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 22da4eed3c chore(repo): retire agent-native; root is now a pure Cargo workspace
- Remove the Zig `agent-native` git submodule (no Rust crate depends on it;
  the built-in agent runtime is the Rust `agent` crate under vendor/agent).
- Make the repo root a pure Cargo workspace: delete root package.json + bun.lock;
  move all web-SDK JS/Bun tooling into packages/ (new packages/package.json
  workspace root, generate-iconify-catalog.mjs, and the oxlint/oxfmt configs).
- Scrub agent-native from all docs and fix README dev commands + prerequisites
  to reflect the Rust product (cargo directly; bun tooling runs from packages/).
- Drop the deleted-root-package.json read from the op-host-web ci_workflow test.
2026-07-01 22:16:04 +08:00
Kayshen-X 77dca8c01b chore: retire TypeScript OpenPencil, delete apps/* + pen-* packages
The product is now Rust (crates/) + the Zig agent runtime
(packages/agent-native) + the wasm-backed web SDK (packages/op-web-sdk*).
Delete the retired TypeScript editor/desktop/CLI (apps/*), the pen-*
packages, and their orphaned TS tooling, Dockerfile, and root tsconfig.

Rust-side hooks into the deleted TS are rehomed so the workspace still
builds, tests, and releases green:
- op-mcp: vendor the 10 element-tool-defs shards it include_str!'d from
  pen-mcp into crates/op-mcp/assets/element-tool-defs/ (git renames), and
  repoint the compile-time includes + the runtime parity test's read_dir.
- op-orchestrator: reword the parity panic that named the retired
  dump-planner-golden.ts generator (goldens stay as frozen baselines).
- CI: drop the TS-derive golden-drift + planner-parity oracle jobs and the
  TS path filters from rust-check.yml; repoint the cargo-bundle icon in
  rust-release.yml to crates/op-host-desktop/assets/icon.png.
- Release (Windows): recover the deleted apps/desktop/build/icon.ico into
  crates/op-host-desktop/assets/icon.ico and repoint the NSIS installer
  (rust-release.yml /DICON_FILE + package-windows.nsi ICON_FILE fallback +
  its example invocation), so the Windows release build still finds it.
- Remove the dead .githooks/post-commit hook — it rebuilt the deleted
  out/mcp-server.cjs via the removed mcp:compile script and only watched
  now-deleted pen-* paths; the Rust MCP is built by cargo.
- Recover apps/web/public/logo-discord.svg to screenshot/ and repoint the
  15 READMEs' logo/link paths.

package.json is now Rust-first (dev/build/test -> cargo + serve-web) and
docs (CLAUDE.md/AGENTS.md/packages+crates CLAUDE.md) describe the Rust
product. The retired TS remains recoverable via git (last tag v0.7.5).

Verified: cargo check --workspace green; cargo test -p op-mcp 353 passed;
cargo test -p op-orchestrator 848 passed; cargo test --workspace --no-run
compiles all targets; rust-release.yml parses and references no deleted
build assets.

Pre-commit fmt hook bypassed: its cargo fmt --check is pre-red from a
repo-wide stable-vs-nightly rustfmt config drift affecting unrelated files;
the .rs files touched here produce no fmt diff.
2026-07-01 21:12:39 +08:00
Kayshen-X a4ee78ba86 fix(ai): chat panel hover/close/send-slot refinements (#41/#42/#43)
- #41: collapse chevron renders through IconButton so it shows the ghost
  button-hover wash instead of only swapping the icon color
- #42: send/stop share one circle slot (toggle in place); footer cluster
  sits snug with no reserved stop gap; hit-test routes streaming->stop else send
- #43: example cards stay clickable without a connected model (clicking one
  fills the input; sending still requires a model)
- tab close glyph shows only while the tab is hovered (inset still reserved
  on the active tab so the title doesn't reflow)
2026-06-25 22:40:48 +08:00
Kayshen-X d603f2f388 chore: bump jian submodule (node promotion for batch_design) 2026-06-25 00:15:55 +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 541da7bcb7 test: adapt cleanup + chat-session tests to origin's rebase
op-orchestrator:
- import EffectField directly (origin's cleanup.rs no longer re-exports it
  via `use super::*`)
- insert both concurrent-cleanup roots in one InsertSubtree, since origin's
  command_root_replace now replaces an empty root on single-node top-level
  inserts (two sequential empty inserts would collapse to one child)
- defer the bottom-nav upward-shadow assertion pending reconciliation with
  Kayshen's e3ed2f1e "normalize mobile bottom tabs" (top-navbar transparency
  assertion retained)

op-host-desktop:
- import clear_fresh_starter_frame_for_design via `super::launch::` so the
  retained starter-frame tests resolve it after the merge
2026-06-21 23:18:23 +08:00
Fini d353a58450 chore: bump jian submodule (image cover + leaf flex-shrink) 2026-06-21 23:18:22 +08:00
Fini d517c0a2c0 chore(ai): smoke concurrency override + ab-v9 matrix 2026-06-21 23:18:21 +08:00
Fini ea3f94093c fix(editor): desktop chat session + builtin http handling 2026-06-21 23:18:20 +08:00
Fini df57392a1a fix(canvas): avoid double-applying text position in draw_text 2026-06-21 23:18:19 +08:00
Fini f1ceafb06d fix(ai): tighten mobile overflow / jsonl / decomposition skills 2026-06-21 23:18:18 +08:00
Fini 4ac5b5fa69 fix(lint): guard active nav pill against sibling corner-radius flattening
A 100%-rounded active tab nested in a nav pill was flattened to a sharp
square by the sibling corner-radius consistency detectors. Skip the fix when
a group's radius is pill-scale (>= 40) so the active pill survives validation.
2026-06-21 23:18:17 +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 c4a9d8b3c6 fix(ai): harden style guide isolation 2026-06-21 22:45:32 +08:00
Kayshen-X 5de9bb9734 fix(ai): improve provider design generation prompts 2026-06-21 22:23:26 +08:00
Kayshen-X 53f0a3121d fix(ai): keep a bare ellipsis when ellipsize space is sub-glyph
ellipsize_to_width returned an empty string when not even one glyph
plus the ellipsis fit, dropping the only usable truncation marker. Keep
the bare `…` (matching the per-module ellipsize helpers) so the
truncation stays visible. Updates the unit test accordingly.
2026-06-21 22:08:52 +08:00
Kayshen-X e3c487bf75 fix(ai): ellipsize the collapsed chat pill title
The collapsed AI-chat pill is a fixed 150px wide, but its title was
drawn untruncated, so a long chat title (e.g. the design prompt)
overflowed past the chevron and the pill's right edge. Ellipsize the
title to the space between the bubble icon and the chevron. Adds a
shared width-aware util::ellipsize_to_width (measure-closure based, so
it stays decoupled from PaintCx) + a unit test. Covers native + web
(shared widget).
2026-06-21 21:56:46 +08:00
Kayshen-X 3e4286c332 fix(ai): improve chat-generated document handling 2026-06-21 21:26:34 +08:00
Kayshen-X 992947539b fix(orchestrator): normalize mobile bottom tabs 2026-06-21 21:23:15 +08:00
Kayshen-X 84a668611f fix(orchestrator): strip misrolled mobile search wrappers 2026-06-21 21:08:00 +08:00
Kayshen-X 4c113b2d4a test(panels): move fill-ref removal test to fills_tests
Keep command_tests.rs under the 800-line file limit by relocating the
remove_selected_fill_clears_the_variable_ref test to fills_tests.rs,
where the other fill mutator tests live.
2026-06-21 19:57:41 +08:00
Kayshen-X 6068a3db72 fix(panels): clear fill variable binding when removing a fill
A fill bound to a colour variable keeps a node->variable entry in
ui.variables.fill_refs. The scene resolver's fill_for lets a registered
fill ref WIN over container.fill, so removing the fill row cleared
container.fill (panel goes empty) but left the dangling fill_ref — the
variable colour kept painting. "Deleted the fill but the colour stays"
on token-based (old .op) designs. remove_selected_fill now drops the
fill_refs entry for the primary fill too. In-memory only; old .op files
load unchanged. Adds a core unit test + 4 host scene-clearing tests
(plain / nested / multi-fill / variable-bound end-to-end).
2026-06-21 19:51:52 +08:00
Kayshen-X c697a3036a fix(orchestrator): strip mobile chrome shells 2026-06-21 19:31:18 +08:00
Kayshen-X 387385fc67 fix(orchestrator): resolve scaffold root after replacement 2026-06-21 19:00:50 +08:00
Kayshen-X 8049cd5144 fix(orchestrator): tighten mobile generation rhythm 2026-06-21 18:47:48 +08:00
Kayshen-X 953749cfee fix(panels): stroke-width seed matches the painted value
Clicking the inline stroke-width input on a node with no stroke seeded
"1" (auto-filling a width the user never typed), and the round() seed
snapped fractional widths like 2.5 to "3". Seed via the same
format_panel_number(snapshot width, 0 when unset) the input paints, so
focusing never changes the displayed value. Fixed on native + web; adds
2 seed regression tests.
2026-06-21 18:26:11 +08:00