@@ -277,6 +277,45 @@ describe("SubAgentDirector tool failure recovery", () => {
277277 expect ( ephemeralTexts ( later ) ) . toBeUndefined ( ) ;
278278 } ) ;
279279
280+ test ( "recovery nudge appends to ephemeral turns already on the infer" , async ( ) => {
281+ const director = new SubAgentDirector ( "system" , [ ] , undefined , 30 ) ;
282+ const caps = capabilities ( ) ;
283+ // Seed an ephemeral turn only when the caller did not supply any, so the
284+ // infer action applyPendingNudge rewrites already carries ephemeral turns.
285+ const seeding : ReactorCapabilities = {
286+ ...caps ,
287+ infer : ( options ) => {
288+ const existing = ( options as { ephemeralTurns ?: unknown [ ] } | undefined )
289+ ?. ephemeralTurns ;
290+ return caps . infer ( {
291+ ...( options ?? { } ) ,
292+ ...( existing === undefined
293+ ? {
294+ ephemeralTurns : [
295+ {
296+ role : "user" ,
297+ content : [ { type : "text" , text : "PRE-SEEDED-EPHEMERAL" } ] ,
298+ timestamp : 0 ,
299+ } ,
300+ ] ,
301+ }
302+ : { } ) ,
303+ } ) ;
304+ } ,
305+ } ;
306+
307+ await director . decide ( inferenceDone ( [ "seeded-fail" ] ) , state , seeding ) ;
308+ const texts = ephemeralTexts (
309+ inferAction (
310+ await director . decide ( toolDone ( "seeded-fail" , true ) , state , seeding ) ,
311+ ) ,
312+ ) ;
313+
314+ expect ( texts ) . toHaveLength ( 2 ) ;
315+ expect ( texts ?. [ 0 ] ) . toBe ( "PRE-SEEDED-EPHEMERAL" ) ;
316+ expect ( texts ?. [ 1 ] ) . toContain ( "A tool call failed" ) ;
317+ } ) ;
318+
280319 test ( "failed-tool recovery supersedes soft re-read guidance" , async ( ) => {
281320 const director = new SubAgentDirector ( "system" , [ ] , undefined , 30 ) ;
282321 const caps = capabilities ( ) ;
0 commit comments