/** * Loader fixture that holds the parent's second step until settlement delivery. * @module subagent-settlement-fence */ import type { Context } from '@deepseek-ai/cordis' import type {} from '@deepseek-ai/dsh-agent-loop' import type {} from '@deepseek-ai/dsh-subagent' /** Fixture plugin name. */ export const name = 'subagent-settlement-fence' /** * Fence the parent's post-spawn request behind admission of the manager notice. * * This pins content order, not step placement: the held pre-step runs after its * own `Inbox.claim()`, so the notice lands after step 2's claim and is claimed at * step 3 because the child's settlement pipeline is strictly longer than the * parent's claim path, not because a barrier forces it. * @param ctx - assembled headless-agent context. */ export function apply(ctx: Context): void { const delivered = Promise.withResolvers() let hasDelivered = false ctx.effect(() => { const disposeInbox = ctx.root.on('agent/inbox/inserted', ({ agent, message }) => { if (agent.session.header.parentSession !== undefined || message.source.kind !== 'subagent-settled') return hasDelivered = true delivered.resolve(undefined) }) const disposeStep = ctx.root.on('agent/pre-step', async ({ agent, turn, step }, next) => { if (agent.session.header.parentSession === undefined && turn === 1 && step === 2 && !hasDelivered) { await delivered.promise } return next() }) return () => { disposeStep() disposeInbox() } }, 'subagent-settlement-fence.listeners') }