Skip to content

FE-738: Petri semantic lanes with two-lane subnet and engine factory#148

Open
kostandinang wants to merge 7 commits into
ka/fe-730-orchestrator-poc-dual-enginefrom
ka/fe-738-petri-semantic-lanes
Open

FE-738: Petri semantic lanes with two-lane subnet and engine factory#148
kostandinang wants to merge 7 commits into
ka/fe-730-orchestrator-poc-dual-enginefrom
ka/fe-738-petri-semantic-lanes

Conversation

@kostandinang
Copy link
Copy Markdown
Contributor

@kostandinang kostandinang commented May 21, 2026

Summary

  • Introduces the first Petri slice model where mechanical test success and semantic evaluator satisfaction are separate lanes; a slice completes only when both gates clear.
  • Adds structured orchestration events and transition metadata so observers can reason about firing without parsing ad-hoc logs.
  • Splits net compilation into topology blueprint vs handler wiring, and centralizes engine construction behind a single factory so proc/petri paths do not diverge on every frontier.

Context

  • FE-730 validated cook on a greenfield fixture with a minimal Petri loop. This PR is the substrate step toward richer plans where “tests green” and “evaluator says done” are intentionally different concerns.
  • Semantic rework is bounded via a dedicated budget place and RunPolicy.maxSemanticReworks, so assess/eval cycles cannot run unbounded when the evaluator never marks a slice satisfied.
  • Unblocks later work on parallel firing (FE-743) and graph-level analysis by making transition contracts and events first-class.

What changed

  • Two-lane subnet per slice: mechanical path evaluate → write-tests → write-code → run-tests; semantic path assess-semantic → semantic-satisfied; completion requires progress on both lanes.
  • TransitionContract metadata on transitions plus §7 event vocabulary (transition_fired, net_halted, net_deadlocked) with enough structure for contract tests and future tooling.
  • HandlerDescriptor union and typed handler wiring at the subnet boundary instead of growing ad-hoc closure dispatch.
  • Compiler split: compileTopology produces NetBlueprint; wireHandlers materializes PetriNet; createOrchestrator(policy) replaces duplicated orchestrator setup.

Verification

  • Full repo gate: npm run verify (fmt/lint check, test, build).
  • Engine contract suite extended for dual-lane semantics, semantic budget exhaustion, and structured events (1378 tests at PR time).

Out of scope

  • Stale-graph routing and full graph compilation/reachability (deferred to Phase 3; pairs with declarative routing in FE-747 and broader FE-700 work).
  • Parallel slice execution and resource pools (FE-743).

Traceability

  • Requirements 46–50; SPEC §2, §4, §6, §7, §8, §10; frontier petri-semantic-lanes in memory/PLAN.md; umbrella H-6476.

@kostandinang kostandinang changed the title FE-738: two-lane subnet with semantic completion gate FE-738: Petri semantic lanes — two-lane subnet, compiler split, engine factory May 21, 2026
@kostandinang kostandinang marked this pull request as ready for review May 22, 2026 12:38
@cursor
Copy link
Copy Markdown

cursor Bot commented May 22, 2026

PR Summary

Medium Risk
Changes core orchestration topology and completion gates (slice cannot complete without semantic satisfaction); engine/proc duality is removed in favor of one serial path—behavior shifts are covered by expanded contract tests but cook CLI flags changed.

Overview
Petri semantic lanes (FE-738) split mechanical TDD completion from semantic acceptance in the orchestrator subnet, and refactor how nets are built and run.

Each slice now has a mechanical lane (evaluate → write-tests → write-code → run-tests → done-spec) and a semantic lane (assess-semantic after done-spec, then semantic-satisfied). return-done only fires on semantic-satisfied, so tests passing alone cannot finish a slice. Failed semantic checks route back to needs-more (extra TDD cycles); maxSemanticReworks on RunPolicy and in-net semantic-budget tokens cap infinite rework.

Compiler refactor: compileTopology → pure NetBlueprint with HandlerDescriptor recipes and TransitionContract metadata; wireHandlers attaches runtime closures. createOrchestrator(policy) replaces duplicate PetriOrchestrator / ProceduralOrchestrator and engine-run.ts. brunch cook uses --policy=serial instead of --engine=proc|petri. RunCtx moves to types.ts.

Interpreter: optional NetEventSink emits §7-style transition_fired, net_halted, and net_deadlocked (with benign residual places so clean completion is not misclassified). Contract tests cover semantic rework and event capture; pi-actions adds a POC assess-semantic that auto-satisfies.

Planning docs: memory/CARDS.md removed; memory/PLAN.md marks petri-semantic-lanes done and defers stale-graph work to petri-graph-compilation.

Reviewed by Cursor Bugbot for commit 78706a2. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread src/orchestrator/src/cook-cli.ts
Comment thread src/orchestrator/src/petri-net.ts
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 22, 2026

🤖 Augment PR Summary

Summary: 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:

  • Introduces a two-lane slice subnet (mechanical TDD loop + semantic assessment) with a completion gate so slices can’t finish without semantic satisfaction.
  • Adds TransitionContract metadata to transitions (kind/lane/actor/guard) to classify execution without parsing IDs.
  • Splits the compiler into compileTopology(plan, policy) → NetBlueprint (pure topology) and wireHandlers(...) (runtime closures), plus a convenience compilePlan wrapper.
  • Consolidates engine entrypoints into createOrchestrator(firingPolicy), removing duplicated Petri/procedural engine classes.
  • Adds semantic rework budgeting via a semantic-budget token (reworkCount) and RunPolicy.maxSemanticReworks to prevent infinite semantic-rejection loops.
  • Defines §7-style interpreter events (transition_fired, net_halted, net_deadlocked) and updates adapter tests to assert event emission.
  • Updates engine contract tests to cover semantic-gate rework and semantic budget exhaustion scenarios.

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 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/orchestrator/src/net-compiler.ts
Comment thread src/orchestrator/src/cook-cli.ts Outdated
@kostandinang kostandinang force-pushed the ka/fe-730-orchestrator-poc-dual-engine branch from b72d1ad to 934ea57 Compare May 22, 2026 14:14
@kostandinang kostandinang force-pushed the ka/fe-738-petri-semantic-lanes branch from 8e56a7c to f959557 Compare May 22, 2026 14:14
Comment thread src/orchestrator/src/net-compiler.ts
@kostandinang kostandinang force-pushed the ka/fe-738-petri-semantic-lanes branch from f959557 to 1747538 Compare May 22, 2026 14:59
@kostandinang kostandinang changed the base branch from ka/fe-730-orchestrator-poc-dual-engine to graphite-base/148 May 25, 2026 11:01
@kostandinang kostandinang force-pushed the ka/fe-738-petri-semantic-lanes branch from da2bb0d to 6c4fd65 Compare May 25, 2026 11:02
@kostandinang kostandinang changed the base branch from graphite-base/148 to ka/fe-730-orchestrator-poc-dual-engine May 25, 2026 11:02
@kostandinang kostandinang force-pushed the ka/fe-730-orchestrator-poc-dual-engine branch from ab20ef2 to 5585e4e Compare May 25, 2026 11:05
@kostandinang kostandinang force-pushed the ka/fe-738-petri-semantic-lanes branch 3 times, most recently from e76b68a to 745c45a Compare May 25, 2026 11:23
@kostandinang kostandinang self-assigned this May 26, 2026
@kostandinang kostandinang requested a review from lunelson May 26, 2026 07:52
@kostandinang kostandinang changed the title FE-738: Petri semantic lanes — two-lane subnet, compiler split, engine factory FE-738: Petri semantic lanes with two-lane subnet and engine factory May 27, 2026
@kostandinang kostandinang force-pushed the ka/fe-738-petri-semantic-lanes branch from 745c45a to 78b15a6 Compare May 27, 2026 23:16
@kostandinang kostandinang force-pushed the ka/fe-730-orchestrator-poc-dual-engine branch from 44300a6 to 052f6e7 Compare May 27, 2026 23:16
kostandinang and others added 7 commits May 28, 2026 01:20
- 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>
…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>
…ion.

Register assess-semantic in createPiActions, replace the obsolete --engine flag with --policy wired to createOrchestrator, and skip net_deadlocked when only resource or completion tokens remain.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kostandinang kostandinang force-pushed the ka/fe-730-orchestrator-poc-dual-engine branch from 052f6e7 to 6d35473 Compare May 27, 2026 23:21
@kostandinang kostandinang force-pushed the ka/fe-738-petri-semantic-lanes branch from 78b15a6 to 78706a2 Compare May 27, 2026 23:21
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 78706a2. Configure here.

expect(net.transitionCount).toBe(13);
// Should have a net_halted event (ctx.halted becomes true after retry exhaustion)
const halted = events.filter((e) => e.kind === 'net_halted');
expect(halted.length).toBe(1);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test name says "net_deadlocked" but asserts "net_halted"

Medium Severity

The test is named "retry exhaustion emits net_deadlocked" but the assertion on line 827 checks for net_halted events, not net_deadlocked. These are semantically distinct §7 events: net_halted fires when shouldHalt() returns true (external halt signal from ctx.halted), while net_deadlocked fires when no transition is enabled but work-bearing tokens remain. Retry exhaustion sets ctx.halted = true, triggering net_halted on the next loop iteration — it never produces a net_deadlocked event. The test name misrepresents what behavior is actually being verified, which could mislead developers reasoning about the event model.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 78706a2. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant