Improve agent recovery, integrations, and visual editing - #2498
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Builder reviewed your changes and found 3 potential issues 🔴
Review Details
Code Review Summary
This large PR strengthens agent run recovery and terminal telemetry, adds workspace URL/org and MCP integration behavior, improves analytics reliability, and substantially expands Design visual-editing access and interaction flows. The overall direction is thoughtful: terminal-state ordering is covered by focused tests, migrations are additive, and the new request-context/loopback plumbing is explicit. I classified this as High risk because the change introduces session handoff and access-control behavior around a local visual editor.
Key Findings
- 🔴 HIGH — A visual-edit action returns a normal bearer session token in a URL that can be retained or exposed through agent/tool transcripts.
- 🔴 HIGH — Server-side loopback peer detection can treat remote tunnel visitors as local editors and expose write-capable preview access.
- 🟡 MEDIUM — Terminal telemetry may be emitted even when terminal status persistence and reconciliation both fail, producing an analytics event that claims a durable terminal state that is not actually stored.
The recovery and telemetry changes otherwise show good attention to ordering, failure isolation, and test coverage. 🧪 Browser testing: Will run after this review (PR touches UI code)
…rtRun options The bridge guard requires each *.bridge.ts to have a committed .generated counterpart; source-location.bridge.ts was missing one. .generated is gitignored but its bridge artifacts are force-added by convention. webhook-handler builds runOptions once and deliberately mutates it after handing it to startRun (model/engineName are filled in inside the run callback so run-manager's terminal event can read them in .finally()), and it carries attemptCount from construction. The exact-object assertions were the stale side; these two tests are about which soft-timeout ceiling is chosen, so they now pin those fields via objectContaining.
|
Here's a visual recap of what changed: Open the full interactive recap
|
There was a problem hiding this comment.
Builder reviewed your changes and found 1 potential issue 🟡
Review Details
Code Review Summary
PR #2498 is a large cross-cutting update covering Design visual editing, agent continuation/recovery, workspace routing, MCP/data-source integrations, and terminal observability. The approach is generally sound: the new recovery state is explicit about transient continuation budgets, organization URLs are normalized before comparison, provider connection failures preserve an unknown state rather than falsely reporting disconnection, and the localhost visual-edit authorization now combines loopback origin with localhost source. I also verified that the previously reported loopback authorization issue and terminal telemetry ordering issue are fixed and resolved those stale threads; the bearer session token embedded in the visual-edit action link remains the existing open issue and was not reposted.
Key Findings
🟡 MEDIUM — The cookie-preserving _session redirect does not preserve the staged Referrer-Policy: no-referrer header, allowing the live session token in the source URL to be exposed as a referrer to the destination document/server.
The PR is high risk because it changes authentication/session handling and security-sensitive visual-edit access. Apart from the finding above, the reviewed changes show good attention to failure-state honesty, scoped access, and persistence ordering.
🧪 Browser testing: Will run after this review (PR touches UI code)
…ource anchors, board drop - resolveServerFiles: design?.files ?? EMPTY constant, killing the render loop that fired 1000+/min (setPendingNodeRewriteProposals([]) re-entering on a fresh [] identity while the design query was still pending) - layer lock/hide now reach the live frame via the layer-states message - delete resolves live selectors for in-canvas selections - React source anchors read _debugSource (<=18) and _debugStack (19) plus owner/ownerKey to disambiguate .map() siblings - board primitive -> live screen structural insert path
… and render-loop fix
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Builder reviewed your changes and found 1 potential issue 🟡
Review Details
Code Review Summary
This increment expands PR #2498 with additional Design live-layer operations, deletion handling, render-loop stabilization, and continued recovery/integration work. The broader approach remains well structured: live snapshots now use real history entries, empty design-file identity is stabilized, and the new layer-state paths distinguish preview-only handoffs from unresolved runtime anchors.
Key Findings
🟡 MEDIUM — Breakpoint-scoped deletion still structurally removes the selected node from the live iframe. The persisted snapshot receives a breakpoint-scoped display: none patch, but the live-preview path calls deleteFromLiveDom, so the node disappears at all breakpoints until the iframe is reloaded or fully synchronized.
I verified that the previously reported bearer-token and no-referrer findings remain present and left both existing comments untouched. The previously reported loopback authorization concern was also not reposted because it is the same issue at the same location rather than a distinct regression. The MCP scope concern was not included because the dialog resets scope when its validated default changes, so the reported stale-state scenario was not confirmed.
The PR remains high risk because it includes authentication/session handling and security-sensitive visual-edit access. Browser testing is planned for the affected Design flows.
🧪 Browser testing: Will run after this review (PR touches UI code)
…e delete, label anchor precision - appendCanvasPrimitiveToHtml/insertClonedHtmlLayers fail closed on URL-shaped content: a localhost screen's file.content IS its route URL, and parsing it as HTML replaced the route with a static document, silently destroying the screen's live binding. Draw/paste/duplicate/image-drop now refuse loudly and name the working path instead. - locked layers paint a neutral dashed outline via the same layer-states message that already carried hidden, so lock is no longer invisible - delete records a pending live edit and accepts layers-panel selections - React source anchors carry their provenance: a React 19 _debugStack position is a transformed line, not an authored one, and no longer claims otherwise
… complete insert lifecycle - replacePreviewContent and handleDesignStateSelect refuse when the content is a standalone http URL: a localhost screen's file.content IS its route URL, and pushing it as document content silently replaced the running app with that text in single view (survived hard refresh, layers went empty, no error) - Edit/Annotate chosen from a focused screen now return to the canvas instead of stranding a single-screen Edit state; toolbar hidden while Interact is active - insert lifecycle: Apply preflight exempts inserts (no subject anchor by definition), redo reissues runtime-structure-insert rather than a move that cannot find its subject, and delete cancels the matching pending insertion - owner source provenance threaded through to the agent handoff; execution-mode routing narrowed to the board->live-screen case
…d writes - postOneShotBridgeMessage returned true while silently queueing forever: a live-edit screen keeps its iframe across a canvas remount, so the replacement DesignCanvas never saw editor-chrome-ready and recovery was passive. It now actively pokes the frame so the queue drains. A call that reports success and delivers nothing is the failure shape this repo's rules single out. - commitVisualStyles owns the localhost branch: push to the live DOM, then queue a pending edit. Inspector style commits previously updated only the snapshot and undo stacks, which is why the value appeared solely on redo. - handleCreatePrimitive stamps baseUpdatedAt on the optimistic write; without it the pending overlay retired on content equality and an in-flight get-design reverted the board, so a drawn primitive vanished until reload.
…producers A localhost screen's file.content IS its route URL. Four separate gestures have now each found a way to concatenate HTML onto it, permanently destroying the live binding — the last one survived a full reload and was masked on a React target by Vite's SPA fallback. Point-guards were added reactively three times; this closes it at the shared write boundary instead. moveNodeBetweenDocuments and applyVisualEdit both refuse when the base content is URL-shaped, and the persist gate reports a typed url-backed-screen-replaced issue. applyVisualEdit was the remaining hole: ~40 call sites pass file.content in raw, including the agent-callable apply-visual-edit/apply-shader-fill/ apply-a11y-fix actions. Re-pointing the URL itself still succeeds — the guard is one-way, not a freeze.
A localhost screen runs two disjoint node-id namespaces: the injected bridge stamps runtime-<hash> on the live document, while the host stamps an-<hash> on an independently-fetched source projection. The forward style push already sent runtimeSourceId, but the recorded pending edit kept only the projection pair, so every undo/redo replay addressed nodes that do not exist in the running document and silently no-opped while the queue still popped. pending-edits now carries runtimeSelector/runtimeSourceId and resolves them through one runtimeStyleTarget helper, runtime-first with the canonical pair as fallback, so inline screens are byte-identical. DesignCanvas's redo/repaint replay uses the same helper. Also refuses a patch with no resolvable candidates: findRuntimeTarget returns the current selection when the candidate list is empty, so an unaddressable revert was restyling whatever happened to be selected.
Completes the live-namespace fix. recordPendingVisualStyleEdit stored only the source-projection pair, so undo/redo replays addressed nodes that do not exist in the running document; the redo branch builds its patch inline and needed the pair explicitly too. Both now carry runtimeSelector/runtimeSourceId, which runtimeStyleTarget prefers when resolving against the live frame.
setProperty(prop, "") already removes the declaration per CSSOM, so the removeProperty branch was equivalent and its comment claimed the opposite. Verified in Chrome: clearing border-top-left-radius on an element with inline border-radius:44px falls back to the stylesheet's 12px.
This comment has been minimized.
This comment has been minimized.
A queued one-shot command reports success, so the single fire-and-forget readiness probe had to land. A frame mid-navigation drops it and an idle frame never speaks again, stranding the queue permanently — undo of a live style edit ran, reported sent, and never reached the running app.


Summary
Current status
This is the initial visibility PR Steve requested while the visual-edit completion workflow continues. Follow-up commits are expected for the remaining Design E2E gaps before final shipping and merge.
The current Design snapshot has 3,544 tests passing and a clean TypeScript check from the active workflow. GitHub Actions is the authoritative validation for the combined branch.