The HIR pipeline turns user-authored TypeScript into checked, source-spanned buffer programs. Scenario code retains a separate same-realm compiler hardened against accidents, not attackers.
InitialMarking
for scenarios
SDCPNItemError) → surfaced as protocol
error messages / result objects
Dynamics, lambdas, kernels, and metrics all compile through the HIR. The
first three are authored as export default Wrapper(fn)
modules; metrics are authored as function bodies.
lsp/generate-virtual-files.ts) are the type-level twin of
this pipeline: they generate the Color_*,
Parameters, Dynamics,
TransitionKernel… declarations that Monaco checks against, so
editor diagnostics and runtime artifacts are produced from the same HIR
checks and emitters.
| Surface | Authored as | Compiled by | Executed in | Signature at runtime |
|---|---|---|---|---|
| Transition lambda | module, Lambda(fn) |
compileHirArtifacts in the LSP worker |
Worker, per enablement check |
(f64, u64, u8, placeBases, indices) → boolean | rate
|
| Transition kernel | module, TransitionKernel(fn) |
compileHirArtifacts in the LSP worker |
Worker, per firing |
(views, placeBases, indices, outputViews, sink) → void
|
| Dynamics | module, Dynamics(fn) |
compileHirArtifacts (colours with a real element)
|
Worker, per step per place |
(placeBytes, tokenCount) → Float64Array
|
| Metric | plain function body (no module) | compileHirArtifacts in the LSP worker |
Main thread (timeline) · MC worker (experiments) |
(f64, u64, u8, placeCounts, placeOffsets) → finite number
— NaN/∞ throw
|
| Scenario | per-place expressions or one code-mode body | authoring/scenario/compile-scenario.ts |
Main thread, before createSimulation |
→ InitialMarking (+ scenario parameter values) |
| Place visualizer | module, Visualization(fn) returning JSX |
Host UI package (@hashintel/petrinaut,
ui/lib/compile-visualizer.ts — the one inherently
React-based surface, since visualizers author JSX)
|
Main thread render | ({tokens, parameters}) → ReactElement |
createSimulation, packed to
binary in buildSimulation.
metrics/specs.ts).
authoring/sandbox.ts)var window, document, globalThis, self, fetch, XMLHttpRequest,
importScripts, Function, setTimeout, setInterval, queueMicrotask
— name lookups resolve to undefined.
runSandboxed(action): blocks the
constructor-chain escape (({}).constructor.constructor →
Function) for the duration of the call, since shadowing
only stops identifier lookup.
new Function in the worker/main realm. Treat this as
robustness hardening (typos, accidental API use), not isolation.
HIR-emitted kernels construct small runtime values for
Distribution.Gaussian / Uniform / Lognormal. Kernels defer
sampling through the ABI sink; the engine samples each value once per
token with the seeded RNG (sample-distribution.ts), so
chained .map(fn) transforms share a single draw and runs stay
reproducible. When stochasticity is disabled, the runtime isn’t injected
and plain values are required.