@@ -385,26 +385,30 @@ it('fails a Claude install (AB7006) when plugin list --json reports load errors
385385 listings += 1 ;
386386 return listings === 1 ? '[]' : claudeRefusedInventory ( installed ) ;
387387 } ) ;
388- const error = await installBundle ( { commandRunner : fresh . runner , from : fixture . from , host : 'claude' , scope : 'user' } )
388+ const error = await installBundle ( { ... isolated ( fixture ) , commandRunner : fresh . runner , from : fixture . from , host : 'claude' , scope : 'user' } )
389389 . catch ( ( failure : unknown ) => failure ) ;
390390 expect ( error ) . toBeInstanceOf ( DiagnosticError ) ;
391391 const [ diagnostic ] = ( error as DiagnosticError ) . diagnostics ;
392392 expect ( diagnostic ) . toMatchObject ( { code : 'AB7006' , severity : 'error' , target : 'claude' } ) ;
393393 expect ( diagnostic ?. message ) . toContain ( `claude refused to load install-fixture@install-fixture-marketplace (version 1.2.3) at ${ JSON . stringify ( installed ) } (scope user) after installation` ) ;
394394 expect ( diagnostic ?. message ) . toContain ( 'Duplicate hooks file detected' ) ;
395395 expect ( diagnostic ?. message ) . toContain ( '--replace' ) ;
396+ // The receipt lands before the load verdict, so the refused copy stays receipt-owned for `uninstall`.
396397 expect ( fresh . calls . map ( ( call ) => call . args . join ( ' ' ) ) ) . toEqual ( [
397398 'plugin list --json' ,
399+ 'plugin marketplace list --json' ,
398400 `plugin marketplace add ${ fixture . bundleRoot } ` ,
399401 'plugin install install-fixture@install-fixture-marketplace --scope user' ,
400402 'plugin list --json' ,
401403 ] ) ;
404+ expect ( await readInstallReceiptFile ( join ( fixture . cleanupRoot , 'claude-config' , 'agent-bundle' , 'receipts' , 'install-fixture.user.json' ) ) )
405+ . toMatchObject ( { plugin : 'install-fixture' , scope : 'user' } ) ;
402406
403407 // A byte-identical copy the host already refuses is never "already installed": reinstalling the same
404408 // bytes cannot help, so the defect is reported instead of a success.
405409 await cp ( fixture . bundleRoot , installed , { recursive : true } ) ;
406410 const identical = recordingRunner ( ( call ) => isInventoryCall ( call ) ? claudeRefusedInventory ( installed ) : '' ) ;
407- const existing = await installBundle ( { commandRunner : identical . runner , from : fixture . from , host : 'claude' , scope : 'user' } )
411+ const existing = await installBundle ( { ... isolated ( fixture ) , commandRunner : identical . runner , from : fixture . from , host : 'claude' , scope : 'user' } )
408412 . catch ( ( failure : unknown ) => failure ) ;
409413 expect ( existing ) . toBeInstanceOf ( DiagnosticError ) ;
410414 expect ( ( existing as DiagnosticError ) . diagnostics [ 0 ] ) . toMatchObject ( { code : 'AB7006' , target : 'claude' } ) ;
@@ -413,7 +417,7 @@ it('fails a Claude install (AB7006) when plugin list --json reports load errors
413417
414418 // Healthy rows (no `errors` key) keep the install result unchanged.
415419 const healthy = recordingRunner ( ( call ) => isInventoryCall ( call ) ? claudeInventory ( installed ) : '' ) ;
416- await expect ( installBundle ( { commandRunner : healthy . runner , from : fixture . from , host : 'claude' , scope : 'user' } ) )
420+ await expect ( installBundle ( { ... isolated ( fixture ) , commandRunner : healthy . runner , from : fixture . from , host : 'claude' , scope : 'user' } ) )
417421 . resolves . toMatchObject ( { state : 'already-installed' } ) ;
418422 } finally {
419423 await rm ( fixture . cleanupRoot , { force : true , recursive : true } ) ;
0 commit comments