FE-1153: Collapse per-type switches into a type-policy registry#8964
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
PR SummaryMedium Risk Overview Refactors call sites to delegate to the registry: Exports Mode-specific LSP widening (e.g. stochastic Reviewed by Cursor Bugbot for commit 30ca842. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Pull request overview
Refactors Petrinaut’s token-dimension “per-type” behavior into a single TYPE_POLICIES registry in @hashintel/petrinaut-core, replacing multiple scattered switch (element.type) blocks while keeping existing exported wrapper APIs stable.
Changes:
- Adds
simulation/engine/type-policies.ts(TYPE_POLICIES,COLOR_ELEMENT_TYPES,TypePolicy) to centralize per-type defaults, coercion, layout kind, at-rest encoding, and editor parsing. - Migrates key consumers (token codec/layout, LSP virtual-file generation, scenario compilation, schema migration, UI spreadsheet parsing) to read behavior from the registry.
- Adds a conformance test (
type-policies.test.ts) and derives the Zod enum fromCOLOR_ELEMENT_TYPESto keep the union/list/schema in lockstep.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| libs/@hashintel/petrinaut/src/ui/components/spreadsheet.tsx | Uses core TYPE_POLICIES for spreadsheet cell parsing instead of a local per-type switch. |
| libs/@hashintel/petrinaut/src/react/simulation/provider/migrate-initial-marking.ts | Simplifies stored-value coercion via shared coerceToStoredTokenAttributeValue. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/type-policies.ts | Introduces the centralized type-policy registry and canonical COLOR_ELEMENT_TYPES list. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/type-policies.test.ts | Adds conformance coverage to ensure registry/schema/layout invariants stay aligned. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/token-values.ts | Replaces switches with policy-driven defaults/coercion/decoding; adds coerceToStoredTokenAttributeValue. |
| libs/@hashintel/petrinaut-core/src/simulation/engine/token-layout.ts | Derives physical layout kind via TYPE_POLICIES rather than a switch. |
| libs/@hashintel/petrinaut-core/src/simulation/authoring/scenario/compile-scenario.ts | Encodes compiled initial state to JSON-safe at-rest form via policies. |
| libs/@hashintel/petrinaut-core/src/schemas/entity-schemas.ts | Derives the color-element type enum from COLOR_ELEMENT_TYPES. |
| libs/@hashintel/petrinaut-core/src/schema-migration.ts | Reuses policy-driven stored coercion/defaulting for scenario row migration. |
| libs/@hashintel/petrinaut-core/src/lsp/lib/generate-virtual-files.ts | Uses policy-driven TS type strings and optionality for generated token types. |
| libs/@hashintel/petrinaut-core/src/index.ts | Exposes TYPE_POLICIES, COLOR_ELEMENT_TYPES, and related types/utility to consumers. |
| libs/@hashintel/petrinaut-core/src/default-codes.ts | Uses policy-driven defaultValueSource for generated default code. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ab6eaa4 to
cace8f7
Compare
1665496 to
d1f4562
Compare
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
cace8f7 to
9c85e16
Compare
d1f4562 to
0344187
Compare
9c85e16 to
d27b847
Compare
0344187 to
83dabe0
Compare
TYPE_POLICIES collapses the per-type switches (physical kind, defaults, coercion, at-rest encoding, LSP type strings, editor parsing) into one registry consumed across core and UI, with a conformance test so a new element type fails loudly until every touchpoint is defined. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
83dabe0 to
dabfc56
Compare
d27b847 to
30ca842
Compare

🌟 What is the purpose of this PR?
Pure refactor closing out the discrete-types architecture retrospective: adding a token dimension type previously meant editing
switch (element.type)statements in seven far-apart places (buffer layout, coercion/defaults, generated kernel code, LSP virtual files, schema migration, scenario compilation, spreadsheet cell parsing) that stayed consistent by convention only. This PR gathers the per-type data into a singleTYPE_POLICIESregistry in petrinaut-core and adds a conformance test so a sixth type fails loudly until every touchpoint is defined.🔗 Related links
🚫 Blocked by
🔍 What does this change?
New
simulation/engine/type-policies.ts:TYPE_POLICIES: Record<ColorElementType, TypePolicy>where each policy carries:physicalKind(f64|u8|u64|u64x2) — packed-struct layout kinddefaultValue(runtime form) anddefaultValueSource(TS expression for generated default kernels, e.g.Uuid.generate())tsInputType/tsKernelOutputType/kernelOutputOptional— LSP virtual-file type stringscoerce(value, context)— runtime coercion (the old switch bodies)decodeNumberSlot— f64/u8 slot decode,nullfor uuid/string (decoded intoken-layout.ts)encodeAtRest(value)— runtime → JSON-safe document form (uuid bigint → canonical lowercase string)parseEditorText(raw)— total spreadsheet cell parsePlus
COLOR_ELEMENT_TYPES, the canonical runtime list of the union (as const satisfieskeeps it in lockstep; theRecordshape guarantees the reverse direction at compile time).Consumers converted (existing exported function names kept as thin wrappers, so the public API is unchanged):
token-values.ts(defaults/coercion/number-slot decode; new sharedcoerceToStoredTokenAttributeValuehelper),token-layout.ts(physicalTypeFor),default-codes.ts,lsp/lib/generate-virtual-files.ts,schema-migration.ts,compile-scenario.ts, and in the React packagemigrate-initial-marking.tsand the spreadsheet'sparseCellValue. The zod colour element schema'stypeenum now derives fromCOLOR_ELEMENT_TYPES.Deliberately left structural (control flow, not per-type data): uuid sentinel/RNG handling and string interning in
encode-kernel-token.ts; uuid-lane/string-pool read-write paths intoken-layout.ts; thereal+stochasticityDistributionunion and?: neverderivative exclusions in the LSP generator; spreadsheet uuid short-form/overlay and boolean-checkbox rendering (presentation);scenario-mapping.ts/initial-state-editor.tsxat-rest decoding (intentionally laxer semantics than core coercion — converting them would change behaviour).Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
fe-1153-type-policy-registry.md— the registry and its types are new public exports)📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
🐾 Next steps
TypePolicyrecord plus the structural sites the conformance test points at.🛡 What tests cover this?
type-policies.test.ts(32 assertions): registry keys ≡COLOR_ELEMENT_TYPES≡ the zod enum's options; per type:physicalKindagrees withcomputeTokenSlotLayout(kind, width, alignment);decodeNumberSlotpresent iff f64/u8; defaults round-trip coercion unchanged; at-rest encode is JSON-serializable; editor parse is total and coercion-stable.❓ How to test this?
npx turbo run lint:tsc lint:eslint test:unit --filter '@hashintel/petrinaut-core' --filter '@hashintel/petrinaut'— behaviour is otherwise identical to #8956.📹 Demo
N/A — no user-facing change.