Skip to content

feat(canvas): add targeted design revisions - #709

Merged
Neonforge98 merged 11 commits into
developfrom
junyu/canvas-design-revisions
Aug 14, 2026
Merged

feat(canvas): add targeted design revisions#709
Neonforge98 merged 11 commits into
developfrom
junyu/canvas-design-revisions

Conversation

@beruro

@beruro beruro commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Problem

Canvas follow-up edits currently require the agent to regenerate and resend the full Canvas source before useful progress appears. Even small copy changes can therefore take minutes, the UI does not preserve a clear logical relationship between the original Canvas and its revision, and narrow chat rows can overflow while revision activity is rendered.

Solution

Add a complete targeted Canvas revision lifecycle:

  • select an element or region in the existing Canvas and submit bounded context through the shared compact InputArea;
  • register revise_inline_canvas with a required same-session target_event_id;
  • prefer bounded exact edits for localized changes while retaining complete replacement payloads for structural changes;
  • keep immutable tool events authoritative and project the latest valid materialized version into one logical Canvas;
  • coalesce receiving/applying progress to at most 20 Hz while retaining the last valid Canvas;
  • persist 1–6 request-specific agent steps and derive completion/failure from the real tool lifecycle;
  • clear transient revision state on completion, failure, cancellation, reset, and session deletion;
  • reuse shared event headers, pills, composer shells, replay navigation, and contained/truncated narrow-row presentation.

The latest develop conflict resolution preserves the current always-available mode control in the normal composer while hiding mode/model controls only in the contextual compact Canvas composer.

Potential risks

This spans the Rust tool contract, persisted event projection, streaming state, DOM selection, and shared composer presentation. Revision ancestry is bounded to 32 events; malformed or stale patches retain the last valid Canvas rather than applying partial content. Agent-step metadata is bounded to six labels of 80 characters; malformed metadata is rejected for new calls and omitted defensively for legacy replay. No schema migration or persistence-format rewrite is introduced, so rollback is a normal revert of the three feature commits.

The remaining review gap is rendered desktop verification: the isolated browser cannot initialize the required Tauri sidecar, so a current Tauri recording covering selection, compact submission, streaming progress, completion navigation, failure, and cancellation is still required. That rendered desktop recording remains a manual review follow-up; the PR is Ready with automated checks complete.

Audit

  • Architecture: covered compilation, call chain, naming, ownership, default branches, domain boundaries, serialization, registration parity, and target-resolution symmetry. Persisted tool events remain authoritative; the Jotai draft is transient progress only.
  • Frontend UI: the checked-in reports cover the contextual composer, revision activity, and progress presentation. Shared controls and event primitives are retained rather than duplicated.
  • Lifecycle/performance: no polling or persistent per-token write was added. A single trailing timer per store coalesces updates at 50 ms; terminal, reset, and session-deletion paths evict transient state.
  • Effects: one retained Canvas inspector Effect synchronizes DOM listeners, ResizeObserver, and requestAnimationFrame; cleanup removes listeners, disconnects the observer, and cancels the frame.

Verification

Completed on the published head 4ea58aa0e, rebased onto develop at 9a2d6f6cf:

  • test_files=(${(f)"$(git diff --name-only origin/develop...HEAD | rg '(test|spec)\\.(ts|tsx)$')"}); PATH=../../../node_modules/.bin:$PATH vitest run "${test_files[@]}" — passed, 24 files / 117 tests.
  • cargo test -p core_types tool_names --lib — passed, 2/2 tests.
  • cargo test -p agent_core ui_metadata --lib — passed, 13/13 tests.
  • PATH=../../../node_modules/.bin:$PATH tsc --noEmit — passed after the current-base rebase.
  • git diff --check and conflict-marker scan — passed.
  • Final diff inspection — 81 files, all mapping to the Canvas revision lifecycle, its direct tests, localization, and required audit reports; no secrets, personal paths, build artifacts, or debug output found.

Additional current-head verification:

  • GitHub CI run 31463061048 passed frontend typecheck, lint, all unit tests, Rust Clippy, and the attribution check on head 4a353877a.
  • Merge-conflict verification passed: ESLint and Prettier on the resolved composer files, 6 focused test files / 24 tests, full pnpm typecheck, git diff --check, and a conflict-marker scan.

Not completed:

  • Current rendered Tauri recording, for the sidecar limitation described above.

@beruro
beruro marked this pull request as ready for review August 6, 2026 10:40
@beruro
beruro marked this pull request as draft August 10, 2026 03:35
@beruro
beruro force-pushed the junyu/canvas-design-revisions branch from 232ff9c to 74805f7 Compare August 10, 2026 04:30
@beruro
beruro force-pushed the junyu/canvas-design-revisions branch from 74805f7 to 4ea58aa Compare August 10, 2026 05:24
@beruro
beruro marked this pull request as ready for review August 11, 2026 05:16
Neonforge98 and others added 8 commits August 11, 2026 13:38
Also aligns revise in the derived preview and serializes revise
execution.

- load_session_pinned_artifact_events merges canvas tool events into the
  initial turn window so a canvas created in an unloaded turn still
  projects after restart (root cause of canvas vanishing on reload)
- latest_canvas_preview recognizes revise_inline_canvas via tool_names
  constants
- revise is no longer concurrency-safe (TOCTOU with fire-and-forget event
  persistence); DB validation moved off the async executor and the
  target row double-fetch consolidated
- canvas acceptance text now carries event_id for follow-up revisions;
  sde.md documents mode requiredness
- depth vs cycle errors split with actionable remedy; revise gets its own
  chat-row label keys; shared tool_call_event_id helper
Composer expansion when maximized; inspector fixes. 709-scoped subset:
share-feature material from the source commit is excluded because this
branch has no CanvasShare.

- ReactArtifactRunner probes CSP eval support, renders a localized notice
  instead of a silent blank card, and surfaces live errors via a visible
  banner (LiveError onChange never fires in react-live v4)
- maximized default composer can expand on multiline again
- edits-only revisions materialize against the previous payload before
  writing canvasPreviewAtom; never overwrite with contentless payloads
- revision progress header subscribes to a boolean, not the 20 Hz draft
- diff view capped and rewritten with rolling-row LCS; semantic tokens
- inspector: geometry-only refresh on scroll/hover, scoped Escape,
  hover cleared on empty target; draft cleanup keyed by explicit session
- delta metadata parsed once per coalescer flush; aria announces phases
  only; DOM selection preview framed and localized
Restore manage-issues keys.

- restore chat.panels.manageIssues.closeAsCompleted/closeAsNotPlanned/
  statusUpdateFailed (en/zh/zh-Hant) deleted while still referenced
- register reviseInlineCanvas tool labels in all 13 locales
- register canvasApp design/compare/revision keys and the domSelection
  section (en/zh/zh-Hant); pluralize revisionTargetedSummary
- 709-scoped subset: share keys (768) and canvas arg hint / New Canvas
  action (767) are excluded
Resolves CanvasApp.tsx Design/Share union: the share availability gate
now counts an in-flight revision (revisionActive) as streaming, per the
canvas-share protocol doc. Locale canvasApp sections merged as union.
@Neonforge98
Neonforge98 merged commit e6353af into develop Aug 14, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants