FE-522: Add subnet composition support to Petrinaut#8662
Conversation
|
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.
01705ea to
0e89ed3
Compare


🌟 What is the purpose of this PR?
Adds initial subnet composition support to Petrinaut so reusable subnet definitions can be authored in core and instantiated in the editor.
This introduces component instances and wiring declarations for merging a parent-net place with a port place inside a subnet.
🔗 Related links
🔍 What does this change?
Place.isPorttypes to@hashintel/petrinaut-core.targetSubnetIdsupport to net-local mutations so places, transitions, arcs, types, parameters, and equations can be edited inside the active subnet.ActiveNetProviderand active-net-aware editor state, lists, selection cleanup, keyboard shortcuts, commands, and mutations.Hospital Network with Subnetbundled example.ANALYSIS.mddocumenting implementation notes and follow-up questions.Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
🐾 Next steps
🛡 What tests cover this?
❓ How to test this?
Hospital Network with Subnetexample.