Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 4 Skipped Deployments
|
There was a problem hiding this comment.
🟡 Changes recommended
Valid definitions can produce identifier collisions, rejected kernels, blocked item consumers, and ambiguous input routing.
4 open issues
What changed in this PR
Adds @local/flow-petri-net to compile Flow Definitions into Petrinaut nets for future visualization and execution, while keeping definitions as the source of truth.
Changes:
- Compiles action lifecycles, for-each steps, and value routing.
- Adds deterministic IDs, token colours, metadata, kernels, and layout.
- Includes compatibility tests, documentation, and package setup.
| File | Description |
|---|---|
yarn.lock |
Registers the workspace package. |
libs/@local/flow-petri-net/turbo.json |
Configures build and test dependencies. |
libs/@local/flow-petri-net/tsconfig.json |
Configures TypeScript checking. |
libs/@local/flow-petri-net/tsconfig.build.json |
Configures build output. |
libs/@local/flow-petri-net/src/compile-flow-definition/shared/value-places.ts |
Allocates value storage and consumer copies. |
libs/@local/flow-petri-net/src/compile-flow-definition/shared/step-places.ts |
Defines lifecycle place IDs. |
libs/@local/flow-petri-net/src/compile-flow-definition/shared/net-elements.ts |
Defines transition roles and element helpers. |
libs/@local/flow-petri-net/src/compile-flow-definition/shared/net-builder.ts |
Accumulates root-net elements. |
libs/@local/flow-petri-net/src/compile-flow-definition/shared/lay-out.ts |
Positions net nodes. |
libs/@local/flow-petri-net/src/compile-flow-definition/shared/kernels.ts |
Generates placeholder token kernels. |
libs/@local/flow-petri-net/src/compile-flow-definition/shared/flow-steps.ts |
Indexes steps and resolves payload shapes. |
libs/@local/flow-petri-net/src/compile-flow-definition/shared/colors.ts |
Defines token schemas and colours. |
libs/@local/flow-petri-net/src/compile-flow-definition/shared/action-subnet-ids.ts |
Defines subnet and port IDs. |
libs/@local/flow-petri-net/src/compile-flow-definition/generate-action-subnet.ts |
Generates action lifecycle subnets. |
libs/@local/flow-petri-net/src/compile-flow-definition/generate-action-subnet.test.ts |
Tests subnet ports and lifecycle structure. |
libs/@local/flow-petri-net/src/compile-flow-definition/compile-for-each-step.ts |
Compiles iteration and collection. |
libs/@local/flow-petri-net/src/compile-flow-definition/compile-action-step.ts |
Compiles action instances and connections. |
libs/@local/flow-petri-net/src/compile-flow-definition.ts |
Coordinates validation and net compilation. |
libs/@local/flow-petri-net/src/compile-flow-definition.test.ts |
Tests compatibility, routing, and determinism. |
libs/@local/flow-petri-net/README.md |
Documents architecture and limitations. |
libs/@local/flow-petri-net/package.json |
Declares exports, scripts, and dependencies. |
libs/@local/flow-petri-net/LICENSE.md |
Declares the package licence. |
libs/@local/flow-petri-net/eslint.config.js |
Configures package linting. |
libs/@local/flow-petri-net/docs/task-dependencies.json |
Records task dependency relationships. |
Review effort: Balanced
…om its consumer with ~, so no step id can collide with another key
…ther than its label, so kernels can address it
…tion's inputs takes, which its arcs alone don't say
… own, as other values do, so two consumers don't race for one token
757ad7f to
415425e
Compare
…copy's value from its consumer with the step run id separator rather than a literal
PR SummaryMedium Risk Overview The compiler wires action steps as component instances of per-action subnets (ports, attempt/retry/give-up lifecycle, Root Coverage includes compiling all in-repo hardcoded flows, routing cases, determinism, and Petrinaut import/model build checks; README documents net shape and known limitations. Reviewed by Cursor Bugbot for commit ca0fef0. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a79133c. Configure here.
…tor, and name each value's place by its key, so no two outputs share a place or a name
…sts, rather than through a RunRequests place and startRun transition
|
|
||
| if (key) { | ||
| getValue(key).consumers.push({ | ||
| key: `${step.stepId}.${inputName}`, |
There was a problem hiding this comment.
These keys are rebuilt in compile-action-step.ts L90 and compile-for-each-step.ts L66/L115. Could placeValues own them?
| getValue(key).consumers.push({ | ||
| key: `${step.stepId}.${inputName}`, | ||
| label: `${step.stepId}.${inputName}`, | ||
| consumes: consumes(source), |
There was a problem hiding this comment.
A step inside a for-each that consumes an outer value only gets one token, so items after the first get stuck.
| * collected output. | ||
| * - A step that gives up puts a token in `FailedStepRuns`. | ||
| * | ||
| * Transitions carry their role in `metadata.role`, for the executor to interpret: the net has no guards or |
There was a problem hiding this comment.
there are placeholder kernels now.
| "exports": { | ||
| "./compile-flow-definition": { | ||
| "types": "./src/compile-flow-definition.ts", | ||
| "default": "./dist/compile-flow-definition.js" | ||
| } | ||
| }, |
There was a problem hiding this comment.
Only compileFlowDefinition is exported, but the executor and run view will need TransitionRole, the metadata shapes, and the key helpers. The README says ids are worked out from keys. Export those too?
| } from "@local/hash-isomorphic-utils/flows/types"; | ||
|
|
||
| describe("generateActionSubnet", () => { | ||
| it("gives an action a port per input and output, and one it gives up through", async () => { |
There was a problem hiding this comment.
some actions never get compiled in any test. Could we loop over every action definition here?



🌟 Purpose
We want to use Petri net (PN) representations for Flows in two places:
The PN representation will not be stored in the database. We will keep using the more minimal Flow Definition format. This gives us the freedom to change how we compile to a PN, for example to change how we compose sub-nets.
This PR adds the compiler: a new package,
@local/flow-petri-net, that turns aFlowDefinitioninto a Petrinaut-format net. The alternative to using a new package would be the existing@local/hash-isomorphic-utils, but making that dependent on@hashintel/petrinaut-core(as the compiler requires) would cause a change topetrinaut-coreto invalidate the build of many other packages. We can always revisit this.Nothing in the app calls the compiler yet. FE-1897 (next) will use it to show a flow as its net in the flow and run pages, and FE-1904 to run them.
This is an initial version – we'll definitely need to change it when we update how subnet composition works in Petrinaut (moving to place fusion), and there are probably lots of improvements that can be made beyond those noted in known issues.
🔍 Changes
libs/@local/flow-petri-net/README.mdsrc/compile-flow-definition.tscompileFlowDefinition, the package's one export: indexes the steps, adds the root net's places andrunStart, compiles each step, and generates the subnets the steps use.src/compile-flow-definition/generate-action-subnet.tssrc/compile-flow-definition/compile-action-step.ts,compile-for-each-step.tsrouteandfailtransitions, and afor-eachstep's iterator and accumulator.src/compile-flow-definition/shared/value-places.tscopytransitions where one token has to become several.src/compile-flow-definition/shared/(the rest)What the executor and a run's view need from the net
metadata.role. The executor (FE-1904) firessucceedAttemptandfailAttemptwhen an action's activity completes, and every other transition as soon as it's enabled. Each role is named for what its transition does, verb first, so that no two kinds of transition share one.metadata.stepId, so a run's view (FE-1932) can map between steps and the net.p.input.promptort.route.<step>. Since FE-1882, Petrinaut converts any id that isn't a UUID to a UUIDv5 when it loads a net. Each id in a compiled net is already that UUID, made from its key withtoPetrinautId.run_idanditem_pathforward, and there are no guards: nothing correlates tokens of one run, or stops the iterator and accumulator. The executor interprets transitions by their role instead (FE-1904).present: false). But a step whose value on a "skip when missing" connection is absent isn't skipped in the net, and an optional output the action didn't produce isn't marked absent: both need the executor's absent tokens (FE-1904).for-eachstep's item tokens stay after their item finishes.t.startItemputs one token per item in the step's item place, and the steps inside thefor-eachread it, so each of them can see the item. Nothing consumes it. Consuming it needs a transition that knows every step of that item has finished, which needs the item correlation that FE-1914 adds.donetoken in its port. No action has no outputs today, so this case isn't tested.