github-issue-tower-defence-management 1.111.2 → 1.112.0
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 +14 -0
- package/README.md +9 -6
- package/bin/adapter/entry-points/console/ui-dist/assets/{index-CT3t4Yje.js → index-Bu5bQZyP.js} +19 -19
- package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +19 -3
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/repositories/ConfigurableSilentSessionMessageComposer.js +6 -0
- package/bin/adapter/repositories/ConfigurableSilentSessionMessageComposer.js.map +1 -1
- package/bin/domain/usecases/DefaultSilentSessionMessageComposer.js +9 -0
- package/bin/domain/usecases/DefaultSilentSessionMessageComposer.js.map +1 -1
- package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js +13 -3
- package/bin/domain/usecases/NotifySilentLiveSessionsUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.test.ts +59 -0
- package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.ts +17 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.test.tsx +79 -0
- package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +10 -5
- package/src/adapter/entry-points/console/ui-dist/assets/{index-CT3t4Yje.js → index-Bu5bQZyP.js} +19 -19
- package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +20 -1
- package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.test.ts +105 -2
- package/src/adapter/repositories/ConfigurableSilentSessionMessageComposer.test.ts +44 -0
- package/src/adapter/repositories/ConfigurableSilentSessionMessageComposer.ts +8 -0
- package/src/domain/usecases/DefaultSilentSessionMessageComposer.test.ts +17 -1
- package/src/domain/usecases/DefaultSilentSessionMessageComposer.ts +11 -0
- package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +86 -1
- package/src/domain/usecases/NotifySilentLiveSessionsUseCase.ts +20 -7
- package/src/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.ts +1 -0
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/repositories/ConfigurableSilentSessionMessageComposer.d.ts +2 -0
- package/types/adapter/repositories/ConfigurableSilentSessionMessageComposer.d.ts.map +1 -1
- package/types/domain/usecases/DefaultSilentSessionMessageComposer.d.ts +1 -0
- package/types/domain/usecases/DefaultSilentSessionMessageComposer.d.ts.map +1 -1
- package/types/domain/usecases/NotifySilentLiveSessionsUseCase.d.ts.map +1 -1
- package/types/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.d.ts +1 -0
- package/types/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.112.0](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.111.3...v1.112.0) (2026-06-28)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **schedule:** re-notify owner instead of staying silent on unanswered owner call ([#1044](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1044)) ([05d83fe](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/05d83fee818548acfaa3fbcc878c8e14528b7e23)), closes [#1042](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1042)
|
|
7
|
+
|
|
8
|
+
## [1.111.3](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.111.2...v1.111.3) (2026-06-28)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **console:** keep the workflow-blocker tab visible regardless of the localStorage done overlay ([#1040](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1040)) ([83213bc](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/commit/83213bc075a02fbcd3cfca894c7e6cbbe503bff1)), closes [#1038](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/issues/1038)
|
|
14
|
+
|
|
1
15
|
## [1.111.2](https://github.com/HiromiShikata/npm-cli-github-issue-tower-defence-management/compare/v1.111.1...v1.111.2) (2026-06-28)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -287,14 +287,15 @@ inTmuxLauncherCommand?: string # Optional: Launcher command that starts an inter
|
|
|
287
287
|
silentNotificationEnabled?: boolean # Optional: Master switch for the silent live session self-check notification. The step is a no-op unless this is `true` (or the `TDPM_SILENT_NOTIFICATION_ENABLED` environment variable equals the string `true`). This gate prevents the step from acting automatically when the daemon is run with a default configuration; it must be explicitly turned on. Default false
|
|
288
288
|
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
|
|
289
289
|
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
|
|
290
|
-
ownerCallMarker?: string # Optional: Marker substring that identifies an assistant message asking the owner for a decision or confirmation. When set,
|
|
290
|
+
ownerCallMarker?: string # Optional: Marker substring that identifies an assistant message asking the owner for a decision or confirmation. When set, a session whose latest marker-bearing assistant message is newer (by full timestamp) than its latest genuine owner reply is treated as waiting on the owner: the main-session stalled section is suppressed, and instead — once the wait exceeds `mainSilentThresholdSeconds` — an owner-re-notification section is sent that tells the agent to re-raise its pending call-to-user so the owner is notified again. When unset, no session is treated as waiting on the owner
|
|
291
291
|
subAgentTranscriptRootDirectory?: string # Optional: Root directory under which each session has a `<sessionName>/subagents/` directory holding one `agent-<id>.jsonl` transcript per sub-agent. A sub-agent whose latest transcript entry reports a `stop_reason` of `end_turn` or `stop_sequence` is treated as finished and skipped; for any other sub-agent the idle time is computed from the transcript file modification time (following symlinks) and the running time from its first entry timestamp. When set, this transcript-based discovery is used instead of `subAgentProcessMatchPattern`. When unset, the process-match discovery is used
|
|
292
|
-
mainSilentThresholdSeconds?: number # Optional: Seconds of main-session output silence after which the main-session self-check section is sent. Default 600
|
|
292
|
+
mainSilentThresholdSeconds?: number # Optional: Seconds of main-session output silence after which the main-session self-check section is sent. The same threshold also gates the owner-re-notification section: a session waiting on the owner is re-reminded only once its silence reaches this value. Default 600
|
|
293
293
|
subAgentSilentThresholdSeconds?: number # Optional: Seconds of sub-process output silence after which the sub-process section is sent. Default 300
|
|
294
294
|
subAgentRunningThresholdSeconds?: number # Optional: Seconds a sub-process may run before the sub-process section is sent regardless of its output silence. Default 900
|
|
295
295
|
silentNotificationCooldownSeconds?: number # Optional: Minimum seconds between notifications to the same session. Default 1800
|
|
296
296
|
silentNotificationStaggerSeconds?: number # Optional: Seconds to wait between consecutive session notifications within one cycle, so the targets are notified sequentially rather than all at once. Default 25
|
|
297
297
|
silentMainStalledMessage?: string # Optional: Overrides the body of the main-session stalled section. When unset, a generic built-in message is used
|
|
298
|
+
silentOwnerReNotificationMessage?: string # Optional: Overrides the body of the owner-re-notification section sent to a session that has been waiting on the owner past `mainSilentThresholdSeconds`. When unset, a generic built-in message is used that instructs the agent to re-raise its pending call-to-user and states the injected message is not the owner replying
|
|
298
299
|
silentSubAgentMessageHeader?: string # Optional: Overrides the line shown above the sub-process list in the sub-process section. When unset, a generic built-in line is used
|
|
299
300
|
silentSubAgentMessageFooter?: string # Optional: Overrides the line shown below the sub-process list in the sub-process section. When unset, a generic built-in line is used
|
|
300
301
|
changeTargetPathAliases?: # Optional: Map of short alias keys to full repository-root-relative directory paths. Allows `change-target:<alias>` labels to reference deeply nested paths that exceed GitHub's 50-character label limit. When a `change-target:` label's value matches a key in this map, it is expanded to the corresponding full path before confinement checking. Values with leading or trailing slashes are normalized automatically. Example below
|
|
@@ -554,17 +555,19 @@ For each `In Tmux by human` issue with no live session, the reconciler launches
|
|
|
554
555
|
|
|
555
556
|
## Silent Live Session Notification
|
|
556
557
|
|
|
557
|
-
Each schedule cycle, when `silentNotificationEnabled` is true, also inspects every live interactive Claude Code session and sends a short
|
|
558
|
+
Each schedule cycle, when `silentNotificationEnabled` is true, also inspects every live interactive Claude Code session and sends a short reminder into a session via `tmux send-keys`. There are three independent reminder paths: (1) the main-session stalled self-check, sent to a session that is silent but not waiting on the owner; (2) the owner-re-notification, sent to a session that IS waiting on the owner and has waited long enough; and (3) the sub-process stall reminder. The reminder is composed of only the sections whose condition is met, so a session receives one combined message containing one or more sections. The main-session stalled section and the owner-re-notification section are mutually exclusive for a given cycle, because a session is either waiting on the owner or not. When `silentNotificationEnabled` is not set, the entire step is a no-op even if the daemon picks up its configuration automatically.
|
|
558
559
|
|
|
559
560
|
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 from its process environment as `<CLAUDE_CONFIG_DIR>/projects/<cwd-slug>/<CLAUDE_CODE_SESSION_ID>.jsonl` (the most recently modified match is used when several exist), so a session that has no issue URL resolves just as reliably as one that does.
|
|
560
561
|
|
|
561
|
-
The main-session stalled section is sent when the session's main output has been idle for at least `mainSilentThresholdSeconds
|
|
562
|
+
The main-session stalled section is sent when the session's main output has been idle for at least `mainSilentThresholdSeconds` and the session is not waiting on the owner. Idle time is computed from the timestamp of the latest `assistant` entry in the session's resolved transcript rather than from the transcript file modification time, so a transcript that is only updated by tool results or owner replies still counts as silent. 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 owner-aware behavior 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 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.
|
|
563
|
+
|
|
564
|
+
The owner-re-notification section replaces the old "suppress and stay silent" behavior for a session that is waiting on the owner. A session waiting on the owner must not be left silent indefinitely, because the owner is only notified when a fresh call-to-user is raised; a single past call-to-user that has gone quiet never reaches them. So when a session is waiting on the owner (an unanswered `ownerCallMarker` call) AND its silence has reached `mainSilentThresholdSeconds`, the monitor sends the owner-re-notification section instead of suppressing. That section instructs the agent to re-raise / re-emit its pending call-to-user now so the owner's call-to-user marker re-fires, and it explicitly states that the injected message is not the owner replying and must not be treated as an owner answer; it does not tell the agent it is stalled or idle, because the session is correctly waiting. Like the other sections it carries the `[TDPM_SILENT_SESSION_SELF_CHECK_REMINDER]` sentinel, so the re-notification itself is never miscounted as an owner reply. The per-session cooldown (`silentNotificationCooldownSeconds`, default 1800 seconds) limits the owner to being re-reminded at most about once every 30 minutes, and the re-notification stops automatically once the owner actually replies, because a genuine owner reply clears the unanswered-owner-call condition. Both this section and the main-session stalled section default to a generic built-in message and can be overridden with `silentOwnerReNotificationMessage` and `silentMainStalledMessage` respectively.
|
|
562
565
|
|
|
563
566
|
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`; the message lists each matched sub-process with its idle and running minutes. Sub-processes are discovered in one of two ways: when `subAgentTranscriptRootDirectory` is configured, each session's `subagents/agent-<id>.jsonl` transcripts are scanned, finished sub-agents (latest transcript entry `stop_reason` equal to `end_turn` or `stop_sequence`) are skipped, and idle time is taken from the transcript file modification time (following symlinks) while running time is taken from its first entry timestamp; otherwise sub-processes are discovered by matching `subAgentProcessMatchPattern` against process command lines.
|
|
564
567
|
|
|
565
|
-
A per-session cooldown (`silentNotificationCooldownSeconds`) prevents repeated notifications, persisted via the
|
|
568
|
+
A per-session cooldown (`silentNotificationCooldownSeconds`) prevents repeated notifications, persisted via the cache. Because the scheduled handler runs once per project but the silent-session monitor inspects the single global set of live tmux sessions, this cooldown is stored in a single project-independent cache scope (a fixed shared path rather than the per-project cache directory). This way the 30-minute cooldown is shared across every per-project pass and a session is notified at most once per cooldown window even when several projects are enabled; all other per-project caches are unaffected. 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. 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.
|
|
566
569
|
|
|
567
|
-
Each config key above has a matching environment variable read when the config key is unset: `TDPM_SILENT_NOTIFICATION_ENABLED` (the string `true` enables the step), `TDPM_SILENT_OWNER_CALL_MARKER`, `TDPM_SUBAGENT_OUTPUT_ROOT_DIRECTORY`, `TDPM_SUBAGENT_PROCESS_MATCH_PATTERN`, `TDPM_SUBAGENT_TRANSCRIPT_ROOT_DIRECTORY`, `TDPM_MAIN_SILENT_THRESHOLD_SECONDS`, `TDPM_SUBAGENT_SILENT_THRESHOLD_SECONDS`, `TDPM_SUBAGENT_RUNNING_THRESHOLD_SECONDS`, `TDPM_SILENT_NOTIFICATION_COOLDOWN_SECONDS`, `TDPM_SILENT_NOTIFICATION_STAGGER_SECONDS`, `TDPM_SILENT_MAIN_STALLED_MESSAGE`, `TDPM_SILENT_SUBAGENT_MESSAGE_HEADER`, and `TDPM_SILENT_SUBAGENT_MESSAGE_FOOTER`.
|
|
570
|
+
Each config key above has a matching environment variable read when the config key is unset: `TDPM_SILENT_NOTIFICATION_ENABLED` (the string `true` enables the step), `TDPM_SILENT_OWNER_CALL_MARKER`, `TDPM_SUBAGENT_OUTPUT_ROOT_DIRECTORY`, `TDPM_SUBAGENT_PROCESS_MATCH_PATTERN`, `TDPM_SUBAGENT_TRANSCRIPT_ROOT_DIRECTORY`, `TDPM_MAIN_SILENT_THRESHOLD_SECONDS`, `TDPM_SUBAGENT_SILENT_THRESHOLD_SECONDS`, `TDPM_SUBAGENT_RUNNING_THRESHOLD_SECONDS`, `TDPM_SILENT_NOTIFICATION_COOLDOWN_SECONDS`, `TDPM_SILENT_NOTIFICATION_STAGGER_SECONDS`, `TDPM_SILENT_MAIN_STALLED_MESSAGE`, `TDPM_SILENT_OWNER_RE_NOTIFICATION_MESSAGE`, `TDPM_SILENT_SUBAGENT_MESSAGE_HEADER`, and `TDPM_SILENT_SUBAGENT_MESSAGE_FOOTER`.
|
|
568
571
|
|
|
569
572
|
## Token Rotation Order File
|
|
570
573
|
|