feat(kanban): add auto_promote_children config toggle

When the kanban auto-decomposer fans a triage task into child tasks,
recompute_ready() immediately promotes parent-free children to 'ready'
so the dispatcher picks them up. Some users want a manual workflow
where children stay in 'todo' for review before dispatch.

Add 'kanban.auto_promote_children' config key (default: true):
- false: children stay in 'todo' after decomposition
- true: existing behavior (auto-promote to 'ready')

Changes:
- kanban_db.py: decompose_triage_task() gains auto_promote param
- kanban_decompose.py: reads auto_promote_children from config
- kanban dashboard API: exposes the new setting in GET/PUT /orchestration

Closes #28016
This commit is contained in:
zccyman 2026-05-18 20:04:26 -07:00 committed by Teknium
parent 7a46c68857
commit 2e09d2567c
3 changed files with 15 additions and 2 deletions

View file

@ -2798,6 +2798,7 @@ def decompose_triage_task(
root_assignee: Optional[str],
children: list[dict],
author: Optional[str] = None,
auto_promote: bool = True,
) -> Optional[list[str]]:
"""Fan a triage task out into child tasks and promote the root to ``todo``.
@ -2983,8 +2984,11 @@ def decompose_triage_task(
# Outside the write_txn: promote parent-free children to 'ready'
# so the dispatcher picks them up on its next tick. Same pattern
# specify_triage_task uses.
recompute_ready(conn)
# specify_triage_task uses. When auto_promote is False children
# stay in 'todo' until the user manually promotes them — useful
# for manual-review-first workflows.
if auto_promote:
recompute_ready(conn)
return child_ids

View file

@ -271,6 +271,8 @@ def decompose_task(
cfg = _load_config()
orchestrator = _resolve_orchestrator_profile(cfg)
default_assignee = _resolve_default_assignee(cfg)
kanban_cfg = cfg.get("kanban", {}) if isinstance(cfg, dict) else {}
auto_promote = bool(kanban_cfg.get("auto_promote_children", True))
roster, valid_names = _build_roster()
try:
@ -410,6 +412,7 @@ def decompose_task(
root_assignee=orchestrator,
children=children,
author=audit_author,
auto_promote=auto_promote,
)
except ValueError as exc:
return DecomposeOutcome(task_id, False, f"DB rejected graph: {exc}")