feat: fix(coder_solve): document and cap session-level concurrency within a drive (#171) - #172
Conversation
There was a problem hiding this comment.
QA panel review — PASS
code-review-structural · head 88965f35f2d3 · formal
[review-synthesizer completed: workflow code-review-structural:report]
Both surviving findings are confirmed nits — no refutations to drop, no uncertains to flag, and no prior blockers/majors to carry (this panel has not reviewed the PR before, so no dispositions block is due). Re-ranking: both are nit-level; I keep finding 1 first because coder_seam.py is the load-bearing dispatch path.
Low-risk change: the only surviving findings are two nit-level hygiene issues, both confirmed by the verifier — a duplication/drift hazard in the coder dispatch path (coder_seam.py) and a misleading-but-correct startup capacity log (loop.py); neither blocks. If any cleanup is done, the seam duplication is the one worth fixing first (a future dispatch-kwarg edit could silently diverge the default max_concurrent_sessions=0 path from the capped path). No panel disagreement: the verifier re-grounded both findings byte-for-byte against the PR diff and matched line anchors 794/919, finding no block-worthy defect and no contradiction with the PR's own log-assertion test. Coverage gap to note: server-side head-SHA file reads for both files 404'd, so grounding came from the PR diff's plus-lines rather than a full head file read — a diff-level read, not a substantive evidence gap.
Findings
| Severity | Location | Finding | Verified | |
|---|---|---|---|---|
| ⚪ | nit | coder_seam.py:794 |
The semaphore if/else duplicates the identical dispatch_coder_tapped(...) call in both branches, so a future edit to one branch (e.g. a new dispatch kwarg) sil… | confirmed |
| ⚪ | nit | loop.py:919 |
The new startup log prints the UNCAPPED peak (max_concurrent × coder_solve_k) as 'peak concurrent ACP sessions' and appends 'capped at N' without stating the e… | confirmed |
findings JSON (machine-readable)
[
{
"file": "coder_seam.py",
"line": 794,
"severity": "nit",
"category": "conventions",
"claim": "The semaphore if/else duplicates the identical dispatch_coder_tapped(...) call in both branches, so a future edit to one branch (e.g. a new dispatch kwarg) silently diverges the default (max_concurrent_sessions=0) path from the capped path.",
"evidence": " if self._session_sem is not None:\n async with self._session_sem:\n reply = await dispatch_coder_tapped(\n self.coder,\n wt,\n _augment_prompt(task, self._compose_feedback(feedback)),\n fid=self.progress_fid,\n gen=self._n,\n tier=self.progress_tier,\n timeout=self.dispatch_timeout,\n env_passthrough=self.env_passthrough,\n )\n else:\n reply = await dispatch_coder_tapped(\n self.coder,\n wt,\n _augment_prompt(task, self._compose_feedback(feedback)),\n fid=self.progress_fid,\n gen=self._n,\n tier=self.progress_tier,\n timeout=self.dispatch_timeout,\n env_passthrough=self.env_passthrough,\n )",
"verdict": "confirmed",
"note": "Quoted block matches the PR diff plus-lines verbatim; both branches contain the byte-identical dispatch_coder_tapped(...) call, and the __init__ hunk (`Semaphore(...) if max_concurrent_sessions > 0 else None`) confirms the else branch is the 0-default path. Line 794 anchors to `if self._session_sem is not None:`. Head-SHA file reads 404'd; grounded on the PR diff (server-resolved head)."
},
{
"file": "loop.py",
"line": 919,
"severity": "nit",
"category": "conventions",
"claim": "The new startup log prints the UNCAPPED peak (max_concurrent × coder_solve_k) as 'peak concurrent ACP sessions' and appends 'capped at N' without stating the effective peak (max_concurrent × min(k, cap)), and its '(set max_concurrent_sessions to cap this)' advice is emitted even when a cap is already set — a misleading capacity number for operators who read it.",
"evidence": " cap_note = f\", capped at {self.max_concurrent_sessions}\" if self.max_concurrent_sessions > 0 else \"\"\n log.info(\n \"[project_board] coder_solve_k=%d: peak concurrent ACP sessions = \"\n \"max_concurrent × coder_solve_k = %d × %d = %d%s \"\n \"(set max_concurrent_sessions to cap this)\",",
"verdict": "confirmed",
"note": "Quoted block matches the PR diff plus-lines verbatim; `peak = max_concurrent * coder_solve_k` is uncapped, `cap_note` appends ', capped at N' without computing the effective peak, and '(set max_concurrent_sessions to cap this)' is an unconditional literal suffix — all three sub-claims check out character-for-character. Line 919 anchors to `log.info(`. Head-SHA file reads 404'd; grounded on the PR diff."
}
]
Summary
Added
max_concurrent_sessionsas a new optional config knob (default 0 = unlimited) that caps concurrent ACP dispatches within a singlecoder.solve()drive. When set to 1, best-of-k candidates run serially rather than in parallel viaasyncio.gather.Key changes:
coder_seam.py:_WorktreeSolveAdaptergains a_session_sem: asyncio.Semaphore | Nonefield;generate()acquires the semaphore (when set) around thedispatch_coder_tappedcall only — worktree creation is unaffected.dispatch()accepts and threadsmax_concurrent_sessionsto the adapter. Docstring now documents themax_concurrent × coder_solve_kpeak relationship.loop.py: Parsesmax_concurrent_sessions(floors at 0), adds it to_coder_solve_settings(), threads it tocoder_seam.dispatch(), and emits a startupINFOline whencoder_solve_k > 1naming the peak ACP session count and the configured cap (if any).README.md:max_concurrentconfig comment now explains it is feature-level and notes the peak formula;max_concurrent_sessionsadded to the example config block with documentation.Fixes #171