FE-762: Petrinaut-format JSON export of the compiled net#157
FE-762: Petrinaut-format JSON export of the compiled net#157kostandinang wants to merge 1 commit into
Conversation
|
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. |
dc53d4c to
f6356f7
Compare
PR SummaryLow Risk Overview A new pure Tests cover envelope, labeling, transition metadata, marking grouping, JSON round-trip, and golden topology counts for fixture plans. Reviewed by Cursor Bugbot for commit ff3504c. Bugbot is set up for automated code reviews on this repo. Configure here. |
🤖 Augment PR SummarySummary: This PR adds a Petrinaut-compatible JSON export for the compiled Petri net so runs can be visualized/validated by the Petrinaut team. Changes:
Technical Notes: The export is designed as a pure serializer (no I/O); file output is owned by the runtime engine path when running via CLI. 🤖 Was this summary useful? React with 👍 or 👎 |
| // Skipped when runDir is absent (library callers / tests). | ||
| if (input.runDir) { | ||
| const net = serializeBlueprint(blueprint, { runId: input.runId ?? 'unknown' }); | ||
| writeFileSync(join(input.runDir, 'net.json'), `${JSON.stringify(net, null, 2)}\n`); |
There was a problem hiding this comment.
src/orchestrator/src/engine.ts:38 — Because the writeFileSync is inside the main try, any failure to write net.json (missing/unwritable runDir, permissions, disk issues) will halt the entire cook run even though compilation succeeded. If this is intended as best-effort integration output, it may be worth ensuring export failures don’t change the run’s success/failure semantics.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Serializes a (refactored, Petri-net-faithful) NetBlueprint into Petrinaut's
expected JSON format and writes it to <runDir>/net.json on every cook run,
so the Petrinaut team can render the compiled topology and pressure-test
the integration end-to-end.
What landed:
- New module src/orchestrator/src/petrinaut-export.ts: pure serializer
serializeBlueprint(blueprint, { runId, tokenIdFn? }) -> PetrinautNet.
- New types: PetrinautNet { schemaVersion, runId, places, transitions,
initialMarking }, PetrinautPlace { id, label }, PetrinautTransition
{ id, label, lane, kind, actor, guard, inputs, outputs }, PetrinautToken
{ id: <UUID>, sliceId?, epicId?, retryCount?, reworkCount? },
PetrinautMarking { place, tokens[] }.
- engine.ts: when input.runDir is present, writes the serialized net
to <runDir>/net.json after compileTopology() returns. Library callers
that omit runDir (tests) are unaffected.
- cook-cli.ts: passes the existing runDir through to the orchestrator.
- types.ts: OrchestratorInput gains optional runDir field.
Cross-team payload shape (2026-05-26 alignment):
- Token shape is { id: <UUID>, ...payload }. UUIDs generated at
serialization time. (Token UUID lifecycle across consume->emit is a
FE-763 open coordination item; v1 generates fresh per token.)
- schemaVersion '0.1.0' on the envelope for forward-compat.
- Place label strips slice:<id>: / epic:<id>: prefix for short visual
names; full internal id preserved as place.id.
Open coordination items (tracked on FE-762):
- exact JSON envelope per Petrinaut's loader (pending team)
- string vs uuid discrete type for semantic IDs (pending H-6518/H-6519)
- place naming convention (full ids vs short labels) — v1 emits both
Tests: 10 new tests in petrinaut-export.test.ts (envelope, places,
transitions, initial marking, round-trip, golden counts pinned for
simplePlan and depPlan). All 125 orchestrator tests pass; npm run fix /
check / build all green.
Co-authored-by: Amp <amp@ampcode.com>
e4be997 to
94351f0
Compare
f6356f7 to
ff3504c
Compare

Summary
petrinaut-export.ts— pure serializerserializeBlueprint(blueprint, { runId, tokenIdFn? }) → PetrinautNetconverting the (FE-761 Petri-net-faithful)NetBlueprintinto Petrinaut's expected JSON shape.<runDir>/net.jsonon every run so the Petrinaut team can render the compiled topology and pressure-test the integration.{ id: <UUID>, ...payload }per the cross-team-agreed format; envelope carriesschemaVersion0.1.0for forward-compatibility.Context
net.jsonforfixtures/txt/to begin their side of the work.What changed
src/orchestrator/src/petrinaut-export.ts: pure serializer.PetrinautNet { schemaVersion, runId, places, transitions, initialMarking },PetrinautPlace { id, label },PetrinautTransition { id, label, lane, kind, actor, guard, inputs, outputs },PetrinautToken { id, sliceId?, epicId?, retryCount?, reworkCount? },PetrinautMarking { place, tokens[] }.id; short visuallabelstrips theslice:<id>:/epic:<id>:prefix.inputscome fromTransitionSkeleton.inputs;outputsfromenumerateCandidateOutputs(so the full reachable output set is visible to Petrinaut, including the FE-761 Slice 4 dispatch →running:*arcs).sliceId,epicId,retryCount,reworkCount) preserved when present.engine.ts: wheninput.runDiris present, writes the serialized net to<runDir>/net.jsonaftercompileTopology()returns. Library callers and tests that omitrunDirare unaffected.cook-cli.ts: passes the existingrunDirthrough to the orchestrator.types.ts:OrchestratorInputgains optionalrunDirfield.Verification
petrinaut-export.test.ts: envelope (schemaVersion, runId), places (label-stripping), transitions (arc shape, contract metadata), initial marking (tokens grouped, UUIDs distinct, payload preserved), JSON round-trip, golden counts pinned per fixture (simplePlan: 22 places, 19 transitions, 5 places hold initial tokens;depPlan: 42 places, 37 transitions, 8 places).npm run verify(check + test + build) green.fixtures/txt/) deferred to cross-team validation once the loader is available.Out of scope
net.jsonand event stream to a live Petrinaut session (FE-764).Traceability
petri-blueprint-exportinmemory/PLAN.md; stacks on FE-761.