integration: builder hardening P0 + canvas decomposition (train) - #39
Conversation
Return 410 Gone so UI relies on client HistoryManager only and empty server Maps cannot lie about canUndo.
Prefer workflow_versions with RLS UPDATE/DELETE; keep in-memory Map only as non-prod fallback when Supabase is unavailable.
Coerce startedAt/completedAt before duration math so JSON-serialized runs no longer throw on .getTime().
Expose connectionIdsTouchingNode so canvas highlight can animate edges on the active run path.
Replace nested h-screen with dvh shell offset so mobile header and sidebar no longer clip the builder.
Use client HistoryManager for undo/redo and canUndo flags, implement version restore via PATCH, select all nodes/edges, highlight running edges, and fix toolbar GlassContainer inner layout.
Add HistoryManager unit tests and canvas coverage for client undo/redo, version restore, and empty-stack toolbar state; shim ResizeObserver in test setup.
Roll back HistoryManager stacks and skip SWR mutate when persist fails, matching restore so Sprint 3 builder demos cannot lie about canUndo.
Split builder-canvas into focused hooks and subscribe HistoryManager via useSyncExternalStore so ASAP sprints can extend the shell without growing the monolith past 800 lines.
Prevent silent in-memory workflow_versions fallback on serverless deploys so marketplace/restore demos cannot lie about persistence.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Avoid assigning to read-only process.env.NODE_ENV so tsc --noEmit passes in CI.
There was a problem hiding this comment.
Summary
Solid Sprint 0 / 0.5 builder hardening: client HistoryManager as the undo/redo source of truth (server routes → 410), Supabase-backed workflow_versions with a production fail-loud guard, canvas decomposition into focused hooks, and meaningful unit/component coverage. Quality is high for a train PR, but CI is currently red and a few correctness gaps undercut the claimed atomic history / honest persistence contracts.
Must Fix
- CI typecheck failure —
tests/lib/version-store.test.tsassignsprocess.env.NODE_ENV, which is readonly under current typings (TS2540). Confirmed incheckrun 30319394919. Usevi.stubEnv("NODE_ENV", "production")(and restore) instead. - Concurrent undo/redo can corrupt stacks and persist the wrong graph —
use-builder-history.tsmutates stacks before PATCH completes, with no in-flight lock. Rapid ⌘Z uses the same stale SWRworkflow, duplicates redo entries, and out-of-order responses can win. Serialize transitions (or ignore overlapping calls) and add a race test. - Version tag/delete can report success with zero rows changed —
tagVersion/deleteVersionreturn!error. Under RLS, a viewer (or a concurrently deleted row) often gets no PostgREST error and zero affected rows, so the API can return200 { success: true }without mutating. Prefer.select(...).maybeSingle()/ affected-row checks and map denial to 403/404.
Should Fix
getVersionmasks DB failures as 404 —if (error || !data) return undefinedturns outages / schema errors into "Version not found". Distinguish no-row from real errors (asgetVersionsFromDbalready does).- Graph mutations still push history before persist — In
use-builder-graph-mutations.ts, most handlers callsaveToHistory()then ignoreresponse.ok(and still toast success / revalidate). Failed edits leave ghost undo entries and clear redo. Align with the atomic undo/redo pattern: commit history only after success, or roll back the snapshot. - Select-all is incomplete — ⌘A selects all nodes/edges locally, but copy / duplicate / delete still operate on the first
selectedNodeIdonly. Wire multi-selection through clipboard/delete (the copy API already acceptsnodeIds[]). - Loose version path parsing —
Number.parseInt(version, 10)accepts"1junk"/"1.5"as1. Validate with Zod (z.coerce.number().int().positive()or equivalent) on version routes. - Non-atomic version numbering —
createVersiondoes read-max-then-insert; concurrent creates race onUNIQUE(workflow_id, version). Allocate in SQL or retry unique violations.
Nice to Have
- Run edge highlight currently marks every edge touching a node (adjacency), not the traversed path; also, execute currently clears highlight rather than applying the returned run path.
durationMsstill accepts JS-Date-normalized invalid calendars and negative spans.execution-monitor.tsxstill setsexecutionfrom any JSON body withoutresponse.ok(pre-existing; crash risk on{ error }viaexecution.logs.length).- Toolbar zoom
%fromgetViewport()may stay stale; preferuseViewport(). - Route-level workspace binding (
getWorkflow(id, workspace.id)) + editor role checks would harden the in-memory fallback path where RLS does not apply.
Positive Highlights
- Honest client history: server undo/redo/status → 410 removes empty-Map lies about
canUndo. - Production no longer silently falls back to a process-local version Map; RLS UPDATE/DELETE policies for
workflow_versionscorrectly scope to owner/editor via workspace membership. - Canvas split into history / mutations / clipboard / highlight hooks keeps
builder-canvas.tsxunder the ~800-line budget while preserving keyboard flows. - Strong new tests for HistoryManager, failed-PATCH undo rollback, version production guard, duration coercion, and select-all updater behavior.
Early feedback on Sprint 0/0.5 as requested — still expecting S2/S3 on this train. Please clear the Must Fix items (especially the CI break and undo race) before treating this slice as merge-ready.
Sent by Cursor Automation: Adrianno’s personal code review
Serialize undo/redo, fail-loud version writes, atomic graph history, multi-select clipboard, strict version params, and workspace-scoped workflow access so Sprint 0/0.5 review threads can resolve honestly.
Review follow-up (
|


Summary
Integration train PR: Builder Hardening Sprint 0 + 0.5 on
integration/builder-asap-runtime. ASAP Sprint 2 (Playground) and Sprint 3 (marketplace → builder + correlation) will land as further commits on this same PR — do not open separate PRs tomainper sprint.Landed so far
/undo//redo//history/status→ 410 Gone)workflow_versions(fail-loud without Supabase in production)Still on this train (not in tip yet)
correlation_idTest plan
pnpm run check/ project gates)/builder— undo/redo across edits; restore version; ⌘A selects all nodesh-screenclip)/marketplace→/builder?asapAgent=Review notes