Skip to content

FE-614: Support disabling SDCPN extensions#8763

Open
kube wants to merge 13 commits into
mainfrom
cf/fe-614-provide-prop-to-turn-onoff-sdcpn-extensions
Open

FE-614: Support disabling SDCPN extensions#8763
kube wants to merge 13 commits into
mainfrom
cf/fe-614-provide-prop-to-turn-onoff-sdcpn-extensions

Conversation

@kube
Copy link
Copy Markdown
Collaborator

@kube kube commented May 26, 2026

🌟 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?

  • Adds PetrinautHandleCapabilities with readonly and disabledExtensions metadata.
  • Defines supported extension keys: colors, stochasticity, dynamics, and parameters.
  • Resolves effective instance capabilities from both host config and handle metadata.
  • Ensures dynamics is resolved as disabled whenever colors is disabled.
  • Exposes active extension settings through Petrinaut core and React context.
  • Makes JSON handles no-op direct changes when handle-level read-only mode is enabled.
  • Refactors Petrinaut Core handle code into src/handle/, with the JSON implementation in its own folder.
  • Moves the generic ReadableStore primitive into src/store/ so playback, simulation, LSP, and handles do not depend on a handle-specific module for store types.
  • Sanitizes mutations and paste commands so disabled extension/global parameter data is not introduced or retained.
  • Hides token type, differential equation, and global parameter navigation when unavailable.
  • Hides place colour, dynamics, visualizer, transition result, stochastic, and parameter controls when unavailable.
  • Treats simulation scenarios and timelines as untyped when colours are disabled.
  • Ignores global parameter defaults and scenario overrides in simulation/experiment runtime paths when parameters are disabled.
  • Adds Petrinaut/ExtensionsDisabled Storybook coverage for a bare Petri net with SDCPN extensions and global parameters disabled.
  • Adds focused tests for read-only capabilities, extension sanitization, colour/dynamics normalization, parameter disabling, paste behavior, and handle history behavior.

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • modifies an npm-publishable library and I have added a changeset file(s)

📜 Does this require a change to the docs?

The changes in this PR:

  • are in a state where docs changes are not yet required but will be

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

⚠️ Known Issues

  • This does not implement CatCollabPetriNetHandle; it only adds the capability surface and UI/core behavior it can use later.
  • Lambda authoring/diagnostics still need a capability-aware pass: stochastic lambda code should be linted only when stochasticity is enabled, predicate lambda code should be linted only when coloured standard inputs are available, and file-format lambda fields should likely become optional at the import boundary.
  • AI assistant tool schemas and prompts are not yet filtered by active extensions; core mutations still sanitize disabled extension data.
  • Import/export-level sanitation has not been added, so external conversion paths should still be reviewed before treating disabled extension data as fully impossible at file boundaries.

🐾 Next Steps

  • Implement CatCollabPetriNetHandle once CatCollab's source model and edit semantics are finalized.
  • Move website/demo persistence toward a repository/storage-adapter layer instead of wiring handle persistence in a React useEffect.
  • Decide whether additional Petri-net features should become capability flags for a stricter bare-net mode, such as inhibitor arcs, scenarios, metrics, or simulation-only views.
  • Make read-only reasons more specific in the UI, distinguishing host prop, handle-level read-only, simulate mode, and active simulation state.
  • Update public Petrinaut docs once the extension capability behavior and lambda/file-format rules are finalized.

🛡 What tests cover this?

  • yarn workspace @hashintel/petrinaut-core lint:tsc
  • yarn workspace @hashintel/petrinaut-core lint:eslint
  • yarn workspace @hashintel/petrinaut-core test:unit src/handle/json-doc-handle/create-json-doc-handle.test.ts --run
  • yarn lint:eslint in libs/@hashintel/petrinaut-core
  • yarn lint:tsc in libs/@hashintel/petrinaut-core
  • yarn test:unit --run in libs/@hashintel/petrinaut-core
  • turbo run lint:tsc --filter='@hashintel/petrinaut'
  • turbo run lint:eslint --filter='@hashintel/petrinaut'
  • turbo run test:unit --filter='@hashintel/petrinaut' -- --run
  • git diff --check

❓ How to test this?

  1. Open Storybook and load Petrinaut/ExtensionsDisabled.
  2. Confirm token type, differential equation, global parameter, dynamics, visualizer, transition result, and stochastic controls are hidden.
  3. Create or use a Petrinaut handle with capabilities.disabledExtensions set to ['colors'] and confirm instance.extensions.dynamics resolves to false.
  4. Create or use a Petrinaut handle with capabilities.disabledExtensions set to ['parameters'] and confirm global parameter UI and simulation defaults are unavailable.
  5. Paste or mutate SDCPN data containing disabled extension fields and confirm the stored definition is sanitized.
  6. Set capabilities.readonly and confirm edit mutations are ignored and the editor reports read-only state.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment Jun 4, 2026 10:36am
petrinaut Ready Ready Preview, Comment Jun 4, 2026 10:36am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hashdotdesign-tokens Ignored Ignored Preview Jun 4, 2026 10:36am

@cursor
Copy link
Copy Markdown

cursor Bot commented May 26, 2026

PR Summary

Medium Risk
Broad cross-cutting behavior changes to mutation, simulation compile paths, and LSP diagnostics; incorrect sanitization could silently drop or alter net data for embedded hosts.

Overview
Handle capabilities let embedded documents declare readonly and disabledExtensions (colors, stochasticity, dynamics, parameters). Disabling colors also disables dynamics. Resolved settings flow through createPetrinaut, React SDCPNContext, and exported core APIs.

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 change/undo/redo run the same sanitizers. Simulation and Monte Carlo accept optional extensions, sanitize SDCPN before compile, skip parameter merging when parameters are disabled, and omit Distribution when stochasticity is off.

LSP receives extension settings, generates virtual files and diagnostics only for active code surfaces. AI prompts and the latest-net tool now document extensions in the returned state.

React wires extensions into LSP, experiments, simulation parameter paths, selection typing, and docs. File format defaults optional transition lambda/kernel fields. ReadableStore moves to src/store/; handle types live under src/handle/.

Reviewed by Cursor Bugbot for commit 51da097. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions github-actions Bot added area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team area/apps > hash.design Affects the `hash.design` design site (app) labels May 26, 2026
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 26, 2026

🤖 Augment PR Summary

Summary: Adds handle-level capability metadata so Petrinaut can run against “bare” Petri nets (e.g. CatCollab embeds) without exposing HASH SDCPN extensions.

Changes:

  • Introduced PetrinautHandleCapabilities (readonly, disabledExtensions) and extension keys (colors, stochasticity, dynamics).
  • Added core extension utilities to resolve capabilities, determine selection availability, and sanitize/strip disabled extension data.
  • Derived effective instance readonly + extensions from handle capabilities (and host readonly) and exposed them on the instance/context.
  • Updated mutation and paste paths to no-op or sanitize so disabled extension data can’t be introduced/retained.
  • Made JSON doc handles ignore change() when handle-level read-only is enabled.
  • Updated React/UI surfaces to hide token-type, dynamics, visualizer, transition-result, and stochastic controls when unavailable.
  • Adjusted simulation timeline/scenario views to treat places as untyped when colors are disabled.
  • Added focused unit tests for read-only behavior, mutation sanitization, and paste sanitization.
  • Added libs/@hashintel/petrinaut/ANALYSIS.md documenting touchpoints and follow-ups, plus a changeset.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread libs/@hashintel/petrinaut-core/src/extensions.ts Outdated
Comment thread libs/@hashintel/petrinaut-core/src/instance.ts
Comment thread libs/@hashintel/petrinaut-core/src/extensions.ts
Comment thread libs/@hashintel/petrinaut-core/src/actions.ts
Comment thread libs/@hashintel/petrinaut/src/react/simulation/provider.tsx
Comment thread libs/@hashintel/petrinaut-core/src/commands.ts
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-core and exposes instance.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.

Comment thread libs/@hashintel/petrinaut-core/src/actions.ts
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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() and createPatchStream() both call handle.subscribe(...), but createPetrinaut().dispose() never unsubscribes those upstream subscriptions (the disposers array 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;
    },
  };

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 running sanitizeSDCPNForExtensions() and re-diffing with produceWithPatches(). Because sanitizeSDCPNForExtensions() 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.definition is sanitized via sanitizeSDCPNForExtensions() before being exposed, but instance.patches forwards event.patches from the underlying handle verbatim. If a handle emits patches that touch extension-disabled fields (or otherwise yields a next SDCPN that sanitizes differently than the raw next), consumers applying instance.patches to the sanitized instance.definition can 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);
    }

Base automatically changed from cf/fe-740-add-read-arcs-to-petrinaut to main June 4, 2026 08:49
@kube kube force-pushed the cf/fe-614-provide-prop-to-turn-onoff-sdcpn-extensions branch from 1161b8b to 51da097 Compare June 4, 2026 10:30
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread libs/@hashintel/petrinaut-core/src/extensions.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/apps > hash.design Affects the `hash.design` design site (app) area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

2 participants