Add LLM-driven mission decomposition#1533
Conversation
Overlap with PR #975Both PRs implement LLM-driven mission decomposition ( Note: PR #975 review (run 25) found a critical infinite decomposition loop bug — verify #1533 doesn't have the same issue. One of these should be chosen as the base implementation. |
|
@Koan-Bot rr |
|
Flagging two critical issues found during review that should be addressed before merge:
Also, this PR overlaps with #975 which includes a |
PR Review — feat(decompose): LLM-driven mission decompositionThe decomposition feature is well-structured at the design level (classifier prompt, config, lifecycle sweep), but has two critical bugs that must be fixed before merge. First, decomposed parent missions are not skipped by the picker, so they get executed via Claude alongside their sub-tasks — this defeats the entire feature and could waste significant quota. Second, there is dead unreachable code ( 🔴 Blocking1. Dead code: unreachable `return False` after `return ready` (`koan/app/missions.py`, L2379)There is a stray return ready
return False # <- unreachable, type mismatchRemove the trailing 2. Decomposed parent missions will be picked and executed by Claude (`koan/app/iteration_manager.py`, L1548-1579)After decomposition, the parent mission stays in Pending tagged This means the original complex mission runs alongside its sub-tasks, defeating the purpose of decomposition. The @Koan-Bot overlap comment flagged PR #975 had an infinite decomposition loop — this is the same class of bug. Fix: After if mission_project and mission_title:
from app.missions import extract_decomposed_tag
if extract_decomposed_tag(mission_title):
# Parent is waiting for sub-tasks to complete — skip
return _make_result(
action="autonomous", ...,
decision_reason="Decomposed parent waiting for sub-tasks",
)
decomposed = _maybe_decompose_mission(...)Alternatively, teach the picker to skip 🟡 Important1. Uses `print(file=stderr)` instead of project logging pattern (`koan/app/decompose.py`, L48-55)The quality scan flagged 4 print statements (lines 48, 55, 85, 105). The project convention uses from app.run_log import log_safe
log_safe("error", f"CLI call failed: {result.stderr[:200]}")Categories to use: 2. Misleading docstring: `enabled` does not auto-decompose all missions (`koan/app/config.py`, L873-878)The docstring says "setting True enables auto-decompose for all missions" for enabled (bool): master switch for automatic decomposition. Tag-based
opt-in ([decompose]) still works when False. Combine with auto=True
to classify all missions. Default False.3. Sweep calls `complete_mission()` — verify this transitions from Pending correctly (`koan/app/iteration_manager.py`, L1283-1306)The sweep calls Checklist
To rebase specific severity levels, mention me: Silent Failure Analysis🟠 **HIGH** — dead code / unreachable return (`koan/app/missions.py:2379`)Risk: Unreachable Fix: Delete the unreachable 🟠 **HIGH** — batch failure — one bad item blocks all (`koan/app/iteration_manager.py:1286-1295`)Risk: All ready parents are processed in a single Fix: Wrap each 🟡 **MEDIUM** — stderr-only logging in daemon context (`koan/app/decompose.py:45-56`)Risk: All error paths in Fix: Use 🟡 **MEDIUM** — silent type coercion hides misconfiguration (`koan/app/config.py:889-891`)Risk: If a user writes Fix: Log a warning when the Automated review by Kōanb227938 |
Rebase with requested adjustmentsBranch Changes applied
StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
b227938 to
0c1b4fe
Compare
|
Verified against #975's 'infinite decomposition loop' concern: #1533 does not loop infinitely (it correctly recognizes Mission picking here is strict FIFO: So whichever PR becomes the base, the picker must learn to skip |
PR Review — feat(decompose): LLM-driven mission decompositionThe feature is well-organized (clean classifier prompt with anti-over-decomposition bias, isolated config, structured logging after the rebase, broad unit coverage), but it has a blocking correctness bug that makes it non-functional. Because mission picking is strict FIFO and 🔴 Blocking1. Decomposed parent deadlocks the queue — sub-tasks can never be picked (`koan/app/iteration_manager.py`, L1581-1599)This Step 4a guard returns early whenever the picked mission carries a
S1/S2 are never reached, so they never leave Pending, so the sweep never completes the parent. The parent permanently occupies the head of the FIFO queue and stalls every subsequent mission in the instance, not just its own sub-tasks. The feature is non-functional and bricks the queue. The earlier rebase added this guard believing it fixed the 're-execution' bug, but returning early without advancing the picker converts re-execution into starvation. Fix options: (a) make 🟡 Important1. Sub-tasks do not inherit the parent's [project:NAME] tag in the real call path (`koan/app/missions.py`, L2228-2236)
In a multi-project instance, untagged sub-tasks are treated by 2. Parent auto-completes even when all sub-tasks failed, masking failures (`koan/app/missions.py`, L2320-2348)
Checklist
SummaryThe feature is well-organized (clean classifier prompt with anti-over-decomposition bias, isolated config, structured logging after the rebase, broad unit coverage), but it has a blocking correctness bug that makes it non-functional. Because mission picking is strict FIFO and To rebase specific severity levels, mention me: Silent Failure Analysis🟠 **HIGH** — unchecked silent no-op treated as success (`koan/app/iteration_manager.py:1380-1410`)Risk: Both inject_subtasks and mark_parent_decomposed silently return content unchanged when the parent line isn't matched in Pending, yet _maybe_decompose_mission still returns the truthy subtasks list, so the caller skips the iteration believing decomposition succeeded — the parent is never tagged [decomposed] and no sub-tasks exist, so the same mission is re-picked and re-classified every loop, burning Haiku quota indefinitely with no visible error. Fix: Have inject_subtasks/mark_parent_decomposed report whether the parent was found (e.g. return a bool or sentinel), and only return subtasks / skip the iteration when the mutation actually applied; otherwise log a warning and fall through to run the mission as-is. 🟡 **MEDIUM** — error conflated with valid result (silent null return) (`koan/app/decompose.py:38-50`)Risk: decompose_mission returns None for both a genuine 'atomic' classification and any CLI failure/exception, so callers cannot distinguish a working atomic result from a broken classifier; under auto: true a persistently failing model degrades every mission to undecomposed silently, visible only as scattered log lines and never surfaced to the operator. Fix: Distinguish failure from atomic (e.g. raise or return a distinct error sentinel on CLI failure) so callers can optionally retry or surface a one-time Telegram warning when the classifier is consistently failing. |
|
@Koan-Bot rebase important |
Rebase with requested adjustmentsBranch Changes applied
StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
0c1b4fe to
1c9ce86
Compare
|
@Koan-Bot rebase and validate no more critical issues remain |
Simple rebaseBranch StatsActions performed
CI statusCI will be checked asynchronously. Automated by Kōan |
1c9ce86 to
b003406
Compare
|
@Koan-Bot squash |
Split complex missions into focused sub-tasks via lightweight LLM classifier. Missions tagged [decompose] classified by Haiku. Composite ones split into [group:ID] sub-tasks; parent marked [decomposed:ID], auto-completes when subtasks finish. Adds decompose.py classifier, missions.py lifecycle helpers, iteration_manager integration (group-completion sweep at Step 3d, decomposition gate at Step 4a). 37 new tests across decompose, missions, iteration_manager. Also removes unused dashboard nickname feature. Closes Anantys-oss#739
b003406 to
ee73ab7
Compare
Squash: 3 commits → 1Branch Commit messageActions
Automated by Koan |
|
@Koan-Bot ask explain me simply the workflow and life cycle of that current decomposition. I want to understand all steps. Divide it step by step and explain it simply. |
What
Split complex missions into focused sub-tasks via LLM classifier.
Why
Some missions span multiple phases (refactor, test, document). Decomposition makes phases explicit, enabling separate PR review and independent failure recovery.
How
[decompose]triggers Haiku classification[group:ID]; parent marked[decomposed:ID]Closes #739