@@ -33,30 +33,61 @@ export class LogStore {
3333 this . entries . push ( entry ) ;
3434 }
3535
36- clear ( options ?: { session ?: string ; scope ?: 'soft' | 'hard' } ) {
36+ clear ( options ?: { session ?: string ; scope ?: 'soft' | 'hard' ; project ?: string } ) {
3737 const scope = options ?. scope || 'hard' ;
3838 const session = options ?. session ;
39+ const project = options ?. project ;
3940
4041 if ( scope === 'soft' ) {
41- const key = session || '__global__' ;
42- this . baselineTimestamps . set ( key , Date . now ( ) ) ;
43- } else {
44- if ( session ) {
45- this . entries = this . entries . filter ( e => ( e . sessionId || '' ) . slice ( 0 , 8 ) !== session ) ;
46- this . baselineTimestamps . delete ( session ) ;
42+ if ( project && project . trim ( ) ) {
43+ this . baselineTimestamps . set ( `project:${ project } ` , Date . now ( ) ) ;
44+ } else if ( session && session . trim ( ) ) {
45+ this . baselineTimestamps . set ( `session:${ session . slice ( 0 , 8 ) } ` , Date . now ( ) ) ;
4746 } else {
48- this . entries . length = 0 ;
49- this . baselineTimestamps . clear ( ) ;
47+ // Global soft baseline (discouraged for multi-project, kept for backward compat)
48+ this . baselineTimestamps . set ( '__global__' , Date . now ( ) ) ;
5049 }
50+ return ;
5151 }
52+
53+ // Hard clear
54+ if ( project && project . trim ( ) ) {
55+ // Remove only entries for this project and drop its baseline
56+ const p = project ;
57+ this . entries = this . entries . filter ( e => ( e . project || '' ) !== p ) ;
58+ this . baselineTimestamps . delete ( `project:${ p } ` ) ;
59+ return ;
60+ }
61+
62+ if ( session && session . trim ( ) ) {
63+ const s = session . slice ( 0 , 8 ) ;
64+ this . entries = this . entries . filter ( e => ( e . sessionId || '' ) . slice ( 0 , 8 ) !== s ) ;
65+ this . baselineTimestamps . delete ( `session:${ s } ` ) ;
66+ return ;
67+ }
68+
69+ // Global hard clear
70+ this . entries . length = 0 ;
71+ this . baselineTimestamps . clear ( ) ;
5272 }
5373
5474 /** Set a baseline timestamp without deleting entries. If session omitted, use global baseline. */
5575 baseline ( session ?: string , when : number = Date . now ( ) ) {
56- const key = session || '__global__' ;
76+ const key = session ? `session: ${ session . slice ( 0 , 8 ) } ` : '__global__' ;
5777 this . baselineTimestamps . set ( key , when ) ;
5878 }
5979
80+ /** Set a baseline for a specific project (recommended for multi-project use). */
81+ baselineProject ( project : string , when : number = Date . now ( ) ) {
82+ if ( ! project || ! project . trim ( ) ) return ;
83+ this . baselineTimestamps . set ( `project:${ project } ` , when ) ;
84+ }
85+
86+ /** Set a global baseline (discouraged for multi-project; kept for backward compatibility). */
87+ baselineGlobal ( when : number = Date . now ( ) ) {
88+ this . baselineTimestamps . set ( '__global__' , when ) ;
89+ }
90+
6091 toText ( session ?: string ) : string {
6192 return this . snapshot ( session ) . map ( ( e ) => {
6293 const sid = ( e . sessionId || 'anon' ) . slice ( 0 , 8 ) ;
@@ -76,17 +107,23 @@ export class LogStore {
76107 let items = this . entries . slice ( ) ;
77108 if ( session ) items = items . filter ( e => ( e . sessionId || '' ) . slice ( 0 , 8 ) === session ) ;
78109
79- const baselineKey = session || '__global__' ;
80- const baseline = this . baselineTimestamps . get ( baselineKey ) ;
81- if ( baseline ) {
82- items = items . filter ( e => ! e . time || e . time >= baseline ) ;
83- if ( items . length === 0 && this . entries . length > 0 ) {
84- // eslint-disable-next-line no-console
85- console . warn ( `All ${ this . entries . length } logs filtered out by baseline. Check timestamp format.` ) ;
86- }
110+ const globalTs = this . baselineTimestamps . get ( '__global__' ) || 0 ;
111+ const sessionTs = session ? ( this . baselineTimestamps . get ( `session:${ session } ` ) || 0 ) : 0 ;
112+
113+ const filtered = items . filter ( ( e ) => {
114+ const t = e . time || 0 ;
115+ const projectTs = e . project ? ( this . baselineTimestamps . get ( `project:${ e . project } ` ) || 0 ) : 0 ;
116+ // Session baseline only applies when caller filtered by that session.
117+ const threshold = Math . max ( globalTs , sessionTs , projectTs ) ;
118+ return t === 0 || t >= threshold ;
119+ } ) ;
120+
121+ if ( filtered . length === 0 && this . entries . length > 0 && ( globalTs || sessionTs ) ) {
122+ // eslint-disable-next-line no-console
123+ console . warn ( `All ${ this . entries . length } logs filtered out by baseline. Check timestamp format or baseline scope.` ) ;
87124 }
88125
89- return items ;
126+ return filtered ;
90127 }
91128}
92129
0 commit comments