github-issue-tower-defence-management 1.116.7 → 1.116.9

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [1.116.9](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.116.8...v1.116.9) (2026-06-29)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **silent-notification:** monitor only github.com issue or pull-request named sessions ([#1094](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1094)) ([e7f0fca](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/e7f0fca786d93a3cb9dc1899ee0c40bd9f371a2a)), closes [#1093](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1093)
7
+
8
+ ## [1.116.8](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.116.7...v1.116.8) (2026-06-29)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **silent-notification:** resolve the parent transcript by candidate-id priority ([#1092](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1092)) ([d3fcefb](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/d3fcefb2ba761e7ae4cf1c1688c970cda5de590d)), closes [#1090](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1090)
14
+
1
15
  ## [1.116.7](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.116.6...v1.116.7) (2026-06-29)
2
16
 
3
17
 
package/README.md CHANGED
@@ -555,7 +555,7 @@ For each `In Tmux by human` issue with no live session, the reconciler launches
555
555
 
556
556
  Each schedule cycle, when `silentNotificationEnabled` is true, also inspects every live interactive Claude Code session and sends a short self-check reminder into a session via `tmux send-keys` when either of two independent conditions holds. The reminder is composed of only the sections whose condition is met, so a session receives one combined message containing one or both sections. When `silentNotificationEnabled` is not set, the entire step is a no-op even if the daemon picks up its configuration automatically.
557
557
 
558
- Sessions are selected purely from the live process tree, independently of session naming or any GitHub issue linkage: every live tmux session is taken, the descendants of each session's pane processes are walked, and the first descendant that is an interactive Claude Code process (its command line contains `claude` and does not contain the owner-handover marker `Take ownership of`, and its environment exposes both `CLAUDE_CODE_SESSION_ID` and `CLAUDE_CONFIG_DIR`) is taken as that session's process. Both issue-url-named sessions and plain-named sessions (for example `workbench`) are selected equally. Because the walk is anchored on tmux panes, background owner-handover spawns, the preparation daemon, and monitor processes — none of which run inside an interactive tmux pane — are excluded; the owner-handover marker check is an additional guard. Each selected session's transcript is then resolved by scanning the `projects/<cwd-slug>/` subdirectories of two roots — the per-session `<CLAUDE_CONFIG_DIR>/projects/` and the shared `~/.claude/projects/` — for a `<sessionId>.jsonl` file named by any of the session's candidate session ids. The candidate ids are derived from the process tree, in priority order: the current session id recorded in `<CLAUDE_CONFIG_DIR>/sessions/<pid>.json` (the session id rotates on resume or compaction, and this record holds the current value), then the interactive process's own launch id from the `CLAUDE_CODE_SESSION_ID` environment variable, then the distinct ids propagated to its descendant processes, all deduped. Searching the shared root and the rotated current id is required because, for a resumed or compacted session, the actively-written transcript is named by the current id and lives under the shared root rather than under the per-session config directory; the descendant-propagated ids are required because, for a session started without `--resume`, the own launch id names no transcript on disk and the live transcript is named by the descendant id. The candidate files are matched across both roots by existence; the most recently modified match is used only as a tiebreak when several candidate files exist. This way a non-resume session and a session that has no issue URL both resolve just as reliably as a resume, issue-url-named one.
558
+ Candidate sessions are first selected from the live process tree: every live tmux session is taken, the descendants of each session's pane processes are walked, and the first descendant that is an interactive Claude Code process (its command line contains `claude` and does not contain the owner-handover marker `Take ownership of`, and its environment exposes both `CLAUDE_CODE_SESSION_ID` and `CLAUDE_CONFIG_DIR`) is taken as that session's process. Because the walk is anchored on tmux panes, background owner-handover spawns, the preparation daemon, and monitor processes — none of which run inside an interactive tmux pane — are excluded; the owner-handover marker check is an additional guard. The monitor then acts only on sessions whose tmux name encodes a `github.com` issue or pull-request URL — that is, a name of the form `https_//github_com/{owner}/{repo}/issues/{N}` or `https_//github_com/{owner}/{repo}/pull/{N}` (the form tmux derives from the raw issue/PR URL by replacing only `.` and `:` with `_`; the raw `https://github.com/...` form is matched as well). Sessions whose name does not encode such a URL — for example an orchestrator session named with a plain word such as `workbench` — are left untouched: they receive neither a main-stall nor a sub-process notification, and the count of non-github-named sessions ignored each cycle is logged. Each selected session's transcript is then resolved by scanning the `projects/<cwd-slug>/` subdirectories of two roots — the per-session `<CLAUDE_CONFIG_DIR>/projects/` and the shared `~/.claude/projects/` — for a `<sessionId>.jsonl` file named by any of the session's candidate session ids. The candidate ids are derived from the process tree, in priority order: the current session id recorded in `<CLAUDE_CONFIG_DIR>/sessions/<pid>.json` (the session id rotates on resume or compaction, and this record holds the current value), then the interactive process's own launch id from the `CLAUDE_CODE_SESSION_ID` environment variable, then the distinct ids propagated to its descendant processes, all deduped. Searching the shared root and the rotated current id is required because, for a resumed or compacted session, the actively-written transcript is named by the current id and lives under the shared root rather than under the per-session config directory; the descendant-propagated ids are required because, for a session started without `--resume`, the own launch id names no transcript on disk and the live transcript is named by the descendant id. The candidate ids are tried strictly in this priority order, and the first candidate id that names an existing `<sessionId>.jsonl` file in either root is selected; the most recently modified match is used only as a tiebreak when that same id exists in both roots. Resolving by candidate-id priority rather than by the globally most recently modified file across all candidate ids is required because a session running a sub-agent has the sub-agent's own transcript on disk too, and that sub-agent transcript can be more recently modified than the parent session's transcript while not naming the parent. The parent session's own ids (the rotated current id and the launch id) come before any descendant-propagated id, so the parent's own transcript is selected ahead of a sub-agent transcript; a sub-agent transcript, which lives under `projects/<cwd-slug>/<parentSessionId>/subagents/agent-<id>.jsonl` rather than as a top-level `<sessionId>.jsonl` file, is never reached. This way a non-resume session and a session that has no issue URL both resolve just as reliably as a resume, issue-url-named one, and a session that is waiting on the owner while a sub-agent runs is evaluated against its own transcript rather than the sub-agent's.
559
559
 
560
560
  The main-session stalled section is sent when the session's main output has been idle for at least `mainSilentThresholdSeconds`, unless the session is currently waiting on the owner (in that case the silence is expected and the section is suppressed). Idle time is computed from the timestamp of the latest entry of any kind in the session's resolved transcript rather than from the transcript file modification time, so a session that keeps appending tool results, owner replies, or any other entry type while emitting no assistant text still counts as active and is not mistaken for a silent one. Whether a session is waiting on the owner is determined through an injectable port; the built-in default reports no session as waiting, so the suppression is only applied when a host provides an implementation. When `ownerCallMarker` is configured, a transcript-based implementation is used: it reads each session's resolved transcript and treats the session as waiting on the owner when the latest entry containing `ownerCallMarker` is newer (by full timestamp) than the latest genuine owner reply. A self-check reminder that the monitor injects into a session via `tmux send-keys` itself lands in that session's transcript as a `user` text entry; every injected reminder carries a fixed sentinel tag (`[TDPM_SILENT_SESSION_SELF_CHECK_REMINDER]`), and a `user` entry whose text contains that sentinel is not counted as a genuine owner reply. This prevents the monitor's own reminder from being mistaken for the owner answering, which would otherwise make a genuinely waiting session stop being suppressed. The stalled section's owner-call self-check point also instructs the agent on the required owner-call notification format: the owner-call must be emitted as the configured owner-call marker tag (interpolated from `ownerCallMarker` when set) as a complete matching pair — opening marker, content, then closing marker — on a single line with no newline inside the tag, and the content between the markers must begin with the 🔴 emoji immediately, because the owner's app only surfaces the notification together with its content when the exact, well-formed tag with the leading 🔴 is present and a malformed tag results in only a red indicator with no readable content. The same self-check point also tells the agent when to fire the owner-call: if the agent has completed or answered a request from the owner in this session, it must fire the owner-call to report the result to the owner, because completing or answering an owner's requested action is itself a reason to fire the owner-call. Completing or answering an owner request without firing the owner-call means the owner is never notified — the owner's app only surfaces the session when the owner-call fires — so the task silently stalls; the point states the causal link explicitly, noting that if the self-check reminder keeps arriving it is likely because an owner request was completed or answered without firing the owner-call, so the agent should fire the owner-call to report the result to the owner.
561
561
 
@@ -62,20 +62,27 @@ class FileSystemInteractiveLiveSessionTranscriptResolver {
62
62
  };
63
63
  this.resolveTranscriptPath = (session) => {
64
64
  const projectsDirectories = this.listProjectsDirectories(session.configDir);
65
+ for (const candidateSessionId of session.candidateSessionIds) {
66
+ const transcriptPath = this.resolveCandidateTranscriptPath(candidateSessionId, projectsDirectories);
67
+ if (transcriptPath !== null) {
68
+ return transcriptPath;
69
+ }
70
+ }
71
+ return null;
72
+ };
73
+ this.resolveCandidateTranscriptPath = (candidateSessionId, projectsDirectories) => {
74
+ const fileName = `${candidateSessionId}.jsonl`;
65
75
  let latestPath = null;
66
76
  let latestEpochMs = -Infinity;
67
- for (const candidateSessionId of session.candidateSessionIds) {
68
- const fileName = `${candidateSessionId}.jsonl`;
69
- for (const projectsDirectory of projectsDirectories) {
70
- for (const candidate of this.listCandidatePaths(projectsDirectory, fileName)) {
71
- const epochMs = modifiedEpochMs(candidate);
72
- if (epochMs === null) {
73
- continue;
74
- }
75
- if (epochMs > latestEpochMs) {
76
- latestEpochMs = epochMs;
77
- latestPath = candidate;
78
- }
77
+ for (const projectsDirectory of projectsDirectories) {
78
+ for (const candidate of this.listCandidatePaths(projectsDirectory, fileName)) {
79
+ const epochMs = modifiedEpochMs(candidate);
80
+ if (epochMs === null) {
81
+ continue;
82
+ }
83
+ if (epochMs > latestEpochMs) {
84
+ latestEpochMs = epochMs;
85
+ latestPath = candidate;
79
86
  }
80
87
  }
81
88
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystemInteractiveLiveSessionTranscriptResolver.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FileSystemInteractiveLiveSessionTranscriptResolver.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NotifySilentLiveSessionsUseCase = exports.parseHubTaskIssueUrlFromSessionName = exports.DEFAULT_NOTIFICATION_STAGGER_SECONDS = exports.DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS = exports.DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS = exports.DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS = void 0;
3
+ exports.NotifySilentLiveSessionsUseCase = exports.isGitHubIssueOrPullRequestSessionName = exports.parseHubTaskIssueUrlFromSessionName = exports.DEFAULT_NOTIFICATION_STAGGER_SECONDS = exports.DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS = exports.DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS = exports.DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS = void 0;
4
4
  const ResolveInteractiveLiveSessionsUseCase_1 = require("./ResolveInteractiveLiveSessionsUseCase");
5
5
  exports.DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS = 10 * 60;
6
6
  exports.DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS = 5 * 60;
@@ -11,6 +11,9 @@ const parseHubTaskIssueUrlFromSessionName = (sessionName) => {
11
11
  return GITHUB_ISSUE_URL_PATTERN.test(sessionName) ? sessionName : null;
12
12
  };
13
13
  exports.parseHubTaskIssueUrlFromSessionName = parseHubTaskIssueUrlFromSessionName;
14
+ const GITHUB_ISSUE_OR_PULL_REQUEST_SESSION_NAME_PATTERN = /^https(:\/\/|_\/\/)github(\.com|_com)\/[^/]+\/[^/]+\/(issues|pull)\/\d+$/;
15
+ const isGitHubIssueOrPullRequestSessionName = (sessionName) => GITHUB_ISSUE_OR_PULL_REQUEST_SESSION_NAME_PATTERN.test(sessionName);
16
+ exports.isGitHubIssueOrPullRequestSessionName = isGitHubIssueOrPullRequestSessionName;
14
17
  class NotifySilentLiveSessionsUseCase {
15
18
  constructor(liveSessionProcessSnapshotProvider, interactiveLiveSessionTranscriptResolver, sessionOutputActivityRepository, subAgentActivityRepository, ownerCallStatusProvider, notificationRepository, messageComposer, sleeper, hubTaskStatusResolver = null) {
16
19
  this.liveSessionProcessSnapshotProvider = liveSessionProcessSnapshotProvider;
@@ -25,7 +28,12 @@ class NotifySilentLiveSessionsUseCase {
25
28
  this.resolveInteractiveLiveSessions = new ResolveInteractiveLiveSessionsUseCase_1.ResolveInteractiveLiveSessionsUseCase();
26
29
  this.run = async (params) => {
27
30
  const snapshot = await this.liveSessionProcessSnapshotProvider.getSnapshot();
28
- const interactiveSessions = this.resolveInteractiveLiveSessions.resolve(snapshot);
31
+ const allInteractiveSessions = this.resolveInteractiveLiveSessions.resolve(snapshot);
32
+ const interactiveSessions = allInteractiveSessions.filter((session) => (0, exports.isGitHubIssueOrPullRequestSessionName)(session.sessionName));
33
+ const skippedNonGitHubSessionCount = allInteractiveSessions.length - interactiveSessions.length;
34
+ if (skippedNonGitHubSessionCount > 0) {
35
+ console.log(`Silent live session notification: ignoring ${skippedNonGitHubSessionCount} non-github-named interactive session(s); only sessions named after a github.com issue or pull-request URL are monitored.`);
36
+ }
29
37
  const transcriptPathBySessionName = this.interactiveLiveSessionTranscriptResolver.resolveTranscriptPaths(interactiveSessions);
30
38
  const snapshots = await this.collectSnapshots(interactiveSessions, transcriptPathBySessionName, params.now);
31
39
  const candidates = [];
@@ -1 +1 @@
1
- {"version":3,"file":"NotifySilentLiveSessionsUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/NotifySilentLiveSessionsUseCase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NotifySilentLiveSessionsUseCase.js","sourceRoot":"","sources":["../../../src/domain/usecases/NotifySilentLiveSessionsUseCase.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-issue-tower-defence-management",
3
- "version": "1.116.7",
3
+ "version": "1.116.9",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -13,7 +13,7 @@ import {
13
13
 
14
14
  const NOW = new Date('2026-06-26T00:00:00.000Z');
15
15
  const NOW_EPOCH_SECONDS = Math.floor(NOW.getTime() / 1000);
16
- const SESSION_NAME = 'workbench';
16
+ const SESSION_NAME = 'https_//github_com/HiromiShikata/repo/issues/9';
17
17
  const SESSION_ID = 'wb-uuid';
18
18
  const PANE_PID = 200;
19
19
  const CLAUDE_PID = 201;
@@ -121,7 +121,7 @@ describe('notifySilentTmuxSessions', () => {
121
121
  ...DEFAULT_NOTIFY_SILENT_TMUX_SESSIONS_PARAMS,
122
122
  });
123
123
 
124
- it('sends a main stalled notification to a silent plain-named live session', async () => {
124
+ it('sends a main stalled notification to a silent github-named live session', async () => {
125
125
  silentAssistantTranscript();
126
126
  const runner = liveSessionRunner();
127
127
 
@@ -134,6 +134,34 @@ describe('notifySilentTmuxSessions', () => {
134
134
  expect(sendCall?.[1][4]).toContain('You have produced no output for');
135
135
  });
136
136
 
137
+ it('sends no notification to a silent non-github-named live session', async () => {
138
+ silentAssistantTranscript();
139
+ const runner = createMockRunner();
140
+ runner.runCommand.mockImplementation(async (program, args) => {
141
+ if (program === 'tmux' && args[0] === 'list-sessions') {
142
+ return { stdout: 'orchestrator\n', stderr: '', exitCode: 0 };
143
+ }
144
+ if (program === 'tmux' && args[0] === 'list-panes') {
145
+ return { stdout: `${PANE_PID}\n`, stderr: '', exitCode: 0 };
146
+ }
147
+ if (program === 'ps') {
148
+ return {
149
+ stdout: ` ${PANE_PID} 1 shell\n ${CLAUDE_PID} ${PANE_PID} claude --name orchestrator\n`,
150
+ stderr: '',
151
+ exitCode: 0,
152
+ };
153
+ }
154
+ return { stdout: '', stderr: '', exitCode: 0 };
155
+ });
156
+
157
+ await notifySilentTmuxSessions(baseParams(runner));
158
+
159
+ const sendCall = runner.runCommand.mock.calls.find(
160
+ (call) => call[0] === 'tmux' && call[1][0] === 'send-keys',
161
+ );
162
+ expect(sendCall).toBeUndefined();
163
+ });
164
+
137
165
  it('does nothing when the step is not enabled', async () => {
138
166
  silentAssistantTranscript();
139
167
  const runner = liveSessionRunner();
@@ -2,6 +2,7 @@ import * as fs from 'fs';
2
2
  import * as os from 'os';
3
3
  import * as path from 'path';
4
4
  import { FileSystemInteractiveLiveSessionTranscriptResolver } from './FileSystemInteractiveLiveSessionTranscriptResolver';
5
+ import { TranscriptOwnerCallStatusProvider } from './TranscriptOwnerCallStatusProvider';
5
6
 
6
7
  describe('FileSystemInteractiveLiveSessionTranscriptResolver', () => {
7
8
  let configRoot: string;
@@ -41,6 +42,35 @@ describe('FileSystemInteractiveLiveSessionTranscriptResolver', () => {
41
42
  return filePath;
42
43
  };
43
44
 
45
+ const writeSubagentTranscript = (params: {
46
+ projectsDirectory: string;
47
+ cwdSlug: string;
48
+ parentSessionId: string;
49
+ agentId: string;
50
+ mtimeEpochSeconds?: number;
51
+ }): string => {
52
+ const subagentDirectory = path.join(
53
+ params.projectsDirectory,
54
+ params.cwdSlug,
55
+ params.parentSessionId,
56
+ 'subagents',
57
+ );
58
+ fs.mkdirSync(subagentDirectory, { recursive: true });
59
+ const filePath = path.join(
60
+ subagentDirectory,
61
+ `agent-${params.agentId}.jsonl`,
62
+ );
63
+ fs.writeFileSync(filePath, '{"type":"custom-title"}', 'utf8');
64
+ if (params.mtimeEpochSeconds !== undefined) {
65
+ fs.utimesSync(
66
+ filePath,
67
+ params.mtimeEpochSeconds,
68
+ params.mtimeEpochSeconds,
69
+ );
70
+ }
71
+ return filePath;
72
+ };
73
+
44
74
  it('resolves a resume-case transcript by config dir and session id', () => {
45
75
  const configDir = path.join(configRoot, 'workbench');
46
76
  const filePath = writeTranscript({
@@ -186,6 +216,123 @@ describe('FileSystemInteractiveLiveSessionTranscriptResolver', () => {
186
216
  expect(result.get('workbench')).toBe(newerPath);
187
217
  });
188
218
 
219
+ it('selects the parent transcript over a newer descendant id transcript', () => {
220
+ const configDir = path.join(configRoot, 'with-subagent');
221
+ const parentPath = writeTranscript({
222
+ projectsDirectory: path.join(configDir, 'projects'),
223
+ cwdSlug: '-home-user',
224
+ sessionId: 'parent-id',
225
+ mtimeEpochSeconds: 1700000000,
226
+ });
227
+ writeTranscript({
228
+ projectsDirectory: path.join(configDir, 'projects'),
229
+ cwdSlug: '-home-user',
230
+ sessionId: 'subagent-id',
231
+ mtimeEpochSeconds: 1700000500,
232
+ });
233
+ const resolver = new FileSystemInteractiveLiveSessionTranscriptResolver(
234
+ sharedProjectsDirectory,
235
+ );
236
+
237
+ const result = resolver.resolveTranscriptPaths([
238
+ {
239
+ sessionName: 'with-subagent',
240
+ sessionId: 'parent-id',
241
+ candidateSessionIds: ['parent-id', 'subagent-id'],
242
+ configDir,
243
+ },
244
+ ]);
245
+
246
+ expect(result.get('with-subagent')).toBe(parentPath);
247
+ });
248
+
249
+ it('selects the rotated parent transcript over a newer descendant id transcript', () => {
250
+ const configDir = path.join(configRoot, 'rotated-with-subagent');
251
+ const rotatedParentPath = writeTranscript({
252
+ projectsDirectory: path.join(configDir, 'projects'),
253
+ cwdSlug: '-home-user',
254
+ sessionId: 'rotated-id',
255
+ mtimeEpochSeconds: 1700000000,
256
+ });
257
+ writeTranscript({
258
+ projectsDirectory: path.join(configDir, 'projects'),
259
+ cwdSlug: '-home-user',
260
+ sessionId: 'subagent-id',
261
+ mtimeEpochSeconds: 1700000500,
262
+ });
263
+ const resolver = new FileSystemInteractiveLiveSessionTranscriptResolver(
264
+ sharedProjectsDirectory,
265
+ );
266
+
267
+ const result = resolver.resolveTranscriptPaths([
268
+ {
269
+ sessionName: 'rotated-with-subagent',
270
+ sessionId: 'launch-id',
271
+ candidateSessionIds: ['rotated-id', 'launch-id', 'subagent-id'],
272
+ configDir,
273
+ },
274
+ ]);
275
+
276
+ expect(result.get('rotated-with-subagent')).toBe(rotatedParentPath);
277
+ });
278
+
279
+ it('selects the parent transcript and never a newer subagent transcript nested under subagents', () => {
280
+ const configDir = path.join(configRoot, 'subagent-nested');
281
+ const parentPath = writeTranscript({
282
+ projectsDirectory: path.join(configDir, 'projects'),
283
+ cwdSlug: '-home-user',
284
+ sessionId: 'parent-id',
285
+ mtimeEpochSeconds: 1700000000,
286
+ });
287
+ const subagentPath = writeSubagentTranscript({
288
+ projectsDirectory: path.join(configDir, 'projects'),
289
+ cwdSlug: '-home-user',
290
+ parentSessionId: 'parent-id',
291
+ agentId: 'worker',
292
+ mtimeEpochSeconds: 1700000500,
293
+ });
294
+ const resolver = new FileSystemInteractiveLiveSessionTranscriptResolver(
295
+ sharedProjectsDirectory,
296
+ );
297
+
298
+ const result = resolver.resolveTranscriptPaths([
299
+ {
300
+ sessionName: 'subagent-nested',
301
+ sessionId: 'parent-id',
302
+ candidateSessionIds: ['parent-id', 'subagent-id'],
303
+ configDir,
304
+ },
305
+ ]);
306
+
307
+ expect(result.get('subagent-nested')).toBe(parentPath);
308
+ expect(result.get('subagent-nested')).not.toBe(subagentPath);
309
+ });
310
+
311
+ it('omits a session whose only transcript is nested under a subagents directory', () => {
312
+ const configDir = path.join(configRoot, 'subagent-only');
313
+ writeSubagentTranscript({
314
+ projectsDirectory: path.join(configDir, 'projects'),
315
+ cwdSlug: '-home-user',
316
+ parentSessionId: 'parent-id',
317
+ agentId: 'worker',
318
+ mtimeEpochSeconds: 1700000500,
319
+ });
320
+ const resolver = new FileSystemInteractiveLiveSessionTranscriptResolver(
321
+ sharedProjectsDirectory,
322
+ );
323
+
324
+ const result = resolver.resolveTranscriptPaths([
325
+ {
326
+ sessionName: 'subagent-only',
327
+ sessionId: 'parent-id',
328
+ candidateSessionIds: ['parent-id', 'subagent-id'],
329
+ configDir,
330
+ },
331
+ ]);
332
+
333
+ expect(result.has('subagent-only')).toBe(false);
334
+ });
335
+
189
336
  it('resolves several sessions in one call', () => {
190
337
  const workbenchConfig = path.join(configRoot, 'workbench');
191
338
  const controlRoomConfig = path.join(configRoot, 'control-room');
@@ -272,3 +419,96 @@ describe('FileSystemInteractiveLiveSessionTranscriptResolver', () => {
272
419
  expect(result.size).toBe(0);
273
420
  });
274
421
  });
422
+
423
+ describe('parent transcript resolution feeding owner-call detection', () => {
424
+ let configRoot: string;
425
+ let sharedProjectsDirectory: string;
426
+
427
+ beforeEach(() => {
428
+ configRoot = fs.mkdtempSync(
429
+ path.join(os.tmpdir(), 'interactive-transcript-ownercall-'),
430
+ );
431
+ sharedProjectsDirectory = path.join(configRoot, 'shared', 'projects');
432
+ });
433
+
434
+ afterEach(() => {
435
+ fs.rmSync(configRoot, { force: true, recursive: true });
436
+ });
437
+
438
+ const ownerCallMarker = '<<OWNER_CALL>>';
439
+
440
+ const writeJsonlTranscript = (
441
+ filePath: string,
442
+ lines: object[],
443
+ mtimeEpochSeconds: number,
444
+ ): void => {
445
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
446
+ fs.writeFileSync(
447
+ filePath,
448
+ lines.map((line) => JSON.stringify(line)).join('\n'),
449
+ 'utf8',
450
+ );
451
+ fs.utimesSync(filePath, mtimeEpochSeconds, mtimeEpochSeconds);
452
+ };
453
+
454
+ it('identifies a session running a subagent as waiting on the owner', () => {
455
+ const configDir = path.join(configRoot, 'waiting');
456
+ const projectDirectory = path.join(configDir, 'projects', '-home-user');
457
+ writeJsonlTranscript(
458
+ path.join(projectDirectory, 'parent-id.jsonl'),
459
+ [
460
+ {
461
+ type: 'assistant',
462
+ timestamp: '2026-01-01T00:00:00.000Z',
463
+ message: {
464
+ role: 'assistant',
465
+ content: [
466
+ { type: 'text', text: `${ownerCallMarker} please decide` },
467
+ ],
468
+ },
469
+ },
470
+ ],
471
+ 1700000000,
472
+ );
473
+ writeJsonlTranscript(
474
+ path.join(
475
+ projectDirectory,
476
+ 'parent-id',
477
+ 'subagents',
478
+ 'agent-worker.jsonl',
479
+ ),
480
+ [
481
+ {
482
+ type: 'assistant',
483
+ timestamp: '2026-01-01T00:05:00.000Z',
484
+ message: {
485
+ role: 'assistant',
486
+ content: [{ type: 'text', text: 'subagent progress' }],
487
+ },
488
+ },
489
+ ],
490
+ 1700000500,
491
+ );
492
+ const resolver = new FileSystemInteractiveLiveSessionTranscriptResolver(
493
+ sharedProjectsDirectory,
494
+ );
495
+ const ownerCallStatusProvider = new TranscriptOwnerCallStatusProvider(
496
+ ownerCallMarker,
497
+ );
498
+
499
+ const transcriptPaths = resolver.resolveTranscriptPaths([
500
+ {
501
+ sessionName: 'waiting',
502
+ sessionId: 'parent-id',
503
+ candidateSessionIds: ['parent-id', 'subagent-id'],
504
+ configDir,
505
+ },
506
+ ]);
507
+
508
+ return ownerCallStatusProvider
509
+ .listSessionNamesWithUnansweredOwnerCall(transcriptPaths)
510
+ .then((waiting) => {
511
+ expect(waiting.has('waiting')).toBe(true);
512
+ });
513
+ });
514
+ });
@@ -38,23 +38,37 @@ export class FileSystemInteractiveLiveSessionTranscriptResolver implements Inter
38
38
  session: InteractiveLiveSession,
39
39
  ): string | null => {
40
40
  const projectsDirectories = this.listProjectsDirectories(session.configDir);
41
+ for (const candidateSessionId of session.candidateSessionIds) {
42
+ const transcriptPath = this.resolveCandidateTranscriptPath(
43
+ candidateSessionId,
44
+ projectsDirectories,
45
+ );
46
+ if (transcriptPath !== null) {
47
+ return transcriptPath;
48
+ }
49
+ }
50
+ return null;
51
+ };
52
+
53
+ private resolveCandidateTranscriptPath = (
54
+ candidateSessionId: string,
55
+ projectsDirectories: string[],
56
+ ): string | null => {
57
+ const fileName = `${candidateSessionId}.jsonl`;
41
58
  let latestPath: string | null = null;
42
59
  let latestEpochMs = -Infinity;
43
- for (const candidateSessionId of session.candidateSessionIds) {
44
- const fileName = `${candidateSessionId}.jsonl`;
45
- for (const projectsDirectory of projectsDirectories) {
46
- for (const candidate of this.listCandidatePaths(
47
- projectsDirectory,
48
- fileName,
49
- )) {
50
- const epochMs = modifiedEpochMs(candidate);
51
- if (epochMs === null) {
52
- continue;
53
- }
54
- if (epochMs > latestEpochMs) {
55
- latestEpochMs = epochMs;
56
- latestPath = candidate;
57
- }
60
+ for (const projectsDirectory of projectsDirectories) {
61
+ for (const candidate of this.listCandidatePaths(
62
+ projectsDirectory,
63
+ fileName,
64
+ )) {
65
+ const epochMs = modifiedEpochMs(candidate);
66
+ if (epochMs === null) {
67
+ continue;
68
+ }
69
+ if (epochMs > latestEpochMs) {
70
+ latestEpochMs = epochMs;
71
+ latestPath = candidate;
58
72
  }
59
73
  }
60
74
  }
@@ -2,6 +2,7 @@ import {
2
2
  NotifySilentLiveSessionsUseCase,
3
3
  HubTaskStatusResolver,
4
4
  parseHubTaskIssueUrlFromSessionName,
5
+ isGitHubIssueOrPullRequestSessionName,
5
6
  DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
6
7
  DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
7
8
  DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
@@ -38,6 +39,11 @@ describe('NotifySilentLiveSessionsUseCase', () => {
38
39
  let mockHubTaskStatusResolver: Mocked<HubTaskStatusResolver>;
39
40
  const now = new Date('2026-06-26T00:00:00Z');
40
41
  const nowEpochSeconds = Math.floor(now.getTime() / 1000);
42
+ const GITHUB_SESSION = 'https_//github_com/HiromiShikata/repo/issues/42';
43
+ const GITHUB_SESSION_ALPHA =
44
+ 'https_//github_com/HiromiShikata/repo/issues/100';
45
+ const GITHUB_SESSION_BRAVO =
46
+ 'https_//github_com/HiromiShikata/repo/issues/200';
41
47
 
42
48
  const runParams = (
43
49
  overrides?: Partial<{ activeHubTaskStatus: string | null }>,
@@ -208,12 +214,12 @@ describe('NotifySilentLiveSessionsUseCase', () => {
208
214
  expect(DEFAULT_NOTIFICATION_STAGGER_SECONDS).toBe(25);
209
215
  });
210
216
 
211
- it('notifies a plain-named live interactive session independently of any issue', async () => {
212
- setupLiveInteractiveSession('workbench');
217
+ it('notifies a session whose name encodes a github.com issue URL', async () => {
218
+ setupLiveInteractiveSession(GITHUB_SESSION);
213
219
  mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
214
220
  [
215
221
  {
216
- sessionName: 'workbench',
222
+ sessionName: GITHUB_SESSION,
217
223
  lastOutputEpochSeconds:
218
224
  nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
219
225
  },
@@ -227,15 +233,100 @@ describe('NotifySilentLiveSessionsUseCase', () => {
227
233
  );
228
234
  expect(
229
235
  mockNotificationRepository.sendSelfCheckNotification,
230
- ).toHaveBeenCalledWith('workbench', MAIN_STALLED_SECTION);
236
+ ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
237
+ });
238
+
239
+ it('notifies a session whose name encodes a github.com pull-request URL', async () => {
240
+ const pullRequestSession = 'https_//github_com/HiromiShikata/repo/pull/77';
241
+ setupLiveInteractiveSession(pullRequestSession);
242
+ mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
243
+ [
244
+ {
245
+ sessionName: pullRequestSession,
246
+ lastOutputEpochSeconds:
247
+ nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
248
+ },
249
+ ],
250
+ );
251
+
252
+ await useCase.run(runParams());
253
+
254
+ expect(
255
+ mockNotificationRepository.sendSelfCheckNotification,
256
+ ).toHaveBeenCalledWith(pullRequestSession, MAIN_STALLED_SECTION);
257
+ });
258
+
259
+ it('excludes a non-github-named session from selection so it is never notified', async () => {
260
+ mockSnapshotProvider.getSnapshot.mockResolvedValue(
261
+ snapshotWithSessions(['workbench']),
262
+ );
263
+ mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
264
+ [
265
+ {
266
+ sessionName: 'workbench',
267
+ lastOutputEpochSeconds:
268
+ nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
269
+ },
270
+ ],
271
+ );
272
+
273
+ await useCase.run(runParams());
274
+
275
+ expect(mockTranscriptResolver.resolveTranscriptPaths).toHaveBeenCalledWith(
276
+ [],
277
+ );
278
+ expect(
279
+ mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName,
280
+ ).toHaveBeenCalledWith([]);
281
+ expect(
282
+ mockMessageComposer.composeMainStalledSection,
283
+ ).not.toHaveBeenCalled();
284
+ expect(
285
+ mockNotificationRepository.sendSelfCheckNotification,
286
+ ).not.toHaveBeenCalled();
287
+ });
288
+
289
+ it('monitors only the github-named session when mixed with a non-github-named session', async () => {
290
+ mockSnapshotProvider.getSnapshot.mockResolvedValue(
291
+ snapshotWithSessions([GITHUB_SESSION, 'orchestrator']),
292
+ );
293
+ mockTranscriptResolver.resolveTranscriptPaths.mockReturnValue(
294
+ transcriptMapFor([GITHUB_SESSION]),
295
+ );
296
+ mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
297
+ [
298
+ {
299
+ sessionName: GITHUB_SESSION,
300
+ lastOutputEpochSeconds:
301
+ nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
302
+ },
303
+ {
304
+ sessionName: 'orchestrator',
305
+ lastOutputEpochSeconds:
306
+ nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
307
+ },
308
+ ],
309
+ );
310
+
311
+ await useCase.run(runParams());
312
+
313
+ expect(mockTranscriptResolver.resolveTranscriptPaths).toHaveBeenCalledWith([
314
+ sessionFor(GITHUB_SESSION),
315
+ ]);
316
+ expect(
317
+ mockNotificationRepository.sendSelfCheckNotification,
318
+ ).toHaveBeenCalledTimes(1);
319
+ expect(
320
+ mockNotificationRepository.sendSelfCheckNotification,
321
+ ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
231
322
  });
232
323
 
233
324
  it('passes the resolved transcript paths to the output and owner-call providers', async () => {
234
- setupLiveInteractiveSession('workbench');
325
+ setupLiveInteractiveSession(GITHUB_SESSION);
235
326
 
236
327
  await useCase.run(runParams());
237
328
 
238
- const expectedMap = transcriptMapFor(['workbench']);
329
+ const expectedMap = transcriptMapFor([GITHUB_SESSION]);
239
330
  expect(
240
331
  mockSessionOutputActivityRepository.listSessionOutputActivities,
241
332
  ).toHaveBeenCalledWith(expectedMap);
@@ -244,22 +335,22 @@ describe('NotifySilentLiveSessionsUseCase', () => {
244
335
  ).toHaveBeenCalledWith(expectedMap);
245
336
  expect(
246
337
  mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName,
247
- ).toHaveBeenCalledWith(['workbench']);
338
+ ).toHaveBeenCalledWith([GITHUB_SESSION]);
248
339
  });
249
340
 
250
341
  it('suppresses the stalled section and sends nothing when an owner call is pending past the threshold', async () => {
251
- setupLiveInteractiveSession('workbench');
342
+ setupLiveInteractiveSession(GITHUB_SESSION);
252
343
  mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
253
344
  [
254
345
  {
255
- sessionName: 'workbench',
346
+ sessionName: GITHUB_SESSION,
256
347
  lastOutputEpochSeconds:
257
348
  nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
258
349
  },
259
350
  ],
260
351
  );
261
352
  mockOwnerCallStatusProvider.listSessionNamesWithUnansweredOwnerCall.mockResolvedValue(
262
- new Set(['workbench']),
353
+ new Set([GITHUB_SESSION]),
263
354
  );
264
355
 
265
356
  await useCase.run(runParams());
@@ -273,11 +364,11 @@ describe('NotifySilentLiveSessionsUseCase', () => {
273
364
  });
274
365
 
275
366
  it('sends the main stalled section when the session is silent past the threshold and not waiting on the owner', async () => {
276
- setupLiveInteractiveSession('workbench');
367
+ setupLiveInteractiveSession(GITHUB_SESSION);
277
368
  mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
278
369
  [
279
370
  {
280
- sessionName: 'workbench',
371
+ sessionName: GITHUB_SESSION,
281
372
  lastOutputEpochSeconds:
282
373
  nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
283
374
  },
@@ -294,15 +385,15 @@ describe('NotifySilentLiveSessionsUseCase', () => {
294
385
  );
295
386
  expect(
296
387
  mockNotificationRepository.sendSelfCheckNotification,
297
- ).toHaveBeenCalledWith('workbench', MAIN_STALLED_SECTION);
388
+ ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
298
389
  });
299
390
 
300
391
  it('does not send the main stalled section when output is within the threshold', async () => {
301
- setupLiveInteractiveSession('workbench');
392
+ setupLiveInteractiveSession(GITHUB_SESSION);
302
393
  mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
303
394
  [
304
395
  {
305
- sessionName: 'workbench',
396
+ sessionName: GITHUB_SESSION,
306
397
  lastOutputEpochSeconds:
307
398
  nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS + 1,
308
399
  },
@@ -317,7 +408,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
317
408
  });
318
409
 
319
410
  it('sends the sub-agent section when a sub-agent exceeds the silent threshold', async () => {
320
- setupLiveInteractiveSession('workbench');
411
+ setupLiveInteractiveSession(GITHUB_SESSION);
321
412
  const subAgents: SubAgentActivity[] = [
322
413
  {
323
414
  label: 'sub-process-1',
@@ -326,7 +417,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
326
417
  },
327
418
  ];
328
419
  mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName.mockResolvedValue(
329
- new Map([['workbench', subAgents]]),
420
+ new Map([[GITHUB_SESSION, subAgents]]),
330
421
  );
331
422
 
332
423
  await useCase.run(runParams());
@@ -336,7 +427,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
336
427
  );
337
428
  expect(
338
429
  mockNotificationRepository.sendSelfCheckNotification,
339
- ).toHaveBeenCalledWith('workbench', SUBAGENT_SECTION);
430
+ ).toHaveBeenCalledWith(GITHUB_SESSION, SUBAGENT_SECTION);
340
431
  });
341
432
 
342
433
  it('excludes an owner-handover spawn from selection so no notification is sent', async () => {
@@ -374,11 +465,11 @@ describe('NotifySilentLiveSessionsUseCase', () => {
374
465
  });
375
466
 
376
467
  it('re-notifies a session on every consecutive cycle while it remains a valid silent target', async () => {
377
- setupLiveInteractiveSession('workbench');
468
+ setupLiveInteractiveSession(GITHUB_SESSION);
378
469
  mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
379
470
  [
380
471
  {
381
- sessionName: 'workbench',
472
+ sessionName: GITHUB_SESSION,
382
473
  lastOutputEpochSeconds:
383
474
  nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
384
475
  },
@@ -393,18 +484,18 @@ describe('NotifySilentLiveSessionsUseCase', () => {
393
484
  ).toHaveBeenCalledTimes(2);
394
485
  expect(
395
486
  mockNotificationRepository.sendSelfCheckNotification,
396
- ).toHaveBeenNthCalledWith(1, 'workbench', MAIN_STALLED_SECTION);
487
+ ).toHaveBeenNthCalledWith(1, GITHUB_SESSION, MAIN_STALLED_SECTION);
397
488
  expect(
398
489
  mockNotificationRepository.sendSelfCheckNotification,
399
- ).toHaveBeenNthCalledWith(2, 'workbench', MAIN_STALLED_SECTION);
490
+ ).toHaveBeenNthCalledWith(2, GITHUB_SESSION, MAIN_STALLED_SECTION);
400
491
  });
401
492
 
402
493
  it('notifies on every repeated cycle at the same instant without reading any cooldown state', async () => {
403
- setupLiveInteractiveSession('workbench');
494
+ setupLiveInteractiveSession(GITHUB_SESSION);
404
495
  mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
405
496
  [
406
497
  {
407
- sessionName: 'workbench',
498
+ sessionName: GITHUB_SESSION,
408
499
  lastOutputEpochSeconds:
409
500
  nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
410
501
  },
@@ -426,20 +517,20 @@ describe('NotifySilentLiveSessionsUseCase', () => {
426
517
 
427
518
  it('sends to multiple sessions sequentially with a stagger delay between sends', async () => {
428
519
  mockSnapshotProvider.getSnapshot.mockResolvedValue(
429
- snapshotWithSessions(['alpha', 'bravo']),
520
+ snapshotWithSessions([GITHUB_SESSION_ALPHA, GITHUB_SESSION_BRAVO]),
430
521
  );
431
522
  mockTranscriptResolver.resolveTranscriptPaths.mockReturnValue(
432
- transcriptMapFor(['alpha', 'bravo']),
523
+ transcriptMapFor([GITHUB_SESSION_ALPHA, GITHUB_SESSION_BRAVO]),
433
524
  );
434
525
  mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
435
526
  [
436
527
  {
437
- sessionName: 'alpha',
528
+ sessionName: GITHUB_SESSION_ALPHA,
438
529
  lastOutputEpochSeconds:
439
530
  nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
440
531
  },
441
532
  {
442
- sessionName: 'bravo',
533
+ sessionName: GITHUB_SESSION_BRAVO,
443
534
  lastOutputEpochSeconds:
444
535
  nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
445
536
  },
@@ -458,7 +549,11 @@ describe('NotifySilentLiveSessionsUseCase', () => {
458
549
 
459
550
  await useCase.run(runParams());
460
551
 
461
- expect(callOrder).toEqual(['send:alpha', 'sleep', 'send:bravo']);
552
+ expect(callOrder).toEqual([
553
+ `send:${GITHUB_SESSION_ALPHA}`,
554
+ 'sleep',
555
+ `send:${GITHUB_SESSION_BRAVO}`,
556
+ ]);
462
557
  expect(mockSleeper.sleep).toHaveBeenCalledTimes(1);
463
558
  expect(mockSleeper.sleep).toHaveBeenCalledWith(
464
559
  DEFAULT_NOTIFICATION_STAGGER_SECONDS * 1000,
@@ -466,11 +561,11 @@ describe('NotifySilentLiveSessionsUseCase', () => {
466
561
  });
467
562
 
468
563
  it('does not suppress errors raised while sending a notification', async () => {
469
- setupLiveInteractiveSession('workbench');
564
+ setupLiveInteractiveSession(GITHUB_SESSION);
470
565
  mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
471
566
  [
472
567
  {
473
- sessionName: 'workbench',
568
+ sessionName: GITHUB_SESSION,
474
569
  lastOutputEpochSeconds:
475
570
  nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
476
571
  },
@@ -538,7 +633,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
538
633
  ).not.toHaveBeenCalled();
539
634
  });
540
635
 
541
- it('leaves a non-URL session name unchecked and sends as before', async () => {
636
+ it('excludes a non-github-named session before the hub-task gate so the resolver is never consulted', async () => {
542
637
  setupSilentMainSession('workbench');
543
638
 
544
639
  await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
@@ -546,7 +641,7 @@ describe('NotifySilentLiveSessionsUseCase', () => {
546
641
  expect(mockHubTaskStatusResolver.getIssueByUrl).not.toHaveBeenCalled();
547
642
  expect(
548
643
  mockNotificationRepository.sendSelfCheckNotification,
549
- ).toHaveBeenCalledWith('workbench', MAIN_STALLED_SECTION);
644
+ ).not.toHaveBeenCalled();
550
645
  });
551
646
 
552
647
  it('does not call the resolver at all when the active status is unconfigured', async () => {
@@ -616,6 +711,72 @@ describe('NotifySilentLiveSessionsUseCase', () => {
616
711
  });
617
712
  });
618
713
 
714
+ describe('isGitHubIssueOrPullRequestSessionName', () => {
715
+ it('accepts the encoded form of a github.com issue URL session name', () => {
716
+ expect(
717
+ isGitHubIssueOrPullRequestSessionName(
718
+ 'https_//github_com/HiromiShikata/repo/issues/42',
719
+ ),
720
+ ).toBe(true);
721
+ });
722
+
723
+ it('accepts the encoded form of a github.com pull-request URL session name', () => {
724
+ expect(
725
+ isGitHubIssueOrPullRequestSessionName(
726
+ 'https_//github_com/HiromiShikata/repo/pull/77',
727
+ ),
728
+ ).toBe(true);
729
+ });
730
+
731
+ it('accepts the raw form of a github.com issue and pull-request URL session name', () => {
732
+ expect(
733
+ isGitHubIssueOrPullRequestSessionName(
734
+ 'https://github.com/HiromiShikata/repo/issues/42',
735
+ ),
736
+ ).toBe(true);
737
+ expect(
738
+ isGitHubIssueOrPullRequestSessionName(
739
+ 'https://github.com/HiromiShikata/repo/pull/77',
740
+ ),
741
+ ).toBe(true);
742
+ });
743
+
744
+ it('rejects a plain orchestrator-style session name', () => {
745
+ expect(isGitHubIssueOrPullRequestSessionName('workbench')).toBe(false);
746
+ expect(isGitHubIssueOrPullRequestSessionName('orchestrator')).toBe(false);
747
+ expect(isGitHubIssueOrPullRequestSessionName('aw-host')).toBe(false);
748
+ });
749
+
750
+ it('rejects a non-github host even in the encoded form', () => {
751
+ expect(
752
+ isGitHubIssueOrPullRequestSessionName(
753
+ 'https_//example_com/HiromiShikata/repo/issues/42',
754
+ ),
755
+ ).toBe(false);
756
+ });
757
+
758
+ it('rejects a github.com session name that is neither an issue nor a pull request', () => {
759
+ expect(
760
+ isGitHubIssueOrPullRequestSessionName(
761
+ 'https_//github_com/HiromiShikata/repo',
762
+ ),
763
+ ).toBe(false);
764
+ expect(
765
+ isGitHubIssueOrPullRequestSessionName(
766
+ 'https_//github_com/HiromiShikata/repo/discussions/42',
767
+ ),
768
+ ).toBe(false);
769
+ });
770
+
771
+ it('rejects a github.com issue URL whose trailing segment is not a number', () => {
772
+ expect(
773
+ isGitHubIssueOrPullRequestSessionName(
774
+ 'https_//github_com/HiromiShikata/repo/issues/new',
775
+ ),
776
+ ).toBe(false);
777
+ });
778
+ });
779
+
619
780
  it('uses the session entity helper for type completeness', () => {
620
781
  expect(sessionFor('workbench')).toEqual({
621
782
  sessionName: 'workbench',
@@ -25,6 +25,14 @@ export const parseHubTaskIssueUrlFromSessionName = (
25
25
  return GITHUB_ISSUE_URL_PATTERN.test(sessionName) ? sessionName : null;
26
26
  };
27
27
 
28
+ const GITHUB_ISSUE_OR_PULL_REQUEST_SESSION_NAME_PATTERN =
29
+ /^https(:\/\/|_\/\/)github(\.com|_com)\/[^/]+\/[^/]+\/(issues|pull)\/\d+$/;
30
+
31
+ export const isGitHubIssueOrPullRequestSessionName = (
32
+ sessionName: string,
33
+ ): boolean =>
34
+ GITHUB_ISSUE_OR_PULL_REQUEST_SESSION_NAME_PATTERN.test(sessionName);
35
+
28
36
  export type HubTaskStatusResolver = Pick<IssueRepository, 'getIssueByUrl'>;
29
37
 
30
38
  type NotifyCandidate = {
@@ -58,8 +66,18 @@ export class NotifySilentLiveSessionsUseCase {
58
66
  }): Promise<void> => {
59
67
  const snapshot =
60
68
  await this.liveSessionProcessSnapshotProvider.getSnapshot();
61
- const interactiveSessions =
69
+ const allInteractiveSessions =
62
70
  this.resolveInteractiveLiveSessions.resolve(snapshot);
71
+ const interactiveSessions = allInteractiveSessions.filter((session) =>
72
+ isGitHubIssueOrPullRequestSessionName(session.sessionName),
73
+ );
74
+ const skippedNonGitHubSessionCount =
75
+ allInteractiveSessions.length - interactiveSessions.length;
76
+ if (skippedNonGitHubSessionCount > 0) {
77
+ console.log(
78
+ `Silent live session notification: ignoring ${skippedNonGitHubSessionCount} non-github-named interactive session(s); only sessions named after a github.com issue or pull-request URL are monitored.`,
79
+ );
80
+ }
63
81
  const transcriptPathBySessionName =
64
82
  this.interactiveLiveSessionTranscriptResolver.resolveTranscriptPaths(
65
83
  interactiveSessions,
@@ -5,6 +5,7 @@ export declare class FileSystemInteractiveLiveSessionTranscriptResolver implemen
5
5
  constructor(sharedProjectsDirectory?: string);
6
6
  resolveTranscriptPaths: (sessions: InteractiveLiveSession[]) => Map<string, string>;
7
7
  private resolveTranscriptPath;
8
+ private resolveCandidateTranscriptPath;
8
9
  private listProjectsDirectories;
9
10
  private listCandidatePaths;
10
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystemInteractiveLiveSessionTranscriptResolver.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AACtF,OAAO,EAAE,wCAAwC,EAAE,MAAM,mFAAmF,CAAC;AAc7I,qBAAa,kDAAmD,YAAW,wCAAwC;IAE/G,OAAO,CAAC,QAAQ,CAAC,uBAAuB;gBAAvB,uBAAuB,GAAE,MAAyC;IAGrF,sBAAsB,GACpB,UAAU,sBAAsB,EAAE,KACjC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CASpB;IAEF,OAAO,CAAC,qBAAqB,CAyB3B;IAEF,OAAO,CAAC,uBAAuB,CAM7B;IAEF,OAAO,CAAC,kBAAkB,CAsBxB;CACH"}
1
+ {"version":3,"file":"FileSystemInteractiveLiveSessionTranscriptResolver.d.ts","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AACtF,OAAO,EAAE,wCAAwC,EAAE,MAAM,mFAAmF,CAAC;AAc7I,qBAAa,kDAAmD,YAAW,wCAAwC;IAE/G,OAAO,CAAC,QAAQ,CAAC,uBAAuB;gBAAvB,uBAAuB,GAAE,MAAyC;IAGrF,sBAAsB,GACpB,UAAU,sBAAsB,EAAE,KACjC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CASpB;IAEF,OAAO,CAAC,qBAAqB,CAc3B;IAEF,OAAO,CAAC,8BAA8B,CAuBpC;IAEF,OAAO,CAAC,uBAAuB,CAM7B;IAEF,OAAO,CAAC,kBAAkB,CAsBxB;CACH"}
@@ -12,6 +12,7 @@ export declare const DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS: number;
12
12
  export declare const DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS: number;
13
13
  export declare const DEFAULT_NOTIFICATION_STAGGER_SECONDS = 25;
14
14
  export declare const parseHubTaskIssueUrlFromSessionName: (sessionName: string) => string | null;
15
+ export declare const isGitHubIssueOrPullRequestSessionName: (sessionName: string) => boolean;
15
16
  export type HubTaskStatusResolver = Pick<IssueRepository, 'getIssueByUrl'>;
16
17
  export declare class NotifySilentLiveSessionsUseCase {
17
18
  private readonly liveSessionProcessSnapshotProvider;
@@ -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;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
+ {"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;AAKF,eAAO,MAAM,qCAAqC,GAChD,aAAa,MAAM,KAClB,OACkE,CAAC;AAEtE,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,CAiEf;IAEF,OAAO,CAAC,eAAe,CAmCrB;IAEF,OAAO,CAAC,gBAAgB,CA8CtB;IAEF,OAAO,CAAC,cAAc,CAqCpB;CACH"}