test: Added integration tests for the sub-agent spawning system and inter-agent communication mechanisms
This commit is contained in:
@@ -66,7 +66,53 @@
|
||||
| `test_task_node_is_runnable` | Pending + unblocked = runnable |
|
||||
| `test_task_node_not_runnable_when_blocked` | Blocked = not runnable |
|
||||
|
||||
**Total: 40 new tests (382 total in suite)**
|
||||
### src/function/supervisor.rs (36 new handler integration tests)
|
||||
|
||||
| Test name | What it verifies |
|
||||
|---|---|
|
||||
| `handle_list_empty_supervisor` | Empty supervisor → 0 active, empty agents |
|
||||
| `handle_list_with_agents` | Registered agents appear in list |
|
||||
| `handle_list_no_supervisor_errors` | No supervisor → error |
|
||||
| `handle_check_unknown_agent` | Check unknown → error status |
|
||||
| `handle_check_pending_agent` | Check running agent → pending status |
|
||||
| `handle_cancel_registered_agent` | Cancel removes and signals abort |
|
||||
| `handle_cancel_unknown_agent` | Cancel unknown → error status |
|
||||
| `handle_cancel_no_supervisor_errors` | No supervisor → error |
|
||||
| `handle_send_message_to_registered_agent` | Message delivered to inbox |
|
||||
| `handle_send_message_to_unknown_agent` | Unknown agent → error status |
|
||||
| `handle_check_inbox_with_messages` | Inbox drains messages with count |
|
||||
| `handle_check_inbox_no_inbox` | No inbox → count 0 |
|
||||
| `handle_check_inbox_empty_inbox` | Empty inbox → count 0 |
|
||||
| `handle_reply_escalation_success` | Reply delivered via oneshot |
|
||||
| `handle_reply_escalation_missing_id` | Missing id → error status |
|
||||
| `handle_reply_escalation_no_queue_errors` | No queue → error |
|
||||
| `handle_task_create_simple` | Simple task created with id |
|
||||
| `handle_task_create_with_dependencies` | Task with blocked_by |
|
||||
| `handle_task_create_with_dispatch_agent` | Auto-dispatch flag set |
|
||||
| `handle_task_create_agent_without_prompt_errors` | Agent without prompt → error |
|
||||
| `handle_task_list_empty` | Empty queue → empty tasks array |
|
||||
| `handle_task_list_with_tasks` | Tasks listed |
|
||||
| `handle_task_complete_unblocks_dependents` | Complete unblocks with newly_runnable |
|
||||
| `handle_task_fail_marks_failed` | Fail sets status |
|
||||
| `handle_task_fail_reports_blocked_dependents` | Reports blocked deps |
|
||||
| `handle_task_fail_missing_task` | Missing task → error status |
|
||||
| `dispatch_unknown_action_errors` | Unknown action → error |
|
||||
| `dispatch_routes_list` | agent__list → handle_list |
|
||||
| `dispatch_routes_task_list` | agent__task_list → handle_task_list |
|
||||
| `new_for_child_inherits_escalation_queue` | Shared Arc |
|
||||
| `new_for_child_sets_depth_and_id` | Depth and self_agent_id |
|
||||
| `new_for_child_has_inbox` | Shared inbox Arc |
|
||||
| `new_for_child_inherits_parent_supervisor` | parent_supervisor set |
|
||||
| `new_for_child_starts_with_empty_scope` | Empty functions, mcp, role, session |
|
||||
| `ensure_root_escalation_queue_creates_on_first_call` | Lazy init |
|
||||
| `ensure_root_escalation_queue_returns_same_on_second_call` | Same Arc |
|
||||
|
||||
### Infrastructure
|
||||
|
||||
- Added `AppState::test_default()` method for cross-module test construction
|
||||
- Refactored `input.rs` and `request_context.rs` test helpers to use `test_default()`
|
||||
|
||||
**Total: 76 new tests (418 total in suite)**
|
||||
|
||||
## Bugs discovered
|
||||
|
||||
@@ -92,10 +138,20 @@ None.
|
||||
pattern — not ideal but necessary since JoinHandle can't be
|
||||
mocked.
|
||||
|
||||
5. **Most spawn/collect/check behaviors require integration tests**:
|
||||
The actual agent__spawn handler needs a full RequestContext with
|
||||
agent config on disk. The Supervisor struct itself is fully
|
||||
testable in isolation.
|
||||
5. **handle_spawn requires real agent config on disk**: This is the
|
||||
only handler that calls Agent::init. All other handlers (list,
|
||||
check, cancel, messaging, tasks, escalation) work with just a
|
||||
RequestContext + Supervisor, which we can construct in tests.
|
||||
|
||||
6. **Handler integration tests cover the full dispatch chain**: The
|
||||
tests call handler functions with real RequestContext instances
|
||||
containing real Supervisor/EscalationQueue/Inbox instances. This
|
||||
verifies the JSON arg parsing, supervisor interactions, and
|
||||
response formatting all at once.
|
||||
|
||||
7. **AppState::test_default() centralizes test construction**: Added
|
||||
a `#[cfg(test)]` constructor that avoids importing private
|
||||
modules (mcp_factory, rag_cache) from outside the config module.
|
||||
|
||||
## Next iteration
|
||||
|
||||
|
||||
@@ -10,50 +10,71 @@ to request user input through the parent.
|
||||
## Behaviors to test
|
||||
|
||||
### Spawn
|
||||
- [ ] agent__spawn creates child agent in background (integration)
|
||||
- [ ] Child gets own RequestContext with incremented depth (integration)
|
||||
- [ ] Child gets own session, model, functions (integration)
|
||||
- [ ] Child gets shared root_escalation_queue (integration)
|
||||
- [ ] Child gets inbox for teammate messaging (integration)
|
||||
- [ ] Child MCP servers acquired if configured (integration)
|
||||
- [ ] agent__spawn creates child agent in background (requires agent config on disk)
|
||||
- [x] Child gets own RequestContext with incremented depth (new_for_child)
|
||||
- [x] Child starts with empty scope (new_for_child)
|
||||
- [x] Child gets shared root_escalation_queue (new_for_child)
|
||||
- [x] Child gets inbox for teammate messaging (new_for_child)
|
||||
- [x] Child inherits parent_supervisor (new_for_child)
|
||||
- [ ] Child MCP servers acquired if configured (requires live MCP)
|
||||
- [x] Max concurrent agents enforced (Supervisor.register)
|
||||
- [x] Max depth enforced (Supervisor.register)
|
||||
- [ ] Agent not found → error (integration)
|
||||
- [ ] can_spawn_agents=false → no spawn tools available (integration)
|
||||
- [ ] Agent not found → error (requires agent config on disk)
|
||||
- [ ] can_spawn_agents=false → no spawn tools available (requires agent init)
|
||||
|
||||
### Collect/Check
|
||||
- [ ] agent__check returns PENDING or result (integration)
|
||||
- [ ] agent__collect blocks until done, returns output (integration)
|
||||
- [ ] Output summarization when exceeds threshold (integration)
|
||||
- [ ] Summarization uses configured model (integration)
|
||||
- [x] agent__check returns PENDING for running agent
|
||||
- [x] agent__check returns error for unknown agent
|
||||
- [ ] agent__collect blocks until done, returns output (requires real child completion)
|
||||
- [ ] Output summarization when exceeds threshold (requires LLM client)
|
||||
- [ ] Summarization uses configured model (requires LLM client)
|
||||
|
||||
### Task queue
|
||||
- [x] agent__task_create creates tasks with dependencies
|
||||
- [x] agent__task_complete marks done, unblocks dependents
|
||||
- [x] Auto-dispatch agent/prompt stored on task
|
||||
- [x] agent__task_list shows all tasks with status
|
||||
### Task queue (handler integration tests)
|
||||
- [x] handle_task_create creates tasks (simple, with deps, with dispatch_agent)
|
||||
- [x] handle_task_create errors when agent set without prompt
|
||||
- [x] handle_task_complete unblocks dependents
|
||||
- [x] handle_task_list shows all tasks
|
||||
- [x] handle_task_fail marks failed and reports blocked dependents
|
||||
- [x] handle_task_fail returns error for missing task
|
||||
|
||||
### Escalation
|
||||
- [x] Escalation submitted and retrievable
|
||||
### Escalation (handler integration tests)
|
||||
- [x] handle_reply_escalation delivers reply via oneshot channel
|
||||
- [x] handle_reply_escalation errors for missing escalation_id
|
||||
- [x] handle_reply_escalation errors when no queue
|
||||
- [x] Pending summary contains correct fields
|
||||
- [x] Reply reaches receiver via oneshot channel
|
||||
- [ ] Escalation timeout → fallback message (integration)
|
||||
- [ ] Escalation timeout → fallback message (requires tokio timeout)
|
||||
|
||||
### Teammate messaging
|
||||
- [x] Deliver to inbox
|
||||
- [x] Drain empties inbox
|
||||
- [x] Drain ordering: shutdown > task_completed > text
|
||||
### Teammate messaging (handler integration tests)
|
||||
- [x] handle_send_message delivers to registered agent's inbox
|
||||
- [x] handle_send_message errors for unknown agent
|
||||
- [x] handle_check_inbox returns messages with count
|
||||
- [x] handle_check_inbox returns empty when no inbox
|
||||
- [x] handle_check_inbox returns empty for empty inbox
|
||||
|
||||
### Cancel/List (handler integration tests)
|
||||
- [x] handle_list returns empty for fresh supervisor
|
||||
- [x] handle_list returns registered agents
|
||||
- [x] handle_list errors when no supervisor
|
||||
- [x] handle_cancel removes agent and signals abort
|
||||
- [x] handle_cancel errors for unknown agent
|
||||
- [x] handle_cancel errors when no supervisor
|
||||
|
||||
### Dispatch routing
|
||||
- [x] Unknown action → error with "Unknown supervisor action"
|
||||
- [x] agent__list routes to handle_list
|
||||
- [x] agent__task_list routes to handle_task_list
|
||||
|
||||
### Child agent lifecycle
|
||||
- [ ] run_child_agent loops (integration)
|
||||
- [ ] Child uses before/after_chat_completion (integration)
|
||||
- [ ] Child tool calls evaluated (integration)
|
||||
- [ ] Child exits cleanly (integration)
|
||||
- [ ] run_child_agent loops (requires LLM client)
|
||||
- [ ] Child uses before/after_chat_completion (requires LLM client)
|
||||
- [ ] Child tool calls evaluated (requires LLM client)
|
||||
- [ ] Child exits cleanly (requires LLM client)
|
||||
|
||||
## Context switching scenarios
|
||||
- [ ] Parent spawns child with MCP (integration)
|
||||
- [ ] Parent exits agent → all children cancelled (integration)
|
||||
- [ ] Multiple children share escalation queue correctly (integration)
|
||||
- [ ] Parent spawns child with MCP (requires live MCP + agent config)
|
||||
- [ ] Parent exits agent → all children cancelled (requires agent init)
|
||||
- [x] Multiple children share escalation queue (new_for_child + ensure_root_escalation_queue)
|
||||
|
||||
## Additional behaviors tested (not in original plan)
|
||||
|
||||
@@ -73,6 +94,13 @@ to request user input through the parent.
|
||||
- [x] TaskQueue: dependency on nonexistent errors, complete nonexistent
|
||||
- [x] TaskNode: is_runnable when pending+unblocked, not when blocked
|
||||
|
||||
## Integration handler tests added
|
||||
|
||||
- [x] All handle_* functions tested via handler integration tests (36 tests)
|
||||
- [x] new_for_child: depth, id, inbox, escalation queue, parent supervisor, empty scope
|
||||
- [x] ensure_root_escalation_queue: lazy init, same Arc on repeated calls
|
||||
- [x] AppState::test_default() helper added for cross-module test construction
|
||||
|
||||
## Old code reference
|
||||
- `src/function/supervisor.rs` — all handler functions
|
||||
- `src/supervisor/` — Supervisor, EscalationQueue, Inbox, TaskQueue
|
||||
|
||||
Reference in New Issue
Block a user