Repository navigation
Explain why features stay Pending when the orchestrator can't start any - #306
zwanski-start wants to merge 2 commits into
Conversation
) When nothing was running and no feature was ready, the orchestrator idled forever with the agent shown as "running", printing only a vague "may be blocked by dependencies" line every 10 seconds. Features whose dependencies had permanently failed, pointed at non-existent features, formed a cycle, or were waiting on human input stayed Pending for hours with no explanation. - Add explain_stalled_features() to the dependency resolver, which gives a per-feature reason (missing dep, cycle, failed dep, human input, ...) - Print that report from the orchestrator when the queue stalls, only re-printing when it changes - Surface agent spawn/resume failures in the log instead of only the debug file Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🔍 QA report: ❌ FailedTester: Ada (cubefarm agent, in a fresh session) · Round: 1 · Author: Ken The stalled-queue report replaces the vague 'may be blocked' line with a reason for each feature. Its dedup and the spawn/resume error logging work, and lint, mypy on the changed files and tests pass. The cycle part is wrong: explain_stalled_features uses _detect_cycles(), which stops after the first cycle and leaves stale path/rec_stack state behind. Any later feature that depends on a cycle member is then reported as part of a cycle with a path that doesn't exist (e.g. 'circular dependency #3 -> #4 -> #9 -> #3' when only 3<->4 is a cycle), which tells users to remove a valid dependency.
🧪 Commands run
🔧 What needs fixingIn explain_stalled_features, don't rely on _detect_cycles() for per-feature cycle membership. Its DFS returns early without popping path/rec_stack, so later roots see stale back edges. Either compute strongly connected components (Tarjan/Kosaraju) over the pending features and mark only features in an SCC of size > 1 (or with a self-loop) as circular, building the shown cycle path from edges inside that SCC; or fix _detect_cycles to pop path/rec_stack on every return (and to keep searching rather than stopping at the first cycle), checking that its existing callers still behave. Features that depend on a cycle member but are not in it must get 'waiting on unfinished feature(s) #X'. Add a regression test with features [{3 deps [4]}, {4 deps [3]}, {9 deps [3]}] in ID order that asserts reasons[9] does not mention 'circular' and that reasons[3] and reasons[4] read '#3 -> #4 -> #3' (or the equivalent rotation). No browser screenshots were taken in this round. Posted by cubefarm · sent back to the developer for fixes |
…utoForgeAI#27) explain_stalled_features relied on _detect_cycles(), whose DFS returns on the first cycle without unwinding path/rec_stack. Later DFS roots then hit stale back edges, so a feature that merely depended on a cycle member was reported as part of a fabricated cycle (e.g. AutoForgeAI#3 -> AutoForgeAI#4 -> AutoForgeAI#9 -> AutoForgeAI#3 when only 3 <-> 4 is circular), telling users to remove a valid dependency. Use Tarjan SCCs instead: only features in an SCC of size > 1 (or with a self-loop) are circular, and each gets the shortest real cycle through itself. Dependents of a cycle now read 'waiting on unfinished feature(s)'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🔍 QA report: ✅ PassedTester: Dennis (cubefarm agent, in a fresh session) · Round: 2 · Author: Ada Last round's cycle bug is fixed. explain_stalled_features now uses a new helper, _find_cycle_members (Tarjan's algorithm without recursion), so only features actually inside a loop are called circular, and features that only depend on a cycle get 'waiting on unfinished feature(s) #X'. The requested regression test is there and passes, and a fuzz test on 5,000 random graphs matched a brute-force check with correct shortest cycles. Tests and ruff pass; the only mypy errors are in temp_cleanup.py, which this PR doesn't touch, and the stalled-queue report prints correctly and is not repeated when nothing changes.
🧪 Commands run
No browser screenshots were taken in this round. Posted by cubefarm · merges automatically once GitHub's checks pass |
) Adaptations: combined with AutoForgeAI#296's stall states, the report is printed for 'blocked' and 'human_input' stalls before the orchestrator stops (blocked) or waits (human input), replacing AutoForgeAI#296's one-line notices. Ported AutoForgeAI#255's 2-line rec_stack/path reset in _detect_cycles, which reported features that merely depend on a cycle as cyclic; new regression test. New test for the report's content and de-duplication. Integrates AutoForgeAI#306 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeH26pcsqoxPb3CDs8g1VN
Closes #27
Problem
In the reported case, 51 features sat in Pending for hours. The agent showed as "running" and nothing appeared in the log. In
parallel_orchestrator.run_loop, when no feature is ready and no agent is running, the loop just waits and repeats a vague line every 10s:No ready features available. All remaining features may be blocked by dependencies.Several situations trigger this, and none of them were explained:MAX_FEATURE_RETRIES(3) times, so it's never retried.get_all_complete()counts it as done, but anything that depends on it stays Pending foreverAgent spawn and resume failures were also written only to the debug file, so a repeated
Popenfailure looked exactly the same: nothing happens.Changes
api/dependency_resolver.py: new pure functionexplain_stalled_features(features, failed_ids)that gives a reason for each unfinished feature (missing dependency, cycle, failed dependency, human input, waiting on another unfinished feature).parallel_orchestrator.py:test_dependency_resolver.py: new test covering each type of reason.Verification
python -m pytest test_dependency_resolver.py test_rate_limit_utils.py test_client.py: 56 passedpython test_dependency_resolver.py: 13 passed;python test_security.py: all passedruff check .: clean.mypy .reports no errors in the changed files (the 25 errors it does report are in other files and already exist on master)._report_stalled_queueon a sample feature set: the output above is real, and a second call with the same state printed nothing.Assumptions
Rate limit hit…/Claude Code Limit Reached…messages and is unchanged here. This PR covers the case where no message was shown at all.zwanski-startfork because this account only has read access to upstream.🤖 Generated with Claude Code