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