test(subagent): reach full continuable coverage and simplify unreachable paths

Adds coverage for the fork-seeded descriptor turn numbering, omitted and declared
descriptor composition fields, a routeless cold resume, and the drain no-op.

Splits materialize's create-versus-resume inputs so the impossible
create-without-meta case disappears, drops the observer's unreachable
pre-residency guard, and annotates the three remaining paths that only a
non-deterministic send-versus-dispose race can reach.
This commit is contained in:
Dudu-0223
2026-07-30 14:09:24 +08:00
committed by Tianyi Cui
parent bc504195df
commit 3911b7117e
4 changed files with 163 additions and 49 deletions

View File

@@ -362,17 +362,17 @@ export class SubagentService extends Service {
parent: Agent | undefined,
): ActivationObserver {
const identity = { runId: SubagentRunId(randomUUID()), provider, id: childId, local: true }
let started = false
let settled = false
return {
start: (): void => {
started = true
this.emitLifecycle('subagent/start', identity, parent)
},
settle: (child: Agent, failure: unknown): void => {
// A failure before residency has no start edge to pair, and inventing
// one would report a lifecycle the child never had.
if (settled || !started) return
// Exactly one terminal edge per epoch: host shutdown, manager unload,
// child release, and normal settlement all converge on one disposal.
/* v8 ignore next -- the memoized disposal already collapses those callers into a
* single settle(); this guard keeps the edge single if that memoization ever changes. */
if (settled) return
settled = true
const output = failure === undefined ? lastAssistantOutput(child) : undefined
this.emitLifecycle('subagent/end', {