FE-1121: Add UUID token dimension type#8953
Conversation
128-bit RFC-4122 UUIDs as a fourth colour element type: - Buffers: two 64-bit little-endian lanes (u64x2, 16 B, align 8) read through a shared BigUint64Array view; whole-token byte copies keep arbitrary bit patterns intact (no NaN-canonicalization hazard). - Runtime: one 128-bit `bigint` (value-semantic ===). At rest (documents, scenario JSON): canonical lowercase strings. - Kernels: uuid output fields are optional — omitted values are auto-generated from the seeded simulation RNG (deterministic per seed, v4 version/variant bits). Explicit `Uuid.generate()` and `Uuid.from(value)` sentinels are injected into user code like `Distribution`; forwarding an input uuid is plain pass-through. Kernel encoding is deduplicated into engine/encode-kernel-token.ts, shared by the interactive and Monte Carlo paths. - Coercion: total `toUuid` — valid strings parse, anything else (numbers, free text) converts deterministically via UUIDv5 under a fixed Petrinaut namespace; nil UUID (0n) is the typed default. - LSP: inputs type uuid as `bigint`; kernel outputs generate per-element Output_ types in both stochasticity modes with `uuid?: bigint | string | PetrinautUuid`; Distribution stays rejected for uuid; dynamics derivatives stay `?: never`. - UI: UUID option in the dimension type select; spreadsheet uuid cells show an 8-hex short form (full string on select/edit, free text v5-converted on commit); scenario forms round-trip strings⇄bigints; playground renders u64x2 slots with lo/hi lane labels. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
PR SummaryMedium Risk Overview Engine & storage: Frame buffers gain a Kernel semantics: Authoring surface: Schema, LSP virtual types ( Reviewed by Cursor Bugbot for commit c903c36. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Pull request overview
Adds a new uuid token dimension type to Petrinaut (UI + persistence + simulation/LSP), represented as bigint at runtime, encoded as u64x2 in frame buffers, and stored as canonical UUID strings at rest.
Changes:
- Introduces UUID parsing/formatting/coercion (
toUuid, seeded generation, v5 fallback) and wires it through kernel output encoding and token-layout packed structs. - Extends UI editors (type dropdown, initial state + scenario spreadsheets, encoding playground) to display/edit UUIDs and round-trip at-rest strings ⇄ runtime bigints.
- Updates schemas, LSP virtual files, AI guidance, and adds broad test coverage for UUID behavior and determinism.
Reviewed changes
Copilot reviewed 48 out of 48 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| libs/@hashintel/petrinaut/src/ui/views/shared/place-state-visualization.tsx | Coerces initial marking token records so uuid strings become runtime bigints. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/view-scenario-drawer.tsx | Plumbs token-row context and uses mapping helpers for scenario spreadsheet data. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/scenario-mapping.ts | Converts scenario persisted rows (uuid strings) ⇄ spreadsheet runtime values (bigints). |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/create-scenario-drawer.tsx | Provides token-row context when creating new scenarios. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/PropertiesPanel/type-properties/subviews/main.tsx | Adds UUID to the dimension type selector. |
| libs/@hashintel/petrinaut/src/ui/views/Editor/panels/PropertiesPanel/place-properties/subviews/place-initial-state/initial-state-editor.tsx | Parses at-rest uuid strings to bigints for the initial marking spreadsheet. |
| libs/@hashintel/petrinaut/src/ui/lib/compile-visualizer.ts | Allows visualizers to receive bigint token attributes. |
| libs/@hashintel/petrinaut/src/ui/dev/token-encoding-playground/token-memory-view.tsx | Displays uuid values in canonical string form and labels u64x2 lanes. |
| libs/@hashintel/petrinaut/src/ui/dev/token-encoding-playground/playground-monaco.ts | Types uuid fields as `bigint |
| libs/@hashintel/petrinaut/src/ui/dev/token-encoding-playground/physical-layout.ts | Updates token decode to use unified token views; documents u64x2 bit ordering. |
| libs/@hashintel/petrinaut/src/ui/dev/token-encoding-playground/physical-layout.test.ts | Adds layout/round-trip/bit-order coverage for uuid (u64x2) fields. |
| libs/@hashintel/petrinaut/src/ui/dev/token-encoding-playground/dimension-editor.tsx | Adds UUID option in the playground dimension editor. |
| libs/@hashintel/petrinaut/src/ui/components/spreadsheet.tsx | Supports uuid columns (bigint values), display truncation, and text editing/coercion. |
| libs/@hashintel/petrinaut/docs/simulation.md | Documents UUID behavior in the initial marking spreadsheet. |
| libs/@hashintel/petrinaut/docs/scenarios.md | Documents UUID behavior in scenario spreadsheets. |
| libs/@hashintel/petrinaut/docs/petri-net-extensions.md | Documents the new UUID dimension type and kernel semantics. |
| libs/@hashintel/petrinaut-core/src/types/sdcpn.ts | Extends element types + token attribute value types; updates scenario row typing. |
| libs/@hashintel/petrinaut-core/src/simulation/monte-carlo/transition-effect.ts | Reuses shared kernel-token encoder and unified token views. |
| libs/@hashintel/petrinaut-core/src/simulation/monte-carlo/frame-reader.ts | Reads tokens via unified token views. |
| libs/@hashintel/petrinaut-core/src/simulation/monte-carlo/frame-buffer.ts | Adds shared f64/u64/u8 token region views to Monte Carlo frames. |
| libs/@hashintel/petrinaut-core/src/simulation/frames/internal-frame.ts | Adds shared f64/u64/u8 token region views to engine frames. |
| libs/@hashintel/petrinaut-core/src/simulation/frames/frame-reader.ts | Reads tokens via unified token views. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/uuid.ts | Implements uuid parsing/formatting/total coercion + seeded v4 generation. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/uuid.test.ts | Tests uuid parsing/formatting/coercion and RNG-based generation invariants. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/types.ts | Expands kernel output typing to include optional uuid + uuid sentinels. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/token-values.ts | Adds uuid default/coercion and updates encoder return type for uuid lanes. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/token-layout.ts | Adds u64x2 physical kind + BigUint64Array view; reads/writes uuid lanes. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/token-layout.test.ts | Adds layout + lane-level correctness tests for uuid fields. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/token-layout.test-helpers.ts | Updates helpers to use unified token views. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/encode-kernel-token.ts | Deduplicates kernel output token encoding (Distribution + uuid sentinel handling). |
| libs/@hashintel/petrinaut-core/src/simulation/engine/compute-possible-transition.ts | Uses shared kernel-token encoder and unified token views. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/compute-possible-transition.test.ts | Adds behavioral tests for uuid kernel outputs (omit/generate/from/forward/errors). |
| libs/@hashintel/petrinaut-core/src/simulation/engine/compute-next-frame.test.ts | Adds end-to-end test ensuring uuid lanes survive pipeline without NaN canonicalization. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/build-simulation.ts | Reads tokens via unified token views for dynamics input. |
| libs/@hashintel/petrinaut-core/src/simulation/authoring/user-code/uuid-runtime.ts | Adds Uuid.generate/from sentinels for user code. |
| libs/@hashintel/petrinaut-core/src/simulation/authoring/user-code/compile-user-code.ts | Injects Uuid runtime code unconditionally into compiled user code. |
| libs/@hashintel/petrinaut-core/src/simulation/authoring/user-code/compile-user-code.test.ts | Tests Uuid runtime injection (including when Distribution is disabled). |
| libs/@hashintel/petrinaut-core/src/simulation/authoring/scenario/compile-scenario.ts | Normalizes uuid values to canonical strings for JSON-safe compiled scenario output. |
| libs/@hashintel/petrinaut-core/src/simulation/authoring/scenario/compile-scenario.test.ts | Adds scenario compilation tests for uuid normalization and deterministic v5 mapping. |
| libs/@hashintel/petrinaut-core/src/simulation/api.ts | Introduces JSON-safe initial marking typing that can accept uuid strings. |
| libs/@hashintel/petrinaut-core/src/schemas/scenario-schema.ts | Allows strings in persisted token rows (to support uuid-at-rest strings). |
| libs/@hashintel/petrinaut-core/src/schemas/entity-schemas.ts | Extends element type schema with uuid and updates descriptions. |
| libs/@hashintel/petrinaut-core/src/lsp/lib/generate-virtual-files.ts | Types uuid as bigint; generates kernel output types with optional uuid + sentinels. |
| libs/@hashintel/petrinaut-core/src/lsp/lib/checker.test.ts | Adds LSP checker tests around uuid typing and invalid Distribution-on-uuid outputs. |
| libs/@hashintel/petrinaut-core/src/index.ts | Exports uuid utilities and token region views. |
| libs/@hashintel/petrinaut-core/src/default-codes.ts | Uses Uuid.generate() as the default value source for uuid elements. |
| libs/@hashintel/petrinaut-core/src/ai.ts | Updates AI guidance for uuid typing and kernel/scenario semantics. |
| .changeset/fe-1121-uuid-token-dimension-type.md | Publishes a minor changeset describing the uuid dimension feature. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (typeof cell === "string") { | ||
| return elements?.[columnIndex]?.type === "boolean" | ||
| ? cell.trim().toLowerCase() === "true" | ||
| : Number.parseFloat(cell) || 0; | ||
| } |
| if (column.type === "uuid") { | ||
| return toUuid(raw); | ||
| } | ||
| return typeof raw === "string" ? Number.parseFloat(raw) || 0 : raw; | ||
| }; |
- Selecting a uuid spreadsheet cell now expands it to the full canonical string in an opaque overlay that spills over neighbouring cells (anchored right for columns in the right half of the table so the scroll container never clips it); unselected cells keep the short 8-hex form with the full value as a hover tooltip. New "Typed columns" spreadsheet story covers all four dimension types. - generateUuidFromRng now takes the top 16 bits of eight draws instead of 32 bits of four: the seeded LCG's multiply exceeds 2^53 for large states, so each draw's low ~8 bits are float-precision artifacts — previously every generated UUID visibly ended each word in zeros. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| export function formatUuid(value: bigint): string { | ||
| const hex = value.toString(16).padStart(32, "0"); | ||
| return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`; | ||
| } |
| const toCanonicalUuidString = (value: SpreadsheetCellValue): string => | ||
| formatUuid(typeof value === "bigint" ? value : toUuid(value)); |
| if ( | ||
| elements?.[columnIndex]?.type === "uuid" || | ||
| typeof cell === "bigint" | ||
| ) { | ||
| return formatUuid(typeof cell === "bigint" ? cell : toUuid(cell)); | ||
| } |
🌟 What is the purpose of this PR?
Adds
uuidas a fourth colour element type: 128-bit RFC-4122 identifiers on tokens, enabling entity-identity modelling (track a specific token across places, correlate firings, derive stable IDs from data). This is the first token attribute wider than one f64 slot — it exercises the format-v2 packed-struct layout exactly as designed.🔗 Related links
🚫 Blocked by
🔍 What does this change?
Representation (three layers):
u64x2physical kind — two 64-bit little-endian lanes (16 B, align 8; JS has no 128-bit load, so 8-byte alignment is deliberate), read/written through a sharedBigUint64Arrayview. Whole-token byte copies keep arbitrary bit patterns intact — a NaN-payload UUID (ffffffff-ffff-4fff-bfff-…) round-trips through marking → dynamics → firing → compaction → clone → reader (tested).bigint— value-semantic (tokenA.id === tokenB.idjust works), measured cheaper than the string form.JSON.stringify-safe.Kernel semantics:
crypto.randomUUID).Uuid.generate()(explicit seeded generation) andUuid.from(value)(derive a stable ID from any value) are injected into user code as engine-resolved sentinels, mirroringDistribution. Forwarding an input token's uuid is plain pass-through.engine/encode-kernel-token.ts, shared by the interactive engine and Monte Carlo (was copy-pasted).Distributionon a uuid field stays a type error (LSP) and a runtime error.Coercion — total
toUuid(value): bigint, never throws: valid UUID strings parse (any case → canonical);bigintin range passes through; anything else (numbers, free text) converts deterministically via UUIDv5 under a fixed exportedPETRINAUT_UUID_NAMESPACE; nil UUID (0n) is the typed default.LSP: input tokens type uuid as
bigint; kernel outputs now generate per-elementOutput_<colour>types in both stochasticity modes withuuid?: bigint | string | PetrinautUuid;Uuid/PetrinautUuiddeclarations always available; dynamics derivatives keepuuid?: never.UI: UUID option in the dimension type select; spreadsheet uuid cells show an 8-hex short form (full canonical string via
titleand when selected/edited; committed text goes throughtoUuid, so free text likealiceyields a stable ID; Delete → nil); scenario drawers round-trip strings⇄bigints; the token-encoding playground renders u64x2 slots withlo/hilane labels and the canonical string in the hover panel.Docs/schema/AI guidance updated (
petri-net-extensions.md+ scenario/simulation notes, Zod descriptions,ai.ts).Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
petri-net-extensions.mdshows a 3-option dropdown and should be re-captured with UUID visible🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
uuidlibrary all assume 16 bytes; the layout machinery generalizes tou64×4later if a real need for wider IDs appears (noted on the ticket).bigint— fine for comparison/counting, butJSON.stringifyon a whole token would throw in user code (standard bigint behaviour).🐾 Next steps
🛡 What tests cover this?
engine/uuid.test.ts(parse/format, toUuid fixtures incl. stable v5,generateUuidFromRngdeterminism + version/variant bits)compute-next-frame.test.tsUuid.fromstability, forwarding, Distribution-on-uuid throwsUuid.generate()outputs valid, Distribution on uuid invalidlint:tsc+lint:eslintclean❓ How to test this?
yarn devinlibs/@hashintel/petrinaut.Uuid.from(input.Source[0].some_value)for derived IDs.📹 Demo
The playground story renders the exact wire format: a UUID slot with lane labels and the input → stored → reads-back round-trip.