1ae8f4cf9f
Co-authored-by: nova28 <17953305+nova28@users.noreply.github.com> Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
3.8 KiB
3.8 KiB
id, title, status, wave, depends_on, plan, spec
| id | title | status | wave | depends_on | plan | spec | |
|---|---|---|---|---|---|---|---|
| 04-orchestrator-wiring | Orchestrator frame wiring | pending | 4 |
|
plan.md | ../../specs/subagent-context-persistence/spec.md |
Amendment 1 update: the orchestrator must supply the execution identity (
agent_execution_id) alongside the existing frame fields — see the "Amendment 1 update" note near the top ofplan.mdfor the current wiring shape.
Task 04: Orchestrator frame wiring
Call the writer from the two frame handlers that already parse the subagent
payload, and wire the adapter in backendapp.
Acceptance
- A
subagent_taskframe onhandleToolCallEventrecords a context with the active turn id; a later frame for the same tool call onpersistToolUpdateMessagerecords again so the upsert's merge path runs. A nested frame (ParentToolCallIDset) is recorded, not dropped. (AC-1, AC-3, AC-6) - A non-
subagent_tasknormalized kind records nothing, and a nil recorder is safe — no panic, and the message write still happens. (AC-27) - Neither handler exceeds the package's
funlenlimit (80 lines / 50 statements); the guard and request build live in onerecordSubagentContextFromFramehelper.
Files likely touched
apps/backend/internal/orchestrator/service.go— newSubagentContextRecorderinterface besideMessageCreator(line ~86) and an optionalsubagentContextsfield onService.apps/backend/internal/orchestrator/event_handlers_streaming.go— newrecordSubagentContextFromFramehelper; call it fromhandleToolCallEvent(~line 312, after theCreateToolCallMessageblock) and frompersistToolUpdateMessage(~line 565, afterUpdateToolCallMessage).apps/backend/internal/backendapp/adapters.go— newsubagentContextAdapterover*taskservice.Service, wired wheremessageCreatorAdapteris wired.apps/backend/internal/orchestrator/event_handlers_streaming_subagent_test.go— new.
Dependencies
Task 03 — the service method is what the interface abstracts.
Parallelism
sequential.
Inputs
- Plan § Orchestrator wiring (task 04) — carries the interface shape, both call sites, and the turn-id sourcing rule.
- Spec AC-1, AC-1a, AC-2a, AC-3, AC-6, AC-11, AC-27.
- Turn id must come from what each call site already resolved, not from a
fresh lookup:
handleToolCallEventusess.getActiveTurnID(payload.SessionID)andpersistToolUpdateMessageuses its localturnID, which ispeekActiveTurnIDfor terminal frames andgetActiveTurnIDotherwise. A terminal frame on a settled turn deliberately resolves to"", and AC-2a's original-turn preservation lives in the upsert, not here — do not re-derive a turn to "fix" an empty one. payload.SessionIDis the Kandev task session id, despite theagentSessionIDparameter name downstream:messageCreatorAdapterpasses the same value intoCreateMessageRequest.TaskSessionID(internal/backendapp/adapters.go:879).- Guard on
payload.Data.Normalized.Kind() == streams.ToolKindSubagentTaskand a non-nilNormalized.SubagentTask(). - Test patterns:
event_handlers_streaming_test.go:906(newServiceBackedMessageCreator(repo)) for the end-to-end handler → service → repo case, andmockMessageCreatorfor the unit cases.
Verification
cd apps/backend && gofmt -l internal/orchestrator internal/backendapp && make lint && go test -run 'Subagent' ./internal/orchestrator/... && go test ./internal/orchestrator/... ./internal/backendapp/...
Results
Pending. Before marking the task done, replace this with every exact command
actually run and its outcome/count, generated artifact paths, and cleanup or
teardown evidence. Record security/trust and external side-effect boundaries
when applicable, or explicitly state None.