@@ -441,7 +441,12 @@ describe.each([publicAccessorAdapter, sqliteAdapter])(
441441 orphanTranscriptMinAgeMs : 300_000 ,
442442 nowMs,
443443 } ) ,
444- ) . resolves . toEqual ( { removedEntries : 2 , archivedTranscriptArtifacts : 2 } ) ;
444+ ) . resolves . toEqual ( {
445+ // Only the removed entry's transcript is archived: the orphan's route
446+ // row still targets it, and route-referenced history is retained.
447+ removedEntries : 2 ,
448+ archivedTranscriptArtifacts : 1 ,
449+ } ) ;
445450
446451 expect (
447452 adapter . loadSessionEntry ( scopedEntry ( "agent:main:lifecycle-cleanup-missing" ) ) ,
@@ -500,7 +505,11 @@ describe.each([publicAccessorAdapter, sqliteAdapter])(
500505 file . startsWith ( "orphan-lifecycle.jsonl.deleted." ) ,
501506 ) ;
502507 expect ( removedArchive ) . toBeDefined ( ) ;
503- expect ( orphanArchive ) . toBeDefined ( ) ;
508+ // Route-referenced orphan history is retained in SQLite, not archived.
509+ expect ( orphanArchive ) . toBeUndefined ( ) ;
510+ await expect (
511+ adapter . loadTranscriptEvents ( scopedTranscript ( "agent:main:orphan" , "orphan-lifecycle" ) ) ,
512+ ) . resolves . not . toEqual ( [ ] ) ;
504513 expect (
505514 readSessionArchiveContentSync (
506515 path . join ( path . dirname ( cleanupStorePath ) , removedArchive ?? "" ) ,
@@ -1616,7 +1625,7 @@ describe("sqlite session normalization", () => {
16161625 } ) ;
16171626 } ) ;
16181627
1619- it ( "evicts old SQLite transcript rows only when no remaining entry references them " , async ( ) => {
1628+ it ( "keeps live entries and transcripts under byte pressure at save time " , async ( ) => {
16201629 vi . mocked ( getRuntimeConfig ) . mockReturnValue ( {
16211630 session : {
16221631 maintenance : {
@@ -1697,6 +1706,9 @@ describe("sqlite session normalization", () => {
16971706 modelOverride : "gpt-5.5" ,
16981707 } ) ) ;
16991708
1709+ // Live sessions are never save-time budget victims: byte pressure is
1710+ // handled by the async physical-budget pass, which only reclaims
1711+ // historical generations no entry, route, or admission references.
17001712 expect (
17011713 listSqliteSessionEntries ( {
17021714 agentId : "main" ,
@@ -1705,7 +1717,7 @@ describe("sqlite session normalization", () => {
17051717 } )
17061718 . map ( ( summary ) => summary . sessionKey )
17071719 . toSorted ( ) ,
1708- ) . toEqual ( [ "agent:main:active-budget" ] ) ;
1720+ ) . toEqual ( [ "agent:main:active-budget" , "agent:main:old-budget" , "agent:main:unshared-budget" ] ) ;
17091721 await expect (
17101722 loadSqliteTranscriptEvents ( {
17111723 agentId : "main" ,
@@ -1725,18 +1737,14 @@ describe("sqlite session normalization", () => {
17251737 sessionId : "unshared-budget-session" ,
17261738 storePath : paths . sqlitePath ,
17271739 } ) ,
1728- ) . resolves . toEqual ( [ ] ) ;
1729- const archivedOldBudget = fs
1730- . readdirSync ( paths . tempDir )
1731- . filter ( ( file ) => file . startsWith ( "old-budget-session.jsonl.deleted." ) ) ;
1732- expect ( archivedOldBudget ) . toHaveLength ( 0 ) ;
1733- const archivedUnsharedBudget = fs
1734- . readdirSync ( paths . tempDir )
1735- . filter ( ( file ) => file . startsWith ( "unshared-budget-session.jsonl.deleted." ) ) ;
1736- expect ( archivedUnsharedBudget ) . toHaveLength ( 1 ) ;
1740+ ) . resolves . toEqual ( [
1741+ expect . objectContaining ( {
1742+ id : "unshared-budget-event" ,
1743+ } ) ,
1744+ ] ) ;
17371745 expect (
1738- readSessionArchiveContentSync ( path . join ( paths . tempDir , archivedUnsharedBudget [ 0 ] ?? " ") ) ,
1739- ) . toContain ( "unshared-budget-event" ) ;
1746+ fs . readdirSync ( paths . tempDir ) . filter ( ( file ) => file . includes ( ".jsonl.deleted. ") ) ,
1747+ ) . toEqual ( [ ] ) ;
17401748 } ) ;
17411749
17421750 it ( "resolves confirmed lowercased legacy SQLite session aliases" , async ( ) => {
0 commit comments