Implement Flows as first-class entities and same-Canvas baseline routing (Slices 1–2)#43
Conversation
- Implement FlowRoute schema, routeFlow/unrouteFlow service ops, and getRoutedFlowIdsForEdge query for same-Canvas flow-to-connection binding - Add getCanvas.edgeFlows aggregation (total/routed/unrouted/orphan counts per edge) and surface via routed-count pill on Connection body - Wire "+ flow" popover on selected Connection to list and route unrouted Flows from either endpoint - Extend deleteEdge to mint deletionId and cascade-sweep incident FlowRoutes; add restoreEdge symmetry for batch undo - Extend deleteNode cascade to pre-check idx_flow_route_dedup before restore - Update CONTEXT.md Flow/FlowRoute/getCanvas/Deletion id entries; amend ADR-0008 for deleteEdge cascade; ship Slice 2 in flow-routed-connections plan
…ature/feat/flows-first-class
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (14)
📝 WalkthroughWalkthroughThis PR implements Slice 2 of flow-routed-connections, adding the ability to route Flow objects onto Connections (Edges) and displaying routed-flow counts plus an affordance to assign more flows. It introduces a FlowRoute schema, routing service operations, cascading soft-delete/restoration mechanics that thread FlowRoute rows through the deletion undo model, a canvas aggregation layer computing per-edge flow counts, and frontend UI components (routed pill, "+ flow" popover) with optimistic updates. Flow-Routed Connections Slice 2
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/p/`[slug]/_canvas/canvas.tsx:
- Around line 817-899: The rollback currently replaces the whole edgeFlows entry
with prevEdgeFlows in commitRouteFlow and commitUnrouteFlow, which can clobber
overlapping optimistic updates; instead compute and store the exact optimistic
delta you applied (e.g. for commitRouteFlow: routed +=1, unrouted -=1; for
commitUnrouteFlow: routed -=1, unrouted +=1) when calling patchCanvas and on
failure apply an inverse delta patch that adjusts only the numeric fields (using
Math.max(0, ...)) rather than restoring prevEdgeFlows wholesale; additionally,
when applying the inverse delta, reconcile by checking current values (from
utils.architecture.getCanvas.getData(canvasInput) or the patch callback’s
current state) to ensure you only revert if the current counts still include
your optimistic change so you don’t overwrite newer successful updates.
- Line 1013: Update the Tailwind v3-style important modifiers used in the Canvas
panel's className by converting the prefixed form "!top-0 !right-0 !bottom-0
!m-0 flex" to the Tailwind v4 suffix form "top-0! right-0! bottom-0! m-0! flex";
locate the JSX element that contains the className string (search for the exact
"!top-0 !right-0 !bottom-0 !m-0 flex" text) and replace each prefixed utility
with the corresponding trailing-! variant so Tailwind v4 applies the important
flag correctly.
In `@src/app/p/`[slug]/_canvas/connection-edge.tsx:
- Around line 147-153: The "+ flow" button is currently shown whenever canEdit
and hasUnrouted are true, but it must only appear for the currently selected
edge; update the showFlowButton computation to also require the edge selection
check used elsewhere (e.g., ensure selectedEdgeId === d.id or d.isSelected) so
the control appears only on the selected edge; apply the same selection gating
to the identical logic region around the 245-265 block so both places use the
selection-aware condition (referencing flows, hasUnrouted, showFlowButton and
the file's selection identifier).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 68e76734-9a79-4782-9b40-6820c2d22bb7
📒 Files selected for processing (18)
CONTEXT.mddocs/adr/0008-cascading-soft-delete-stamped-batch.mddocs/plans/flow-routed-connections.mdprisma/migrations/20260530004633_add_flow_route/migration.sqlprisma/schema.prismasrc/app/p/[slug]/_canvas/canvas.tsxsrc/app/p/[slug]/_canvas/connection-edge.tsxsrc/app/p/[slug]/_canvas/route-flow-popover.tsxsrc/lib/schemas.tssrc/server/api/routers/architecture.tssrc/server/architecture/__tests__/edge.service.test.tssrc/server/architecture/__tests__/flow-route.service.test.tssrc/server/architecture/__tests__/helpers/test-db.tssrc/server/architecture/edge.service.tssrc/server/architecture/errors.tssrc/server/architecture/flow-route.service.tssrc/server/architecture/node.service.tssrc/server/architecture/prisma-errors.ts
Summary
Ships Slices 1 and 2 of the flow-routed-connections master plan (issue #2), establishing Flows as first-class Component-owned entities and implementing same-Canvas baseline routing via
FlowRoute.kind,key(unique per owner),title,polarity,signature,sourceSpecId(derived vs. user-authored). Individually addressable, soft-deletable, MCP-resolvable.deletionIdper batch; source is UNTRUSTED with bounded loader (1 MB cap, 32 depth, 500 ops).(outerEdgeId, flowId)de-dupe via partial unique index; service-enforcedtouches-endpointinvariant (Flow owner is an endpoint of the outer Edge).attachFlowSpec,addFlow,updateFlow,deleteFlow,routeFlow,unrouteFlow;deleteNodecascade extended to owned Flows + FlowSpec;deleteEdgemintsdeletionIdwhen sweeping FlowRoutes, symmetrically restored by newrestoreEdge.edgeFlowsaggregation per interior Edge:{ edgeId, total, routed, unrouted, orphan, byKind }powering the pills and popover.Testing
flow.service.test.ts(528 lines):attachFlowSpec(with OpenAPI parse + non-destructive re-parse),addFlow,updateFlow,deleteFlow, cascade arms indeleteNode, concurrency regression foridx_flow_deduppartial unique indexflow-parser.test.ts(207 lines): OpenAPI walker, operation extraction, error handling (OOM, depth/size caps, malformed specs)flow-route.service.test.ts(573 lines):routeFlow,unrouteFlow, polarity-vs-endpoint validation (touched endpoint only), orphan handling,deleteEdgecascade withrestoreEdgesymmetry, concurrency regression foridx_flow_route_dedupnode.service.test.tsexpanded: Flow + FlowRoute sweep indeleteNodecascade, pre-checks inrestoreNodefor dedup collisionssourceSpecId IS NULL)ConflictError(named pattern per ADR-0010)restoreNode/restoreEdge) restores exact deletion set keyed bydeletionIdNotes
routeFlowto an inner Edge is authorized only by that inner Canvas owner (ADR-0012 forthcoming).Summary by CodeRabbit
New Features
Documentation