github-issue-tower-defence-management 1.114.2 → 1.115.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +3 -4
  3. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +10 -17
  4. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  5. package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js +3 -4
  6. package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js.map +1 -1
  7. package/bin/adapter/repositories/TmuxSilentSessionNotificationRepository.js +1 -26
  8. package/bin/adapter/repositories/TmuxSilentSessionNotificationRepository.js.map +1 -1
  9. package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js +34 -9
  10. package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +6 -21
  13. package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.test.ts +110 -62
  14. package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts +8 -12
  15. package/src/adapter/repositories/TmuxSilentSessionNotificationRepository.test.ts +2 -98
  16. package/src/adapter/repositories/TmuxSilentSessionNotificationRepository.ts +1 -45
  17. package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +221 -11
  18. package/src/domain/usecases/NotifySilentLiveSessionsUseCase.ts +55 -18
  19. package/src/domain/usecases/adapter-interfaces/SilentSessionNotificationRepository.ts +0 -5
  20. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  21. package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts +3 -4
  22. package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts.map +1 -1
  23. package/types/adapter/repositories/TmuxSilentSessionNotificationRepository.d.ts +1 -6
  24. package/types/adapter/repositories/TmuxSilentSessionNotificationRepository.d.ts.map +1 -1
  25. package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts +7 -3
  26. package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts.map +1 -1
  27. package/types/domain/usecases/adapter-interfaces/SilentSessionNotificationRepository.d.ts +0 -2
  28. package/types/domain/usecases/adapter-interfaces/SilentSessionNotificationRepository.d.ts.map +1 -1
@@ -1,11 +1,13 @@
1
1
  import {
2
2
  NotifySilentLiveSessionsUseCase,
3
+ HubTaskStatusResolver,
4
+ parseHubTaskIssueUrlFromSessionName,
3
5
  DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
4
6
  DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
5
7
  DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
6
- DEFAULT_NOTIFICATION_COOLDOWN_SECONDS,
7
8
  DEFAULT_NOTIFICATION_STAGGER_SECONDS,
8
9
  } from './NotifySilentLiveSessionsUseCase';
10
+ import { Issue } from '../entities/Issue';
9
11
  import { LiveSessionProcessSnapshotProvider } from './adapter-interfaces/LiveSessionProcessSnapshotProvider';
10
12
  import { InteractiveLiveSessionTranscriptResolver } from './adapter-interfaces/InteractiveLiveSessionTranscriptResolver';
11
13
  import { SessionOutputActivityRepository } from './adapter-interfaces/SessionOutputActivityRepository';
@@ -33,23 +35,27 @@ describe('NotifySilentLiveSessionsUseCase', () => {
33
35
  let mockNotificationRepository: Mocked<SilentSessionNotificationRepository>;
34
36
  let mockMessageComposer: Mocked<SilentSessionMessageComposer>;
35
37
  let mockSleeper: Mocked<Sleeper>;
38
+ let mockHubTaskStatusResolver: Mocked<HubTaskStatusResolver>;
36
39
  const now = new Date('2026-06-26T00:00:00Z');
37
40
  const nowEpochSeconds = Math.floor(now.getTime() / 1000);
38
41
 
39
- const runParams = (): {
42
+ const runParams = (
43
+ overrides?: Partial<{ activeHubTaskStatus: string | null }>,
44
+ ): {
40
45
  mainSilentThresholdSeconds: number;
41
46
  subAgentSilentThresholdSeconds: number;
42
47
  subAgentRunningThresholdSeconds: number;
43
- cooldownSeconds: number;
44
48
  staggerSeconds: number;
49
+ activeHubTaskStatus: string | null;
45
50
  now: Date;
46
51
  } => ({
47
52
  mainSilentThresholdSeconds: DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
48
53
  subAgentSilentThresholdSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
49
54
  subAgentRunningThresholdSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
50
- cooldownSeconds: DEFAULT_NOTIFICATION_COOLDOWN_SECONDS,
51
55
  staggerSeconds: DEFAULT_NOTIFICATION_STAGGER_SECONDS,
56
+ activeHubTaskStatus: null,
52
57
  now,
58
+ ...overrides,
53
59
  });
54
60
 
55
61
  const emptySnapshot: LiveSessionProcessSnapshot = {
@@ -118,8 +124,6 @@ describe('NotifySilentLiveSessionsUseCase', () => {
118
124
  .mockResolvedValue(new Set<string>()),
119
125
  };
120
126
  mockNotificationRepository = {
121
- getLastNotifiedEpochSeconds: jest.fn().mockResolvedValue(null),
122
- setLastNotifiedEpochSeconds: jest.fn().mockResolvedValue(undefined),
123
127
  sendSelfCheckNotification: jest.fn().mockResolvedValue(undefined),
124
128
  };
125
129
  mockMessageComposer = {
@@ -131,6 +135,9 @@ describe('NotifySilentLiveSessionsUseCase', () => {
131
135
  mockSleeper = {
132
136
  sleep: jest.fn().mockResolvedValue(undefined),
133
137
  };
138
+ mockHubTaskStatusResolver = {
139
+ getIssueByUrl: jest.fn().mockResolvedValue(null),
140
+ };
134
141
  useCase = new NotifySilentLiveSessionsUseCase(
135
142
  mockSnapshotProvider,
136
143
  mockTranscriptResolver,
@@ -140,9 +147,51 @@ describe('NotifySilentLiveSessionsUseCase', () => {
140
147
  mockNotificationRepository,
141
148
  mockMessageComposer,
142
149
  mockSleeper,
150
+ mockHubTaskStatusResolver,
143
151
  );
144
152
  });
145
153
 
154
+ const issueFor = (overrides: Partial<Issue>): Issue => ({
155
+ nameWithOwner: 'HiromiShikata/repo',
156
+ number: 42,
157
+ title: 'Hub task',
158
+ state: 'OPEN',
159
+ status: 'In tmux',
160
+ story: null,
161
+ nextActionDate: null,
162
+ nextActionHour: null,
163
+ estimationMinutes: null,
164
+ dependedIssueUrls: [],
165
+ completionDate50PercentConfidence: null,
166
+ url: 'https://github.com/HiromiShikata/repo/issues/42',
167
+ assignees: [],
168
+ labels: [],
169
+ org: 'HiromiShikata',
170
+ repo: 'repo',
171
+ body: '',
172
+ itemId: 'item-id',
173
+ isPr: false,
174
+ isInProgress: false,
175
+ isClosed: false,
176
+ createdAt: now,
177
+ author: 'HiromiShikata',
178
+ closingIssueReferenceUrls: [],
179
+ ...overrides,
180
+ });
181
+
182
+ const setupSilentMainSession = (sessionName: string): void => {
183
+ setupLiveInteractiveSession(sessionName);
184
+ mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
185
+ [
186
+ {
187
+ sessionName,
188
+ lastOutputEpochSeconds:
189
+ nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
190
+ },
191
+ ],
192
+ );
193
+ };
194
+
146
195
  const setupLiveInteractiveSession = (sessionName: string): void => {
147
196
  mockSnapshotProvider.getSnapshot.mockResolvedValue(
148
197
  snapshotWithSessions([sessionName]),
@@ -156,7 +205,6 @@ describe('NotifySilentLiveSessionsUseCase', () => {
156
205
  expect(DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS).toBe(600);
157
206
  expect(DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS).toBe(300);
158
207
  expect(DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS).toBe(900);
159
- expect(DEFAULT_NOTIFICATION_COOLDOWN_SECONDS).toBe(30 * 60);
160
208
  expect(DEFAULT_NOTIFICATION_STAGGER_SECONDS).toBe(25);
161
209
  });
162
210
 
@@ -325,7 +373,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
325
373
  ).not.toHaveBeenCalled();
326
374
  });
327
375
 
328
- it('does not re-notify a session within the cooldown window', async () => {
376
+ it('re-notifies a session on every consecutive cycle while it remains a valid silent target', async () => {
329
377
  setupLiveInteractiveSession('workbench');
330
378
  mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
331
379
  [
@@ -336,15 +384,44 @@ describe('NotifySilentLiveSessionsUseCase', () => {
336
384
  },
337
385
  ],
338
386
  );
339
- mockNotificationRepository.getLastNotifiedEpochSeconds.mockResolvedValue(
340
- nowEpochSeconds - DEFAULT_NOTIFICATION_COOLDOWN_SECONDS + 1,
387
+
388
+ await useCase.run(runParams());
389
+ await useCase.run(runParams());
390
+
391
+ expect(
392
+ mockNotificationRepository.sendSelfCheckNotification,
393
+ ).toHaveBeenCalledTimes(2);
394
+ expect(
395
+ mockNotificationRepository.sendSelfCheckNotification,
396
+ ).toHaveBeenNthCalledWith(1, 'workbench', MAIN_STALLED_SECTION);
397
+ expect(
398
+ mockNotificationRepository.sendSelfCheckNotification,
399
+ ).toHaveBeenNthCalledWith(2, 'workbench', MAIN_STALLED_SECTION);
400
+ });
401
+
402
+ it('notifies on every repeated cycle at the same instant without reading any cooldown state', async () => {
403
+ setupLiveInteractiveSession('workbench');
404
+ mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
405
+ [
406
+ {
407
+ sessionName: 'workbench',
408
+ lastOutputEpochSeconds:
409
+ nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
410
+ },
411
+ ],
341
412
  );
342
413
 
414
+ await useCase.run(runParams());
415
+ await useCase.run(runParams());
343
416
  await useCase.run(runParams());
344
417
 
345
418
  expect(
346
419
  mockNotificationRepository.sendSelfCheckNotification,
347
- ).not.toHaveBeenCalled();
420
+ ).toHaveBeenCalledTimes(3);
421
+ expect(Object.keys(mockNotificationRepository)).toEqual([
422
+ 'sendSelfCheckNotification',
423
+ ]);
424
+ expect(runParams()).not.toHaveProperty('cooldownSeconds');
348
425
  });
349
426
 
350
427
  it('sends to multiple sessions sequentially with a stagger delay between sends', async () => {
@@ -406,6 +483,139 @@ describe('NotifySilentLiveSessionsUseCase', () => {
406
483
  await expect(useCase.run(runParams())).rejects.toThrow('send-keys failed');
407
484
  });
408
485
 
486
+ describe('hub-task active-status pre-send gate', () => {
487
+ const HUB_TASK_SESSION = 'https://github.com/HiromiShikata/repo/issues/42';
488
+ const ACTIVE_STATUS = 'In tmux';
489
+
490
+ it('sends when the hub task is open and in the active status', async () => {
491
+ setupSilentMainSession(HUB_TASK_SESSION);
492
+ mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
493
+ issueFor({
494
+ url: HUB_TASK_SESSION,
495
+ state: 'OPEN',
496
+ status: ACTIVE_STATUS,
497
+ }),
498
+ );
499
+
500
+ await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
501
+
502
+ expect(mockHubTaskStatusResolver.getIssueByUrl).toHaveBeenCalledWith(
503
+ HUB_TASK_SESSION,
504
+ );
505
+ expect(
506
+ mockNotificationRepository.sendSelfCheckNotification,
507
+ ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
508
+ });
509
+
510
+ it('skips when the hub task status differs from the active status', async () => {
511
+ setupSilentMainSession(HUB_TASK_SESSION);
512
+ mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
513
+ issueFor({ url: HUB_TASK_SESSION, state: 'OPEN', status: 'Todo' }),
514
+ );
515
+
516
+ await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
517
+
518
+ expect(
519
+ mockNotificationRepository.sendSelfCheckNotification,
520
+ ).not.toHaveBeenCalled();
521
+ });
522
+
523
+ it('skips when the hub task issue is closed', async () => {
524
+ setupSilentMainSession(HUB_TASK_SESSION);
525
+ mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
526
+ issueFor({
527
+ url: HUB_TASK_SESSION,
528
+ state: 'CLOSED',
529
+ status: ACTIVE_STATUS,
530
+ isClosed: true,
531
+ }),
532
+ );
533
+
534
+ await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
535
+
536
+ expect(
537
+ mockNotificationRepository.sendSelfCheckNotification,
538
+ ).not.toHaveBeenCalled();
539
+ });
540
+
541
+ it('leaves a non-URL session name unchecked and sends as before', async () => {
542
+ setupSilentMainSession('workbench');
543
+
544
+ await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
545
+
546
+ expect(mockHubTaskStatusResolver.getIssueByUrl).not.toHaveBeenCalled();
547
+ expect(
548
+ mockNotificationRepository.sendSelfCheckNotification,
549
+ ).toHaveBeenCalledWith('workbench', MAIN_STALLED_SECTION);
550
+ });
551
+
552
+ it('does not call the resolver at all when the active status is unconfigured', async () => {
553
+ setupSilentMainSession(HUB_TASK_SESSION);
554
+
555
+ await useCase.run(runParams({ activeHubTaskStatus: null }));
556
+
557
+ expect(mockHubTaskStatusResolver.getIssueByUrl).not.toHaveBeenCalled();
558
+ expect(
559
+ mockNotificationRepository.sendSelfCheckNotification,
560
+ ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
561
+ });
562
+
563
+ it('fails open and logs a warning when status resolution throws', async () => {
564
+ setupSilentMainSession(HUB_TASK_SESSION);
565
+ const warnSpy = jest
566
+ .spyOn(console, 'warn')
567
+ .mockImplementation(() => undefined);
568
+ mockHubTaskStatusResolver.getIssueByUrl.mockRejectedValue(
569
+ new Error('GitHub API timeout'),
570
+ );
571
+
572
+ await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
573
+
574
+ expect(
575
+ mockNotificationRepository.sendSelfCheckNotification,
576
+ ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
577
+ expect(warnSpy).toHaveBeenCalledWith(
578
+ expect.stringContaining('fail-open'),
579
+ );
580
+ warnSpy.mockRestore();
581
+ });
582
+
583
+ it('fails open and logs a warning when the hub task cannot be resolved', async () => {
584
+ setupSilentMainSession(HUB_TASK_SESSION);
585
+ const warnSpy = jest
586
+ .spyOn(console, 'warn')
587
+ .mockImplementation(() => undefined);
588
+ mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(null);
589
+
590
+ await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
591
+
592
+ expect(
593
+ mockNotificationRepository.sendSelfCheckNotification,
594
+ ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
595
+ expect(warnSpy).toHaveBeenCalledWith(
596
+ expect.stringContaining('fail-open'),
597
+ );
598
+ warnSpy.mockRestore();
599
+ });
600
+
601
+ it('parses a github.com issue URL session name and rejects other names', () => {
602
+ expect(parseHubTaskIssueUrlFromSessionName(HUB_TASK_SESSION)).toBe(
603
+ HUB_TASK_SESSION,
604
+ );
605
+ expect(parseHubTaskIssueUrlFromSessionName('workbench')).toBeNull();
606
+ expect(
607
+ parseHubTaskIssueUrlFromSessionName(
608
+ 'https://github.com/HiromiShikata/repo/pull/42',
609
+ ),
610
+ ).toBeNull();
611
+ expect(
612
+ parseHubTaskIssueUrlFromSessionName(
613
+ 'https://example.com/HiromiShikata/repo/issues/42',
614
+ ),
615
+ ).toBeNull();
616
+ });
617
+ });
618
+
409
619
  it('uses the session entity helper for type completeness', () => {
410
620
  expect(sessionFor('workbench')).toEqual({
411
621
  sessionName: 'workbench',
@@ -8,14 +8,25 @@ import { SessionSubAgentActivityRepository } from './adapter-interfaces/SessionS
8
8
  import { SilentSessionMessageComposer } from './adapter-interfaces/SilentSessionMessageComposer';
9
9
  import { SilentSessionNotificationRepository } from './adapter-interfaces/SilentSessionNotificationRepository';
10
10
  import { Sleeper } from './adapter-interfaces/Sleeper';
11
+ import { IssueRepository } from './adapter-interfaces/IssueRepository';
11
12
  import { ResolveInteractiveLiveSessionsUseCase } from './ResolveInteractiveLiveSessionsUseCase';
12
13
 
13
14
  export const DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS = 10 * 60;
14
15
  export const DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS = 5 * 60;
15
16
  export const DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS = 15 * 60;
16
- export const DEFAULT_NOTIFICATION_COOLDOWN_SECONDS = 30 * 60;
17
17
  export const DEFAULT_NOTIFICATION_STAGGER_SECONDS = 25;
18
18
 
19
+ const GITHUB_ISSUE_URL_PATTERN =
20
+ /^https:\/\/github\.com\/[^/]+\/[^/]+\/issues\/\d+$/;
21
+
22
+ export const parseHubTaskIssueUrlFromSessionName = (
23
+ sessionName: string,
24
+ ): string | null => {
25
+ return GITHUB_ISSUE_URL_PATTERN.test(sessionName) ? sessionName : null;
26
+ };
27
+
28
+ export type HubTaskStatusResolver = Pick<IssueRepository, 'getIssueByUrl'>;
29
+
19
30
  type NotifyCandidate = {
20
31
  sessionName: string;
21
32
  message: string;
@@ -34,14 +45,15 @@ export class NotifySilentLiveSessionsUseCase {
34
45
  private readonly notificationRepository: SilentSessionNotificationRepository,
35
46
  private readonly messageComposer: SilentSessionMessageComposer,
36
47
  private readonly sleeper: Sleeper,
48
+ private readonly hubTaskStatusResolver: HubTaskStatusResolver | null = null,
37
49
  ) {}
38
50
 
39
51
  run = async (params: {
40
52
  mainSilentThresholdSeconds: number;
41
53
  subAgentSilentThresholdSeconds: number;
42
54
  subAgentRunningThresholdSeconds: number;
43
- cooldownSeconds: number;
44
55
  staggerSeconds: number;
56
+ activeHubTaskStatus: string | null;
45
57
  now: Date;
46
58
  }): Promise<void> => {
47
59
  const snapshot =
@@ -78,22 +90,14 @@ export class NotifySilentLiveSessionsUseCase {
78
90
  `Silent live session notification: ${candidates.length} candidate(s) of ${interactiveSessions.length} interactive session(s).`,
79
91
  );
80
92
 
81
- const nowEpochSeconds = Math.floor(params.now.getTime() / 1000);
82
93
  let sentCount = 0;
83
94
  for (const candidate of candidates) {
84
- const lastNotifiedEpochSeconds =
85
- await this.notificationRepository.getLastNotifiedEpochSeconds(
86
- candidate.sessionName,
87
- );
88
95
  if (
89
- lastNotifiedEpochSeconds !== null &&
90
- nowEpochSeconds - lastNotifiedEpochSeconds < params.cooldownSeconds
96
+ !(await this.isHubTaskActive(
97
+ candidate.sessionName,
98
+ params.activeHubTaskStatus,
99
+ ))
91
100
  ) {
92
- console.log(
93
- `Skipping ${candidate.sessionName}: notified ${
94
- nowEpochSeconds - lastNotifiedEpochSeconds
95
- } seconds ago, within cooldown ${params.cooldownSeconds} seconds.`,
96
- );
97
101
  continue;
98
102
  }
99
103
  if (sentCount > 0) {
@@ -103,15 +107,48 @@ export class NotifySilentLiveSessionsUseCase {
103
107
  candidate.sessionName,
104
108
  candidate.message,
105
109
  );
106
- await this.notificationRepository.setLastNotifiedEpochSeconds(
107
- candidate.sessionName,
108
- nowEpochSeconds,
109
- );
110
110
  sentCount += 1;
111
111
  console.log(`Notified ${candidate.sessionName}.`);
112
112
  }
113
113
  };
114
114
 
115
+ private isHubTaskActive = async (
116
+ sessionName: string,
117
+ activeHubTaskStatus: string | null,
118
+ ): Promise<boolean> => {
119
+ if (activeHubTaskStatus === null || this.hubTaskStatusResolver === null) {
120
+ return true;
121
+ }
122
+ const hubTaskIssueUrl = parseHubTaskIssueUrlFromSessionName(sessionName);
123
+ if (hubTaskIssueUrl === null) {
124
+ return true;
125
+ }
126
+ try {
127
+ const issue =
128
+ await this.hubTaskStatusResolver.getIssueByUrl(hubTaskIssueUrl);
129
+ if (issue === null) {
130
+ console.warn(
131
+ `Hub task ${hubTaskIssueUrl} for session ${sessionName} could not be resolved; sending notification (fail-open).`,
132
+ );
133
+ return true;
134
+ }
135
+ if (issue.state !== 'OPEN' || issue.status !== activeHubTaskStatus) {
136
+ console.log(
137
+ `Skipping ${sessionName}: hub task ${hubTaskIssueUrl} is no longer active (state "${issue.state}", status "${issue.status ?? 'null'}", active status "${activeHubTaskStatus}").`,
138
+ );
139
+ return false;
140
+ }
141
+ return true;
142
+ } catch (error) {
143
+ console.warn(
144
+ `Failed to resolve hub task status for session ${sessionName} (${hubTaskIssueUrl}); sending notification (fail-open): ${
145
+ error instanceof Error ? error.message : String(error)
146
+ }`,
147
+ );
148
+ return true;
149
+ }
150
+ };
151
+
115
152
  private collectSnapshots = async (
116
153
  interactiveSessions: InteractiveLiveSession[],
117
154
  transcriptPathBySessionName: Map<string, string>,
@@ -1,9 +1,4 @@
1
1
  export interface SilentSessionNotificationRepository {
2
- getLastNotifiedEpochSeconds: (sessionName: string) => Promise<number | null>;
3
- setLastNotifiedEpochSeconds: (
4
- sessionName: string,
5
- epochSeconds: number,
6
- ) => Promise<void>;
7
2
  sendSelfCheckNotification: (
8
3
  sessionName: string,
9
4
  message: string,
@@ -1 +1 @@
1
- {"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AA0D3D,qBAAa,kCAAkC;IAC7C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,KAChB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,IAAI,EAAE,CAAC;KACzB,GAAG,IAAI,CAAC,CAyiBP;CACH"}
1
+ {"version":3,"file":"HandleScheduledEventUseCaseHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAC;AAiD3D,qBAAa,kCAAkC;IAC7C,MAAM,GACJ,gBAAgB,MAAM,EACtB,UAAU,OAAO,KAChB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,KAAK,EAAE,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,eAAe,EAAE,IAAI,EAAE,CAAC;KACzB,GAAG,IAAI,CAAC,CAmiBP;CACH"}
@@ -1,12 +1,11 @@
1
1
  import { LocalCommandRunner } from '../../../domain/usecases/adapter-interfaces/LocalCommandRunner';
2
2
  import { ProcessEnvironReader } from '../../../domain/usecases/adapter-interfaces/ProcessEnvironReader';
3
- import { LocalStorageCacheRepository } from '../../repositories/LocalStorageCacheRepository';
3
+ import { HubTaskStatusResolver } from '../../../domain/usecases/NotifySilentLiveSessionsUseCase';
4
4
  import { SilentSessionMessageTemplates } from '../../repositories/ConfigurableSilentSessionMessageComposer';
5
5
  export type NotifySilentTmuxSessionsParams = {
6
6
  enabled: boolean;
7
7
  localCommandRunner: LocalCommandRunner;
8
8
  processEnvironReader?: ProcessEnvironReader;
9
- cacheRepository: Pick<LocalStorageCacheRepository, 'getLatest' | 'set'>;
10
9
  ownerCallMarker: string | null;
11
10
  subAgentOutputRootDirectory: string | null;
12
11
  subAgentProcessMatchPattern: string | null;
@@ -14,8 +13,9 @@ export type NotifySilentTmuxSessionsParams = {
14
13
  mainSilentThresholdSeconds: number;
15
14
  subAgentSilentThresholdSeconds: number;
16
15
  subAgentRunningThresholdSeconds: number;
17
- cooldownSeconds: number;
18
16
  staggerSeconds: number;
17
+ activeHubTaskStatus: string | null;
18
+ hubTaskStatusResolver: HubTaskStatusResolver | null;
19
19
  messageTemplates: SilentSessionMessageTemplates;
20
20
  now: Date;
21
21
  };
@@ -24,7 +24,6 @@ export declare const DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS: {
24
24
  readonly mainSilentThresholdSeconds: number;
25
25
  readonly subAgentSilentThresholdSeconds: number;
26
26
  readonly subAgentRunningThresholdSeconds: number;
27
- readonly cooldownSeconds: number;
28
27
  readonly staggerSeconds: 25;
29
28
  };
30
29
  //# sourceMappingURL=notifySilentTmuxSessions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"notifySilentTmuxSessions.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gEAAgE,CAAC;AAGpG,OAAO,EAAE,oBAAoB,EAAE,MAAM,kEAAkE,CAAC;AAexG,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAQ7F,OAAO,EAEL,6BAA6B,EAC9B,MAAM,6DAA6D,CAAC;AAGrE,MAAM,MAAM,8BAA8B,GAAG;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,eAAe,EAAE,IAAI,CAAC,2BAA2B,EAAE,WAAW,GAAG,KAAK,CAAC,CAAC;IACxE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,+BAA+B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,0BAA0B,EAAE,MAAM,CAAC;IACnC,8BAA8B,EAAE,MAAM,CAAC;IACvC,+BAA+B,EAAE,MAAM,CAAC;IACxC,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,6BAA6B,CAAC;IAChD,GAAG,EAAE,IAAI,CAAC;CACX,CAAC;AAoCF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,8BAA8B,KACrC,OAAO,CAAC,IAAI,CA0Dd,CAAC;AAEF,eAAO,MAAM,0CAA0C;;;;;;CAM7C,CAAC"}
1
+ {"version":3,"file":"notifySilentTmuxSessions.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gEAAgE,CAAC;AAGpG,OAAO,EAAE,oBAAoB,EAAE,MAAM,kEAAkE,CAAC;AACxG,OAAO,EAEL,qBAAqB,EAKtB,MAAM,0DAA0D,CAAC;AAclE,OAAO,EAEL,6BAA6B,EAC9B,MAAM,6DAA6D,CAAC;AAGrE,MAAM,MAAM,8BAA8B,GAAG;IAC3C,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,2BAA2B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,+BAA+B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,0BAA0B,EAAE,MAAM,CAAC;IACnC,8BAA8B,EAAE,MAAM,CAAC;IACvC,+BAA+B,EAAE,MAAM,CAAC;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,qBAAqB,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACpD,gBAAgB,EAAE,6BAA6B,CAAC;IAChD,GAAG,EAAE,IAAI,CAAC;CACX,CAAC;AAoCF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,8BAA8B,KACrC,OAAO,CAAC,IAAI,CAwDd,CAAC;AAEF,eAAO,MAAM,0CAA0C;;;;;CAK7C,CAAC"}
@@ -1,13 +1,8 @@
1
1
  import { SilentSessionNotificationRepository } from '../../domain/usecases/adapter-interfaces/SilentSessionNotificationRepository';
2
2
  import { LocalCommandRunner } from '../../domain/usecases/adapter-interfaces/LocalCommandRunner';
3
- import { LocalStorageCacheRepository } from './LocalStorageCacheRepository';
4
3
  export declare class TmuxSilentSessionNotificationRepository implements SilentSessionNotificationRepository {
5
4
  private readonly localCommandRunner;
6
- private readonly cacheRepository;
7
- constructor(localCommandRunner: LocalCommandRunner, cacheRepository: Pick<LocalStorageCacheRepository, 'getLatest' | 'set'>);
8
- getLastNotifiedEpochSeconds: (sessionName: string) => Promise<number | null>;
9
- setLastNotifiedEpochSeconds: (sessionName: string, epochSeconds: number) => Promise<void>;
5
+ constructor(localCommandRunner: LocalCommandRunner);
10
6
  sendSelfCheckNotification: (sessionName: string, message: string) => Promise<void>;
11
- private toCacheKey;
12
7
  }
13
8
  //# sourceMappingURL=TmuxSilentSessionNotificationRepository.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TmuxSilentSessionNotificationRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/TmuxSilentSessionNotificationRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mCAAmC,EAAE,MAAM,8EAA8E,CAAC;AACnI,OAAO,EAAE,kBAAkB,EAAE,MAAM,6DAA6D,CAAC;AACjG,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAe5E,qBAAa,uCAAwC,YAAW,mCAAmC;IAE/F,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe;gBADf,kBAAkB,EAAE,kBAAkB,EACtC,eAAe,EAAE,IAAI,CACpC,2BAA2B,EAC3B,WAAW,GAAG,KAAK,CACpB;IAGH,2BAA2B,GACzB,aAAa,MAAM,KAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQvB;IAEF,2BAA2B,GACzB,aAAa,MAAM,EACnB,cAAc,MAAM,KACnB,OAAO,CAAC,IAAI,CAAC,CAId;IAEF,yBAAyB,GACvB,aAAa,MAAM,EACnB,SAAS,MAAM,KACd,OAAO,CAAC,IAAI,CAAC,CA4Bd;IAEF,OAAO,CAAC,UAAU,CACyC;CAC5D"}
1
+ {"version":3,"file":"TmuxSilentSessionNotificationRepository.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/TmuxSilentSessionNotificationRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mCAAmC,EAAE,MAAM,8EAA8E,CAAC;AACnI,OAAO,EAAE,kBAAkB,EAAE,MAAM,6DAA6D,CAAC;AAEjG,qBAAa,uCAAwC,YAAW,mCAAmC;IACrF,OAAO,CAAC,QAAQ,CAAC,kBAAkB;gBAAlB,kBAAkB,EAAE,kBAAkB;IAEnE,yBAAyB,GACvB,aAAa,MAAM,EACnB,SAAS,MAAM,KACd,OAAO,CAAC,IAAI,CAAC,CA4Bd;CACH"}
@@ -6,11 +6,13 @@ import { SessionSubAgentActivityRepository } from './adapter-interfaces/SessionS
6
6
  import { SilentSessionMessageComposer } from './adapter-interfaces/SilentSessionMessageComposer';
7
7
  import { SilentSessionNotificationRepository } from './adapter-interfaces/SilentSessionNotificationRepository';
8
8
  import { Sleeper } from './adapter-interfaces/Sleeper';
9
+ import { IssueRepository } from './adapter-interfaces/IssueRepository';
9
10
  export declare const DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS: number;
10
11
  export declare const DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS: number;
11
12
  export declare const DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS: number;
12
- export declare const DEFAULT_NOTIFICATION_COOLDOWN_SECONDS: number;
13
13
  export declare const DEFAULT_NOTIFICATION_STAGGER_SECONDS = 25;
14
+ export declare const parseHubTaskIssueUrlFromSessionName: (sessionName: string) => string | null;
15
+ export type HubTaskStatusResolver = Pick<IssueRepository, 'getIssueByUrl'>;
14
16
  export declare class NotifySilentLiveSessionsUseCase {
15
17
  private readonly liveSessionProcessSnapshotProvider;
16
18
  private readonly interactiveLiveSessionTranscriptResolver;
@@ -20,16 +22,18 @@ export declare class NotifySilentLiveSessionsUseCase {
20
22
  private readonly notificationRepository;
21
23
  private readonly messageComposer;
22
24
  private readonly sleeper;
25
+ private readonly hubTaskStatusResolver;
23
26
  private readonly resolveInteractiveLiveSessions;
24
- constructor(liveSessionProcessSnapshotProvider: LiveSessionProcessSnapshotProvider, interactiveLiveSessionTranscriptResolver: InteractiveLiveSessionTranscriptResolver, sessionOutputActivityRepository: SessionOutputActivityRepository, subAgentActivityRepository: SessionSubAgentActivityRepository, ownerCallStatusProvider: OwnerCallStatusProvider, notificationRepository: SilentSessionNotificationRepository, messageComposer: SilentSessionMessageComposer, sleeper: Sleeper);
27
+ constructor(liveSessionProcessSnapshotProvider: LiveSessionProcessSnapshotProvider, interactiveLiveSessionTranscriptResolver: InteractiveLiveSessionTranscriptResolver, sessionOutputActivityRepository: SessionOutputActivityRepository, subAgentActivityRepository: SessionSubAgentActivityRepository, ownerCallStatusProvider: OwnerCallStatusProvider, notificationRepository: SilentSessionNotificationRepository, messageComposer: SilentSessionMessageComposer, sleeper: Sleeper, hubTaskStatusResolver?: HubTaskStatusResolver | null);
25
28
  run: (params: {
26
29
  mainSilentThresholdSeconds: number;
27
30
  subAgentSilentThresholdSeconds: number;
28
31
  subAgentRunningThresholdSeconds: number;
29
- cooldownSeconds: number;
30
32
  staggerSeconds: number;
33
+ activeHubTaskStatus: string | null;
31
34
  now: Date;
32
35
  }) => Promise<void>;
36
+ private isHubTaskActive;
33
37
  private collectSnapshots;
34
38
  private composeMessage;
35
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"NotifySilentLiveSessionsUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifySilentLiveSessionsUseCase.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kCAAkC,EAAE,MAAM,yDAAyD,CAAC;AAC7G,OAAO,EAAE,wCAAwC,EAAE,MAAM,+DAA+D,CAAC;AACzH,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,sDAAsD,CAAC;AACvG,OAAO,EAAE,iCAAiC,EAAE,MAAM,wDAAwD,CAAC;AAC3G,OAAO,EAAE,4BAA4B,EAAE,MAAM,mDAAmD,CAAC;AACjG,OAAO,EAAE,mCAAmC,EAAE,MAAM,0DAA0D,CAAC;AAC/G,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAGvD,eAAO,MAAM,qCAAqC,QAAU,CAAC;AAC7D,eAAO,MAAM,yCAAyC,QAAS,CAAC;AAChE,eAAO,MAAM,0CAA0C,QAAU,CAAC;AAClE,eAAO,MAAM,qCAAqC,QAAU,CAAC;AAC7D,eAAO,MAAM,oCAAoC,KAAK,CAAC;AAOvD,qBAAa,+BAA+B;IAKxC,OAAO,CAAC,QAAQ,CAAC,kCAAkC;IACnD,OAAO,CAAC,QAAQ,CAAC,wCAAwC;IACzD,OAAO,CAAC,QAAQ,CAAC,+BAA+B;IAChD,OAAO,CAAC,QAAQ,CAAC,0BAA0B;IAC3C,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAX1B,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CACD;gBAG3B,kCAAkC,EAAE,kCAAkC,EACtE,wCAAwC,EAAE,wCAAwC,EAClF,+BAA+B,EAAE,+BAA+B,EAChE,0BAA0B,EAAE,iCAAiC,EAC7D,uBAAuB,EAAE,uBAAuB,EAChD,sBAAsB,EAAE,mCAAmC,EAC3D,eAAe,EAAE,4BAA4B,EAC7C,OAAO,EAAE,OAAO;IAGnC,GAAG,GAAU,QAAQ;QACnB,0BAA0B,EAAE,MAAM,CAAC;QACnC,8BAA8B,EAAE,MAAM,CAAC;QACvC,+BAA+B,EAAE,MAAM,CAAC;QACxC,eAAe,EAAE,MAAM,CAAC;QACxB,cAAc,EAAE,MAAM,CAAC;QACvB,GAAG,EAAE,IAAI,CAAC;KACX,KAAG,OAAO,CAAC,IAAI,CAAC,CAmEf;IAEF,OAAO,CAAC,gBAAgB,CA8CtB;IAEF,OAAO,CAAC,cAAc,CAqCpB;CACH"}
1
+ {"version":3,"file":"NotifySilentLiveSessionsUseCase.d.ts","sourceRoot":"","sources":["../../../src/domain/usecases/NotifySilentLiveSessionsUseCase.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kCAAkC,EAAE,MAAM,yDAAyD,CAAC;AAC7G,OAAO,EAAE,wCAAwC,EAAE,MAAM,+DAA+D,CAAC;AACzH,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,sDAAsD,CAAC;AACvG,OAAO,EAAE,iCAAiC,EAAE,MAAM,wDAAwD,CAAC;AAC3G,OAAO,EAAE,4BAA4B,EAAE,MAAM,mDAAmD,CAAC;AACjG,OAAO,EAAE,mCAAmC,EAAE,MAAM,0DAA0D,CAAC;AAC/G,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAGvE,eAAO,MAAM,qCAAqC,QAAU,CAAC;AAC7D,eAAO,MAAM,yCAAyC,QAAS,CAAC;AAChE,eAAO,MAAM,0CAA0C,QAAU,CAAC;AAClE,eAAO,MAAM,oCAAoC,KAAK,CAAC;AAKvD,eAAO,MAAM,mCAAmC,GAC9C,aAAa,MAAM,KAClB,MAAM,GAAG,IAEX,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;AAO3E,qBAAa,+BAA+B;IAKxC,OAAO,CAAC,QAAQ,CAAC,kCAAkC;IACnD,OAAO,CAAC,QAAQ,CAAC,wCAAwC;IACzD,OAAO,CAAC,QAAQ,CAAC,+BAA+B;IAChD,OAAO,CAAC,QAAQ,CAAC,0BAA0B;IAC3C,OAAO,CAAC,QAAQ,CAAC,uBAAuB;IACxC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAZxC,OAAO,CAAC,QAAQ,CAAC,8BAA8B,CACD;gBAG3B,kCAAkC,EAAE,kCAAkC,EACtE,wCAAwC,EAAE,wCAAwC,EAClF,+BAA+B,EAAE,+BAA+B,EAChE,0BAA0B,EAAE,iCAAiC,EAC7D,uBAAuB,EAAE,uBAAuB,EAChD,sBAAsB,EAAE,mCAAmC,EAC3D,eAAe,EAAE,4BAA4B,EAC7C,OAAO,EAAE,OAAO,EAChB,qBAAqB,GAAE,qBAAqB,GAAG,IAAW;IAG7E,GAAG,GAAU,QAAQ;QACnB,0BAA0B,EAAE,MAAM,CAAC;QACnC,8BAA8B,EAAE,MAAM,CAAC;QACvC,+BAA+B,EAAE,MAAM,CAAC;QACxC,cAAc,EAAE,MAAM,CAAC;QACvB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;QACnC,GAAG,EAAE,IAAI,CAAC;KACX,KAAG,OAAO,CAAC,IAAI,CAAC,CAuDf;IAEF,OAAO,CAAC,eAAe,CAmCrB;IAEF,OAAO,CAAC,gBAAgB,CA8CtB;IAEF,OAAO,CAAC,cAAc,CAqCpB;CACH"}
@@ -1,6 +1,4 @@
1
1
  export interface SilentSessionNotificationRepository {
2
- getLastNotifiedEpochSeconds: (sessionName: string) => Promise<number | null>;
3
- setLastNotifiedEpochSeconds: (sessionName: string, epochSeconds: number) => Promise<void>;
4
2
  sendSelfCheckNotification: (sessionName: string, message: string) => Promise<void>;
5
3
  }
6
4
  //# sourceMappingURL=SilentSessionNotificationRepository.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SilentSessionNotificationRepository.d.ts","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/SilentSessionNotificationRepository.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mCAAmC;IAClD,2BAA2B,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7E,2BAA2B,EAAE,CAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,yBAAyB,EAAE,CACzB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}
1
+ {"version":3,"file":"SilentSessionNotificationRepository.d.ts","sourceRoot":"","sources":["../../../../src/domain/usecases/adapter-interfaces/SilentSessionNotificationRepository.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mCAAmC;IAClD,yBAAyB,EAAE,CACzB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,KACZ,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB"}