github-issue-tower-defence-management 1.122.3 → 1.122.4

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 (62) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +3 -3
  3. package/bin/adapter/entry-points/console/consoleDoneStore.js +19 -5
  4. package/bin/adapter/entry-points/console/consoleDoneStore.js.map +1 -1
  5. package/bin/adapter/entry-points/handlers/consoleListsWriter.js +2 -0
  6. package/bin/adapter/entry-points/handlers/consoleListsWriter.js.map +1 -1
  7. package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js +1 -1
  8. package/bin/adapter/entry-points/handlers/notifySilentTmuxSessions.js.map +1 -1
  9. package/bin/adapter/repositories/ConfigurableSilentSessionMessageComposer.js +6 -7
  10. package/bin/adapter/repositories/ConfigurableSilentSessionMessageComposer.js.map +1 -1
  11. package/bin/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.js +60 -11
  12. package/bin/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.js.map +1 -1
  13. package/bin/adapter/repositories/ProcessListSessionSubAgentActivityRepository.js +1 -0
  14. package/bin/adapter/repositories/ProcessListSessionSubAgentActivityRepository.js.map +1 -1
  15. package/bin/adapter/repositories/TranscriptSessionSubAgentActivityRepository.js +64 -7
  16. package/bin/adapter/repositories/TranscriptSessionSubAgentActivityRepository.js.map +1 -1
  17. package/bin/domain/usecases/DefaultSilentSessionMessageComposer.js +5 -7
  18. package/bin/domain/usecases/DefaultSilentSessionMessageComposer.js.map +1 -1
  19. package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js +51 -16
  20. package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/adapter/entry-points/console/consoleDoneStore.test.ts +38 -0
  23. package/src/adapter/entry-points/console/consoleDoneStore.ts +29 -4
  24. package/src/adapter/entry-points/handlers/consoleListsWriter.test.ts +72 -0
  25. package/src/adapter/entry-points/handlers/consoleListsWriter.ts +3 -0
  26. package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts +1 -0
  27. package/src/adapter/repositories/ConfigurableSilentSessionMessageComposer.test.ts +60 -37
  28. package/src/adapter/repositories/ConfigurableSilentSessionMessageComposer.ts +7 -18
  29. package/src/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.test.ts +223 -0
  30. package/src/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.ts +94 -10
  31. package/src/adapter/repositories/ProcessListSessionSubAgentActivityRepository.test.ts +12 -2
  32. package/src/adapter/repositories/ProcessListSessionSubAgentActivityRepository.ts +1 -0
  33. package/src/adapter/repositories/TranscriptSessionSubAgentActivityRepository.test.ts +196 -4
  34. package/src/adapter/repositories/TranscriptSessionSubAgentActivityRepository.ts +91 -7
  35. package/src/domain/entities/LiveSessionActivitySnapshot.ts +1 -0
  36. package/src/domain/usecases/DefaultSilentSessionMessageComposer.test.ts +112 -51
  37. package/src/domain/usecases/DefaultSilentSessionMessageComposer.ts +8 -17
  38. package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +250 -18
  39. package/src/domain/usecases/NotifySilentLiveSessionsUseCase.ts +72 -22
  40. package/src/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.ts +8 -0
  41. package/src/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.ts +4 -7
  42. package/types/adapter/entry-points/console/consoleDoneStore.d.ts +2 -0
  43. package/types/adapter/entry-points/console/consoleDoneStore.d.ts.map +1 -1
  44. package/types/adapter/entry-points/handlers/consoleListsWriter.d.ts.map +1 -1
  45. package/types/adapter/entry-points/handlers/notifySilentTmuxSessions.d.ts.map +1 -1
  46. package/types/adapter/repositories/ConfigurableSilentSessionMessageComposer.d.ts +2 -3
  47. package/types/adapter/repositories/ConfigurableSilentSessionMessageComposer.d.ts.map +1 -1
  48. package/types/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.d.ts +13 -2
  49. package/types/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.d.ts.map +1 -1
  50. package/types/adapter/repositories/ProcessListSessionSubAgentActivityRepository.d.ts.map +1 -1
  51. package/types/adapter/repositories/TranscriptSessionSubAgentActivityRepository.d.ts +5 -1
  52. package/types/adapter/repositories/TranscriptSessionSubAgentActivityRepository.d.ts.map +1 -1
  53. package/types/domain/entities/LiveSessionActivitySnapshot.d.ts +1 -0
  54. package/types/domain/entities/LiveSessionActivitySnapshot.d.ts.map +1 -1
  55. package/types/domain/usecases/DefaultSilentSessionMessageComposer.d.ts +2 -3
  56. package/types/domain/usecases/DefaultSilentSessionMessageComposer.d.ts.map +1 -1
  57. package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts +2 -1
  58. package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts.map +1 -1
  59. package/types/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.d.ts +8 -0
  60. package/types/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.d.ts.map +1 -1
  61. package/types/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.d.ts +4 -4
  62. package/types/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.d.ts.map +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [1.122.4](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.122.3...v1.122.4) (2026-07-12)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **console:** reset per-tab .done.json on list regeneration to bound optimistic-hide store ([#1157](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1157)) ([d632054](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/d632054c3d8b38d30feb09eea62c235b1aaab280))
7
+ * **silent-monitor:** judge sub-agent wait state instead of time-window suppression ([#1160](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1160)) ([14cbb6c](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/14cbb6cbb31a2424a445f764ac0cee160f2d8ea4))
8
+
1
9
  ## [1.122.3](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.122.2...v1.122.3) (2026-07-11)
2
10
 
3
11
 
package/README.md CHANGED
@@ -92,7 +92,7 @@ Behind the token gate the server exposes three groups of routes:
92
92
  - Operation APIs (POST, JSON body): `POST /api/review` (`approve`, `request_changes`, `close`), `POST /api/triage` (`set_status`, `set_story`, `close`, `close_not_planned`, `snooze_1day`, `snooze_1week`), and `POST /api/intmux` (`set_intmux`). These routes are multi-project: every request body carries the `pjcode` of the project the UI is currently viewing (taken from the UI's own `/projects/{pjcode}` URL path), the server resolves that `pjcode` to its GitHub Project URL through the `pjcode → projectUrl` mapping described below, loads that project's status and story options (lazily, cached per `pjcode`), and applies the operation against the resolved project. A request with no `pjcode`, or a `pjcode` that has no configured project URL, is rejected with HTTP 400. Each confirmed operation records the affected `projectItemId` into the `.done` exclusion under the resolved `pjcode` so it disappears from every tab's served list for that project only. One running `serveWeb` instance therefore serves both reads and writes for every configured project.
93
93
  - Comment APIs (POST, JSON body, backed by the server-side `GH_TOKEN`): `POST /api/comment` posts a top-level comment on the issue or pull request named by the request body's `url`. `POST /api/reviewcomment` posts a line-anchored inline review comment on a pull request diff; its request body carries `url` (the pull request URL), `path` (the changed file path), `line` (a positive integer diff line number), `side` (`RIGHT` for added or context lines on the new side, `LEFT` for removed lines on the old side), and `body`. The server resolves owner, repo, and pull request number from `url`, fetches the pull request head commit sha, and calls GitHub `POST /repos/{owner}/{repo}/pulls/{number}/comments` with `commit_id` set to that sha. When GitHub rejects the request, the response is HTTP 502 with the GitHub error message in the `error` field of the body so the UI can show the real reason.
94
94
 
95
- The `.done` exclusion is persisted per tab in a `.done.json` file alongside each tab's `list.json` under `consoleDataOutputDir`. The file is never directly servable because the dot-segment block rejects any path containing it.
95
+ The `.done` exclusion is persisted per tab in a `.done.json` file alongside each tab's `list.json` under `consoleDataOutputDir`. The file is never directly servable because the dot-segment block rejects any path containing it. It is an optimistic-hide store scoped to a single regeneration cycle: each confirmed operation records the affected `projectItemId` so the item disappears immediately, and the schedule cycle resets every tab's `.done.json` back to `{ "projectItemIds": [] }` right after it regenerates that project's `list.json` files. This bounds the store to at most one cycle of recorded ids, so it can never accumulate and over-hide items that legitimately re-enter a visible status.
96
96
 
97
97
  Multi-project operation routing is configured through an optional `consoleProjects` mapping in the config file. It maps each `pjcode` to that project's GitHub Project URL so the operation APIs can resolve the correct project per request. The configured `projectName` is always added to this mapping automatically (pointing at the configured `projectUrl`), so a single-project deployment needs no `consoleProjects` entry at all. When the same `serveWeb` instance serves write operations for several projects, list each additional project explicitly:
98
98
 
@@ -287,7 +287,7 @@ silentNotificationEnabled?: boolean # Optional: Master switch for the silent liv
287
287
  subAgentOutputRootDirectory?: string # Optional: Root directory holding one output file per sub-process (file name derived from the sub-process label). The modification time of each file is read to compute how long the sub-process output has been idle. When unset, sub-process idle time is reported as 0 and only the running-time threshold can trigger a sub-process notification
288
288
  subAgentProcessMatchPattern?: string # Optional: Regular expression matched against each process command line to discover the sub-processes that belong to a monitored session. The expression must define a named capture group `session` whose value equals the monitored session name, and may define a named capture group `label` used as the display name. When unset, the sub-process check is skipped
289
289
  ownerCallMarker?: string # Optional: Marker substring that identifies an assistant message asking the owner for a decision or confirmation. When set, the main-session stalled section is suppressed while a session's latest marker-bearing assistant message is newer (by full timestamp) than its latest genuine owner reply. When unset, no session is treated as waiting on the owner
290
- subAgentTranscriptRootDirectory?: string # Optional: Projects root directory (for example `~/.claude/projects`) under which each session's transcript is stored as `<cwd-slug>/<sessionId>.jsonl` and its sub-agent transcripts live in the sibling `<cwd-slug>/<sessionId>/subagents/` directory as one `agent-<id>.jsonl` file per sub-agent. Because the on-disk directory is keyed by the session's working-directory slug and session id rather than by the tmux session name, the sub-agent directory is derived from the already-resolved main-session transcript path (the `.jsonl` suffix is stripped and `subagents` is appended). A sub-agent is treated as finished and skipped when the last meaningful entry of its transcript is a completion or termination marker: an assistant message whose `stop_reason` is `end_turn` or `stop_sequence`, an assistant message whose final content block is `text` (a final answer returned to the parent, which Claude Code often writes with a `null` `stop_reason`), a user message whose final content block is `text` (a terminal user entry such as `[Request interrupted by user]`), a user message whose final content block is a `tool_result` (the tool call completed and no assistant turn followed, the shape a sub-agent leaves when it ends right after its last tool — including the final `StructuredOutput` result — or when its process is gone), or a user message with no content blocks. Only a sub-agent whose last entry is an assistant message with a pending `tool_use` block and no following tool result is still considered active; its idle time is computed from the transcript file modification time (following symlinks) and the running time from its first entry timestamp, and it is flagged whenever it crosses the idle or running threshold regardless of how old it is. When set, this transcript-based discovery is used instead of `subAgentProcessMatchPattern`. When unset, the process-match discovery is used
290
+ subAgentTranscriptRootDirectory?: string # Optional: Projects root directory (for example `~/.claude/projects`) under which each session's transcript is stored as `<cwd-slug>/<sessionId>.jsonl` and its sub-agent transcripts live in the sibling `<cwd-slug>/<sessionId>/subagents/` directory as one `agent-<id>.jsonl` file per sub-agent. Because the on-disk directory is keyed by the session's working-directory slug and session id rather than by the tmux session name, the sub-agent directory is derived from the already-resolved main-session transcript path (the `.jsonl` suffix is stripped and `subagents` is appended). A sub-agent is treated as finished and skipped when the last meaningful entry of its transcript is a completion or termination marker: an assistant message whose `stop_reason` is `end_turn` or `stop_sequence`, an assistant message whose final content block is `text` (a final answer returned to the parent, which Claude Code often writes with a `null` `stop_reason`), a user message whose final content block is `text` (a terminal user entry such as `[Request interrupted by user]`), a user message whose final content block is a `tool_result` (the tool call completed and no assistant turn followed, the shape a sub-agent leaves when it ends right after its last tool — including the final `StructuredOutput` result — or when its process is gone), or a user message with no content blocks. Only a sub-agent whose last entry is an assistant message with a pending `tool_use` block and no following tool result is still considered active; its idle time is computed from the transcript file modification time (following symlinks) and the running time from its first entry timestamp. An active sub-agent whose pending tool command matches a live host process is classified as waiting on that external process and is exempt from the idle threshold (a genuinely hung sub-agent whose matching process is absent is still flagged), and the running threshold announces once per crossing per label. When set, this transcript-based discovery is used instead of `subAgentProcessMatchPattern`. When unset, the process-match discovery is used
291
291
  mainSilentThresholdSeconds?: number # Optional: Seconds of main-session output silence after which the main-session self-check section is sent. Default 600
292
292
  subAgentSilentThresholdSeconds?: number # Optional: Seconds of sub-process output silence after which the sub-process section is sent. Default 300
293
293
  subAgentRunningThresholdSeconds?: number # Optional: Seconds a sub-process may run before the sub-process section is sent regardless of its output silence. Default 900
@@ -562,7 +562,7 @@ Candidate sessions are first selected from the live process tree: every live tmu
562
562
 
563
563
  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.
564
564
 
565
- The sub-process section is sent, regardless of main output, when at least one sub-process of the session has been output-idle for `subAgentSilentThresholdSeconds` or has been running for `subAgentRunningThresholdSeconds`. It is composed of up to two distinct messages, one per condition: an idle message that lists each sub-process that produced no output for at least `subAgentSilentThresholdSeconds` with its no-output minutes, tells the agent to treat that system-detected idle duration as the authoritative signal rather than re-deriving whether the sub-process is alive, forbids dismissing the signal from speculation, and requires the agent to determine the cause by a concrete check (whether there is genuinely no recent activity anywhere, including a very recent push or commit or output from nested sub-processes it started, versus being legitimately blocked on an external dependency such as a continuous-integration run, an external API, or another process), to act if stuck or state the waiting conclusion with concrete evidence if waiting, and to output that investigation result into the session as a log even though owner notification is not required, and a long-running message that lists each sub-process that has been running for at least `subAgentRunningThresholdSeconds` with its running minutes and asks the agent to verify it is genuinely advancing rather than caught in an infinite loop, a task that is too large, or a stuck approach. The long-running message foregrounds the running duration and does not surface the short idle time, so a sub-process flagged only for running long is not dismissed because its silent time looks small; a sub-process that matches both conditions appears in both messages. The long-running threshold is overridable per project via `subAgentRunningThresholdSeconds` (default 900 seconds) for repositories whose continuous integration legitimately runs longer. Sub-processes are discovered in one of two ways: when `subAgentTranscriptRootDirectory` is configured, each session's `subagents/agent-<id>.jsonl` transcripts are scanned. The sub-agent directory is the `subagents/` directory that sits next to the session's already-resolved main-session transcript file under `projects/<cwd-slug>/<sessionId>/subagents/`, derived by stripping the `.jsonl` suffix from the main-session transcript path and appending `subagents`; this on-disk path is keyed by the session's working-directory slug and session id, not by the tmux session name. Finished sub-agents are skipped, determined from the last meaningful transcript entry rather than from the last non-null `stop_reason` seen anywhere in the file. A sub-agent is treated as finished when its last entry is a completion or termination marker: an assistant message whose `stop_reason` is `end_turn` or `stop_sequence`, an assistant message whose final content block is `text` (a final answer returned to the parent, which Claude Code often writes with a `null` `stop_reason`), a user message whose final content block is `text` (a terminal user entry such as `[Request interrupted by user]`), a user message whose final content block is a `tool_result`, or a user message with no content blocks. The `tool_result` and empty-user terminal shapes are the ones a sub-agent leaves when it ends right after its last tool call completes — for example the `tool_result` of the final `StructuredOutput` call a sub-agent uses to return its result, the launch acknowledgement of a background command, or any other tool whose result is written but no assistant turn follows because the sub-agent's process is gone (killed, crashed, or token-exhausted). Recognizing these shapes as terminal is what lets a marker-less dead transcript be excluded by the completion signal itself rather than by an age cap. Only a sub-agent whose last entry is an assistant message with a pending `tool_use` block and no following tool result is still considered active and subject to the idle and running thresholds; this is the genuinely-incomplete shape — the sub-agent requested a tool that never returned and is hung mid-work. Idle time is taken from the transcript file modification time (following symlinks) while running time is taken from its first entry timestamp. Because sub-agents run in-process inside the parent session rather than as separate operating-system processes, no process-liveness signal can be matched back to a transcript; the completion-or-termination marker at the end of the transcript is the sole signal used to exclude finished sub-agents. There is no age cap: a sub-agent that is past the idle or running threshold and does not end in a completion or termination marker is flagged regardless of how long it has been silent, so a genuinely-stuck sub-agent that has been hung on a pending tool call for hours or days is still reported instead of being silently dropped. Otherwise sub-processes are discovered by matching `subAgentProcessMatchPattern` against process command lines.
565
+ The sub-process section is sent, regardless of main output, when at least one sub-process of the session has been output-idle for `subAgentSilentThresholdSeconds` or has been running for `subAgentRunningThresholdSeconds`. It is composed of up to two distinct messages, one per condition: an idle message that lists each sub-process that produced no output for at least `subAgentSilentThresholdSeconds` with its no-output minutes, tells the agent to treat that system-detected idle duration as the authoritative signal rather than re-deriving whether the sub-process is alive, forbids dismissing the signal from speculation, and requires the agent to determine the cause by a concrete check (whether there is genuinely no recent activity anywhere, including a very recent push or commit or output from nested sub-processes it started, versus being legitimately blocked on an external dependency such as a continuous-integration run, an external API, or another process), to act if stuck or state the waiting conclusion with concrete evidence if waiting, and to output that investigation result into the session as a log even though owner notification is not required, and a long-running message that lists each sub-process that has been running for at least `subAgentRunningThresholdSeconds` with its running minutes and asks the agent to verify it is genuinely advancing rather than caught in an infinite loop, a task that is too large, or a stuck approach. The long-running message foregrounds the running duration and does not surface the short idle time, so a sub-process flagged only for running long is not dismissed because its silent time looks small; a sub-process that matches both conditions appears in both messages. The long-running threshold is overridable per project via `subAgentRunningThresholdSeconds` (default 900 seconds) for repositories whose continuous integration legitimately runs longer. Sub-processes are discovered in one of two ways: when `subAgentTranscriptRootDirectory` is configured, each session's `subagents/agent-<id>.jsonl` transcripts are scanned. The sub-agent directory is the `subagents/` directory that sits next to the session's already-resolved main-session transcript file under `projects/<cwd-slug>/<sessionId>/subagents/`, derived by stripping the `.jsonl` suffix from the main-session transcript path and appending `subagents`; this on-disk path is keyed by the session's working-directory slug and session id, not by the tmux session name. Finished sub-agents are skipped, determined from the last meaningful transcript entry rather than from the last non-null `stop_reason` seen anywhere in the file. A sub-agent is treated as finished when its last entry is a completion or termination marker: an assistant message whose `stop_reason` is `end_turn` or `stop_sequence`, an assistant message whose final content block is `text` (a final answer returned to the parent, which Claude Code often writes with a `null` `stop_reason`), a user message whose final content block is `text` (a terminal user entry such as `[Request interrupted by user]`), a user message whose final content block is a `tool_result`, or a user message with no content blocks. The `tool_result` and empty-user terminal shapes are the ones a sub-agent leaves when it ends right after its last tool call completes — for example the `tool_result` of the final `StructuredOutput` call a sub-agent uses to return its result, the launch acknowledgement of a background command, or any other tool whose result is written but no assistant turn follows because the sub-agent's process is gone (killed, crashed, or token-exhausted). Recognizing these shapes as terminal is what lets a marker-less dead transcript be excluded by the completion signal itself rather than by an age cap. Only a sub-agent whose last entry is an assistant message with a pending `tool_use` block and no following tool result is still considered active and subject to the idle and running thresholds; this is the genuinely-incomplete shape — the sub-agent requested a tool that never returned and is hung mid-work. Idle time is taken from the transcript file modification time (following symlinks) while running time is taken from its first entry timestamp. Because sub-agents run in-process inside the parent session rather than as separate operating-system processes, no process-liveness signal can be matched back to a transcript; the completion-or-termination marker at the end of the transcript is the sole signal used to exclude finished sub-agents. There is no age cap: a sub-agent that is past the idle or running threshold and does not end in a completion or termination marker is flagged regardless of how long it has been silent, so a genuinely-stuck sub-agent that has been hung on a pending tool call for hours or days is still reported instead of being silently dropped. Otherwise sub-processes are discovered by matching `subAgentProcessMatchPattern` against process command lines. Because a sub-agent inside a single blocking call (for example a continuous-integration watch) is otherwise indistinguishable from a hung one, the transcript-based discovery additionally judges the sub-agent's actual wait state instead of applying any time-window suppression. A sub-agent whose transcript tail is an in-flight tool call — the last entry is an assistant tool-use with no following tool result — carrying a command string is classified as WAITING when a live process matching that command exists on the host: each pending tool command is normalized (whitespace collapsed, first 60 characters) and searched as a substring of the normalized host process command lines (`ps -eo etimes=,args=`, supplied through the injectable process lister). A WAITING sub-agent never produces an idle (no-output) reminder, no matter how long its transcript has been silent. A sub-agent whose in-flight tool call has no matching live process is genuinely hung and is reported exactly as before, every cycle while the condition holds. Long-running reminders are transition-triggered rather than level-triggered: a sub-process is announced once when it first crosses `subAgentRunningThresholdSeconds`, the announced labels are persisted per session in the same candidate-state file used by the two-consecutive-cycle debounce, no repeat announcement is made while the same label stays over the threshold, and the record self-clears when the label disappears from the session's sub-agent set (a later new label triggers its own announcement). A reminder that includes the main-session-stalled section is never affected by these judgments, and main-session stall notification behavior is unchanged.
566
566
 
567
567
  A two-consecutive-cycle debounce guards against transient false positives: a session is notified only when it meets the silent-target condition (output silent at or beyond the threshold and not waiting on the owner) in the current cycle and it was also a notification candidate in the immediately previous cycle. The set of candidate session names is persisted across cycles, keyed by the globally-unique session name, in a state file written atomically (the default path is `${XDG_CACHE_HOME:-~/.cache}/tdpm/silent-session-candidates.json`, overridable via `candidateDebounceStateFilePath`). The monitor runs as a fresh process each schedule cycle, so this on-disk state is what carries the previous cycle's candidate set forward. Each cycle loads the candidate set recorded within `candidateDebounceRecencyWindowSeconds` of now (default 900, a small multiple of the schedule interval to tolerate interval jitter), then records the current candidate set with the current timestamp; entries that age past the retention window are dropped on the next save, and a save merges with other recently-recorded session names so concurrent per-project runs do not clobber each other. A candidate that appears for only one isolated cycle — for example because the owner's reply has not yet been flushed to the transcript when the monitor reads it, or because a transient hub-task status resolution error fails open for a single cycle — is therefore deferred and never notified, while a genuine stall that persists across cycles is still caught, one cycle later. Because silence is measured from the latest transcript entry of any type — including the monitor's own injected reminder and the owner's reply — a notified session's measured silence resets as soon as it produces any activity, so a session that has resumed is not re-flagged. When more than one session is notified in the same cycle, the sends are spaced out sequentially with `silentNotificationStaggerSeconds` between consecutive sends (no wait before the first or after the last) so the targets are not all triggered at once. When `activeHubTaskStatus` is configured, each notification is gated on the latest GitHub state and Project Status of the session's hub task: a session whose name identifies a github.com issue or pull request — accepted both as a clean `https://github.com/{owner}/{repo}/issues/{N}` URL and as the real tmux session-name form `https_//github_com/{owner}/{repo}/issues/{N}` produced by replacing `.` and `:` with `_` (the `pull` path is accepted in both forms too) — is notified only while that hub task is open and in the configured active Status, so a session whose hub task has been closed, merged, or moved to another Status (for example Done) is suppressed; sessions whose name does not identify a github.com issue or pull request are never gated. To cut GitHub query load and remove most fail-opens, each resolved status is cached by issue URL in a state file written atomically (the default path is `${XDG_CACHE_HOME:-~/.cache}/tdpm/silent-session-hub-task-status.json`, overridable via `hubTaskStatusCacheStateFilePath`). On each cycle the gate reads the cache first: a cached entry recorded within `hubTaskStatusCacheTtlSeconds` of now (default 300) decides the gate without any GitHub query, and otherwise the hub task is re-resolved and the result written back to the cache. When live resolution fails — the resolver returns no tracked task (a closed or Done issue filtered out of the active project), or a transient API error is thrown — the gate falls back to the cached status even after it has expired: a cached active entry keeps the notification (still notified if genuinely stalled) and a cached closed or non-active entry suppresses it, each logged with a distinct warning. Only when there is no cached status at all and live resolution fails does the gate fail open once (a closed issue and a transient error are indistinguishable in that case without an extra network call), logging a distinct warning, so the next cycle can populate the cache. When `activeHubTaskStatus` is unset, this hub-task check is a no-op. Process-snapshot collection, transcript resolution, owner-call detection, the wait between sends, and the message wording are all performed through injectable ports, so the logic is unit-testable without touching the host, and the host-specific process and environment access, sub-process pattern, and message wording are supplied through adapters or configuration. When `silentNotificationEnabled` is not true the step is a no-op, and any error during the step is logged and swallowed so the schedule cycle is never affected.
568
568
 
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.recordDoneProjectItemIdAcrossTabs = exports.CONSOLE_DONE_TAB_NAMES = exports.recordDoneProjectItemId = exports.readDoneProjectItemIds = exports.doneFilePathForTab = exports.CONSOLE_DONE_FILE_NAME = void 0;
36
+ exports.resetDoneProjectItemIdsAcrossTabs = exports.resetDoneProjectItemIds = exports.recordDoneProjectItemIdAcrossTabs = exports.CONSOLE_DONE_TAB_NAMES = exports.recordDoneProjectItemId = exports.readDoneProjectItemIds = exports.doneFilePathForTab = exports.CONSOLE_DONE_FILE_NAME = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
39
  exports.CONSOLE_DONE_FILE_NAME = '.done.json';
@@ -53,6 +53,12 @@ const parseDoneRecord = (raw) => {
53
53
  };
54
54
  const doneFilePathForTab = (consoleDataOutputDir, pjcode, tab) => path.join(consoleDataOutputDir, pjcode, tab, exports.CONSOLE_DONE_FILE_NAME);
55
55
  exports.doneFilePathForTab = doneFilePathForTab;
56
+ const writeDoneRecordAtomic = (filePath, record) => {
57
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
58
+ const tmpPath = `${filePath}.tmp`;
59
+ fs.writeFileSync(tmpPath, JSON.stringify(record));
60
+ fs.renameSync(tmpPath, filePath);
61
+ };
56
62
  const readDoneProjectItemIds = (consoleDataOutputDir, pjcode, tab) => {
57
63
  const filePath = (0, exports.doneFilePathForTab)(consoleDataOutputDir, pjcode, tab);
58
64
  let raw;
@@ -77,10 +83,7 @@ const recordDoneProjectItemId = (consoleDataOutputDir, pjcode, tab, projectItemI
77
83
  const updated = {
78
84
  projectItemIds: [...existing, projectItemId],
79
85
  };
80
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
81
- const tmpPath = `${filePath}.tmp`;
82
- fs.writeFileSync(tmpPath, JSON.stringify(updated));
83
- fs.renameSync(tmpPath, filePath);
86
+ writeDoneRecordAtomic(filePath, updated);
84
87
  };
85
88
  exports.recordDoneProjectItemId = recordDoneProjectItemId;
86
89
  exports.CONSOLE_DONE_TAB_NAMES = [
@@ -98,4 +101,15 @@ const recordDoneProjectItemIdAcrossTabs = (consoleDataOutputDir, pjcode, project
98
101
  }
99
102
  };
100
103
  exports.recordDoneProjectItemIdAcrossTabs = recordDoneProjectItemIdAcrossTabs;
104
+ const resetDoneProjectItemIds = (consoleDataOutputDir, pjcode, tab) => {
105
+ const filePath = (0, exports.doneFilePathForTab)(consoleDataOutputDir, pjcode, tab);
106
+ writeDoneRecordAtomic(filePath, { projectItemIds: [] });
107
+ };
108
+ exports.resetDoneProjectItemIds = resetDoneProjectItemIds;
109
+ const resetDoneProjectItemIdsAcrossTabs = (consoleDataOutputDir, pjcode) => {
110
+ for (const tab of exports.CONSOLE_DONE_TAB_NAMES) {
111
+ (0, exports.resetDoneProjectItemIds)(consoleDataOutputDir, pjcode, tab);
112
+ }
113
+ };
114
+ exports.resetDoneProjectItemIdsAcrossTabs = resetDoneProjectItemIdsAcrossTabs;
101
115
  //# sourceMappingURL=consoleDoneStore.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consoleDoneStore.js","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleDoneStore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"consoleDoneStore.js","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/consoleDoneStore.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ exports.writeConsoleLists = exports.formatConsoleGeneratedAt = void 0;
7
7
  const fs_1 = __importDefault(require("fs"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const GenerateConsoleListsUseCase_1 = require("../../../domain/usecases/console/GenerateConsoleListsUseCase");
10
+ const consoleDoneStore_1 = require("../console/consoleDoneStore");
10
11
  const CONSOLE_TAB_NAMES = [
11
12
  'workflow-blocker',
12
13
  'prs',
@@ -41,6 +42,7 @@ const writeConsoleLists = (params) => {
41
42
  for (const tab of CONSOLE_TAB_NAMES) {
42
43
  writeJsonAtomic(path_1.default.join(consoleDataOutputDir, pjcode, tab, 'list.json'), lists[tab]);
43
44
  }
45
+ (0, consoleDoneStore_1.resetDoneProjectItemIdsAcrossTabs)(consoleDataOutputDir, pjcode);
44
46
  };
45
47
  exports.writeConsoleLists = writeConsoleLists;
46
48
  //# sourceMappingURL=consoleListsWriter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"consoleListsWriter.js","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/consoleListsWriter.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AAGxB,8GAIsE;AAYtE,MAAM,iBAAiB,GAAqB;IAC1C,kBAAkB;IAClB,KAAK;IACL,QAAQ;IACR,QAAQ;IACR,oBAAoB;IACpB,eAAe;CAChB,CAAC;AAEK,MAAM,wBAAwB,GAAG,CAAC,IAAU,EAAU,EAAE,CAC7D,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;AADlC,QAAA,wBAAwB,4BACU;AAE/C,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAE,IAAa,EAAQ,EAAE;IAChE,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,YAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,GAAG,QAAQ,MAAM,CAAC;IAClC,YAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,YAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC,CAAC;AAEK,MAAM,iBAAiB,GAAG,CAAC,MAAgC,EAAQ,EAAE;IAC1E,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;IAC/D,IAAI,CAAC,oBAAoB,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QACvD,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GACf,MAAM,CAAC,WAAW,IAAI,IAAA,gCAAwB,EAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAiB,IAAI,yDAA2B,EAAE,CAAC,GAAG,CAAC;QAChE,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM;QACN,aAAa;QACb,WAAW;QACX,wBAAwB,EAAE,MAAM,CAAC,wBAAwB,IAAI,IAAI;KAClE,CAAC,CAAC;IAEH,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACpC,eAAe,CACb,cAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,EACzD,KAAK,CAAC,GAAG,CAAC,CACX,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAvBW,QAAA,iBAAiB,qBAuB5B"}
1
+ {"version":3,"file":"consoleListsWriter.js","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/consoleListsWriter.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,gDAAwB;AAGxB,8GAIsE;AACtE,kEAAgF;AAYhF,MAAM,iBAAiB,GAAqB;IAC1C,kBAAkB;IAClB,KAAK;IACL,QAAQ;IACR,QAAQ;IACR,oBAAoB;IACpB,eAAe;CAChB,CAAC;AAEK,MAAM,wBAAwB,GAAG,CAAC,IAAU,EAAU,EAAE,CAC7D,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;AADlC,QAAA,wBAAwB,4BACU;AAE/C,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAE,IAAa,EAAQ,EAAE;IAChE,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,YAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,GAAG,QAAQ,MAAM,CAAC;IAClC,YAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,YAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC,CAAC;AAEK,MAAM,iBAAiB,GAAG,CAAC,MAAgC,EAAQ,EAAE;IAC1E,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;IAC/D,IAAI,CAAC,oBAAoB,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QACvD,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GACf,MAAM,CAAC,WAAW,IAAI,IAAA,gCAAwB,EAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAiB,IAAI,yDAA2B,EAAE,CAAC,GAAG,CAAC;QAChE,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM;QACN,aAAa;QACb,WAAW;QACX,wBAAwB,EAAE,MAAM,CAAC,wBAAwB,IAAI,IAAI;KAClE,CAAC,CAAC;IAEH,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACpC,eAAe,CACb,cAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,CAAC,EACzD,KAAK,CAAC,GAAG,CAAC,CACX,CAAC;IACJ,CAAC;IAED,IAAA,oDAAiC,EAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;AAClE,CAAC,CAAC;AAzBW,QAAA,iBAAiB,qBAyB5B"}
@@ -27,7 +27,7 @@ const createOwnerCallStatusProvider = (ownerCallMarker) => {
27
27
  };
28
28
  const createSubAgentActivityRepository = (subAgentTranscriptRootDirectory, subAgentProcessMatchPattern, subAgentOutputRootDirectory, localCommandRunner, now) => {
29
29
  if (subAgentTranscriptRootDirectory !== null) {
30
- return new TranscriptSessionSubAgentActivityRepository_1.TranscriptSessionSubAgentActivityRepository(new FileSystemSubAgentTranscriptDirectoryResolver_1.FileSystemSubAgentTranscriptDirectoryResolver(subAgentTranscriptRootDirectory), now);
30
+ return new TranscriptSessionSubAgentActivityRepository_1.TranscriptSessionSubAgentActivityRepository(new FileSystemSubAgentTranscriptDirectoryResolver_1.FileSystemSubAgentTranscriptDirectoryResolver(subAgentTranscriptRootDirectory), new NodeSubAgentProcessLister_1.NodeSubAgentProcessLister(localCommandRunner), now);
31
31
  }
32
32
  return new ProcessListSessionSubAgentActivityRepository_1.ProcessListSessionSubAgentActivityRepository(subAgentProcessMatchPattern, new NodeSubAgentProcessLister_1.NodeSubAgentProcessLister(localCommandRunner), new FileSystemSubAgentSilentSecondsResolver_1.FileSystemSubAgentSilentSecondsResolver(subAgentOutputRootDirectory, now));
33
33
  };
@@ -1 +1 @@
1
- {"version":3,"file":"notifySilentTmuxSessions.js","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notifySilentTmuxSessions.js","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts"],"names":[],"mappings":"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"}
@@ -21,24 +21,23 @@ class ConfigurableSilentSessionMessageComposer {
21
21
  }
22
22
  return withReminderSentinel(`${this.templates.mainStalledMessage} ${(0, DefaultSilentSessionMessageComposer_1.composeOwnerCallFormatGuidance)(this.ownerCallMarker)}`);
23
23
  };
24
- this.composeSubAgentSection = (subAgents, thresholds) => {
24
+ this.composeSubAgentSection = (stallSections) => {
25
25
  const hasIdleTemplate = this.templates.subAgentIdleMessageHeader !== null ||
26
26
  this.templates.subAgentIdleMessageFooter !== null;
27
27
  const hasLongRunningTemplate = this.templates.subAgentLongRunningMessageHeader !== null ||
28
28
  this.templates.subAgentLongRunningMessageFooter !== null;
29
29
  if (!hasIdleTemplate && !hasLongRunningTemplate) {
30
- return this.fallback.composeSubAgentSection(subAgents, thresholds);
30
+ return this.fallback.composeSubAgentSection(stallSections);
31
31
  }
32
- const idleSubAgents = subAgents.filter((subAgent) => subAgent.silentSeconds >= thresholds.subAgentSilentThresholdSeconds);
33
- const longRunningSubAgents = subAgents.filter((subAgent) => subAgent.runningSeconds >= thresholds.subAgentRunningThresholdSeconds);
32
+ const { idleSubAgents, longRunningSubAgents } = stallSections;
34
33
  const sections = [];
35
34
  if (idleSubAgents.length > 0 && hasIdleTemplate) {
36
35
  sections.push(this.composeIdleSection(idleSubAgents, this.templates.subAgentIdleMessageHeader, this.templates.subAgentIdleMessageFooter));
37
36
  }
38
37
  else if (idleSubAgents.length > 0) {
39
- sections.push(this.fallback.composeSubAgentSection(idleSubAgents, {
40
- subAgentSilentThresholdSeconds: thresholds.subAgentSilentThresholdSeconds,
41
- subAgentRunningThresholdSeconds: Number.POSITIVE_INFINITY,
38
+ sections.push(this.fallback.composeSubAgentSection({
39
+ idleSubAgents,
40
+ longRunningSubAgents: [],
42
41
  }));
43
42
  }
44
43
  if (longRunningSubAgents.length > 0 && hasLongRunningTemplate) {
@@ -1 +1 @@
1
- {"version":3,"file":"ConfigurableSilentSessionMessageComposer.js","sourceRoot":"","sources":["../../../src/adapter/repositories/ConfigurableSilentSessionMessageComposer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ConfigurableSilentSessionMessageComposer.js","sourceRoot":"","sources":["../../../src/adapter/repositories/ConfigurableSilentSessionMessageComposer.ts"],"names":[],"mappings":"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"}
@@ -33,12 +33,13 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.FileSystemSilentSessionCandidateStateRepository = exports.DEFAULT_STATE_RETENTION_WINDOW_SECONDS = void 0;
36
+ exports.FileSystemSilentSessionCandidateStateRepository = exports.ANNOUNCED_RUNNING_RETENTION_WINDOW_SECONDS = exports.DEFAULT_STATE_RETENTION_WINDOW_SECONDS = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const os = __importStar(require("os"));
39
39
  const path = __importStar(require("path"));
40
40
  const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
41
41
  exports.DEFAULT_STATE_RETENTION_WINDOW_SECONDS = 60 * 60;
42
+ exports.ANNOUNCED_RUNNING_RETENTION_WINDOW_SECONDS = 24 * 60 * 60;
42
43
  const defaultStateFilePath = () => {
43
44
  const base = process.env.XDG_CACHE_HOME ?? path.join(os.homedir(), '.cache');
44
45
  return path.join(base, 'tdpm', 'silent-session-candidates.json');
@@ -50,7 +51,7 @@ class FileSystemSilentSessionCandidateStateRepository {
50
51
  this.loadRecentCandidateSessionNames = async (params) => {
51
52
  const nowEpochSeconds = Math.floor(params.now.getTime() / 1000);
52
53
  const oldestAllowedEpochSeconds = nowEpochSeconds - params.recencyWindowSeconds;
53
- const entries = this.readEntries();
54
+ const entries = this.readCandidateEntries();
54
55
  const recentSessionNames = new Set();
55
56
  for (const entry of entries) {
56
57
  if (entry.recordedEpochSeconds >= oldestAllowedEpochSeconds) {
@@ -64,7 +65,7 @@ class FileSystemSilentSessionCandidateStateRepository {
64
65
  const oldestRetainedEpochSeconds = recordedEpochSeconds - this.retentionWindowSeconds;
65
66
  const currentSessionNames = new Set(params.sessionNames);
66
67
  const mergedBySessionName = new Map();
67
- for (const entry of this.readEntries()) {
68
+ for (const entry of this.readCandidateEntries()) {
68
69
  if (entry.recordedEpochSeconds >= oldestRetainedEpochSeconds &&
69
70
  !currentSessionNames.has(entry.sessionName)) {
70
71
  mergedBySessionName.set(entry.sessionName, entry);
@@ -76,27 +77,48 @@ class FileSystemSilentSessionCandidateStateRepository {
76
77
  recordedEpochSeconds,
77
78
  });
78
79
  }
79
- this.writeEntries(Array.from(mergedBySessionName.values()));
80
+ this.writeState(Array.from(mergedBySessionName.values()), this.readAnnouncedRunningEntries());
80
81
  };
81
- this.readEntries = () => {
82
+ this.loadAnnouncedRunningSubAgentLabels = async (params) => {
83
+ const entry = this.readAnnouncedRunningEntries().find((candidate) => candidate.sessionName === params.sessionName);
84
+ return new Set(entry?.labels ?? []);
85
+ };
86
+ this.saveAnnouncedRunningSubAgentLabels = async (params) => {
87
+ const recordedEpochSeconds = Math.floor(params.now.getTime() / 1000);
88
+ const oldestRetainedEpochSeconds = recordedEpochSeconds - exports.ANNOUNCED_RUNNING_RETENTION_WINDOW_SECONDS;
89
+ const retainedEntries = this.readAnnouncedRunningEntries().filter((entry) => entry.sessionName !== params.sessionName &&
90
+ entry.recordedEpochSeconds >= oldestRetainedEpochSeconds);
91
+ if (params.labels.length > 0) {
92
+ retainedEntries.push({
93
+ sessionName: params.sessionName,
94
+ labels: params.labels,
95
+ recordedEpochSeconds,
96
+ });
97
+ }
98
+ this.writeState(this.readCandidateEntries(), retainedEntries);
99
+ };
100
+ this.readState = () => {
82
101
  let raw;
83
102
  try {
84
103
  raw = fs.readFileSync(this.stateFilePath, 'utf8');
85
104
  }
86
105
  catch {
87
- return [];
106
+ return {};
88
107
  }
89
108
  let parsed;
90
109
  try {
91
110
  parsed = JSON.parse(raw);
92
111
  }
93
112
  catch {
94
- return [];
113
+ return {};
95
114
  }
96
115
  if (!isRecord(parsed)) {
97
- return [];
116
+ return {};
98
117
  }
99
- const storedEntries = parsed.candidates;
118
+ return parsed;
119
+ };
120
+ this.readCandidateEntries = () => {
121
+ const storedEntries = this.readState().candidates;
100
122
  if (!Array.isArray(storedEntries)) {
101
123
  return [];
102
124
  }
@@ -115,11 +137,38 @@ class FileSystemSilentSessionCandidateStateRepository {
115
137
  }
116
138
  return entries;
117
139
  };
118
- this.writeEntries = (entries) => {
140
+ this.readAnnouncedRunningEntries = () => {
141
+ const storedEntries = this.readState().announcedRunningSubAgents;
142
+ if (!Array.isArray(storedEntries)) {
143
+ return [];
144
+ }
145
+ const entries = [];
146
+ for (const storedEntry of storedEntries) {
147
+ if (!isRecord(storedEntry)) {
148
+ continue;
149
+ }
150
+ const sessionName = storedEntry.sessionName;
151
+ const recordedEpochSeconds = storedEntry.recordedEpochSeconds;
152
+ const storedLabels = storedEntry.labels;
153
+ if (typeof sessionName !== 'string' ||
154
+ typeof recordedEpochSeconds !== 'number' ||
155
+ !Number.isFinite(recordedEpochSeconds) ||
156
+ !Array.isArray(storedLabels)) {
157
+ continue;
158
+ }
159
+ const labels = storedLabels.filter((label) => typeof label === 'string');
160
+ if (labels.length !== storedLabels.length) {
161
+ continue;
162
+ }
163
+ entries.push({ sessionName, labels, recordedEpochSeconds });
164
+ }
165
+ return entries;
166
+ };
167
+ this.writeState = (candidates, announcedRunningSubAgents) => {
119
168
  const directory = path.dirname(this.stateFilePath);
120
169
  fs.mkdirSync(directory, { recursive: true });
121
170
  const temporaryPath = `${this.stateFilePath}.${process.pid}.tmp`;
122
- fs.writeFileSync(temporaryPath, JSON.stringify({ candidates: entries }));
171
+ fs.writeFileSync(temporaryPath, JSON.stringify({ candidates, announcedRunningSubAgents }));
123
172
  fs.renameSync(temporaryPath, this.stateFilePath);
124
173
  };
125
174
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystemSilentSessionCandidateStateRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FileSystemSilentSessionCandidateStateRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,7 @@ class ProcessListSessionSubAgentActivityRepository {
27
27
  label,
28
28
  silentSeconds: this.silentSecondsResolver.resolveSilentSeconds(label),
29
29
  runningSeconds: process.elapsedSeconds,
30
+ waitingOnExternalProcess: false,
30
31
  };
31
32
  const existing = result.get(sessionName);
32
33
  if (existing === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"ProcessListSessionSubAgentActivityRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/ProcessListSessionSubAgentActivityRepository.ts"],"names":[],"mappings":";;;AAKA,MAAa,4CAA4C;IAGvD,YACE,YAA2B,EACV,aAAoC,EACpC,qBAAoD;QADpD,kBAAa,GAAb,aAAa,CAAuB;QACpC,0BAAqB,GAArB,qBAAqB,CAA+B;QAQvE,wCAAmC,GAAG,KAAK,EACzC,YAAsB,EACoB,EAAE;YAC5C,MAAM,MAAM,GAAG,IAAI,GAAG,EAA8B,CAAC;YACrD,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;gBAC9B,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;YAC3D,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;gBAChC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;gBACzD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBACjD,SAAS;gBACX,CAAC;gBACD,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;gBACzC,IACE,WAAW,KAAK,SAAS;oBACzB,CAAC,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,EACvC,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,WAAW,CAAC;gBAChD,MAAM,QAAQ,GAAqB;oBACjC,KAAK;oBACL,aAAa,EAAE,IAAI,CAAC,qBAAqB,CAAC,oBAAoB,CAAC,KAAK,CAAC;oBACrE,cAAc,EAAE,OAAO,CAAC,cAAc;iBACvC,CAAC;gBACF,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACzC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACtC,CAAC;qBAAM,CAAC;oBACN,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;QAzCA,IAAI,CAAC,WAAW;YACd,YAAY,KAAK,IAAI,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;gBAChD,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC;IACjC,CAAC;CAsCF;AAlDD,oGAkDC"}
1
+ {"version":3,"file":"ProcessListSessionSubAgentActivityRepository.js","sourceRoot":"","sources":["../../../src/adapter/repositories/ProcessListSessionSubAgentActivityRepository.ts"],"names":[],"mappings":";;;AAKA,MAAa,4CAA4C;IAGvD,YACE,YAA2B,EACV,aAAoC,EACpC,qBAAoD;QADpD,kBAAa,GAAb,aAAa,CAAuB;QACpC,0BAAqB,GAArB,qBAAqB,CAA+B;QAQvE,wCAAmC,GAAG,KAAK,EACzC,YAAsB,EACoB,EAAE;YAC5C,MAAM,MAAM,GAAG,IAAI,GAAG,EAA8B,CAAC;YACrD,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;gBAC9B,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;YAC3D,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;gBAChC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;gBACzD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBACjD,SAAS;gBACX,CAAC;gBACD,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC;gBACzC,IACE,WAAW,KAAK,SAAS;oBACzB,CAAC,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,EACvC,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,WAAW,CAAC;gBAChD,MAAM,QAAQ,GAAqB;oBACjC,KAAK;oBACL,aAAa,EAAE,IAAI,CAAC,qBAAqB,CAAC,oBAAoB,CAAC,KAAK,CAAC;oBACrE,cAAc,EAAE,OAAO,CAAC,cAAc;oBACtC,wBAAwB,EAAE,KAAK;iBAChC,CAAC;gBACF,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACzC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACtC,CAAC;qBAAM,CAAC;oBACN,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC;QA1CA,IAAI,CAAC,WAAW;YACd,YAAY,KAAK,IAAI,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;gBAChD,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC;IACjC,CAAC;CAuCF;AAnDD,oGAmDC"}
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.TranscriptSessionSubAgentActivityRepository = void 0;
36
+ exports.TranscriptSessionSubAgentActivityRepository = exports.normalizeCommandFragment = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
39
  const isRecord = (value) => typeof value === 'object' && value !== null;
@@ -48,6 +48,12 @@ const parseEpochSeconds = (timestamp) => {
48
48
  const parsed = Date.parse(timestamp);
49
49
  return Number.isNaN(parsed) ? null : Math.floor(parsed / 1000);
50
50
  };
51
+ const PENDING_TOOL_COMMAND_FRAGMENT_LENGTH = 60;
52
+ const normalizeCommandFragment = (command) => command
53
+ .replace(/\s+/g, ' ')
54
+ .trim()
55
+ .slice(0, PENDING_TOOL_COMMAND_FRAGMENT_LENGTH);
56
+ exports.normalizeCommandFragment = normalizeCommandFragment;
51
57
  const readContentBlocks = (message) => {
52
58
  const content = message.content;
53
59
  if (!Array.isArray(content)) {
@@ -81,9 +87,32 @@ const entryIndicatesCompletion = (entry) => {
81
87
  }
82
88
  return false;
83
89
  };
90
+ const entryPendingToolCommands = (entry) => {
91
+ const type = readString(entry, 'type');
92
+ const message = entry.message;
93
+ if (type !== 'assistant' || !isRecord(message)) {
94
+ return [];
95
+ }
96
+ const commands = [];
97
+ for (const block of readContentBlocks(message)) {
98
+ if (readString(block, 'type') !== 'tool_use') {
99
+ continue;
100
+ }
101
+ const input = block.input;
102
+ if (!isRecord(input)) {
103
+ continue;
104
+ }
105
+ const command = readString(input, 'command');
106
+ if (command !== null && command.trim().length > 0) {
107
+ commands.push(command);
108
+ }
109
+ }
110
+ return commands;
111
+ };
84
112
  const parseTranscript = (content) => {
85
113
  let firstEntryEpochSeconds = null;
86
114
  let lastEntryIndicatesCompletion = false;
115
+ let pendingToolCommands = [];
87
116
  for (const line of content.split('\n')) {
88
117
  const trimmed = line.trim();
89
118
  if (trimmed.length === 0) {
@@ -105,32 +134,46 @@ const parseTranscript = (content) => {
105
134
  }
106
135
  if (isRecord(parsed.message)) {
107
136
  lastEntryIndicatesCompletion = entryIndicatesCompletion(parsed);
137
+ pendingToolCommands = entryPendingToolCommands(parsed);
108
138
  }
109
139
  }
110
- return { firstEntryEpochSeconds, lastEntryIndicatesCompletion };
140
+ return {
141
+ firstEntryEpochSeconds,
142
+ lastEntryIndicatesCompletion,
143
+ pendingToolCommands,
144
+ };
111
145
  };
112
146
  const clampToZero = (value) => (value > 0 ? value : 0);
113
147
  class TranscriptSessionSubAgentActivityRepository {
114
- constructor(directoryResolver, now) {
148
+ constructor(directoryResolver, processLister, now) {
115
149
  this.directoryResolver = directoryResolver;
150
+ this.processLister = processLister;
116
151
  this.now = now;
117
152
  this.listSubAgentActivitiesBySessionName = async (sessionNames, transcriptPathBySessionName) => {
118
153
  const result = new Map();
119
154
  const nowEpochSeconds = Math.floor(this.now.getTime() / 1000);
155
+ let normalizedProcessCommandLines = null;
156
+ const loadNormalizedProcessCommandLines = async () => {
157
+ if (normalizedProcessCommandLines === null) {
158
+ const processes = await this.processLister.listProcesses();
159
+ normalizedProcessCommandLines = processes.map((process) => process.commandLine.replace(/\s+/g, ' ').trim());
160
+ }
161
+ return normalizedProcessCommandLines;
162
+ };
120
163
  for (const sessionName of sessionNames) {
121
164
  const mainTranscriptPath = transcriptPathBySessionName.get(sessionName) ?? null;
122
165
  const directory = this.directoryResolver.resolveSubAgentsDirectory(sessionName, mainTranscriptPath);
123
166
  if (directory === null) {
124
167
  continue;
125
168
  }
126
- const activities = this.collectActivities(directory, nowEpochSeconds);
169
+ const activities = await this.collectActivities(directory, nowEpochSeconds, loadNormalizedProcessCommandLines);
127
170
  if (activities.length > 0) {
128
171
  result.set(sessionName, activities);
129
172
  }
130
173
  }
131
174
  return result;
132
175
  };
133
- this.collectActivities = (directory, nowEpochSeconds) => {
176
+ this.collectActivities = async (directory, nowEpochSeconds, loadNormalizedProcessCommandLines) => {
134
177
  let entries;
135
178
  try {
136
179
  entries = fs.readdirSync(directory, { withFileTypes: true });
@@ -145,14 +188,14 @@ class TranscriptSessionSubAgentActivityRepository {
145
188
  continue;
146
189
  }
147
190
  const filePath = path.join(directory, fileName);
148
- const activity = this.toActivity(filePath, fileName, nowEpochSeconds);
191
+ const activity = await this.toActivity(filePath, fileName, nowEpochSeconds, loadNormalizedProcessCommandLines);
149
192
  if (activity !== null) {
150
193
  activities.push(activity);
151
194
  }
152
195
  }
153
196
  return activities;
154
197
  };
155
- this.toActivity = (filePath, fileName, nowEpochSeconds) => {
198
+ this.toActivity = async (filePath, fileName, nowEpochSeconds, loadNormalizedProcessCommandLines) => {
156
199
  let content;
157
200
  let stats;
158
201
  try {
@@ -174,8 +217,22 @@ class TranscriptSessionSubAgentActivityRepository {
174
217
  label: fileName.replace(/\.jsonl$/, ''),
175
218
  silentSeconds,
176
219
  runningSeconds,
220
+ waitingOnExternalProcess: await this.hasLiveMatchingProcess(transcript.pendingToolCommands, loadNormalizedProcessCommandLines),
177
221
  };
178
222
  };
223
+ this.hasLiveMatchingProcess = async (pendingToolCommands, loadNormalizedProcessCommandLines) => {
224
+ if (pendingToolCommands.length === 0) {
225
+ return false;
226
+ }
227
+ const fragments = pendingToolCommands
228
+ .map(exports.normalizeCommandFragment)
229
+ .filter((fragment) => fragment.length > 0);
230
+ if (fragments.length === 0) {
231
+ return false;
232
+ }
233
+ const processCommandLines = await loadNormalizedProcessCommandLines();
234
+ return fragments.some((fragment) => processCommandLines.some((commandLine) => commandLine.includes(fragment)));
235
+ };
179
236
  }
180
237
  }
181
238
  exports.TranscriptSessionSubAgentActivityRepository = TranscriptSessionSubAgentActivityRepository;