Conversation
Introduces the Subnet type (isolated sub-networks within a net) across the core types, file format, import/export, mutation layer, and UI. Adds a "Nets" subview to the left sidebar listing the root net and subnets, with a button to create new subnets. Includes a Hospital Network example demonstrating the feature. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces ActiveNetContext to decouple "which net is being viewed" from the full SDCPN. Display consumers (canvas, sidebar lists, properties panel, diagnostics) read from ActiveNetContext while export/simulation/LSP keep reading the full SDCPN. Mutations route through resolveNet() so edits target the active subnet. Adds "add-component" edition mode with componentSubnetId in EditorContext, a Component dropdown in the BottomBar toolbar (root net only), and a cursor-following tooltip showing what will be created on click. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lace Introduces the ComponentInstance entity: a subnet instantiation with parameter values, wiring (place-to-port connections), and canvas positioning. Places gain an `isPort` flag to mark them as ports exposed on component instances. Rendering: sharp-cornered rectangle node with port handles derived from the subnet's port places. Wiring rendered as a dedicated "wire" edge type (dashed, bezier) distinct from arcs. Edges array replaces the former arcs-only array to hold both arc and wire edge types. Mutations: addComponentInstance, updateComponentInstance, removeComponentInstance, plus deleteItemsByIds and commitNodePositions support. Hospital Network example updated with an ER Triage component instance wired to the root net. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Render a properties panel when a component instance node is selected, showing instance details and parameter overrides for the underlying subnet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
PR SummaryMedium Risk Overview Introduces an Adds UI for managing/viewing nets (new Reviewed by Cursor Bugbot for commit 01705ea. Bugbot is set up for automated code reviews on this repo. Configure here. |
🤖 Augment PR SummarySummary: This draft PR explores “subnets” and component-based composition in Petrinaut by introducing a notion of an “active net” (root vs selected subnet) and rendering subnet instances as nodes with wiring. Changes:
Technical Notes: Graph layout and selection cleanup now operate on the active net; 🤖 Was this summary useful? React with 👍 or 👎 |
| @@ -75,12 +89,13 @@ export const MutationProvider: React.FC<MutationProviderProps> = ({ | |||
| }, | |||
| removePlace(placeId) { | |||
There was a problem hiding this comment.
libs/@hashintel/petrinaut/src/state/mutation-provider.tsx:L90 — When a place is removed from a net, any componentInstances[].wiring entries that reference it (as externalPlaceId, or indirectly via a port ID) aren’t cleaned up, which can leave dangling wire edges/handles in the ReactFlow view. This same issue can also occur when places are deleted via deleteItemsByIds (wires aren’t considered there either).
Severity: medium
Other Locations
libs/@hashintel/petrinaut/src/state/mutation-provider.tsx:403
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| sdcpn.subnets = subnets; | ||
| }); | ||
| }, | ||
| removeSubnet(subnetId) { |
There was a problem hiding this comment.
libs/@hashintel/petrinaut/src/state/mutation-provider.tsx:L389 — removeSubnet removes the subnet definition but doesn’t address any componentInstances (in the root net or other nets) that reference that subnetId, which can leave instances/wires pointing at non-existent ports. Consider either preventing subnet deletion while referenced or cleaning up dependent instances/wiring to avoid inconsistent state.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| ); | ||
| const rafRef = useRef(0); | ||
|
|
||
| useEffect(() => { |
There was a problem hiding this comment.
libs/@hashintel/petrinaut/src/views/SDCPN/components/cursor-tooltip.tsx:L40 — This useEffect attaches a global mousemove listener and calls setPosition(...) on every mouse move even when not in an add mode (when the tooltip returns null). That can cause unnecessary re-renders across long sessions; consider only subscribing/updating while label is non-null (i.e., when the tooltip would actually render).
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| }; | ||
| }; | ||
|
|
||
| /** |
There was a problem hiding this comment.
libs/@hashintel/petrinaut/src/core/types/sdcpn.ts:L117 — The JSDoc for “An instance of a subnet…” currently sits above Wire, so it looks like it’s documenting the wrong type (and the Wire docblock follows immediately after). Consider moving that first docblock onto ComponentInstance to avoid misleading generated docs/tooltips.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 01705ea. Configure here.
| type === "place" || | ||
| type === "transition" || | ||
| type === "componentInstance" | ||
| ) { |
There was a problem hiding this comment.
Component instances treated as non-canvas items in selection
Medium Severity
The hasNonCanvasItems check (around line 86) only considers place, transition, and arc as canvas item types. Since this PR adds componentInstance as a new canvas node type, any selected component instance is incorrectly treated as a "non-canvas" item. This causes the selection base to be cleared when a component instance is in the selection and the user interacts with canvas selection, breaking multi-select behavior for component instances.
Reviewed by Cursor Bugbot for commit 01705ea. Configure here.
| }, | ||
| commitNodePositions(commits) { | ||
| guardedMutate((sdcpn) => { | ||
| const net = resolveNet(sdcpn); |
There was a problem hiding this comment.
Paste always targets root net, ignoring active subnet
Medium Severity
pasteEntities calls pasteFromClipboard(mutatePetriNetDefinition) which directly mutates the root SDCPN's places, transitions, etc. arrays. Unlike all other mutation functions in this provider, it does not use resolveNet to target the active net. When a user is viewing a subnet and pastes, entities are incorrectly added to the root net instead of the active subnet.
Reviewed by Cursor Bugbot for commit 01705ea. Configure here.
| break; | ||
| } | ||
| } | ||
| }); |
There was a problem hiding this comment.
Removing subnet leaves dangling component instance references
Medium Severity
removeSubnet splices the subnet from the array but does not clean up componentInstances in the root net (or other subnets) whose subnetId references the deleted subnet. Other removal functions like removeType and removeDifferentialEquation follow a pattern of clearing dangling references, but removeSubnet does not, leaving orphaned component instances pointing to a non-existent subnet.
Reviewed by Cursor Bugbot for commit 01705ea. Configure here.


This is a draft PR, just as an exploration for what subnets and composition should be in Petrinaut.
But the actual implementation will be done after Petrinaut Core Library Extraction (FE-628).