feat(check): streaming Kameo actor pipeline for multi check (MULTI-1368)#145
Merged
Conversation
Contributor
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
acdf915 to
c5a902a
Compare
7964562 to
ec16b2c
Compare
c5a902a to
1a41a21
Compare
…1368)
Re-architect the `multi check` pipeline from its barrier-based shape into a
streaming, fire-and-forget actor pipeline using Kameo (v0.20). Each phase
becomes its own actor wired with one-way `tell`:
DiscoveryActor --CheckDiscovered--> ExecutionActor --CheckCompleted--> ReportingActor
This removes the two synchronization barriers between phases: a check begins
executing the moment Discovery has validated it, and a result is folded into
Reporting the moment its agent returns — no waiting on an owned `Vec`.
- messages.rs: the inter-actor message protocol (CheckJob carried end-to-end,
plus DiscoveryComplete/ExecutionComplete end-of-stream sentinels).
- DiscoveryActor: runs the whole-suite parse + validation gate (discover()),
then streams one CheckDiscovered per check with a run-unique CheckId; any
invalid CHECKS.md aborts the whole run via DiscoveryFailed with no agents
spawned (strict whole-run abort).
- ExecutionActor: offloads each agent run onto a spawned task bounded by a
shared Semaphore(cfg.concurrency) acquired inside the task (the semaphore is
the cap, not the mailbox); retries reframed as RetryCheck self-messages.
- ReportingActor: folds verdicts incrementally, then buffers and sorts by
(req_index, declaration order) before the final render — output ordering,
AND-aggregation, and exit codes are byte-for-byte unchanged.
- Coordinator in run(): spawns the actors, kicks discovery, awaits the terminal
result over a oneshot, and maps a dead actor to a diagnostic rather than
hanging the run.
The CheckExecutor/Sandbox DI seams are reused unchanged. Tests drive the actor
pipeline deterministically (FakeExecutor + NoopSandbox), with new coverage for
concurrent (non-barriered) execution, the retry self-message path, and the
strict abort-without-spawning-agents path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1a41a21 to
541f3cc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Re-architect the
multi checkpipeline from its barrier-based shape into astreaming, fire-and-forget actor pipeline using Kameo (v0.20). Each phase
becomes its own actor wired with one-way
tell:This removes the two synchronization barriers between phases: a check begins
executing the moment Discovery has validated it, and a result is folded into
Reporting the moment its agent returns — no waiting on an owned
Vec.plus DiscoveryComplete/ExecutionComplete end-of-stream sentinels).
then streams one CheckDiscovered per check with a run-unique CheckId; any
invalid CHECKS.md aborts the whole run via DiscoveryFailed with no agents
spawned (strict whole-run abort).
shared Semaphore(cfg.concurrency) acquired inside the task (the semaphore is
the cap, not the mailbox); retries reframed as RetryCheck self-messages.
(req_index, declaration order) before the final render — output ordering,
AND-aggregation, and exit codes are byte-for-byte unchanged.
result over a oneshot, and maps a dead actor to a diagnostic rather than
hanging the run.
The CheckExecutor/Sandbox DI seams are reused unchanged. Tests drive the actor
pipeline deterministically (FakeExecutor + NoopSandbox), with new coverage for
concurrent (non-barriered) execution, the retry self-message path, and the
strict abort-without-spawning-agents path.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com