feat(subagent): deliver continuable child settlement to parents
A continuable child that stopped without reporting — an error, a token ceiling, cancellation, teardown — left its parent nothing to act on. The continuation manager now delivers an unconditional settlement notice to the durable direct parent before releasing ownership, folding consumed work (foldConsumedWork supersedes findLastMessageTurnEnd) so a claimed-but-unrun prompt reads as aborted rather than completed, waking an idle parent, steering a busy one, and never waking a closing tree.
This commit is contained in:
@@ -44,6 +44,9 @@ const CHILD_QUESTION_CONFIG = fileURLToPath(new URL('../child-question.cordis.ym
|
||||
const SESSION_SANDBOX_ROOT_CONFIG = fileURLToPath(new URL('../session-sandbox-root.cordis.yml', import.meta.url))
|
||||
const RETRY_CONFIG = fileURLToPath(new URL('../retry.cordis.yml', import.meta.url))
|
||||
const SESSION_TITLE_CONFIG = fileURLToPath(new URL('../session-title.cordis.yml', import.meta.url))
|
||||
const SUBAGENT_REPORT_QUIET_CONFIG = fileURLToPath(
|
||||
new URL('../subagent-report-quiet.cordis.yml', import.meta.url),
|
||||
)
|
||||
const SUBAGENT_DURABILITY_FAILURE_CONFIG = fileURLToPath(
|
||||
new URL('../subagent-durability-failure.cordis.yml', import.meta.url),
|
||||
)
|
||||
@@ -353,7 +356,13 @@ const SCENARIOS: Scenario[] = [
|
||||
// turns on that same child (the parent is never woken with their output),
|
||||
// send_message to an unknown subagent id fails without delivering, and the
|
||||
// child's retained handle is disposed child-first at teardown despite a
|
||||
// failed final durability confirmation.
|
||||
// failed final durability confirmation. That failed confirmation is also what
|
||||
// the settlement notice must report: the child's last turn claimed the third
|
||||
// message and then died on its durability checkpoint without entering a step,
|
||||
// so the notice opening the parent's second turn says the child FAILED and the
|
||||
// parent must not read the earlier answer as final. The scenario's fixture
|
||||
// fences the child behind the parent's spawn turn so that notice can only
|
||||
// arrive at an idle parent.
|
||||
{
|
||||
name: 'subagent-continuable',
|
||||
hasModelTurn: true,
|
||||
@@ -367,6 +376,8 @@ const SCENARIOS: Scenario[] = [
|
||||
// continuable background child's log carries that override as a
|
||||
// `sandbox/mode` `source: 'delegation'` event, so the child's runtime
|
||||
// context states the inherited policy instead of the deployment default.
|
||||
// The input also waits for the manager-owned settlement turn, keeping that
|
||||
// delivery from racing transcript harvest.
|
||||
{
|
||||
name: 'subagent-continuable-inheritance',
|
||||
hasModelTurn: true,
|
||||
@@ -387,12 +398,16 @@ const SCENARIOS: Scenario[] = [
|
||||
configPath: SUBAGENT_DURABILITY_FAILURE_CONFIG,
|
||||
},
|
||||
// Authored child-to-parent transcript: the child calls its scope-local
|
||||
// `report`, the default waking delivery gives the parked parent one ordinary
|
||||
// turn on that report, and a later prompt still reads it back from the log.
|
||||
// `report`, and the runtime's unconditional settlement notice then wakes the
|
||||
// parked parent into one ordinary turn that claims both. The overlay pins
|
||||
// quiet report delivery because two independent wakes have no orderable
|
||||
// transcript; the shipped waking default is covered by package tests.
|
||||
{
|
||||
name: 'subagent-report',
|
||||
hasModelTurn: true,
|
||||
recorded: false,
|
||||
overridden: false,
|
||||
configPath: SUBAGENT_REPORT_QUIET_CONFIG,
|
||||
pinsChildToolSchemas: [1],
|
||||
pinsChildSystemPrompts: [1],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user