Theme
Lesson 29 — Bounded scheduler and parallel agents
Outcome
Run multiple eligible Tasks concurrently with configurable limits and independent worktrees.
Why this comes now
Parallelism is useful only after isolation, recovery, and readiness are trustworthy. Earlier would multiply failure modes.
Understand
The scheduler is a small local coordinator, not a distributed queue. It repeatedly reacts to meaningful state changes, selects eligible Tasks, and starts work up to configured capacity. Every Task keeps its own Worktree/Run/Operation identities.
Use bounded concurrency. Cancellation and shutdown flow through contexts. Avoid aggressive auto-parallelism that makes human supervision harder.
Build the real project
- Add configurable
max_concurrent_agent_runswith conservative default. - Implement scheduler service driven by state notifications/ticks as simply as reliability allows.
- Select eligible Tasks deterministically/fairly enough for first version.
- Start through existing application/Operation path—scheduler must not bypass domain rules.
- Add tests A+B independent, C depends on both.
- Add graceful shutdown test with active fake Runs.
- Surface active capacity and blocked Tasks in UI.
Completion gate
A and B run concurrently up to limit, C waits, reducing limit does not kill valid work unexpectedly, shutdown is controlled, no duplicate Run starts for one Task.
Pitfalls to avoid
Do not create one goroutine forever per backlog Task. Do not poll the database at millisecond frequency. Do not start dependent branches from unmerged sibling work as an early optimization.
References
Go concurrency patterns: https://go.dev/blog/pipelines ; OPERATIONS_AND_RECOVERY.md.
Checkpoint
M11 is complete when parallel fake/real work remains understandable, not merely technically concurrent.