FE-743: Petri parallel execution with resource pools and per-slice sandboxes#149
Conversation
PR SummaryMedium Risk Overview The interpreter gains a The net compiler and wiring pass route slice actions and tests through
Reviewed by Cursor Bugbot for commit c4ab8b1. Bugbot is set up for automated code reviews on this repo. 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 👎 |
6ff7563 to
d4e9d95
Compare
d4e9d95 to
d43222e
Compare
8e56a7c to
f959557
Compare
d43222e to
55945f9
Compare
13953ca to
386c3cf
Compare
386c3cf to
0f5cdbf
Compare
f959557 to
1747538
Compare
0f5cdbf to
9e6a0e8
Compare
da2bb0d to
6c4fd65
Compare
2f0aba4 to
f1ff792
Compare
6c4fd65 to
c51fdb7
Compare
f1ff792 to
33a84c1
Compare
c51fdb7 to
e76b68a
Compare
421f18b to
9878f8c
Compare
abd05c4 to
8b45a97
Compare
9878f8c to
1de40c9
Compare
1de40c9 to
8e41132
Compare
lunelson
left a comment
There was a problem hiding this comment.
Parallel firing + shared pools land cleanly, and the decision gate (parallel beats serial on wall clock) is the right thing to clear before adding this much machinery. The runSerial/runParallel split with shared restoreClaim/depositClaim helpers is nice.
Three architectural reflections, all comment-only — none block:
-
Parallel failure semantics is all-or-nothing batch.
runParallelusesPromise.allSettled, but on any rejection it restores claims for every transition in the batch and rethrows. That means one slice's transient agent failure aborts every other concurrent slice's in-flight work, not just halts the failing one. The tests don't exercise mixed success/failure batches, so this is currently invisible. Likely too coarse once real agent flakiness shows up — worth naming as an explicit design choice (or queuing per-claim rollback as follow-up). -
wireHandlersnow has a filesystem side effect. FE-738 was careful to keepcompileTopologypure and put runtime concerns inwireHandlers. This PR addsmkdirSync(sliceSandboxDir(...))insidewireHandlers— the wiring pass now also provisions directories on disk. Small but real layering creep. Could factor out aprepareRunFilesystem(blueprint, input)step thatengine.tsinvokes beforewireHandlers. -
Naming drift between abstraction and artifact.
worktreeDir→sandboxDiris done thoroughly across types, CLI flags, and handlers (createWorktree→createSandbox). But the fileworktree.tsstill has that name, and the returnedsandboxDiris still literally.cook/runs/<id>/worktreeon disk. The abstraction says "sandbox," the artifact still says "worktree." OK to defer if FE-755 will revisit the on-disk convention; worth a one-line decision either way.
Pool-token contention and per-slice sandbox isolation look solid. 👍
lunelson
left a comment
There was a problem hiding this comment.
Approving — architectural reflections above are non-blocking. 👍
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>
Deposit fulfilled transition outputs even when a sibling sets ctx.halted in the same batch, matching serial commit semantics while still rolling back on handler rejection. Co-authored-by: Cursor <cursoragent@cursor.com>
Per-slice test-agent/code-agent places were replaced by shared pool:* places in FE-743; pool places are already excluded by the pool: prefix check.
8e41132 to
a865631
Compare
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 a865631. Configure here.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>


Summary
FiringPolicy(serial|parallel) to the Petri interpreter: parallel mode claims all ready transitions and fires them concurrently withPromise.allSettled, subject to pool limits.Context
worktreeDirtosandboxDirclarifies that the path is a per-run filesystem root, not necessarily a git worktree (brownfield worktrees land in FE-755).What changed
FiringPolicy:serialpreserves prior single-fire behavior;parallelbatches independent ready transitions.RunPolicy.agentPoolSize: caps simultaneous agent-backed transitions viapool:test-agentandpool:code-agentplaces.join(sandboxDir, sliceId)so concurrent slices do not stomp the same tree.--engineflag; adds--policy=serial|parallelfor explicit policy selection at cook time.Verification
npm run verifygreen.Out of scope
verify-epic(FE-745).Traceability
petri-parallel-executioninmemory/PLAN.md; umbrella H-6476.