FE-743: Petri parallel execution — concurrent firing, resource pools, worktree-per-slice#149
Conversation
PR SummaryHigh Risk Overview Reworks compilation/runtime to use shared Updates Reviewed by Cursor Bugbot for commit 0f5cdbf. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
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. |
| } | ||
| } | ||
|
|
||
| if (firstError) throw firstError; |
There was a problem hiding this comment.
Parallel batch ignores halt flag
Medium Severity
Under parallel policy, shouldHalt (wired to ctx.halted) is only checked at the start of each loop iteration. If one transition in a concurrent batch sets ctx.halted (retry or semantic exhaustion), sibling transitions in the same Promise.allSettled batch still run to completion, unlike serial mode where the next transition is skipped.
Reviewed by Cursor Bugbot for commit 6ff7563. Configure here.
🤖 Augment PR SummarySummary: This PR completes FE-743 by adding true parallel Petri-net execution, shared agent resource pools, and per-slice worktree isolation to reduce wall-clock time on multi-slice plans. Changes:
Technical Notes: Parallel execution aims for serial parity while allowing bounded concurrency via shared pool tokens. 🤖 Was this summary useful? React with 👍 or 👎 |
| slice, | ||
| epic, | ||
| plan, | ||
| worktreeDir: join(input.worktreeDir, sliceId), |
There was a problem hiding this comment.
worktreeDir is now set to join(input.worktreeDir, sliceId), but createWorktree() currently only creates the parent directory; pi-actions and BunTestRunner use this path as cwd and will fail if the slice subdirectory doesn’t exist. This same assumption shows up in the other join(input.worktreeDir, <sliceId>) call sites in this file as well.
Severity: high
Other Locations
src/orchestrator/src/net-compiler.ts:382src/orchestrator/src/net-compiler.ts:421src/orchestrator/src/net-compiler.ts:488
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| tracker.maxConcurrent = Math.max(tracker.maxConcurrent, active); | ||
| await new Promise((resolve) => setTimeout(resolve, 5)); | ||
| const result = await handler!(ctx); | ||
| active--; |
There was a problem hiding this comment.
In withConcurrencyTracking, if a wrapped handler throws/rejects, active-- won’t run, so the tracker can overcount and make concurrency assertions misleading on failure paths. It may be worth ensuring the active counter is decremented even when the wrapped handler errors.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
6ff7563 to
d4e9d95
Compare
d4e9d95 to
d43222e
Compare
8e56a7c to
f959557
Compare
d43222e to
55945f9
Compare
13953ca to
386c3cf
Compare
Co-authored-by: Amp <amp@ampcode.com>
Parallel firing policy (petri-net.ts): - FiringPolicy = 'serial' | 'parallel' - runParallel: greedy token claiming + Promise.allSettled concurrent fire - Extracted isEnabled() private helper Shared resource pools (net-compiler.ts): - pool:test-agent / pool:code-agent replace per-slice agent places - agentPoolSize on RunPolicy bounds global concurrency - Worktree-per-slice: join(worktreeDir, sliceId) for all action contexts CLI (cook-cli.ts): - Retired dead --engine=proc|petri flag - Added --policy=serial|parallel wired to createOrchestrator Tests (engine-contract.test.ts): - Parallel added to all engines arrays (serial parity) - Concurrency proof, wall-clock benchmark, pool-bounded tests - Extracted withConcurrencyTracking() helper - Worktree isolation adapter test Decision gate passed: parallel measurably beats serial on wall clock. Co-authored-by: Amp <amp@ampcode.com>
386c3cf to
0f5cdbf
Compare
f959557 to
1747538
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 0f5cdbf. Configure here.
| epic, | ||
| plan, | ||
| sandboxDir: join(input.sandboxDir, sliceId), | ||
| reports, |
There was a problem hiding this comment.
Slice id escapes sandbox
Medium Severity
Per-slice sandboxes use join(input.sandboxDir, slice.id) without validating slice.id. A plan id containing .. segments resolves outside the run sandbox for mkdirSync, action cwd, and test runs, so orchestration can write or execute under arbitrary filesystem paths from YAML.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 0f5cdbf. Configure here.



Summary
Phase 2 of the petri orchestrator arc (umbrella H-6476). Parallel firing + shared resource pools + sandbox-per-slice — the categorical break where the Petri engine earns its complexity over proc. Decision gate passed: parallel measurably beats serial on multi-slice plans. Stacks on FE-738 (#148).
Changes
Interpreter (
petri-net.ts)FiringPolicy = 'serial' | 'parallel'runParallel()— greedy token claiming in registration order +Promise.allSettledconcurrent fireisEnabled()helper (was inlined 3×)hasTokens()(PR FE-730: Orchestrator POC — dual-engine execution with contract tests #143 review cleanup)Compiler (
net-compiler.ts)pool:test-agent/pool:code-agentplaces replace per-slice agent placesagentPoolSizeonRunPolicycaps global concurrency (default = slice count = unbounded)join(sandboxDir, sliceId)for all action contextsCLI (
cook-cli.ts)--engine=proc|petriflag (proc engine deleted in FE-730)--policy=serial|parallelwired tocreateOrchestrator()Naming (PR #143 review cleanup)
worktreeDir→sandboxDiracross all orchestrator files — disambiguates from git worktrees.Verification
serialandparallelpoliciesmaxConcurrent > 1under parallelagentPoolSize=1→ 1;=2→ 2; default → 3npm run verifycleanAcceptance (per
memory/PLAN.md)(1)–(6) met including decision gate: wall-clock improvement measurable on a 3+ slice fixture vs serial execution.
Next
Phase 3 —
petri-graph-compilation— blocked on FE-700 (intent-graph-semantics). Frontier definition added tomemory/PLAN.mdcapturing two open constraints from PR #143 review:HandlerDescriptordeclares candidate outputs but selection is runtime. Phase 3 should move conditional routing into topology-level guard predicates + declared output arcs for formal analyzability.