FE-738: Petri semantic lanes — two-lane subnet, compiler split, engine factory#148
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. |
PR SummaryMedium Risk Overview Refactors compilation into a pure topology pass ( Extends the Petri interpreter with Reviewed by Cursor Bugbot for commit 1747538. Bugbot is set up for automated code reviews on this repo. Configure here. |
| const hasTokens = [...this.places.values()].some((tokens) => tokens.length > 0); | ||
| if (hasTokens) { | ||
| eventSink?.emit({ kind: 'net_deadlocked', ts: new Date().toISOString() }); | ||
| } |
There was a problem hiding this comment.
False net_deadlocked on success
Medium Severity
When no transition is enabled, the interpreter emits net_deadlocked whenever any place still holds tokens. After a successful slice, idle test-agent and code-agent tokens remain, so completed runs can record a deadlock event alongside normal transition_fired events.
Reviewed by Cursor Bugbot for commit 8e56a7c. Configure here.
🤖 Augment PR SummarySummary: This PR evolves the Petri-net orchestrator by introducing distinct mechanical vs semantic completion lanes, and refactors compilation/execution so the net shape is testable as pure data. Changes:
Technical Notes: Topology-only adapter tests no longer require action handlers/test runners, and runtime wiring now interprets declarative handler descriptors from the blueprint. 🤖 Was this summary useful? React with 👍 or 👎 |
| const budgetToken = consumed[1]!; | ||
| const reworkCount = budgetToken.reworkCount ?? 0; | ||
|
|
||
| const reportId = await actions[actionKey]!(actCtx); |
There was a problem hiding this comment.
wireHandlers() assumes actions[actionKey] exists (non-null asserted), but the compiled topology now includes an assess-semantic handler kind—createPiActions() currently doesn’t define assess-semantic, so brunch cook will throw once a slice reaches semantic assessment.
Severity: high
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
|
|
||
| const engine: Orchestrator = | ||
| opts.engine === 'petri' ? new PetriOrchestrator() : new ProceduralOrchestrator(); | ||
| const engine = createOrchestrator('serial'); |
There was a problem hiding this comment.
b72d1ad to
934ea57
Compare
8e56a7c to
f959557
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f959557. Configure here.
| const reworkCount = budgetToken.reworkCount ?? 0; | ||
|
|
||
| const reportId = await actions[actionKey]!(actCtx); | ||
| ctx.reportIds.push(reportId); |
There was a problem hiding this comment.
Missing assess-semantic cook handler
High Severity
The subnet now requires an assess-semantic transition before return-done, and wireHandlers invokes actions['assess-semantic'], but createPiActions (used by brunch cook) never registers that handler. Real fixture runs halt or throw once mechanical work reaches semantic assessment.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit f959557. Configure here.
- Add semantic-gate and semantic-satisfied places per slice - Add assess-semantic transition joining done-spec + semantic-gate - On pass: produces semantic-satisfied → return-done proceeds - On fail: routes to needs-more, forcing another TDD rework cycle - return-done now consumes semantic-satisfied (not done-spec directly) - PlanDoneAccepted is topologically unreachable without semantic satisfaction - New contract test #10: semantic gate rejects then accepts - Updated all call-order assertions and adapter test counts Co-authored-by: Amp <amp@ampcode.com>
- Define TransitionContract type (kind, lane, actor, guard) in petri-net.ts - Add contract field to TransitionDef (optional, no behavioral change) - Populate contract metadata for all compiled transitions: mechanical-lane (evaluate, write-tests, write-code, run-tests), semantic-lane (assess-semantic, return-done), structural (slice-ready, epic-complete, epic-deps-met) - Add getTransitions() accessor on PetriNet for inspection - New adapter test verifies contract metadata classification Co-authored-by: Amp <amp@ampcode.com>
- Define NetEvent, NetEventKind, NetEventSink types in petri-net.ts - PetriNet.run() accepts optional event sink (backward compatible) - Emits transition_fired with id, contract, consumed/produced places - Emits net_halted when shouldHalt() triggers - Emits net_deadlocked when no transition enabled but tokens remain - New adapter tests: happy-path event capture + retry-exhaustion halt - Note: deadlock detection is coarse (leftover resource tokens trigger it on clean completion); refined detection is future work Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Amp <amp@ampcode.com>
…dget - Split compilePlan into compileTopology (pure data → NetBlueprint) and wireHandlers (attaches fire closures). Adapter tests use topology-only. - Consolidate identical PetriOrchestrator/ProceduralOrchestrator into createOrchestrator(policy) factory. Delete engine-petri.ts/engine-proc.ts. - Move RunCtx from net-compiler.ts to types.ts (compiler is context-free). - Add semantic-budget place + reworkCount token to prevent infinite rework loops when assess-semantic always rejects (Finding #8 correctness fix). - HandlerDescriptor discriminated union (7 kinds) makes transition routing declarative in the blueprint. All descriptors carry actionKey explicitly. - New net-blueprint.ts for NetBlueprint/TransitionSkeleton/HandlerDescriptor types. - 1378 tests pass across 120 files. Co-authored-by: Amp <amp@ampcode.com>
…compilation Co-authored-by: Amp <amp@ampcode.com>
f959557 to
1747538
Compare



Summary
Phase 1 of the petri orchestrator arc (umbrella H-6476). First frontier where petri models a distinction proc cannot express topologically: mechanical completion ≠ semantic completion. Stacks on FE-730 (#143).
Changes
evaluate→write-tests→write-code→run-tests) and semantic (assess-semantic→semantic-satisfied), joined by a completion gate soPlanDoneAcceptedis unreachable without both.TransitionContractmetadata on every transition (kind, lane, actor, guard).transition_fired,net_halted,net_deadlockedemitted by the interpreter.compileTopology(plan, policy) → NetBlueprint(pure data) +wireHandlers(blueprint, input, ctx) → PetriNet(closures). Adapter tests run on topology alone.createOrchestrator(policy)replaces duplicatedPetriOrchestrator/ProceduralOrchestrator(~120 LOC).HandlerDescriptordiscriminated union — declarative branch outputs per transition (onPass/onFail/onTrue/onFalse/onSatisfied/onRejected).semantic-budgetplace +reworkCounttoken prevents infinite rework loops (review finding Bump picomatch #8). AddsRunPolicy.maxSemanticReworks.Verification
npm run verifyclean — 1378 tests across 120 files.Acceptance (per
memory/PLAN.md)(1)–(4), (6) met. (5) stale-graph routing to reconciliation deferred to follow-up slice.
Next
FE-743 / #149 —
petri-parallel-execution(Phase 2, decision-gated on wall-clock improvement).