Commit Graph

21 Commits

Author SHA1 Message Date
Teknium c5594ec4b3 fix(delegation): a crash mid-unit keeps the children that already finished
Since #104299 a background delegate_task call is split into completion units
(one per `group`, one per ungrouped task). A multi-child unit still joined on
all its children before anything was written durably, so an owner crash
between the first and last child lost the finished work and replayed the whole
unit as "outcome unknown" — the restart-granularity gap that #104233 (Xipong's
#76228/#76229 direction) solved with a second row per child.

Each finished child of a detached unit is now recorded on the unit's OWN row
(`record_unit_child` → result_json {results, partial}) as its future lands;
the real result overwrites it at finalize. `recover_abandoned_delegations`
replays recorded children with their real summaries and marks only the
unfinished ones unknown, naming the count. No new rows, no new consumer shape.
`task_indexes` is persisted so recovery knows a split unit's members.
2026-09-06 09:21:58 -07:00
Teknium 028fe2c4c8 feat(delegation): per-task completion groups — ungrouped subagents return as they finish
A background delegate_task call used to be ONE async unit: the runner joined on
every child and a single consolidated message re-entered the conversation when
the SLOWEST finished. Fifteen independent PR reviews therefore waited on the
fifteenth before the parent could act on the first.

Each task now carries an optional `group`. `_units_of` partitions the call's
children into units — one per distinct group, one per ungrouped task — and each
unit is dispatched to the async registry on its own, so its results re-enter the
conversation as soon as THAT unit is done. Tasks that must be compared or merged
share a group and still return together.

Capacity is unchanged: every unit of one call joins the first unit's pool slot
(`slot_key` in `async_delegation._dispatch`), so splitting never consumes more of
`delegation.max_concurrent_children` than the call did. Unit ids suffix the
call's id (`deleg_xxxx-1`, `-2`, …) so live transcripts stay under one dir; the
completion block names the group and notes that sibling units report separately;
`active_task_count` counts a unit's own tasks.
2026-09-06 07:17:30 -07:00
Teknium 0cb996d977 fix(delegation): number delegation batches per conversation, not per process
`format_batch_tag` handed out `set N` ordinals from one process-wide table,
so every conversation on a shared backend and every child's nested fan-out
advanced the same counter. A user's second wave of 15 lanes rendered as
`[set 20 · 13/15]`, which reads like 20 batches were spawned.

Scope the ordinal table by the parent conversation (`parent_agent.session_id`)
and thread the parent through the three render sites (batch header,
completion lines, child tree-line prefix via the shared session_ref). The
first fan-out in a conversation is `set 1`, the next `set 2`; sibling
conversations and nested child batches no longer inflate it.

Invariant test proven red on origin/main, green with the fix.
2026-09-06 05:03:20 -07:00
Teknium 14791b4d4e simplify(compat): approval — drop 43 facade re-exports + _command_detection_variants late-bind seam, repoint 30 callers + 46 test files
tools/approval.py no longer re-exports sibling names (approval_context/prompt/floors/detection/
human_wait/smart/gateway_wait); it imports only what it uses. Siblings reference sibling-defined
names directly (module-attribute reads on tools.approval_context so patching the defining module
still works); only facade-owned state (_lock, _gateway_queues, _permanent_approved, _denied,
_denial_breaker_addendum, _gateway_notify_cb) is still read back through tools.approval.
approval_detection calls its own _command_detection_variants instead of late-binding through the facade.
2026-09-03 13:49:57 -07:00
Teknium e83816a4d1 review-fix(comments): restore lost #NNNN rationale comments across non-test source (mechanical sweep, condensed, code unchanged)
For each issue anchor present in BASE 63279301bc non-test .py and absent on HEAD, the BASE comment/docstring block was re-attached at the HEAD location of the code it explained (matched by the distinctive code line / enclosing def). Sentences already covered by an existing HEAD comment were deduped; the issue number always survives. Insert-only: no code lines changed.
2026-09-03 09:44:26 -07:00
Teknium 2609eafb9b refactor(delegate): dispatch notes as a constant table; payload byte-identical 2026-09-02 19:56:03 -07:00
Teknium 9cf7c74030 refactor(delegate): module headers condensed (one-line docstrings, logger comment inline) 2026-09-02 19:43:56 -07:00
Teknium defca3639a refactor(delegate): reflow comments/docstrings to 118 cols (word-identical, AST-identical) 2026-09-02 19:25:04 -07:00
Teknium 1283ccd855 refactor(delegate): docstring compaction by hand (every rule/why kept) 2026-09-02 19:16:07 -07:00
Teknium eabec2ff50 refactor(delegate): AST-identical re-layout pass 2 2026-09-02 19:04:50 -07:00
Teknium 089d1aa296 refactor(delegate): dispatch — _Batch.run_child, one future-entry resolver, inline transcript finalize 2026-09-02 18:52:58 -07:00
Teknium b18228f377 refactor(delegate): AST-identical re-layout (pack signatures/call args, join split literals) 2026-09-02 17:59:28 -07:00
Teknium 64957b7e02 refactor(delegate): _Batch dataclass owns batch execution/dispatch; _quiet best-effort contextmanager 2026-09-02 17:50:16 -07:00
Teknium 3da2ff88e3 refactor(delegate): pack re-import block; single blank line between top-level defs (AST-identical) 2026-09-02 17:03:55 -07:00
Teknium 987bc82574 refactor(delegate): compact docstrings/comments by hand (every WHY kept); collapse orchestrator toolset branches 2026-09-02 17:03:05 -07:00
Teknium 016f31375d refactor(delegate): join wrapped logical lines that fit in 120 cols (AST-identical) 2026-09-02 16:59:26 -07:00
Teknium 884c697291 refactor(delegate): split _finalize_child_results (memory/hooks/cost rollup), lift _create_isolated_worktree and _report_child_done, collapse dead worktree-attach import fallback 2026-09-02 16:54:15 -07:00
Teknium 338da30a45 refactor(delegate): _resolve_child_runtime returns AIAgent kwargs (drop _ChildRuntime; routing-filter table); dispatch reuses _detach_child/_signal_child_stop; control actions -> _CONTROL_OUTCOMES table; attribution lookup dedupe 2026-09-02 16:50:57 -07:00
Teknium 4711e8105d refactor(delegate): child_run dedupe — shared close/attach/detach/stop helpers, _defer_close_after_timeout, _build_tool_trace, _num; single _fabricated_entry 2026-09-02 16:37:47 -07:00
Teknium 8e9628e9cf refactor(delegate): progress relay -> _ChildProgressRelay class + event table; split _dispatch_background into collaborators 2026-09-02 15:40:23 -07:00
Teknium 05526b028a refactor(tools/delegate): split delegate_tool into child_run/config/dispatch/progress/registry/results; compact delegation helpers 2026-09-02 14:45:15 -07:00