Skip to content

NO-CODE: Speculative Petrinaut import graph refactor#8705

Draft
lunelson wants to merge 29 commits into
mainfrom
ln/petrinaut-imports
Draft

NO-CODE: Speculative Petrinaut import graph refactor#8705
lunelson wants to merge 29 commits into
mainfrom
ln/petrinaut-imports

Conversation

@lunelson
Copy link
Copy Markdown
Contributor

@lunelson lunelson commented May 6, 2026

🌟 What is the purpose of this PR?

This PR makes Petrinaut cheaper to import and rebuild by reshaping the editor's module graph around the heavy optional systems that were previously reached from the editor shell.

Before this branch, mounting Petrinaut pulled too much into one broad graph: inline application workers, language tooling, Monaco setup, graph layout, Babel visualizer compilation, timeline charting, examples, font CSS, and package CSS. That meant small CSS or UI changes could make the dev toolchain revisit unrelated editor internals.

The target state is a more intentional package boundary:

  • worker internals are emitted as separate assets rather than inline worker string modules
  • React Compiler/Babel avoids worker and non-React modules
  • heavy optional dependencies enter through feature-level lazy boundaries
  • Monaco, language worker, and simulation worker initialize only when used
  • package exports and peer externalization make Petrinaut consumable as a reusable library
  • HASH frontend consumes prebuilt Petrinaut rather than transpiling it as app source
  • CSS and Panda scanning are narrower

🔗 Related links

  • Local characterization artifacts generated while preparing this PR:
    • .context/petrinaut-characterization/before-vs-final.md
    • .context/petrinaut-characterization/2026-05-05T19-23-54-705Z.md
    • .context/petrinaut-characterization/2026-05-06T09-48-25-169Z.md

🚫 Blocked by

None.

🔍 What does this change?

  • Adds a Petrinaut bundle characterization script and regression guard.
  • Encodes explicit package exports for the main module and stylesheet.
  • Removes @hashintel/petrinaut from HASH frontend transpilePackages and imports @hashintel/petrinaut/styles.css.
  • Emits Petrinaut application workers as assets instead of inline worker modules.
  • Narrows the React Compiler/Babel transform surface.
  • Lazy-loads graph layout, visualizer compilation, timeline charting, example nets, Monaco initialization, language worker activation, and simulation worker creation.
  • Splits library and Storybook Panda scanning and removes source-runtime constants from Panda config evaluation.
  • Removes bundled Fontsource package imports from Petrinaut's component entry.
  • Adds lifecycle and bundle topology tests, including StrictMode coverage for lazy worker activation.

Performance report

Measured with yarn workspace @hashintel/petrinaut profile:build --include-checks on the same machine.

Dimension Baseline Final Delta
Production build 6.46s 5.43s -1.03s (-15.9%)
Watch initial build 5.41s 4.65s -0.75s (-13.9%)
Median sampled rebuild 3.31s 2.93s -0.38s (-11.5%)
Main JS 1.4 MiB / 312.8 KiB gzip 589.98 KiB / 151.3 KiB gzip -855.3 KiB / -161.5 KiB gzip
CSS 1.4 MiB / 669 KiB gzip 745.5 KiB / 147.3 KiB gzip -707.7 KiB / -521.7 KiB gzip
Sourcemaps 56.4 MiB / 10.6 MiB gzip 55.8 MiB / 10.5 MiB gzip -546.6 KiB / -50.9 KiB gzip
@font-face rules 21 1 -20
Inline worker imports 3 0 -3
Babel worker deopt warnings present absent fixed

Developer experience samples:

Sample Baseline Final Delta
CSS entry rebuild 3.36s 2.93s -0.43s (-12.7%)
Small component rebuild 3.25s 2.84s -0.41s (-12.6%)
Editor shell rebuild 3.20s 2.82s -0.39s (-12.1%)
Simulation worker rebuild 4.08s 3.34s -0.74s (-18.1%)
Compiler utility rebuild 3.98s 3.28s -0.71s (-17.7%)
Panda shared config rebuild 3.12s 2.91s -0.21s (-6.7%)

Bundle topology signals:

Signal Baseline Final
JS assets 23 files, 12.4 MiB 36 files, 12.0 MiB
@babel/standalone in main yes no
elkjs in main yes no
uplot in main yes no
Source ?worker&inline imports 3 0
Source Fontsource imports 6 0
Source map module count 373 205
DS helper sourcemap sources 6 0

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • I am unsure / need advice

Petrinaut is an npm-publishable library and this changes its package boundary, build topology, and stylesheet export. I did not add a changeset because this branch is primarily a dev/build topology refactor, but reviewers should decide whether the package export and stylesheet contract warrant one.

📜 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:

  • I am unsure / need advice

This adds Petrinaut package scripts for bundle profiling and guarding. I did not update Turbo config because these are package-local commands and existing verification used direct workspace commands.

⚠️ Known issues

  • yarn workspace @apps/hash-frontend lint:tsc and yarn workspace @apps/hash-frontend build currently fail before reaching the Petrinaut package boundary because generated GraphQL/API artifacts are missing and there are existing Block Protocol type import mismatches. No Petrinaut package-resolution, stylesheet-export, or worker-asset error was reached in those checks.
  • Storybook uses the Vite builder and loads Petrinaut's Vite config, but it has its own startup/indexing/prebundle behavior. Storybook startup may need a follow-up profile pass.

🐾 Next steps

  • Profile Petrinaut Storybook startup separately and consider Storybook-specific viteFinal / story graph tuning.
  • Decide whether the Petrinaut package export/style contract needs a changeset.
  • Consider a later tsdown migration spike separately from this graph-topology refactor.

🛡 What tests cover this?

  • libs/@hashintel/petrinaut/src/provider-lifecycle.test.tsx
  • libs/@hashintel/petrinaut/src/lsp/worker/use-language-client.test.ts
  • libs/@hashintel/petrinaut/src/simulation/worker/use-simulation-worker.test.ts
  • libs/@hashintel/petrinaut/src/state/mutation-provider.test.tsx
  • libs/@hashintel/petrinaut/vite.config.test.ts
  • libs/@hashintel/petrinaut/panda.config.shared.test.ts
  • libs/@hashintel/petrinaut/scripts/characterize-build-output.test.mjs
  • Existing Petrinaut unit coverage for simulation, playback, validation, import/export, and editor behavior.

❓ How to test this?

Run:

yarn workspace @hashintel/petrinaut lint:eslint
yarn workspace @hashintel/petrinaut lint:tsc
yarn workspace @hashintel/petrinaut test:unit run
yarn workspace @hashintel/petrinaut build
yarn workspace @hashintel/petrinaut check:bundle

Optional full characterization:

yarn workspace @hashintel/petrinaut profile:build --include-checks

Manual smoke test:

  1. Open the process editor.
  2. Confirm Petrinaut renders.
  3. Open a code editor field to trigger Monaco/language services.
  4. Run, pause, and reset a simulation.
  5. Open the simulation timeline tab.
  6. Preview a visualizer.
  7. Load an example net.

📹 Demo

No visual demo. This PR is primarily build graph, lazy-loading, package boundary, and verification work.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 6, 2026

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

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment May 6, 2026 3:22pm
petrinaut Error Error Comment May 6, 2026 3:22pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hashdotdesign-tokens Ignored Ignored Preview May 6, 2026 3:22pm

@github-actions github-actions Bot added area/deps Relates to third-party dependencies (area) area/apps > hash* Affects HASH (a `hash-*` app) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team area/apps labels May 6, 2026
@lunelson lunelson changed the title Refactor Petrinaut import graph NO-CODE: Refactor Petrinaut import graph May 6, 2026
@lunelson lunelson changed the title NO-CODE: Refactor Petrinaut import graph NO-CODE: Speculative Petrinaut import graph refactor May 6, 2026
Comment on lines +677 to +678
String(value ?? "")
.replace(/\|/g, "\\|")

export function shouldApplyReactCompiler(id: string, code: string) {
return (
reactCompilerIdInclude.test(id) &&
export function shouldApplyReactCompiler(id: string, code: string) {
return (
reactCompilerIdInclude.test(id) &&
!reactCompilerIdExclude.some((pattern) => pattern.test(id)) &&
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/apps > hash* Affects HASH (a `hash-*` app) 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.

2 participants