Skip to content

FE-??: Extract petrinaut demo-site into @apps/petrinaut-website#8528

Open
kube wants to merge 8 commits intocf/h-5655-refactor-selection-logicfrom
cf/petrinaut-extract-website
Open

FE-??: Extract petrinaut demo-site into @apps/petrinaut-website#8528
kube wants to merge 8 commits intocf/h-5655-refactor-selection-logicfrom
cf/petrinaut-extract-website

Conversation

@kube
Copy link
Collaborator

@kube kube commented Mar 10, 2026

🌟 What is the purpose of this PR?

Extract the petrinaut demo-site into its own private package (@apps/petrinaut-website) so it can be developed, built, and deployed independently of the library.

🔍 What does this change?

New package apps/petrinaut-website/:

  • Private package (@apps/petrinaut-website) consuming @hashintel/petrinaut as a workspace dependency
  • Vite 8 + @typescript/native-preview for dev/build
  • All demo-site source moved here with imports rewritten from relative ../../src/ to @hashintel/petrinaut
  • Explicit CSS import (@hashintel/petrinaut/dist/main.css)

Changes to @hashintel/petrinaut:

  • Removed demo-site/ directory and vite.site.config.ts
  • Added exports: ErrorTrackerContext, ErrorTracker, convertOldFormatToSDCPN, isOldFormat, OldFormat
  • Removed build:site script, changed dev to vite build --watch
  • Moved @sentry/react and immer to the website package
  • Set sideEffects: false, removed demo-site from tsconfig includes
  • Bundled Monaco Editor into the library (removed from externals), using selective imports (editor.api.js + typescript.contribution.js) to avoid bundling unnecessary language workers
  • Added define for process.versions to fix Monaco's runtime reference to Node globals
  • Switched simulation and language server workers to ?worker&inline imports

Why ?worker&inline:

Vite library mode emits worker files as separate assets, but consuming apps (like @apps/petrinaut-website) don't copy those assets during their own build — the worker URLs resolve to 404s. This is a known Vite limitation with no clean fix. Using ?worker&inline inlines the compiled worker code as a raw JS string and creates a Blob URL at runtime, making workers fully self-contained in the library bundle. Since Vite 6+, inline workers use raw strings (not base64), so there is no encoding overhead.

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 internal and do not require a docs change

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

The changes in this PR:

  • do not affect the execution graph

❓ How to test this?

  1. Run yarn dev in apps/petrinaut-website (after building petrinaut)
  2. Confirm the demo site loads with styles and undo/redo working
  3. Verify simulation and language server workers load without 404 errors

@vercel
Copy link

vercel bot commented Mar 10, 2026

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

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment Mar 11, 2026 0:46am
petrinaut Error Error Comment Mar 11, 2026 0:46am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
hashdotdesign Ignored Ignored Preview Mar 11, 2026 0:46am
hashdotdesign-tokens Ignored Ignored Preview Mar 11, 2026 0:46am

@cursor
Copy link

cursor bot commented Mar 10, 2026

PR Summary

Medium Risk
Moderate risk due to build/deploy and packaging changes (new app package, updated Vercel/Turbo commands, and @hashintel/petrinaut export/dependency reshuffling) that could break CI, deployment, or bundling/tree-shaking behavior.

Overview
Extracts the Petrinaut demo site into a new private Vite app, @apps/petrinaut-website, with its own package.json/tsconfig.json, Vercel build/install scripts, and build output (./dist).

Updates the website code to consume the library via @hashintel/petrinaut (including importing dist/main.css) and moves demo-only deps like @sentry/react and immer into the app.

Adjusts @hashintel/petrinaut packaging by exporting ErrorTrackerContext/old-format conversion helpers from src/main.ts, removing demo-site TypeScript config, simplifying scripts (dropping build:site), and setting sideEffects: false.

Written by Cursor Bugbot for commit 6398b7b. This will update automatically on new commits. Configure here.

@github-actions github-actions bot added area/deps Relates to third-party dependencies (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team area/apps labels Mar 10, 2026
@augmentcode
Copy link

augmentcode bot commented Mar 10, 2026

🤖 Augment PR Summary

Summary: Extracts the Petrinaut demo site into a standalone, private Vite app so it can be developed and deployed independently from the library.

Changes:

  • Introduces apps/petrinaut-website with its own package.json, tsconfig.json, ESLint config, and Vite build config
  • Moves the former demo-site/ sources into the new app and rewrites imports to consume @hashintel/petrinaut via workspace dependency
  • Updates Vercel install/build scripts and vercel.json to build/deploy the new website output (./dist)
  • Removes the demo-site directory/config from the @hashintel/petrinaut package (scripts, tsconfig, eslint config)
  • Expands Petrinaut’s public exports to include old-format conversion helpers and error tracker context/types
  • Updates simulation and language-server worker loading to use Vite inline-worker imports (?worker&inline)
  • Adjusts Monaco integration to use selective ESM imports and configures a Monaco worker loader
  • Adds a define shim for process.versions in the library build to satisfy Monaco/TS runtime references

Technical Notes: The worker-loading changes are aimed at avoiding missing-worker-asset failures when the library is consumed by another app build (e.g., Vite output not copying dependency worker assets).

🤖 Was this summary useful? React with 👍 or 👎

Copy link

@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. 1 suggestion posted.

Fix All in Augment

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

"sideEffects": [
"demo-site/**/*.ts"
],
"sideEffects": false,
Copy link

Choose a reason for hiding this comment

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

"sideEffects": false looks risky here because Petrinaut emits/ships CSS ("style": "dist/main.css" and CSS imports in the entry), and Webpack consumers can tree-shake CSS side-effect imports away when the package is marked side-effect free, leading to missing styles.

Severity: high

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link

@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 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Copy link
Collaborator Author

kube commented Mar 10, 2026

@kube kube changed the title FE-225: Extract petrinaut demo-site into @apps/petrinaut-website FE-??: Extract petrinaut demo-site into @apps/petrinaut-website Mar 10, 2026
"@local/eslint": "workspace:*",
"@pandacss/dev": "1.4.3",
"@sentry/react": "10.22.0",
"@storybook/react-vite": "10.2.13",
Copy link
Contributor

Choose a reason for hiding this comment

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

Add '@testing-library/react' as a devDependency here since the test files in the library (src/playback/provider.test.tsx and src/simulation/worker/use-simulation-worker.test.ts) still require this dependency for testing React components and hooks.

Spotted by Graphite (based on CI logs)

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 10, 2026

Merging this PR will not alter performance

✅ 80 untouched benchmarks


Comparing cf/petrinaut-extract-website (6398b7b) with cf/h-5655-refactor-selection-logic (70dc746)

Open in CodSpeed

@github-actions
Copy link
Contributor

Benchmark results

@rust/hash-graph-benches – Integrations

policy_resolution_large

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2002 $$28.0 \mathrm{ms} \pm 172 \mathrm{μs}\left({\color{gray}0.350 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.55 \mathrm{ms} \pm 19.0 \mathrm{μs}\left({\color{gray}1.02 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1001 $$13.0 \mathrm{ms} \pm 97.2 \mathrm{μs}\left({\color{gray}-0.192 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 3314 $$44.4 \mathrm{ms} \pm 312 \mathrm{μs}\left({\color{gray}0.409 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$15.3 \mathrm{ms} \pm 114 \mathrm{μs}\left({\color{gray}-0.160 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 1526 $$24.8 \mathrm{ms} \pm 158 \mathrm{μs}\left({\color{gray}-1.227 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 2078 $$28.8 \mathrm{ms} \pm 179 \mathrm{μs}\left({\color{gray}-0.900 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.85 \mathrm{ms} \pm 23.2 \mathrm{μs}\left({\color{gray}1.30 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 1033 $$13.9 \mathrm{ms} \pm 107 \mathrm{μs}\left({\color{gray}-1.225 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_medium

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 102 $$3.92 \mathrm{ms} \pm 23.7 \mathrm{μs}\left({\color{gray}0.161 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.09 \mathrm{ms} \pm 16.4 \mathrm{μs}\left({\color{gray}-0.087 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 51 $$3.46 \mathrm{ms} \pm 18.1 \mathrm{μs}\left({\color{gray}0.128 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 269 $$5.32 \mathrm{ms} \pm 27.2 \mathrm{μs}\left({\color{gray}0.164 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.70 \mathrm{ms} \pm 23.7 \mathrm{μs}\left({\color{gray}1.23 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 107 $$4.24 \mathrm{ms} \pm 19.3 \mathrm{μs}\left({\color{gray}-0.188 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 133 $$4.57 \mathrm{ms} \pm 32.2 \mathrm{μs}\left({\color{gray}-0.571 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.55 \mathrm{ms} \pm 19.9 \mathrm{μs}\left({\color{gray}0.295 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 63 $$4.19 \mathrm{ms} \pm 32.3 \mathrm{μs}\left({\color{gray}-0.228 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_none

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2 $$2.81 \mathrm{ms} \pm 13.8 \mathrm{μs}\left({\color{gray}-0.036 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.78 \mathrm{ms} \pm 14.1 \mathrm{μs}\left({\color{gray}-0.358 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1 $$2.90 \mathrm{ms} \pm 14.7 \mathrm{μs}\left({\color{gray}0.062 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 8 $$3.15 \mathrm{ms} \pm 16.7 \mathrm{μs}\left({\color{gray}-0.350 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.96 \mathrm{ms} \pm 15.0 \mathrm{μs}\left({\color{gray}0.304 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 3 $$3.26 \mathrm{ms} \pm 19.7 \mathrm{μs}\left({\color{gray}-0.374 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_small

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 52 $$3.18 \mathrm{ms} \pm 16.5 \mathrm{μs}\left({\color{gray}0.608 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.89 \mathrm{ms} \pm 15.0 \mathrm{μs}\left({\color{gray}0.204 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 25 $$3.05 \mathrm{ms} \pm 18.7 \mathrm{μs}\left({\color{gray}0.639 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 94 $$3.63 \mathrm{ms} \pm 22.3 \mathrm{μs}\left({\color{gray}0.376 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.16 \mathrm{ms} \pm 15.0 \mathrm{μs}\left({\color{gray}-0.505 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 26 $$3.43 \mathrm{ms} \pm 17.1 \mathrm{μs}\left({\color{gray}-0.247 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 66 $$3.55 \mathrm{ms} \pm 17.9 \mathrm{μs}\left({\color{gray}-0.321 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.15 \mathrm{ms} \pm 20.6 \mathrm{μs}\left({\color{gray}0.285 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 29 $$3.44 \mathrm{ms} \pm 19.7 \mathrm{μs}\left({\color{gray}-0.141 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_complete

Function Value Mean Flame graphs
entity_by_id;one_depth 1 entities $$41.7 \mathrm{ms} \pm 176 \mathrm{μs}\left({\color{gray}0.628 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 10 entities $$79.5 \mathrm{ms} \pm 529 \mathrm{μs}\left({\color{gray}-0.251 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 25 entities $$45.5 \mathrm{ms} \pm 155 \mathrm{μs}\left({\color{gray}-0.573 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 5 entities $$48.7 \mathrm{ms} \pm 238 \mathrm{μs}\left({\color{gray}-0.101 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 50 entities $$56.2 \mathrm{ms} \pm 354 \mathrm{μs}\left({\color{gray}-2.785 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 1 entities $$43.5 \mathrm{ms} \pm 193 \mathrm{μs}\left({\color{gray}1.56 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 10 entities $$421 \mathrm{ms} \pm 958 \mathrm{μs}\left({\color{gray}-0.705 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 25 entities $$93.1 \mathrm{ms} \pm 430 \mathrm{μs}\left({\color{gray}-1.073 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 5 entities $$87.9 \mathrm{ms} \pm 336 \mathrm{μs}\left({\color{gray}0.043 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 50 entities $$285 \mathrm{ms} \pm 571 \mathrm{μs}\left({\color{gray}-1.215 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 1 entities $$16.0 \mathrm{ms} \pm 91.3 \mathrm{μs}\left({\color{gray}-0.701 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 10 entities $$15.8 \mathrm{ms} \pm 76.1 \mathrm{μs}\left({\color{gray}0.252 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 25 entities $$16.2 \mathrm{ms} \pm 86.5 \mathrm{μs}\left({\color{gray}-0.876 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 5 entities $$15.9 \mathrm{ms} \pm 81.6 \mathrm{μs}\left({\color{gray}-0.245 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 50 entities $$19.0 \mathrm{ms} \pm 113 \mathrm{μs}\left({\color{gray}-0.160 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_linkless

Function Value Mean Flame graphs
entity_by_id 1 entities $$15.8 \mathrm{ms} \pm 64.5 \mathrm{μs}\left({\color{gray}-0.700 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10 entities $$15.6 \mathrm{ms} \pm 73.0 \mathrm{μs}\left({\color{gray}-1.291 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 100 entities $$15.8 \mathrm{ms} \pm 88.5 \mathrm{μs}\left({\color{gray}0.078 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 1000 entities $$16.2 \mathrm{ms} \pm 75.4 \mathrm{μs}\left({\color{gray}-1.696 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10000 entities $$23.7 \mathrm{ms} \pm 153 \mathrm{μs}\left({\color{gray}-2.006 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity

Function Value Mean Flame graphs
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1 $$31.3 \mathrm{ms} \pm 285 \mathrm{μs}\left({\color{gray}1.55 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1 $$31.1 \mathrm{ms} \pm 366 \mathrm{μs}\left({\color{gray}-2.867 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1 $$32.5 \mathrm{ms} \pm 234 \mathrm{μs}\left({\color{red}5.20 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1 $$31.7 \mathrm{ms} \pm 345 \mathrm{μs}\left({\color{gray}0.982 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2 $$31.3 \mathrm{ms} \pm 301 \mathrm{μs}\left({\color{gray}1.37 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1 $$31.6 \mathrm{ms} \pm 331 \mathrm{μs}\left({\color{gray}1.13 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1 $$30.7 \mathrm{ms} \pm 340 \mathrm{μs}\left({\color{gray}-3.600 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1 $$31.4 \mathrm{ms} \pm 295 \mathrm{μs}\left({\color{gray}0.157 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1 $$30.8 \mathrm{ms} \pm 327 \mathrm{μs}\left({\color{gray}-3.252 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity_type

Function Value Mean Flame graphs
get_entity_type_by_id Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba $$9.15 \mathrm{ms} \pm 79.1 \mathrm{μs}\left({\color{red}5.61 \mathrm{\%}}\right) $$ Flame Graph

representative_read_multiple_entities

Function Value Mean Flame graphs
entity_by_property traversal_paths=0 0 $$90.6 \mathrm{ms} \pm 489 \mathrm{μs}\left({\color{gray}0.037 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$144 \mathrm{ms} \pm 562 \mathrm{μs}\left({\color{gray}0.156 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$99.1 \mathrm{ms} \pm 558 \mathrm{μs}\left({\color{gray}1.37 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$107 \mathrm{ms} \pm 602 \mathrm{μs}\left({\color{gray}0.175 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$115 \mathrm{ms} \pm 528 \mathrm{μs}\left({\color{gray}0.029 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$123 \mathrm{ms} \pm 513 \mathrm{μs}\left({\color{gray}0.471 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=0 0 $$89.0 \mathrm{ms} \pm 397 \mathrm{μs}\left({\color{gray}0.143 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$117 \mathrm{ms} \pm 542 \mathrm{μs}\left({\color{gray}0.128 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$96.2 \mathrm{ms} \pm 518 \mathrm{μs}\left({\color{gray}0.521 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$105 \mathrm{ms} \pm 567 \mathrm{μs}\left({\color{gray}0.232 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$107 \mathrm{ms} \pm 472 \mathrm{μs}\left({\color{gray}0.635 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$106 \mathrm{ms} \pm 411 \mathrm{μs}\left({\color{gray}0.084 \mathrm{\%}}\right) $$

scenarios

Function Value Mean Flame graphs
full_test query-limited $$139 \mathrm{ms} \pm 473 \mathrm{μs}\left({\color{gray}4.84 \mathrm{\%}}\right) $$ Flame Graph
full_test query-unlimited $$140 \mathrm{ms} \pm 420 \mathrm{μs}\left({\color{gray}4.34 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-limited $$105 \mathrm{ms} \pm 522 \mathrm{μs}\left({\color{gray}-1.094 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-unlimited $$585 \mathrm{ms} \pm 3.52 \mathrm{ms}\left({\color{gray}0.569 \mathrm{\%}}\right) $$ Flame Graph

@kube kube changed the base branch from cf/h-5655-refactor-selection-logic to graphite-base/8528 March 10, 2026 11:43
kube and others added 4 commits March 11, 2026 01:31
Move the demo-site from libs/@hashintel/petrinaut into its own
private package at apps/petrinaut-website, consuming petrinaut
as a workspace dependency instead of importing source directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
kube and others added 4 commits March 11, 2026 01:31
… for website

- Bundle Monaco Editor into petrinaut (removed from externals), using selective
  imports (editor.api.js + typescript.contribution.js) to avoid bundling
  unnecessary language workers
- Add define for process.versions in petrinaut vite config for TypeScript internals
- Fix Monaco provider to use new Worker() directly instead of returning a promise
- Update Monaco type imports to use editor.api.js path across all sync files
- Remove stale demo-site references from petrinaut eslint config
- Add eslint.config.js for @apps/petrinaut-website
- Fix import/export sorting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vite library mode emits worker assets as separate files that consumers
can't resolve. Using ?worker&inline inlines the compiled worker code as
a string and creates a Blob URL at runtime, making workers self-contained
in the library bundle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kube kube force-pushed the cf/petrinaut-extract-website branch from 6398b7b to cbbd3fb Compare March 11, 2026 00:32
@kube kube force-pushed the graphite-base/8528 branch from 70dc746 to 11b1e8b Compare March 11, 2026 00:32
@kube kube changed the base branch from graphite-base/8528 to cf/h-5655-refactor-selection-logic March 11, 2026 00:32
@kube kube marked this pull request as ready for review March 11, 2026 20:06
Copy link

@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. 6 suggestions posted.

Fix All in Augment

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

const pending = pendingRef.current.get(msg.id);
if (!pending) {
return;
void (async () => {
Copy link

Choose a reason for hiding this comment

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

Because the worker is now created asynchronously, callers (e.g. LanguageClientProvider’s mount effect) can hit client.initialize() before workerRef.current is set, so the notification is silently dropped and the language server never initializes.

Severity: high

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

diagnosticsCallbackRef.current?.(msg.params);
}
};
workerRef.current = worker;
Copy link

Choose a reason for hiding this comment

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

There’s an unmount race here: if the component unmounts before the dynamic import resolves, the cleanup runs with workerRef.current === null, but the async task can still create a worker and assign it after unmount (leaking a live worker).

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.


/** Dynamically import and instantiate the simulation worker (inlined as blob URL). */
async function createSimulationWorker(): Promise<Worker> {
const SimulationWorker = await import("./simulation.worker.ts?worker&inline");
Copy link

Choose a reason for hiding this comment

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

Switching to import("./simulation.worker.ts?worker&inline") means tests/mocks that stub the global Worker constructor won’t intercept worker creation anymore (the imported module provides the constructor), so use-simulation-worker.test.ts likely needs to mock this import instead.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

};

workerRef.current = worker;
void (async () => {
Copy link

Choose a reason for hiding this comment

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

Similar to the LSP hook, the worker is now initialized asynchronously, so actions.initialize() can run before workerRef.current is set; in that case postMessage() no-ops and the returned init Promise can hang indefinitely.

Severity: high

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.


return () => {
worker.terminate();
workerRef.current?.terminate();
Copy link

Choose a reason for hiding this comment

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

On unmount you terminate the worker but don’t reject/clear pendingInitRef, so any in-flight initialize() Promise can remain unresolved after teardown.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.


window.MonacoEnvironment = {
getWorker() {
return new Worker(
Copy link

Choose a reason for hiding this comment

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

Worth double-checking that editor.worker.js (loaded via new URL(..., import.meta.url)) is actually available in consuming-app production builds; this looks like it could hit the same “library worker asset not copied → 404” issue that motivated ?worker&inline elsewhere.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/apps area/deps Relates to third-party dependencies (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.

1 participant