Add kind palette with affinity ranking and post-create kind editing#49
Conversation
Expands NodeKind from 6 to 26 values covering the global-infra → code hierarchy, replaces the <select> with a shadcn/cmdk Command palette, and introduces kind affinity — a parent-kind → suggested-children ranking keyed by the current Canvas scope (read off the breadcrumb, which now carries kind). Components can be re-kinded after creation via a narrow updateNodeKind mutation surfaced as a Kind row in the detail panel that reopens the same palette. Kind stays cosmetic per ADR-0018; affinity is ranking, never constraint, per ADR-0019. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (20)
📝 WalkthroughWalkthroughThis PR expands the NodeKind taxonomy from 6 to 26 hierarchical values (infrastructure, networking, runtime, software, data, interfaces, messaging), implements kind-affinity-based ranking for a new ChangesNodeKind Taxonomy & Kind-Affinity System
Sequence Diagram(s)sequenceDiagram
participant User
participant Canvas as CanvasInner
participant AddComponent as AddComponent/Detail
participant KindPickerPopover
participant commitNodeKind as optimistic update
participant updateNodeKind as TRPC mutation
participant Server as node.service
User->>Canvas: load canvas
Canvas->>Server: getCanvas()
Server-->>Canvas: breadcrumbs[{id, title, kind}]
Canvas->>Canvas: parentKind = breadcrumbs[-1]?.kind
User->>AddComponent: click + or select component
AddComponent->>KindPickerPopover: render with parentKind
KindPickerPopover->>KindPickerPopover: suggestedKinds(parentKind)
User->>KindPickerPopover: select kind
KindPickerPopover->>Canvas: onSelect(kind)
Canvas->>commitNodeKind: onChangeKind(nodeId, kind)
commitNodeKind->>Canvas: optimistic: update node.kind + cache
commitNodeKind->>updateNodeKind: call mutation
updateNodeKind->>Server: updateNodeKind(id, kind)
Server->>Server: assertCanWrite(owner)
Server->>Server: UPDATE Node.kind
Server-->>updateNodeKind: success
updateNodeKind-->>Canvas: confirm (cache already updated)
alt mutation fails
updateNodeKind->>Canvas: rollback if cache still matches optimistic
Canvas->>Canvas: restore prior kind
Canvas->>User: show toast error
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes The PR spans 23 files with mixed complexity: documentation and schema updates are straightforward, but the integration of kind picker, affinity ranking, breadcrumb wiring, and optimistic mutation handling requires careful review of consistency across client/server and round-trip behavior. The comprehensive test suite mitigates some risk by covering persistence, authorization, and cosmetic-only semantics. 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 |
Summary
NodeKindfrom 6 → 26 values covering the full hierarchy story: global infrastructure → datacenters → networks → hosts → containers → services/microservices/crons → applications/modules → classes/functions → variables/branches, plus data (TABLE, STORED_PROCEDURE), interface (ENDPOINT, WEBHOOK), and messaging (TOPIC, CONSUMER, PRODUCER) kinds. Kind stays cosmetic (ADR-0018).cmdkCommand popover replacing the<select>. Search + keyboard nav + icons; organized into a "Suggested for inside ⟨parent⟩" group above a separator and "All kinds" (alphabetic) below, so every kind is always reachable.Record<NodeKind | "ROOT", readonly NodeKind[]>map that ranks the palette by the current Canvas scope's parent kind. InsideDATABASE→TABLE/STORED_PROCEDURE; insideHOST→CONTAINER/SERVICE/MICROSERVICE/CRON; at the project root → infrastructure-flavored kinds. Affinity is ranking, never constraint (ADR-0019) — the service accepts any kind regardless of parent.updateNodeKindmutation, surfaced as a Kind row in the Component-detail panel that reopens the same palette (single kind-selection surface).getCanvasbreadcrumbs now carrykind— one-column widening of the recursive CTE (no extra round trip per ADR-0001/0006); the picker readsbreadcrumbs.at(-1)?.kind ?? null.Record<NodeKind, …>forKIND_LABEL,KIND_ICON,KIND_AFFINITY, and the server-side serializer label map. A new kind cannot ship without label + icon + affinity row.New files
src/lib/node-kinds.ts—KIND_LABEL,KIND_ICON,KIND_ORDER,KIND_AFFINITY,suggestedKinds()src/components/ui/command.tsx— Tailwind wrapper overcmdk(no full shadcn install)src/app/p/[slug]/_canvas/kind-palette.tsx—KindPalette+ reusableKindPickerPopoverprisma/migrations/20260531181535_expand_node_kind_taxonomy/migration.sqldocs/adr/0018-nodekind-expanded-taxonomy-stays-cosmetic.mddocs/adr/0019-kind-affinity-is-ranking-not-constraint.mdDocs
assertKindAllowedUnder, server-derived suggestions) recorded with rationale.Test plan
pnpm check— clean (lint + typecheck)pnpm test— 210/210 pass, including:kindordered root→currentgetCanvasupdateNodeKindhappy path, off-parent-affinity accepted, no Edge/Flow cascade, authz, not-found, soft-deleted, Zod rejectionpnpm build— clean (no client/server bundle leak;cmdkand the catalog bundle into the SSR-disabled island)pnpm db:migrate+pnpm db:check— no driftGlobal infrastructure, Data center, Region, Network, Host, External APIfirstDATACENTER→ palette ranksHost, Network, Database, QueuefirstHOST→ ranksContainer, Service, Microservice, CronfirstRefs
feature/kind-palette-affinitybranch (slices 1 + 2 of the kind-palette work bundled here)🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Documentation