FE-614: Support disabling SDCPN extensions#8763
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
PR SummaryMedium Risk Overview A new extensions module centralizes resolution, transition lambda/kernel availability rules, and SDCPN sanitization (strip types, equations, parameters, visualizer code, coerce lambdas/kernels, simplify scenario initial state when colours are off). Mutations and commands no-op or strip data for disabled features; paste and JSON doc LSP receives extension settings, generates virtual files and diagnostics only for active code surfaces. AI prompts and the latest-net tool now document React wires extensions into LSP, experiments, simulation parameter paths, selection typing, and docs. File format defaults optional transition lambda/kernel fields. ReadableStore moves to Reviewed by Cursor Bugbot for commit 51da097. Bugbot is set up for automated code reviews on this repo. Configure here. |
🤖 Augment PR SummarySummary: Adds handle-level capability metadata so Petrinaut can run against “bare” Petri nets (e.g. CatCollab embeds) without exposing HASH SDCPN extensions. Changes:
🤖 Was this summary useful? React with 👍 or 👎 |
7194bc7 to
2cf4bdc
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds handle-level capabilities to let hosts disable SDCPN extensions (colors, stochasticity, dynamics, parameters) and/or force read-only mode, then threads the resolved extension settings through Petrinaut core, React context, runtime providers, and UI so disabled features are hidden and disabled-extension data is sanitized out of edits/pastes.
Changes:
- Introduces capability/extension resolution in
@hashintel/petrinaut-coreand exposesinstance.capabilities+instance.extensions. - Applies extension-aware sanitization in core mutations/commands and updates React/UI surfaces to conditionally hide or coerce extension-dependent controls.
- Adds Storybook coverage, focused unit tests, a changeset, and an analysis doc describing touchpoints/tradeoffs.
Reviewed changes
Copilot reviewed 49 out of 49 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| libs/@hashintel/petrinaut/src/ui/views/SDCPN/hooks/use-sdcpn-to-react-flow.ts | Gates place/arc coloring, dynamics markers, and transition lambda type on extensions. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/simulate-view.stories.tsx | Supplies default extensions in SimulateView story SDCPN context. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/view-scenario-drawer.tsx | Hides parameters/types wiring when parameters/colors are disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/create-scenario-drawer.tsx | Hides parameters/types wiring when parameters/colors are disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/create-scenario-drawer.stories.tsx | Adds default extensions to story context fixture. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/experiments-story-fixtures.tsx | Adds default extensions to experiments story fixture context. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/PropertiesPanel/transition-properties/subviews/transition-firing-time/subview.tsx | Hides stochastic toggle UI when stochasticity disabled; adjusts default template logic. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/PropertiesPanel/transition-properties/main.tsx | Removes transition-results subview when colors disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/PropertiesPanel/properties-panel.stories.tsx | Adds default extensions to properties panel story context. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/PropertiesPanel/place-properties/subviews/main.tsx | Hides token-type + dynamics sections when colors/dynamics disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/PropertiesPanel/place-properties/main.tsx | Removes visualizer subview when colors disabled; avoids resolving place type when colors disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/PropertiesPanel/panel.tsx | Prevents rendering type/equation/parameter property panes when corresponding extensions are disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/subviews/types-list.tsx | Disables type creation/deletion when colors disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/subviews/search-panel.tsx | Filters searchable items by available extensions. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/subviews/parameters-list.tsx | Hides/disables parameter list + add action when parameters disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/subviews/entities-tree.tsx | Removes extension-dependent groups from the entity tree view. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/subviews/differential-equations-list.tsx | Disables equation creation/deletion when colors/dynamics disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/LeftSideBar/panel.tsx | Filters sidebar subviews by enabled extensions (list view). |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/BottomPanel/subviews/simulation-timeline/use-streaming-data.ts | Treats places as untyped and types as unavailable when colors are disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/BottomPanel/subviews/simulation-timeline/header.tsx | Prevents “per-type” timeline mode when colors disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/BottomPanel/subviews/simulation-timeline.tsx | Mirrors timeline gating for colors-disabled mode and avoids using types when disabled. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/BottomPanel/subviews/simulation-settings.tsx | Removes global parameter UI rows when parameters are disabled. |
| libs/@hashintel/petrinaut/src/ui/petrinaut.stories.tsx | Adds a Storybook scenario demonstrating disabled extensions via handle capabilities. |
| libs/@hashintel/petrinaut/src/ui/monaco/code-editor.stories.tsx | Adds default extensions to LSP story context. |
| libs/@hashintel/petrinaut/src/ui/constants/ui-messages.ts | Makes READ_ONLY_MODE message generic to cover more read-only sources. |
| libs/@hashintel/petrinaut/src/react/state/use-selection-cleanup.ts | Treats disabled-extension entities as invalid for selection cleanup. |
| libs/@hashintel/petrinaut/src/react/state/use-read-only-reason.ts | Updates docs to include handle-level read-only as a cause. |
| libs/@hashintel/petrinaut/src/react/state/use-is-read-only.ts | Updates docs to include handle-level read-only as a cause. |
| libs/@hashintel/petrinaut/src/react/state/sdcpn-context.ts | Adds extensions to SDCPN context value and default. |
| libs/@hashintel/petrinaut/src/react/simulation/provider.tsx | Removes parameters from simulation inputs and defaults when parameters extension is disabled. |
| libs/@hashintel/petrinaut/src/react/sdcpn-provider.tsx | Exposes instance extensions via context and gates selection typing on extensions. |
| libs/@hashintel/petrinaut/src/react/index.ts | Re-exports extension/capability types. |
| libs/@hashintel/petrinaut/src/react/hooks/use-petrinaut-mutations.test.tsx | Updates test wrapper context to include default extensions. |
| libs/@hashintel/petrinaut/src/react/hooks/use-petrinaut-commands.test.tsx | Updates test wrapper context to include default extensions. |
| libs/@hashintel/petrinaut/src/react/hooks/use-default-parameter-values.ts | Returns empty defaults when parameters extension is disabled. |
| libs/@hashintel/petrinaut/src/react/experiments/provider.tsx | Removes parameters from experiment inputs/compilation when parameters extension is disabled. |
| libs/@hashintel/petrinaut/src/react/experiments/provider.test.tsx | Updates experiments provider test context to include default extensions. |
| libs/@hashintel/petrinaut/src/main.ts | Re-exports extension/capability types from the package entrypoint. |
| libs/@hashintel/petrinaut/ANALYSIS.md | Adds design/touchpoint analysis for SDCPN extension capabilities. |
| libs/@hashintel/petrinaut-core/src/instance.ts | Resolves handle capabilities; exposes capabilities/extensions; routes extensions into actions/commands; enforces effective readonly. |
| libs/@hashintel/petrinaut-core/src/index.ts | Exports new extension/capability APIs and constants. |
| libs/@hashintel/petrinaut-core/src/handle.ts | Adds optional handle capabilities and enforces handle-level readonly in JSON handle change. |
| libs/@hashintel/petrinaut-core/src/handle.test.ts | Adds tests for handle-level readonly and extension resolution behavior. |
| libs/@hashintel/petrinaut-core/src/extensions.ts | Introduces extension keys, capability resolution, and SDCPN sanitizers/strippers. |
| libs/@hashintel/petrinaut-core/src/commands.ts | Sanitizes pasted SDCPN for disabled extensions and filters selection IDs accordingly. |
| libs/@hashintel/petrinaut-core/src/commands.test.ts | Adds coverage verifying disabled-extension paste sanitization. |
| libs/@hashintel/petrinaut-core/src/actions.ts | Makes core mutations extension-aware and strips disabled data after mutations. |
| libs/@hashintel/petrinaut-core/src/actions.test.ts | Adds coverage verifying disabled-extension sanitization during mutations. |
| .changeset/petrinaut-sdcpn-capabilities.md | Publishes patch changes for petrinaut + petrinaut-core. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 89 out of 89 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
libs/@hashintel/petrinaut-core/src/instance.ts:176
createDefinitionStore()andcreatePatchStream()both callhandle.subscribe(...), butcreatePetrinaut().dispose()never unsubscribes those upstream subscriptions (thedisposersarray is currently never populated). Disposing an instance will therefore leak subscriptions and can keep delivering events to detached listeners / retain memory.
dispose() {
for (const dispose of disposers) {
dispose();
}
disposers.length = 0;
},
};
4466f1b to
ec2c1d5
Compare
ec2c1d5 to
1161b8b
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 96 out of 96 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
libs/@hashintel/petrinaut-core/src/handle/json-doc-handle/create-json-doc-handle.ts:132
applyPatchesAndSanitize()replays history patches by runningsanitizeSDCPNForExtensions()and re-diffing withproduceWithPatches(). BecausesanitizeSDCPNForExtensions()deep-clones the whole SDCPN, Immer will typically emit a broad/root replacement patch set for undo/redo/goToIndex, which is expensive and can make patch consumers (e.g. persistence) process much larger deltas than necessary.
Since history entries are already recorded after stripDisabledExtensionData() runs in change(), re-sanitizing here should be unnecessary in normal operation. Applying the stored patches directly (optionally followed by an idempotent in-place stripDisabledExtensionData() safety pass) keeps undo/redo patches small and consistent with the originally recorded history entries.
libs/@hashintel/petrinaut-core/src/instance.ts:140
instance.definitionis sanitized viasanitizeSDCPNForExtensions()before being exposed, butinstance.patchesforwardsevent.patchesfrom the underlying handle verbatim. If a handle emits patches that touch extension-disabled fields (or otherwise yields anextSDCPN that sanitizes differently than the rawnext), consumers applyinginstance.patchesto the sanitizedinstance.definitioncan diverge.
Consider either (a) sanitizing/deriving patches against the sanitized SDCPN snapshots, or (b) explicitly documenting that instance.patches is the raw handle patch stream and may not apply cleanly to instance.definition when extension sanitization is active.
const unsubscribe = handle.subscribe((event) => {
if (!event.patches) {
return;
}
for (const listener of listeners) {
listener(event.patches);
}
1161b8b to
51da097
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 51da097. Configure here.

🌟 What is the purpose of this PR?
Allow Petrinaut document handles to declare which HASH SDCPN extensions are unavailable, so hosts such as CatCollab can embed Petrinaut around a bare Petri net without exposing colour/type, stochasticity, dynamics, or global-parameter functionality.
This adds handle-level capabilities for read-only mode and extension availability, then adapts core mutation paths, runtime data paths, and the editor UI to respect those capabilities. It also tightens the handle boundary by splitting document handles from the generic store primitive used across core services.
🔗 Related links
🔍 What does this change?
PetrinautHandleCapabilitieswithreadonlyanddisabledExtensionsmetadata.colors,stochasticity,dynamics, andparameters.dynamicsis resolved as disabled whenevercolorsis disabled.src/handle/, with the JSON implementation in its own folder.ReadableStoreprimitive intosrc/store/so playback, simulation, LSP, and handles do not depend on a handle-specific module for store types.Petrinaut/ExtensionsDisabledStorybook coverage for a bare Petri net with SDCPN extensions and global parameters disabled.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:
CatCollabPetriNetHandle; it only adds the capability surface and UI/core behavior it can use later.🐾 Next Steps
CatCollabPetriNetHandleonce CatCollab's source model and edit semantics are finalized.useEffect.🛡 What tests cover this?
yarn workspace @hashintel/petrinaut-core lint:tscyarn workspace @hashintel/petrinaut-core lint:eslintyarn workspace @hashintel/petrinaut-core test:unit src/handle/json-doc-handle/create-json-doc-handle.test.ts --runyarn lint:eslintinlibs/@hashintel/petrinaut-coreyarn lint:tscinlibs/@hashintel/petrinaut-coreyarn test:unit --runinlibs/@hashintel/petrinaut-coreturbo run lint:tsc --filter='@hashintel/petrinaut'turbo run lint:eslint --filter='@hashintel/petrinaut'turbo run test:unit --filter='@hashintel/petrinaut' -- --rungit diff --check❓ How to test this?
Petrinaut/ExtensionsDisabled.capabilities.disabledExtensionsset to['colors']and confirminstance.extensions.dynamicsresolves tofalse.capabilities.disabledExtensionsset to['parameters']and confirm global parameter UI and simulation defaults are unavailable.capabilities.readonlyand confirm edit mutations are ignored and the editor reports read-only state.