idle-draft: fill all free worker slots, not one per completion

try_submit() returned after a single submission and was only called at
startup and once per completion, capping real concurrency at 1 task
regardless of the parallel setting — the ThreadPoolExecutor pool was
sized but never filled. Loop until every free slot is filled or no
eligible candidate remains, per spec §10 (wording sharpened to make the
whole-pool semantics explicit). No stub-claude harness exists yet to
test dispatch concurrency end-to-end; verified live against the real
queue (36 candidates, parallel=20).

Claude-Session: https://claude.ai/code/session_01Lgv4Qn82boNFC1jn8QXSNw
This commit is contained in:
Paul O'Reilly
2026-08-03 07:29:52 +12:00
parent bdd10cbbc1
commit 56c621713d
2 changed files with 23 additions and 18 deletions

View File

@@ -218,8 +218,10 @@ next cycle); the walk continues to the next candidate.
Up to `parallel` tasks run concurrently (`concurrent.futures.ThreadPoolExecutor`).
Each completion is handled **serially** in the main thread (state updates and git
commits never race). On every completion — and before the very first dispatch — the
gates (§6) are recomputed from a fresh probe (§5); a task is submitted to fill a free
worker slot only while an eligible `(item, work_type, provider)` triple remains. The
gates (§6) are recomputed from a fresh probe (§5); tasks are then submitted until
**every** free worker slot is filled or no eligible `(item, work_type, provider)`
triple remains — one completion may therefore trigger multiple submissions, and the
initial call before the first dispatch fills the whole pool, not one slot. The
loop exits (dispatch mode, non-dryrun) when no eligible candidate remains. `--once`
dispatches at most one task total, then exits without waiting for further slots.