@@ -281,85 +281,88 @@ test('diagnostic get/is reads mid-repair are excluded from the healed script by
281281 expect ( freshRun . ok ) . toBe ( true ) ;
282282} ) ;
283283
284- test ( "a --record'ed diagnostic read lands in the healed script (the diverged-step-was-a-get case)" , async ( ) => {
285- const ctx = setup ( 'agent-device-repair-record-exclusion-record-' ) ;
286- const filePath = writeReplayFile ( ctx . root , [
287- 'open "Demo" --relaunch' ,
288- SAVE_ANNOTATION ,
289- 'click id="save"' ,
290- 'click id="confirm"' ,
291- 'close' ,
292- ] ) ;
293- const { invoke, divergence } = await armAndDiverge ( ctx , filePath ) ;
294- const session = ctx . sessionStore . get ( ctx . sessionName ) ! ;
284+ test . each ( [ 'get' , 'snapshot' ] ) (
285+ "a --record'ed %s correction satisfies the resume guard and persists in the healed script" ,
286+ async ( command ) => {
287+ const ctx = setup ( 'agent-device-repair-record-exclusion-record-' ) ;
288+ const filePath = writeReplayFile ( ctx . root , [
289+ 'open "Demo" --relaunch' ,
290+ SAVE_ANNOTATION ,
291+ 'click id="save"' ,
292+ 'click id="confirm"' ,
293+ 'close' ,
294+ ] ) ;
295+ const { invoke, divergence } = await armAndDiverge ( ctx , filePath ) ;
296+ const session = ctx . sessionStore . get ( ctx . sessionName ) ! ;
295297
296- // --- The agent's correction for the diverged step IS itself a read (the
297- // wave-3 E3 shape): `get attrs` on the renamed control, explicitly forced
298- // into the heal with `--record` since it would otherwise be excluded. ---
299- ctx . sessionStore . recordAction ( storeSessionForTest ( ctx . sessionStore , session ) , {
300- command : 'get' ,
301- positionals : [ 'attrs' , '@e7' ] ,
302- flags : { record : true } ,
303- result : { selectorChain : [ 'id="save-v2"' ] } ,
304- interactiveObservation : true ,
305- } ) ;
306- expect ( session . actions . map ( ( a ) => a . command ) ) . toEqual ( [ 'open' , 'get' ] ) ;
298+ // --- The agent's correction for the diverged step IS itself a read (the
299+ // wave-3 E3 shape): `get attrs` on the renamed control, explicitly forced
300+ // into the heal with `--record` since it would otherwise be excluded. ---
301+ ctx . sessionStore . recordAction ( storeSessionForTest ( ctx . sessionStore , session ) , {
302+ command ,
303+ positionals : command === 'get' ? [ 'attrs' , '@e7' ] : [ ] ,
304+ flags : { record : true } ,
305+ result : { selectorChain : [ 'id="save-v2"' ] } ,
306+ interactiveObservation : true ,
307+ } ) ;
308+ expect ( session . actions . map ( ( a ) => a . command ) ) . toEqual ( [ 'open' , command ] ) ;
307309
308- const leg2 = await runReplayForTest ( {
309- req : baseReq ( {
310- positionals : [ filePath ] ,
311- flags : { saveScript : true , replayFrom : 3 , replayPlanDigest : divergence . resume . planDigest } ,
312- } ) ,
313- sessionName : ctx . sessionName ,
314- logPath : ctx . logPath ,
315- sessionStore : ctx . sessionStore ,
316- invoke,
317- } ) ;
318- expect ( leg2 . ok ) . toBe ( true ) ;
319- expect ( session . actions . map ( ( a ) => a . command ) ) . toEqual ( [ 'open' , 'get' , 'click' ] ) ;
310+ const leg2 = await runReplayForTest ( {
311+ req : baseReq ( {
312+ positionals : [ filePath ] ,
313+ flags : { saveScript : true , replayFrom : 3 , replayPlanDigest : divergence . resume . planDigest } ,
314+ } ) ,
315+ sessionName : ctx . sessionName ,
316+ logPath : ctx . logPath ,
317+ sessionStore : ctx . sessionStore ,
318+ invoke,
319+ } ) ;
320+ expect ( leg2 . ok ) . toBe ( true ) ;
321+ expect ( session . actions . map ( ( a ) => a . command ) ) . toEqual ( [ 'open' , command , 'click' ] ) ;
320322
321- const closeResponse = await handleCloseCommand ( {
322- platformServices : daemonPlatformServicesFixture ( ) ,
323- req : {
324- token : 't' ,
325- session : ctx . sessionName ,
326- command : 'close' ,
327- positionals : [ ] ,
328- flags : { saveScript : true } ,
329- } ,
330- sessionName : ctx . sessionName ,
331- logPath : ctx . logPath ,
332- sessionStore : ctx . sessionStore ,
333- leaseRegistry : ctx . leaseRegistry ,
334- } ) ;
335- expect ( closeResponse . ok ) . toBe ( true ) ;
323+ const closeResponse = await handleCloseCommand ( {
324+ platformServices : daemonPlatformServicesFixture ( ) ,
325+ req : {
326+ token : 't' ,
327+ session : ctx . sessionName ,
328+ command : 'close' ,
329+ positionals : [ ] ,
330+ flags : { saveScript : true } ,
331+ } ,
332+ sessionName : ctx . sessionName ,
333+ logPath : ctx . logPath ,
334+ sessionStore : ctx . sessionStore ,
335+ leaseRegistry : ctx . leaseRegistry ,
336+ } ) ;
337+ expect ( closeResponse . ok ) . toBe ( true ) ;
336338
337- const healedPath = path . join ( ctx . root , 'flow.healed.ad' ) ;
338- const healedScript = fs . readFileSync ( healedPath , 'utf8' ) ;
339- const parsed = parseReplayScriptDetailed ( healedScript ) ;
340- // The --record'ed corrective read DOES land in the heal, resolved to a
341- // selector (never a bare @ref).
342- expect ( parsed . actions . map ( ( a ) => a . command ) ) . toEqual ( [ 'open' , 'get' , 'click' , 'close' ] ) ;
343- const getAction = parsed . actions . find ( ( a ) => a . command === 'get' ) ;
344- expect ( getAction ?. positionals ) . toEqual ( [ 'attrs' , 'id="save-v2"' ] ) ;
345- const bareRefs = parsed . actions . flatMap ( ( a ) => a . positionals . filter ( ( p ) => p . startsWith ( '@' ) ) ) ;
346- expect ( bareRefs ) . toEqual ( [ ] ) ;
339+ const healedPath = path . join ( ctx . root , 'flow.healed.ad' ) ;
340+ const healedScript = fs . readFileSync ( healedPath , 'utf8' ) ;
341+ const parsed = parseReplayScriptDetailed ( healedScript ) ;
342+ // The --record'ed corrective read DOES land in the heal, resolved to a
343+ // selector (never a bare @ref).
344+ expect ( parsed . actions . map ( ( a ) => a . command ) ) . toEqual ( [ 'open' , command , 'click' , 'close' ] ) ;
345+ const correction = parsed . actions . find ( ( a ) => a . command === command ) ;
346+ expect ( correction ?. positionals ) . toEqual ( command === 'get' ? [ 'attrs' , 'id="save-v2"' ] : [ ] ) ;
347+ const bareRefs = parsed . actions . flatMap ( ( a ) => a . positionals . filter ( ( p ) => p . startsWith ( '@' ) ) ) ;
348+ expect ( bareRefs ) . toEqual ( [ ] ) ;
347349
348- // --- Replays cleanly in a fresh session too. ---
349- const fresh = setup ( 'agent-device-repair-record-exclusion-record-fresh-' ) ;
350- const freshInvoke = makeRecordingReplayInvoke ( {
351- sessionStore : fresh . sessionStore ,
352- sessionName : fresh . sessionName ,
353- } ) ;
354- const freshRun = await runReplayForTest ( {
355- req : baseReq ( { positionals : [ healedPath ] } ) ,
356- sessionName : fresh . sessionName ,
357- logPath : fresh . logPath ,
358- sessionStore : fresh . sessionStore ,
359- invoke : freshInvoke ,
360- } ) ;
361- expect ( freshRun . ok ) . toBe ( true ) ;
362- } ) ;
350+ // --- Replays cleanly in a fresh session too. ---
351+ const fresh = setup ( 'agent-device-repair-record-exclusion-record-fresh-' ) ;
352+ const freshInvoke = makeRecordingReplayInvoke ( {
353+ sessionStore : fresh . sessionStore ,
354+ sessionName : fresh . sessionName ,
355+ } ) ;
356+ const freshRun = await runReplayForTest ( {
357+ req : baseReq ( { positionals : [ healedPath ] } ) ,
358+ sessionName : fresh . sessionName ,
359+ logPath : fresh . logPath ,
360+ sessionStore : fresh . sessionStore ,
361+ invoke : freshInvoke ,
362+ } ) ;
363+ expect ( freshRun . ok ) . toBe ( true ) ;
364+ } ,
365+ ) ;
363366
364367test ( 'empty-segment guard: a --from resume refuses with an actionable --record hint when only excluded diagnostic reads happened since the divergence' , async ( ) => {
365368 const ctx = setup ( 'agent-device-repair-record-exclusion-empty-segment-' ) ;
@@ -390,6 +393,12 @@ test('empty-segment guard: a --from resume refuses with an actionable --record h
390393 result : { found : true } ,
391394 interactiveObservation : true ,
392395 } ) ;
396+ ctx . sessionStore . recordAction ( storeSessionForTest ( ctx . sessionStore , session ) , {
397+ command : 'snapshot' ,
398+ positionals : [ ] ,
399+ flags : { } ,
400+ interactiveObservation : true ,
401+ } ) ;
393402 expect ( session . actions . map ( ( a ) => a . command ) ) . toEqual ( [ 'open' ] ) ;
394403
395404 const blindResume = await runReplayForTest ( {
0 commit comments