github-issue-tower-defence-management 2.19.1 → 2.19.3

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 (795) hide show
  1. package/bin/adapter/entry-points/cli/index.js +1 -3
  2. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  3. package/bin/adapter/entry-points/console/consoleOperationApi.js +6 -12
  4. package/bin/adapter/entry-points/console/consoleOperationApi.js.map +1 -1
  5. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js +1 -1
  6. package/bin/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.js.map +1 -1
  7. package/bin/adapter/repositories/issue/RestIssueRepository.js +9 -2
  8. package/bin/adapter/repositories/issue/RestIssueRepository.js.map +1 -1
  9. package/package.json +5 -1
  10. package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
  11. package/types/adapter/entry-points/console/consoleOperationApi.d.ts.map +1 -1
  12. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts +1 -1
  13. package/types/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.d.ts.map +1 -1
  14. package/types/adapter/repositories/issue/RestIssueRepository.d.ts +5 -1
  15. package/types/adapter/repositories/issue/RestIssueRepository.d.ts.map +1 -1
  16. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts +1 -1
  17. package/types/domain/usecases/adapter-interfaces/IssueRepository.d.ts.map +1 -1
  18. package/.env.example +0 -7
  19. package/.gitattributes +0 -2
  20. package/.github/CODEOWNERS +0 -6
  21. package/.github/copilot-instructions.md +0 -6
  22. package/.github/dependabot.yml +0 -19
  23. package/.github/instructions/code-review.instructions.md +0 -50
  24. package/.github/workflows/api-created_issue_pr.yml +0 -97
  25. package/.github/workflows/ci-failure-issue-creator.yml +0 -48
  26. package/.github/workflows/close-manual-prs.yml +0 -80
  27. package/.github/workflows/codeql.yml +0 -107
  28. package/.github/workflows/commit-lint.yml +0 -85
  29. package/.github/workflows/configs/commitlint.config.cjs +0 -32
  30. package/.github/workflows/configs/commitlint.config.js +0 -32
  31. package/.github/workflows/console-ui.yml +0 -68
  32. package/.github/workflows/create-pr.yml +0 -116
  33. package/.github/workflows/empty-format-test-job.yml +0 -34
  34. package/.github/workflows/format.yml +0 -28
  35. package/.github/workflows/publish.yml +0 -111
  36. package/.github/workflows/secret-scan.yml +0 -51
  37. package/.github/workflows/test.yml +0 -58
  38. package/.github/workflows/umino-project.yml +0 -207
  39. package/.gitleaks.toml +0 -22
  40. package/.prettierignore +0 -31
  41. package/.prettierrc +0 -5
  42. package/CHANGELOG.md +0 -4162
  43. package/CONTRIBUTING.md +0 -60
  44. package/bin/adapter/entry-points/handlers/resolveUnansweredOwnerCalls.js +0 -12
  45. package/bin/adapter/entry-points/handlers/resolveUnansweredOwnerCalls.js.map +0 -1
  46. package/bin/adapter/repositories/FileSystemSilentSessionNotifiedStateRepository.js +0 -125
  47. package/bin/adapter/repositories/FileSystemSilentSessionNotifiedStateRepository.js.map +0 -1
  48. package/bin/adapter/repositories/issue/issueTimelineUtils.js +0 -38
  49. package/bin/adapter/repositories/issue/issueTimelineUtils.js.map +0 -1
  50. package/bin/domain/entities/UnansweredOwnerCall.js +0 -3
  51. package/bin/domain/entities/UnansweredOwnerCall.js.map +0 -1
  52. package/bin/domain/entities/WorkingTime.js +0 -3
  53. package/bin/domain/entities/WorkingTime.js.map +0 -1
  54. package/bin/domain/usecases/ChangeStatusLongInReviewIssueUseCase.js +0 -37
  55. package/bin/domain/usecases/ChangeStatusLongInReviewIssueUseCase.js.map +0 -1
  56. package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js +0 -118
  57. package/bin/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.js.map +0 -1
  58. package/bin/domain/usecases/GenerateWorkingTimeReportUseCase.js +0 -180
  59. package/bin/domain/usecases/GenerateWorkingTimeReportUseCase.js.map +0 -1
  60. package/bin/domain/usecases/TriagerApprovalDispatchUseCase.js +0 -160
  61. package/bin/domain/usecases/TriagerApprovalDispatchUseCase.js.map +0 -1
  62. package/bin/domain/usecases/adapter-interfaces/SilentSessionNotifiedStateRepository.js +0 -3
  63. package/bin/domain/usecases/adapter-interfaces/SilentSessionNotifiedStateRepository.js.map +0 -1
  64. package/bin/domain/usecases/awaitingOwnerApprovalMessage.js +0 -7
  65. package/bin/domain/usecases/awaitingOwnerApprovalMessage.js.map +0 -1
  66. package/bin/domain/usecases/findLastAgentDeclaringReport.js +0 -12
  67. package/bin/domain/usecases/findLastAgentDeclaringReport.js.map +0 -1
  68. package/bin/domain/usecases/isPullRequestDeclaredUnnecessary.js +0 -25
  69. package/bin/domain/usecases/isPullRequestDeclaredUnnecessary.js.map +0 -1
  70. package/bin/domain/usecases/isWaitingForOwnerApproval.js +0 -16
  71. package/bin/domain/usecases/isWaitingForOwnerApproval.js.map +0 -1
  72. package/bin/domain/usecases/returnedToAwaitingWorkspaceMessage.js +0 -7
  73. package/bin/domain/usecases/returnedToAwaitingWorkspaceMessage.js.map +0 -1
  74. package/commitlint.config.js +0 -6
  75. package/eslint.config.mjs +0 -76
  76. package/jest.config.js +0 -84
  77. package/jest.setup.js +0 -1
  78. package/lib/buffer-equal-constant-time-compat/index.js +0 -17
  79. package/lib/buffer-equal-constant-time-compat/index.test.js +0 -54
  80. package/lib/buffer-equal-constant-time-compat/package.json +0 -5
  81. package/lib/typescript-compat/bin/tsc +0 -2
  82. package/lib/typescript-compat/bin/tsserver +0 -2
  83. package/lib/typescript-compat/lib/typescript.js +0 -1
  84. package/lib/typescript-compat/package.json +0 -13
  85. package/renovate.json +0 -46
  86. package/scripts/copyConsoleUiDist.mjs +0 -35
  87. package/scripts/defaultBranchTipVerify.sh +0 -23
  88. package/scripts/testWorkflowRunVerify.sh +0 -47
  89. package/scripts/verifyConsoleUiDist.mjs +0 -96
  90. package/src/adapter/ci/consoleUiWorkflowTimeout.test.ts +0 -61
  91. package/src/adapter/ci/publishTestWorkflowGate.test.ts +0 -653
  92. package/src/adapter/ci/workflowRunCancellation.test.ts +0 -72
  93. package/src/adapter/entry-points/cli/fleetConfig.test.ts +0 -553
  94. package/src/adapter/entry-points/cli/fleetConfig.ts +0 -266
  95. package/src/adapter/entry-points/cli/index.test.ts +0 -2837
  96. package/src/adapter/entry-points/cli/index.ts +0 -1488
  97. package/src/adapter/entry-points/cli/projectConfig.test.ts +0 -342
  98. package/src/adapter/entry-points/cli/projectConfig.ts +0 -500
  99. package/src/adapter/entry-points/console/consoleAirplaneSnapshotApi.test.ts +0 -658
  100. package/src/adapter/entry-points/console/consoleAirplaneSnapshotApi.ts +0 -482
  101. package/src/adapter/entry-points/console/consoleDataDelivery.test.ts +0 -222
  102. package/src/adapter/entry-points/console/consoleDataDelivery.ts +0 -134
  103. package/src/adapter/entry-points/console/consoleDoneStore.test.ts +0 -169
  104. package/src/adapter/entry-points/console/consoleDoneStore.ts +0 -139
  105. package/src/adapter/entry-points/console/consoleGithubTokenResolver.test.ts +0 -275
  106. package/src/adapter/entry-points/console/consoleGithubTokenResolver.ts +0 -113
  107. package/src/adapter/entry-points/console/consoleImageProxy.test.ts +0 -140
  108. package/src/adapter/entry-points/console/consoleImageProxy.ts +0 -111
  109. package/src/adapter/entry-points/console/consoleItemUrlLookup.test.ts +0 -63
  110. package/src/adapter/entry-points/console/consoleItemUrlLookup.ts +0 -66
  111. package/src/adapter/entry-points/console/consoleOperationApi.test.ts +0 -2523
  112. package/src/adapter/entry-points/console/consoleOperationApi.ts +0 -936
  113. package/src/adapter/entry-points/console/consoleProjectResolver.test.ts +0 -246
  114. package/src/adapter/entry-points/console/consoleProjectResolver.ts +0 -111
  115. package/src/adapter/entry-points/console/consoleReadApi.test.ts +0 -714
  116. package/src/adapter/entry-points/console/consoleReadApi.ts +0 -361
  117. package/src/adapter/entry-points/console/consoleTabNames.test.ts +0 -52
  118. package/src/adapter/entry-points/console/consoleTabNames.ts +0 -37
  119. package/src/adapter/entry-points/console/consoleUiDistSync.test.ts +0 -66
  120. package/src/adapter/entry-points/console/dashboardComposeService.test.ts +0 -595
  121. package/src/adapter/entry-points/console/dashboardComposeService.ts +0 -256
  122. package/src/adapter/entry-points/console/dashboardEmitterComposerKey.test.ts +0 -180
  123. package/src/adapter/entry-points/console/ensureConsoleRunning.test.ts +0 -115
  124. package/src/adapter/entry-points/console/ensureConsoleRunning.ts +0 -64
  125. package/src/adapter/entry-points/console/ui/.storybook/main.ts +0 -12
  126. package/src/adapter/entry-points/console/ui/.storybook/preview.ts +0 -15
  127. package/src/adapter/entry-points/console/ui/biome.json +0 -53
  128. package/src/adapter/entry-points/console/ui/components.json +0 -20
  129. package/src/adapter/entry-points/console/ui/e2e/consoleScenario.spec.ts +0 -725
  130. package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +0 -831
  131. package/src/adapter/entry-points/console/ui/e2e/playwright.config.ts +0 -30
  132. package/src/adapter/entry-points/console/ui/e2e/tsconfig.json +0 -18
  133. package/src/adapter/entry-points/console/ui/index.html +0 -12
  134. package/src/adapter/entry-points/console/ui/jest-globals.cjs +0 -26
  135. package/src/adapter/entry-points/console/ui/jest.setup.ts +0 -1
  136. package/src/adapter/entry-points/console/ui/jest.styleMock.js +0 -1
  137. package/src/adapter/entry-points/console/ui/public/sw.js +0 -60
  138. package/src/adapter/entry-points/console/ui/src/components/ui/badge.stories.tsx +0 -35
  139. package/src/adapter/entry-points/console/ui/src/components/ui/badge.tsx +0 -28
  140. package/src/adapter/entry-points/console/ui/src/components/ui/button.stories.tsx +0 -34
  141. package/src/adapter/entry-points/console/ui/src/components/ui/button.tsx +0 -50
  142. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleCopyCodeButton.stories.tsx +0 -28
  143. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleCopyCodeButton.test.tsx +0 -65
  144. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleCopyCodeButton.tsx +0 -19
  145. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.stories.tsx +0 -61
  146. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.test.tsx +0 -199
  147. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.tsx +0 -166
  148. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMermaidDiagram.stories.tsx +0 -22
  149. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMermaidDiagram.test.tsx +0 -74
  150. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMermaidDiagram.tsx +0 -84
  151. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMermaidDiagramModalScreen.stories.tsx +0 -27
  152. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMermaidDiagramModalScreen.test.tsx +0 -85
  153. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMermaidDiagramModalScreen.tsx +0 -97
  154. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleReferenceLink.stories.tsx +0 -76
  155. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleReferenceLink.test.tsx +0 -56
  156. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleReferenceLink.tsx +0 -39
  157. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleChangedFileList.stories.tsx +0 -32
  158. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleChangedFileList.test.tsx +0 -105
  159. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleChangedFileList.tsx +0 -157
  160. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentComposer.stories.tsx +0 -68
  161. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentComposer.test.tsx +0 -612
  162. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentComposer.tsx +0 -276
  163. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentList.stories.tsx +0 -33
  164. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentList.test.tsx +0 -57
  165. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommentList.tsx +0 -76
  166. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommitList.stories.tsx +0 -25
  167. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommitList.test.tsx +0 -55
  168. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCommitList.tsx +0 -49
  169. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCopyUrlButton.stories.tsx +0 -24
  170. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCopyUrlButton.test.tsx +0 -63
  171. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleCopyUrlButton.tsx +0 -19
  172. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleFetchFailureAlert.stories.tsx +0 -33
  173. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleFetchFailureAlert.test.tsx +0 -62
  174. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleFetchFailureAlert.tsx +0 -59
  175. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleFileDiff.stories.tsx +0 -38
  176. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleFileDiff.test.tsx +0 -151
  177. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleFileDiff.tsx +0 -245
  178. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.stories.tsx +0 -514
  179. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.test.tsx +0 -727
  180. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemDetail.tsx +0 -387
  181. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemIcon.stories.tsx +0 -82
  182. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemIcon.test.tsx +0 -52
  183. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsoleItemIcon.tsx +0 -32
  184. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestDetail.stories.tsx +0 -48
  185. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestDetail.test.tsx +0 -235
  186. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestDetail.tsx +0 -145
  187. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestMergeableChip.stories.tsx +0 -29
  188. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestMergeableChip.test.tsx +0 -30
  189. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestMergeableChip.tsx +0 -50
  190. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestStatusBadges.stories.tsx +0 -38
  191. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestStatusBadges.test.tsx +0 -54
  192. package/src/adapter/entry-points/console/ui/src/features/console/components/detail/ConsolePullRequestStatusBadges.tsx +0 -60
  193. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleAirplaneModeButton.stories.tsx +0 -56
  194. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleAirplaneModeButton.test.tsx +0 -111
  195. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleAirplaneModeButton.tsx +0 -92
  196. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsolePanel.stories.tsx +0 -51
  197. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsolePanel.test.tsx +0 -59
  198. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsolePanel.tsx +0 -39
  199. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTabList.stories.tsx +0 -207
  200. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTabList.test.tsx +0 -332
  201. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTabList.tsx +0 -211
  202. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTimerSettingsModalDialog.stories.tsx +0 -49
  203. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTimerSettingsModalDialog.test.tsx +0 -157
  204. package/src/adapter/entry-points/console/ui/src/features/console/components/layout/ConsoleTimerSettingsModalDialog.tsx +0 -118
  205. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleCopyStoryNameButton.stories.tsx +0 -23
  206. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleCopyStoryNameButton.test.tsx +0 -40
  207. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleCopyStoryNameButton.tsx +0 -17
  208. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemList.stories.tsx +0 -101
  209. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemList.test.tsx +0 -102
  210. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemList.tsx +0 -75
  211. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemSummary.stories.tsx +0 -40
  212. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemSummary.test.tsx +0 -213
  213. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleItemSummary.tsx +0 -115
  214. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleQueuedItemRow.stories.tsx +0 -50
  215. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleQueuedItemRow.test.tsx +0 -98
  216. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleQueuedItemRow.tsx +0 -66
  217. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleQueuedList.stories.tsx +0 -69
  218. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleQueuedList.test.tsx +0 -101
  219. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleQueuedList.tsx +0 -75
  220. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryList.stories.tsx +0 -137
  221. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryList.test.tsx +0 -554
  222. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryList.tsx +0 -400
  223. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryReorderPanel.stories.tsx +0 -30
  224. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryReorderPanel.test.tsx +0 -111
  225. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryReorderPanel.tsx +0 -91
  226. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStorySummary.stories.tsx +0 -27
  227. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStorySummary.test.tsx +0 -24
  228. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStorySummary.tsx +0 -28
  229. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleCloseActions.stories.tsx +0 -14
  230. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleCloseActions.test.tsx +0 -21
  231. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleCloseActions.tsx +0 -26
  232. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleDangerousActions.stories.tsx +0 -14
  233. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleDangerousActions.test.tsx +0 -40
  234. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleDangerousActions.tsx +0 -37
  235. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleErrorToast.stories.tsx +0 -33
  236. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleNextActionDateActions.stories.tsx +0 -20
  237. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleNextActionDateActions.test.tsx +0 -48
  238. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleNextActionDateActions.tsx +0 -42
  239. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOfflinePendingActionsPanel.stories.tsx +0 -115
  240. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOfflinePendingActionsPanel.test.tsx +0 -262
  241. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOfflinePendingActionsPanel.tsx +0 -123
  242. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOperationMenu.stories.tsx +0 -65
  243. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOperationMenu.test.tsx +0 -159
  244. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleOperationMenu.tsx +0 -55
  245. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsolePullRequestReviewActions.stories.tsx +0 -20
  246. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsolePullRequestReviewActions.test.tsx +0 -93
  247. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsolePullRequestReviewActions.tsx +0 -45
  248. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleStatusActions.stories.tsx +0 -17
  249. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleStatusActions.test.tsx +0 -49
  250. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleStatusActions.tsx +0 -66
  251. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleUndoToast.stories.tsx +0 -47
  252. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleUndoToast.test.tsx +0 -95
  253. package/src/adapter/entry-points/console/ui/src/features/console/components/operations/ConsoleUndoToast.tsx +0 -62
  254. package/src/adapter/entry-points/console/ui/src/features/console/components/shared/ConsoleClipboardCopyButton.stories.tsx +0 -32
  255. package/src/adapter/entry-points/console/ui/src/features/console/components/shared/ConsoleClipboardCopyButton.test.tsx +0 -101
  256. package/src/adapter/entry-points/console/ui/src/features/console/components/shared/ConsoleClipboardCopyButton.tsx +0 -80
  257. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useAirplaneMode.test.ts +0 -304
  258. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useAirplaneMode.ts +0 -167
  259. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleActionQueue.test.ts +0 -498
  260. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleActionQueue.ts +0 -277
  261. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleCaches.test.ts +0 -99
  262. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleCaches.ts +0 -90
  263. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleDetailPrefetch.test.ts +0 -110
  264. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleDetailPrefetch.ts +0 -83
  265. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleFeaturesConfig.test.ts +0 -51
  266. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleFeaturesConfig.ts +0 -39
  267. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleItemDetailData.test.ts +0 -229
  268. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleItemDetailData.ts +0 -194
  269. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleNavigation.test.ts +0 -151
  270. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleNavigation.ts +0 -128
  271. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOperations.test.ts +0 -629
  272. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOperations.ts +0 -417
  273. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOverlay.test.ts +0 -40
  274. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOverlay.ts +0 -71
  275. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsolePjcode.test.ts +0 -24
  276. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsolePjcode.ts +0 -17
  277. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleProjectList.test.ts +0 -97
  278. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleProjectList.ts +0 -44
  279. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleProjectTimer.test.ts +0 -59
  280. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleProjectTimer.ts +0 -26
  281. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleReferenceLink.test.ts +0 -48
  282. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleReferenceLink.ts +0 -39
  283. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleResource.test.ts +0 -41
  284. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleResource.ts +0 -57
  285. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleSwipeNavigation.test.ts +0 -115
  286. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleSwipeNavigation.ts +0 -115
  287. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.test.ts +0 -546
  288. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.ts +0 -278
  289. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTimerSettings.test.ts +0 -110
  290. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTimerSettings.ts +0 -70
  291. package/src/adapter/entry-points/console/ui/src/features/console/lib/airplaneSnapshot.test.ts +0 -387
  292. package/src/adapter/entry-points/console/ui/src/features/console/lib/airplaneSnapshot.ts +0 -407
  293. package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.test.ts +0 -446
  294. package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.ts +0 -533
  295. package/src/adapter/entry-points/console/ui/src/features/console/lib/imageProxy.test.ts +0 -78
  296. package/src/adapter/entry-points/console/ui/src/features/console/lib/imageProxy.ts +0 -34
  297. package/src/adapter/entry-points/console/ui/src/features/console/lib/markdown.test.ts +0 -252
  298. package/src/adapter/entry-points/console/ui/src/features/console/lib/markdown.ts +0 -207
  299. package/src/adapter/entry-points/console/ui/src/features/console/lib/mermaidLoader.test.ts +0 -27
  300. package/src/adapter/entry-points/console/ui/src/features/console/lib/mermaidLoader.ts +0 -71
  301. package/src/adapter/entry-points/console/ui/src/features/console/lib/mermaidZoom.test.ts +0 -88
  302. package/src/adapter/entry-points/console/ui/src/features/console/lib/mermaidZoom.ts +0 -34
  303. package/src/adapter/entry-points/console/ui/src/features/console/lib/navigation.ts +0 -7
  304. package/src/adapter/entry-points/console/ui/src/features/console/lib/resourceCache.test.ts +0 -104
  305. package/src/adapter/entry-points/console/ui/src/features/console/lib/resourceCache.ts +0 -79
  306. package/src/adapter/entry-points/console/ui/src/features/console/logic/actionToast.test.ts +0 -200
  307. package/src/adapter/entry-points/console/ui/src/features/console/logic/actionToast.ts +0 -122
  308. package/src/adapter/entry-points/console/ui/src/features/console/logic/clipboard.test.ts +0 -90
  309. package/src/adapter/entry-points/console/ui/src/features/console/logic/clipboard.ts +0 -37
  310. package/src/adapter/entry-points/console/ui/src/features/console/logic/colors.test.ts +0 -34
  311. package/src/adapter/entry-points/console/ui/src/features/console/logic/colors.ts +0 -85
  312. package/src/adapter/entry-points/console/ui/src/features/console/logic/diff.test.ts +0 -81
  313. package/src/adapter/entry-points/console/ui/src/features/console/logic/diff.ts +0 -61
  314. package/src/adapter/entry-points/console/ui/src/features/console/logic/fileStatus.test.ts +0 -35
  315. package/src/adapter/entry-points/console/ui/src/features/console/logic/fileStatus.ts +0 -21
  316. package/src/adapter/entry-points/console/ui/src/features/console/logic/fileTree.test.ts +0 -96
  317. package/src/adapter/entry-points/console/ui/src/features/console/logic/fileTree.ts +0 -93
  318. package/src/adapter/entry-points/console/ui/src/features/console/logic/grouping.test.ts +0 -229
  319. package/src/adapter/entry-points/console/ui/src/features/console/logic/grouping.ts +0 -106
  320. package/src/adapter/entry-points/console/ui/src/features/console/logic/imageFile.test.ts +0 -18
  321. package/src/adapter/entry-points/console/ui/src/features/console/logic/imageFile.ts +0 -16
  322. package/src/adapter/entry-points/console/ui/src/features/console/logic/itemIcons.test.ts +0 -97
  323. package/src/adapter/entry-points/console/ui/src/features/console/logic/itemIcons.ts +0 -95
  324. package/src/adapter/entry-points/console/ui/src/features/console/logic/navigation.test.ts +0 -53
  325. package/src/adapter/entry-points/console/ui/src/features/console/logic/navigation.ts +0 -33
  326. package/src/adapter/entry-points/console/ui/src/features/console/logic/operations.test.ts +0 -72
  327. package/src/adapter/entry-points/console/ui/src/features/console/logic/operations.ts +0 -61
  328. package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.test.ts +0 -325
  329. package/src/adapter/entry-points/console/ui/src/features/console/logic/overlay.ts +0 -94
  330. package/src/adapter/entry-points/console/ui/src/features/console/logic/postedComments.test.ts +0 -44
  331. package/src/adapter/entry-points/console/ui/src/features/console/logic/postedComments.ts +0 -17
  332. package/src/adapter/entry-points/console/ui/src/features/console/logic/references.test.ts +0 -103
  333. package/src/adapter/entry-points/console/ui/src/features/console/logic/references.ts +0 -64
  334. package/src/adapter/entry-points/console/ui/src/features/console/logic/relativeTime.test.ts +0 -74
  335. package/src/adapter/entry-points/console/ui/src/features/console/logic/relativeTime.ts +0 -53
  336. package/src/adapter/entry-points/console/ui/src/features/console/logic/swipe.test.ts +0 -34
  337. package/src/adapter/entry-points/console/ui/src/features/console/logic/swipe.ts +0 -28
  338. package/src/adapter/entry-points/console/ui/src/features/console/logic/tabAdvance.test.ts +0 -89
  339. package/src/adapter/entry-points/console/ui/src/features/console/logic/tabAdvance.ts +0 -30
  340. package/src/adapter/entry-points/console/ui/src/features/console/logic/timerSettings.test.ts +0 -61
  341. package/src/adapter/entry-points/console/ui/src/features/console/logic/timerSettings.ts +0 -77
  342. package/src/adapter/entry-points/console/ui/src/features/console/logic/types.ts +0 -173
  343. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.test.tsx +0 -629
  344. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.tsx +0 -351
  345. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.test.tsx +0 -1469
  346. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsolePage.tsx +0 -736
  347. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleReferenceLinkContainer.tsx +0 -25
  348. package/src/adapter/entry-points/console/ui/src/features/console/testing/fixtures.ts +0 -418
  349. package/src/adapter/entry-points/console/ui/src/index.css +0 -1592
  350. package/src/adapter/entry-points/console/ui/src/lib/utils.ts +0 -4
  351. package/src/adapter/entry-points/console/ui/src/main.tsx +0 -21
  352. package/src/adapter/entry-points/console/ui/src/vite-env.d.ts +0 -1
  353. package/src/adapter/entry-points/console/ui/tsconfig.json +0 -26
  354. package/src/adapter/entry-points/console/ui/vite.config.ts +0 -24
  355. package/src/adapter/entry-points/console/ui-dist/assets/index-BYDbK1Fj.js +0 -88
  356. package/src/adapter/entry-points/console/ui-dist/assets/index-KyQISRuQ.css +0 -2
  357. package/src/adapter/entry-points/console/ui-dist/index.html +0 -13
  358. package/src/adapter/entry-points/console/ui-dist/sw.js +0 -60
  359. package/src/adapter/entry-points/console/webServer.test.ts +0 -2945
  360. package/src/adapter/entry-points/console/webServer.ts +0 -940
  361. package/src/adapter/entry-points/function/getStoryObjectMap.ts +0 -3
  362. package/src/adapter/entry-points/handlers/FileSystemConsoleTabsRepository.test.ts +0 -218
  363. package/src/adapter/entry-points/handlers/FileSystemConsoleTabsRepository.ts +0 -113
  364. package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.test.ts +0 -110
  365. package/src/adapter/entry-points/handlers/GetStoryObjectMapUseCaseHandler.ts +0 -116
  366. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.test.ts +0 -859
  367. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +0 -984
  368. package/src/adapter/entry-points/handlers/InTmuxByHumanSessionTokenCountHandler.test.ts +0 -126
  369. package/src/adapter/entry-points/handlers/InTmuxByHumanSessionTokenCountHandler.ts +0 -80
  370. package/src/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.test.ts +0 -491
  371. package/src/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.ts +0 -137
  372. package/src/adapter/entry-points/handlers/OauthTokenSelectHandler.test.ts +0 -508
  373. package/src/adapter/entry-points/handlers/OauthTokenSelectHandler.ts +0 -156
  374. package/src/adapter/entry-points/handlers/consoleListsWriter.test.ts +0 -332
  375. package/src/adapter/entry-points/handlers/consoleListsWriter.ts +0 -60
  376. package/src/adapter/entry-points/handlers/dashboardRowWriter.test.ts +0 -112
  377. package/src/adapter/entry-points/handlers/dashboardRowWriter.ts +0 -51
  378. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.test.ts +0 -285
  379. package/src/adapter/entry-points/handlers/inTmuxByHumanDataWriter.ts +0 -109
  380. package/src/adapter/entry-points/handlers/inTmuxByHumanSessionReconciler.test.ts +0 -170
  381. package/src/adapter/entry-points/handlers/inTmuxByHumanSessionReconciler.ts +0 -40
  382. package/src/adapter/entry-points/handlers/machineStatusWriter.test.ts +0 -191
  383. package/src/adapter/entry-points/handlers/machineStatusWriter.ts +0 -110
  384. package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.test.ts +0 -548
  385. package/src/adapter/entry-points/handlers/notifySilentTmuxSessions.ts +0 -192
  386. package/src/adapter/entry-points/handlers/ownerCallFileCleaner.test.ts +0 -111
  387. package/src/adapter/entry-points/handlers/ownerCallFileCleaner.ts +0 -25
  388. package/src/adapter/entry-points/handlers/ownerCallFileStore.test.ts +0 -286
  389. package/src/adapter/entry-points/handlers/ownerCallFileStore.ts +0 -145
  390. package/src/adapter/entry-points/handlers/ownerReplyMarkerDirectoryResolve.test.ts +0 -55
  391. package/src/adapter/entry-points/handlers/ownerReplyMarkerDirectoryResolve.ts +0 -36
  392. package/src/adapter/entry-points/handlers/resetDegeneratedTmuxSessions.test.ts +0 -72
  393. package/src/adapter/entry-points/handlers/resetDegeneratedTmuxSessions.ts +0 -74
  394. package/src/adapter/entry-points/handlers/rotationOrderFileWriter.test.ts +0 -181
  395. package/src/adapter/entry-points/handlers/rotationOrderFileWriter.ts +0 -18
  396. package/src/adapter/entry-points/handlers/situationFileWriter.test.ts +0 -489
  397. package/src/adapter/entry-points/handlers/situationFileWriter.ts +0 -176
  398. package/src/adapter/entry-points/handlers/staleTmuxSessionCleaner.test.ts +0 -169
  399. package/src/adapter/entry-points/handlers/staleTmuxSessionCleaner.ts +0 -32
  400. package/src/adapter/entry-points/handlers/subscriptionDisabledTokenHandler.ts +0 -41
  401. package/src/adapter/entry-points/handlers/tokenExhaustionHandover.ts +0 -81
  402. package/src/adapter/entry-points/handlers/tokenStatusWriter.test.ts +0 -266
  403. package/src/adapter/entry-points/handlers/tokenStatusWriter.ts +0 -262
  404. package/src/adapter/proxy/ClaudeMessageResponseParser.test.ts +0 -211
  405. package/src/adapter/proxy/ClaudeMessageResponseParser.ts +0 -181
  406. package/src/adapter/proxy/RateLimitCache.test.ts +0 -1077
  407. package/src/adapter/proxy/RateLimitCache.ts +0 -385
  408. package/src/adapter/proxy/TokenListLoader.test.ts +0 -183
  409. package/src/adapter/proxy/TokenListLoader.ts +0 -75
  410. package/src/adapter/proxy/ensureProxyRunning.test.ts +0 -85
  411. package/src/adapter/proxy/ensureProxyRunning.ts +0 -41
  412. package/src/adapter/proxy/proxyEntry.test.ts +0 -552
  413. package/src/adapter/proxy/proxyEntry.ts +0 -214
  414. package/src/adapter/repositories/BaseGitHubRepository.test.ts +0 -26
  415. package/src/adapter/repositories/BaseGitHubRepository.ts +0 -26
  416. package/src/adapter/repositories/BrowserGitHubProjectRepository.test.ts +0 -108
  417. package/src/adapter/repositories/BrowserGitHubProjectRepository.ts +0 -118
  418. package/src/adapter/repositories/CliGitHubGraphqlRateLimitRepository.test.ts +0 -71
  419. package/src/adapter/repositories/CliGitHubGraphqlRateLimitRepository.ts +0 -21
  420. package/src/adapter/repositories/ConfigurableSilentSessionMessageComposer.test.ts +0 -324
  421. package/src/adapter/repositories/ConfigurableSilentSessionMessageComposer.ts +0 -148
  422. package/src/adapter/repositories/FetchWebhookRepository.ts +0 -8
  423. package/src/adapter/repositories/FileHandoverStateRepository.test.ts +0 -114
  424. package/src/adapter/repositories/FileHandoverStateRepository.ts +0 -73
  425. package/src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.test.ts +0 -514
  426. package/src/adapter/repositories/FileSystemInteractiveLiveSessionTranscriptResolver.ts +0 -109
  427. package/src/adapter/repositories/FileSystemKevReportWatermarkRepository.test.ts +0 -284
  428. package/src/adapter/repositories/FileSystemKevReportWatermarkRepository.ts +0 -128
  429. package/src/adapter/repositories/FileSystemSessionAssistantTurnsRepository.test.ts +0 -138
  430. package/src/adapter/repositories/FileSystemSessionAssistantTurnsRepository.ts +0 -113
  431. package/src/adapter/repositories/FileSystemSessionDegenerationCooldownStateRepository.test.ts +0 -121
  432. package/src/adapter/repositories/FileSystemSessionDegenerationCooldownStateRepository.ts +0 -103
  433. package/src/adapter/repositories/FileSystemSessionOutputActivityRepository.test.ts +0 -360
  434. package/src/adapter/repositories/FileSystemSessionOutputActivityRepository.ts +0 -77
  435. package/src/adapter/repositories/FileSystemSessionRecordReader.test.ts +0 -59
  436. package/src/adapter/repositories/FileSystemSessionRecordReader.ts +0 -31
  437. package/src/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.test.ts +0 -287
  438. package/src/adapter/repositories/FileSystemSilentSessionCandidateStateRepository.ts +0 -125
  439. package/src/adapter/repositories/FileSystemSilentSessionHubTaskStatusCacheRepository.test.ts +0 -285
  440. package/src/adapter/repositories/FileSystemSilentSessionHubTaskStatusCacheRepository.ts +0 -119
  441. package/src/adapter/repositories/FileSystemSubAgentLivenessResolver.test.ts +0 -237
  442. package/src/adapter/repositories/FileSystemSubAgentLivenessResolver.ts +0 -57
  443. package/src/adapter/repositories/FileSystemSubAgentSilentSecondsResolver.test.ts +0 -56
  444. package/src/adapter/repositories/FileSystemSubAgentSilentSecondsResolver.ts +0 -32
  445. package/src/adapter/repositories/FileSystemSubAgentTranscriptDirectoryResolver.test.ts +0 -68
  446. package/src/adapter/repositories/FileSystemSubAgentTranscriptDirectoryResolver.ts +0 -23
  447. package/src/adapter/repositories/GitHubIssueCheckpointRepository.test.ts +0 -51
  448. package/src/adapter/repositories/GitHubIssueCheckpointRepository.ts +0 -47
  449. package/src/adapter/repositories/GitHubIssueCommentRepository.test.ts +0 -278
  450. package/src/adapter/repositories/GitHubIssueCommentRepository.ts +0 -109
  451. package/src/adapter/repositories/GoogleSpreadsheetRepository.integration.test.ts +0 -265
  452. package/src/adapter/repositories/GoogleSpreadsheetRepository.test.ts +0 -431
  453. package/src/adapter/repositories/GoogleSpreadsheetRepository.ts +0 -268
  454. package/src/adapter/repositories/GraphqlProjectRepository.diskCache.test.ts +0 -272
  455. package/src/adapter/repositories/GraphqlProjectRepository.errorHandling.test.ts +0 -111
  456. package/src/adapter/repositories/GraphqlProjectRepository.fetchProjectId.test.ts +0 -254
  457. package/src/adapter/repositories/GraphqlProjectRepository.test.ts +0 -209
  458. package/src/adapter/repositories/GraphqlProjectRepository.ts +0 -707
  459. package/src/adapter/repositories/GraphqlProjectRepositoryProjectLocation.test.ts +0 -297
  460. package/src/adapter/repositories/KyHttpRepository.ts +0 -8
  461. package/src/adapter/repositories/KySlackRepository.test.ts +0 -172
  462. package/src/adapter/repositories/KySlackRepository.ts +0 -298
  463. package/src/adapter/repositories/LocalCommandIssueAttachmentRepository.test.ts +0 -193
  464. package/src/adapter/repositories/LocalCommandIssueAttachmentRepository.ts +0 -106
  465. package/src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.test.ts +0 -190
  466. package/src/adapter/repositories/LocalProcessLiveSessionProcessSnapshotProvider.ts +0 -102
  467. package/src/adapter/repositories/LocalStorageCacheRepository.test.ts +0 -265
  468. package/src/adapter/repositories/LocalStorageCacheRepository.ts +0 -79
  469. package/src/adapter/repositories/LocalStorageRepository.integration.test.ts +0 -142
  470. package/src/adapter/repositories/LocalStorageRepository.test.ts +0 -173
  471. package/src/adapter/repositories/LocalStorageRepository.ts +0 -30
  472. package/src/adapter/repositories/NoUnansweredOwnerCallStatusProvider.test.ts +0 -15
  473. package/src/adapter/repositories/NoUnansweredOwnerCallStatusProvider.ts +0 -9
  474. package/src/adapter/repositories/NodeLocalCommandRunner.largeOutput.test.ts +0 -16
  475. package/src/adapter/repositories/NodeLocalCommandRunner.test.ts +0 -118
  476. package/src/adapter/repositories/NodeLocalCommandRunner.ts +0 -66
  477. package/src/adapter/repositories/NodeProcessSignalRepository.test.ts +0 -82
  478. package/src/adapter/repositories/NodeProcessSignalRepository.ts +0 -47
  479. package/src/adapter/repositories/NodeSubAgentProcessLister.test.ts +0 -44
  480. package/src/adapter/repositories/NodeSubAgentProcessLister.ts +0 -40
  481. package/src/adapter/repositories/NodeTmuxSessionRepository.test.ts +0 -546
  482. package/src/adapter/repositories/NodeTmuxSessionRepository.ts +0 -245
  483. package/src/adapter/repositories/OauthAPIClaudeRepository.ts +0 -279
  484. package/src/adapter/repositories/OauthAPIProxyClaudeRepository.test.ts +0 -166
  485. package/src/adapter/repositories/OauthAPIProxyClaudeRepository.ts +0 -32
  486. package/src/adapter/repositories/OauthProxyClaudeRepository.test.ts +0 -428
  487. package/src/adapter/repositories/OauthProxyClaudeRepository.ts +0 -124
  488. package/src/adapter/repositories/ProcClaudeHandoverSessionRepository.test.ts +0 -242
  489. package/src/adapter/repositories/ProcClaudeHandoverSessionRepository.ts +0 -261
  490. package/src/adapter/repositories/ProcClaudeInteractiveSessionRepository.test.ts +0 -184
  491. package/src/adapter/repositories/ProcClaudeInteractiveSessionRepository.ts +0 -138
  492. package/src/adapter/repositories/ProcClaudeLiveSessionRepository.test.ts +0 -208
  493. package/src/adapter/repositories/ProcClaudeLiveSessionRepository.ts +0 -130
  494. package/src/adapter/repositories/ProcFsProcessEnvironReader.test.ts +0 -60
  495. package/src/adapter/repositories/ProcFsProcessEnvironReader.ts +0 -38
  496. package/src/adapter/repositories/ProcHostMetricsRepository.test.ts +0 -207
  497. package/src/adapter/repositories/ProcHostMetricsRepository.ts +0 -181
  498. package/src/adapter/repositories/ProcTakeOwnershipSpawnRepository.test.ts +0 -231
  499. package/src/adapter/repositories/ProcTakeOwnershipSpawnRepository.ts +0 -134
  500. package/src/adapter/repositories/ProcessListSessionSubAgentActivityRepository.test.ts +0 -121
  501. package/src/adapter/repositories/ProcessListSessionSubAgentActivityRepository.ts +0 -58
  502. package/src/adapter/repositories/ProjectIssuesCacheRepository.test.ts +0 -218
  503. package/src/adapter/repositories/ProjectIssuesCacheRepository.ts +0 -141
  504. package/src/adapter/repositories/ProxyClaudeTokenUsageRepository.test.ts +0 -1195
  505. package/src/adapter/repositories/ProxyClaudeTokenUsageRepository.ts +0 -185
  506. package/src/adapter/repositories/ProxyRateLimitCacheRepository.test.ts +0 -116
  507. package/src/adapter/repositories/ProxyRateLimitCacheRepository.ts +0 -67
  508. package/src/adapter/repositories/RateLimitSnapshotRepository.ts +0 -50
  509. package/src/adapter/repositories/RealSleeper.test.ts +0 -19
  510. package/src/adapter/repositories/RealSleeper.ts +0 -12
  511. package/src/adapter/repositories/RestProjectRepository.test.ts +0 -277
  512. package/src/adapter/repositories/RestProjectRepository.ts +0 -129
  513. package/src/adapter/repositories/SqliteClaudeMessageResponseRepository.test.ts +0 -313
  514. package/src/adapter/repositories/SqliteClaudeMessageResponseRepository.ts +0 -164
  515. package/src/adapter/repositories/SystemDateRepository.test.ts +0 -60
  516. package/src/adapter/repositories/SystemDateRepository.ts +0 -34
  517. package/src/adapter/repositories/TmuxSilentSessionNotificationRepository.test.ts +0 -253
  518. package/src/adapter/repositories/TmuxSilentSessionNotificationRepository.ts +0 -158
  519. package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.queuedReply.test.ts +0 -171
  520. package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.singleScan.test.ts +0 -86
  521. package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.test.ts +0 -996
  522. package/src/adapter/repositories/TranscriptOwnerCallStatusProvider.ts +0 -396
  523. package/src/adapter/repositories/TranscriptRefusalTailStatusProvider.test.ts +0 -208
  524. package/src/adapter/repositories/TranscriptRefusalTailStatusProvider.ts +0 -80
  525. package/src/adapter/repositories/TranscriptSessionSubAgentActivityRepository.test.ts +0 -1674
  526. package/src/adapter/repositories/TranscriptSessionSubAgentActivityRepository.ts +0 -459
  527. package/src/adapter/repositories/clSessionScopeUnitName.test.ts +0 -76
  528. package/src/adapter/repositories/clSessionScopeUnitName.ts +0 -5
  529. package/src/adapter/repositories/clSessionScopeUnitNameFromCgroupContent.test.ts +0 -34
  530. package/src/adapter/repositories/clSessionScopeUnitNameFromCgroupContent.ts +0 -8
  531. package/src/adapter/repositories/githubGraphqlClient.test.ts +0 -479
  532. package/src/adapter/repositories/githubGraphqlClient.ts +0 -243
  533. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.test.ts +0 -5182
  534. package/src/adapter/repositories/issue/ApiV3CheerioRestIssueRepository.ts +0 -3303
  535. package/src/adapter/repositories/issue/ApiV3IssueRepository.test.ts +0 -46
  536. package/src/adapter/repositories/issue/ApiV3IssueRepository.ts +0 -88
  537. package/src/adapter/repositories/issue/GraphqlProjectItemRepository.test.ts +0 -1776
  538. package/src/adapter/repositories/issue/GraphqlProjectItemRepository.ts +0 -1552
  539. package/src/adapter/repositories/issue/RestIssueRepository.test.ts +0 -393
  540. package/src/adapter/repositories/issue/RestIssueRepository.ts +0 -252
  541. package/src/adapter/repositories/issue/gitHubRawUrl.test.ts +0 -29
  542. package/src/adapter/repositories/issue/gitHubRawUrl.ts +0 -30
  543. package/src/adapter/repositories/issue/githubRateLimitRetry.test.ts +0 -167
  544. package/src/adapter/repositories/issue/githubRateLimitRetry.ts +0 -109
  545. package/src/adapter/repositories/localStorageCacheDirectory.test.ts +0 -81
  546. package/src/adapter/repositories/localStorageCacheDirectory.ts +0 -13
  547. package/src/adapter/repositories/projectFieldDefinition.test.ts +0 -191
  548. package/src/adapter/repositories/projectFieldDefinition.ts +0 -144
  549. package/src/adapter/repositories/utils.test.ts +0 -55
  550. package/src/adapter/repositories/utils.ts +0 -45
  551. package/src/domain/entities/ClaudeHandoverSession.ts +0 -12
  552. package/src/domain/entities/ClaudeMessageResponse.ts +0 -31
  553. package/src/domain/entities/ClaudeTokenUsage.ts +0 -17
  554. package/src/domain/entities/ClaudeWindowUsage.ts +0 -5
  555. package/src/domain/entities/Comment.ts +0 -5
  556. package/src/domain/entities/InteractiveLiveSession.ts +0 -6
  557. package/src/domain/entities/Issue.ts +0 -31
  558. package/src/domain/entities/KevReportWatermark.ts +0 -4
  559. package/src/domain/entities/LiveSessionActivitySnapshot.ts +0 -14
  560. package/src/domain/entities/LiveSessionOutputActivity.ts +0 -4
  561. package/src/domain/entities/LiveSessionProcessSnapshot.ts +0 -18
  562. package/src/domain/entities/LiveTmuxSession.ts +0 -4
  563. package/src/domain/entities/Member.ts +0 -3
  564. package/src/domain/entities/OutputDegeneration.ts +0 -10
  565. package/src/domain/entities/Project.ts +0 -88
  566. package/src/domain/entities/ProjectField.ts +0 -3
  567. package/src/domain/entities/ProjectFieldName.ts +0 -2
  568. package/src/domain/entities/ProjectFieldSingleSelect.ts +0 -8
  569. package/src/domain/entities/ProjectFieldSingleSelectOption.ts +0 -8
  570. package/src/domain/entities/RequiredProjectField.ts +0 -68
  571. package/src/domain/entities/SearchedIssue.ts +0 -11
  572. package/src/domain/entities/StoryObjectMap.ts +0 -12
  573. package/src/domain/entities/TokenExhaustionHandoverState.ts +0 -8
  574. package/src/domain/entities/WorkflowStatus.ts +0 -66
  575. package/src/domain/usecases/ActionAnnouncementUseCase.test.ts +0 -91
  576. package/src/domain/usecases/ActionAnnouncementUseCase.ts +0 -78
  577. package/src/domain/usecases/AgentDesignationLabelAdoptUseCase.test.ts +0 -222
  578. package/src/domain/usecases/AgentDesignationLabelAdoptUseCase.ts +0 -76
  579. package/src/domain/usecases/AnalyzeProblemByIssueUseCase.test.ts +0 -118
  580. package/src/domain/usecases/AnalyzeProblemByIssueUseCase.ts +0 -112
  581. package/src/domain/usecases/AnalyzeStoriesUseCase.test.ts +0 -82
  582. package/src/domain/usecases/AnalyzeStoriesUseCase.ts +0 -296
  583. package/src/domain/usecases/AssignNoAssigneeIssueToManagerUseCase.test.ts +0 -578
  584. package/src/domain/usecases/AssignNoAssigneeIssueToManagerUseCase.ts +0 -137
  585. package/src/domain/usecases/CONTRIBUTING_FOR_TEST.md +0 -259
  586. package/src/domain/usecases/ChangeStatusByStoryColorUseCase.test.ts +0 -437
  587. package/src/domain/usecases/ChangeStatusByStoryColorUseCase.ts +0 -80
  588. package/src/domain/usecases/ChangeTargetPullRequestApprover.test.ts +0 -248
  589. package/src/domain/usecases/ChangeTargetPullRequestApprover.ts +0 -69
  590. package/src/domain/usecases/CheckIssueReviewReadinessUseCase.test.ts +0 -411
  591. package/src/domain/usecases/CheckIssueReviewReadinessUseCase.ts +0 -142
  592. package/src/domain/usecases/ClearDependedIssueURLUseCase.test.ts +0 -1120
  593. package/src/domain/usecases/ClearDependedIssueURLUseCase.ts +0 -161
  594. package/src/domain/usecases/ClearPastNextActionDateHourUseCase.test.ts +0 -345
  595. package/src/domain/usecases/ClearPastNextActionDateHourUseCase.ts +0 -81
  596. package/src/domain/usecases/CliErrorReportUseCase.test.ts +0 -162
  597. package/src/domain/usecases/CliErrorReportUseCase.ts +0 -72
  598. package/src/domain/usecases/ConflictedIssueRevertUseCase.test.ts +0 -886
  599. package/src/domain/usecases/ConflictedIssueRevertUseCase.ts +0 -146
  600. package/src/domain/usecases/CreateEstimationIssueUseCase.test.ts +0 -227
  601. package/src/domain/usecases/CreateEstimationIssueUseCase.ts +0 -205
  602. package/src/domain/usecases/CreateNewStoryByLabelUseCase.test.ts +0 -1084
  603. package/src/domain/usecases/CreateNewStoryByLabelUseCase.ts +0 -146
  604. package/src/domain/usecases/DailySecurityScanUseCase.test.ts +0 -1709
  605. package/src/domain/usecases/DailySecurityScanUseCase.ts +0 -476
  606. package/src/domain/usecases/DefaultSilentSessionMessageComposer.test.ts +0 -533
  607. package/src/domain/usecases/DefaultSilentSessionMessageComposer.ts +0 -122
  608. package/src/domain/usecases/GetStoryObjectMapUseCase.test.ts +0 -330
  609. package/src/domain/usecases/GetStoryObjectMapUseCase.ts +0 -79
  610. package/src/domain/usecases/HandleScheduledEventUseCase.test.ts +0 -1913
  611. package/src/domain/usecases/HandleScheduledEventUseCase.ts +0 -846
  612. package/src/domain/usecases/InTmuxByHumanSessionTokenCountUseCase.test.ts +0 -175
  613. package/src/domain/usecases/InTmuxByHumanSessionTokenCountUseCase.ts +0 -63
  614. package/src/domain/usecases/IssueNoStatusUpdateUseCase.test.ts +0 -165
  615. package/src/domain/usecases/IssueNoStatusUpdateUseCase.ts +0 -44
  616. package/src/domain/usecases/IssueRejectionEvaluator.test.ts +0 -1137
  617. package/src/domain/usecases/IssueRejectionEvaluator.ts +0 -340
  618. package/src/domain/usecases/LiveSessionOauthTokenSelectUseCase.test.ts +0 -679
  619. package/src/domain/usecases/LiveSessionOauthTokenSelectUseCase.ts +0 -178
  620. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +0 -5441
  621. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +0 -891
  622. package/src/domain/usecases/NotifySilentLiveSessionsUseCase.test.ts +0 -2069
  623. package/src/domain/usecases/NotifySilentLiveSessionsUseCase.ts +0 -489
  624. package/src/domain/usecases/OauthTokenSelectUseCase.test.ts +0 -662
  625. package/src/domain/usecases/OauthTokenSelectUseCase.ts +0 -274
  626. package/src/domain/usecases/OutputDegenerationDetector.test.ts +0 -167
  627. package/src/domain/usecases/OutputDegenerationDetector.ts +0 -169
  628. package/src/domain/usecases/ProjectRequiredFieldCreateUseCase.test.ts +0 -711
  629. package/src/domain/usecases/ProjectRequiredFieldCreateUseCase.ts +0 -146
  630. package/src/domain/usecases/QualityCheckAdvanceUseCase.test.ts +0 -421
  631. package/src/domain/usecases/QualityCheckAdvanceUseCase.ts +0 -76
  632. package/src/domain/usecases/ReopenedDoneIssueRevertUseCase.test.ts +0 -188
  633. package/src/domain/usecases/ReopenedDoneIssueRevertUseCase.ts +0 -57
  634. package/src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.test.ts +0 -303
  635. package/src/domain/usecases/ResolveInteractiveLiveSessionsUseCase.ts +0 -155
  636. package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.test.ts +0 -1838
  637. package/src/domain/usecases/RevertNotReadyReviewQueueIssueUseCase.ts +0 -221
  638. package/src/domain/usecases/RevertOrphanedPreparationUseCase.test.ts +0 -2392
  639. package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +0 -499
  640. package/src/domain/usecases/SessionOutputDegenerationRecoveryUseCase.test.ts +0 -224
  641. package/src/domain/usecases/SessionOutputDegenerationRecoveryUseCase.ts +0 -142
  642. package/src/domain/usecases/SetDependedIssueUrlForOpenTaskPRsUseCase.test.ts +0 -360
  643. package/src/domain/usecases/SetDependedIssueUrlForOpenTaskPRsUseCase.ts +0 -70
  644. package/src/domain/usecases/SetNoStoryIssueToStoryUseCase.test.ts +0 -400
  645. package/src/domain/usecases/SetNoStoryIssueToStoryUseCase.ts +0 -48
  646. package/src/domain/usecases/SetWorkflowManagementIssueToStoryUseCase.test.ts +0 -696
  647. package/src/domain/usecases/SetWorkflowManagementIssueToStoryUseCase.ts +0 -201
  648. package/src/domain/usecases/SetupTowerDefenceProjectUseCase.test.ts +0 -1363
  649. package/src/domain/usecases/SetupTowerDefenceProjectUseCase.ts +0 -215
  650. package/src/domain/usecases/StaleTaskPullRequestCloseUseCase.test.ts +0 -170
  651. package/src/domain/usecases/StaleTaskPullRequestCloseUseCase.ts +0 -38
  652. package/src/domain/usecases/StaleTmuxSessionKillUseCase.test.ts +0 -283
  653. package/src/domain/usecases/StaleTmuxSessionKillUseCase.ts +0 -98
  654. package/src/domain/usecases/StartPreparationUseCase.test.ts +0 -7822
  655. package/src/domain/usecases/StartPreparationUseCase.ts +0 -876
  656. package/src/domain/usecases/SubscriptionDisabledIssueUseCase.test.ts +0 -200
  657. package/src/domain/usecases/SubscriptionDisabledIssueUseCase.ts +0 -74
  658. package/src/domain/usecases/TokenExhaustionHandoverUseCase.test.ts +0 -838
  659. package/src/domain/usecases/TokenExhaustionHandoverUseCase.ts +0 -439
  660. package/src/domain/usecases/UpdateIssueStatusByLabelUseCase.test.ts +0 -306
  661. package/src/domain/usecases/UpdateIssueStatusByLabelUseCase.ts +0 -64
  662. package/src/domain/usecases/UpdateRateLimitCacheUseCase.test.ts +0 -178
  663. package/src/domain/usecases/UpdateRateLimitCacheUseCase.ts +0 -22
  664. package/src/domain/usecases/adapter-interfaces/ClaudeHandoverSessionRepository.ts +0 -5
  665. package/src/domain/usecases/adapter-interfaces/ClaudeInteractiveSessionRepository.ts +0 -9
  666. package/src/domain/usecases/adapter-interfaces/ClaudeLiveSessionRepository.ts +0 -8
  667. package/src/domain/usecases/adapter-interfaces/ClaudeMessageResponseRepository.ts +0 -5
  668. package/src/domain/usecases/adapter-interfaces/ClaudeRepository.ts +0 -6
  669. package/src/domain/usecases/adapter-interfaces/ClaudeTokenUsageRepository.ts +0 -8
  670. package/src/domain/usecases/adapter-interfaces/ConsoleTabsRepository.ts +0 -12
  671. package/src/domain/usecases/adapter-interfaces/CopilotRepository.ts +0 -3
  672. package/src/domain/usecases/adapter-interfaces/DateRepository.ts +0 -7
  673. package/src/domain/usecases/adapter-interfaces/GitHubGraphqlRateLimitRepository.ts +0 -3
  674. package/src/domain/usecases/adapter-interfaces/HttpRepository.ts +0 -3
  675. package/src/domain/usecases/adapter-interfaces/InteractiveLiveSessionTranscriptResolver.ts +0 -7
  676. package/src/domain/usecases/adapter-interfaces/IssueAttachmentRepository.ts +0 -9
  677. package/src/domain/usecases/adapter-interfaces/IssueCheckpointRepository.ts +0 -3
  678. package/src/domain/usecases/adapter-interfaces/IssueCommentRepository.ts +0 -7
  679. package/src/domain/usecases/adapter-interfaces/IssueRepository.ts +0 -229
  680. package/src/domain/usecases/adapter-interfaces/KevReportWatermarkRepository.ts +0 -11
  681. package/src/domain/usecases/adapter-interfaces/LiveSessionProcessSnapshotProvider.ts +0 -5
  682. package/src/domain/usecases/adapter-interfaces/LocalCommandRunner.ts +0 -16
  683. package/src/domain/usecases/adapter-interfaces/OwnerCallStatusProvider.ts +0 -5
  684. package/src/domain/usecases/adapter-interfaces/ProcessEnvironReader.ts +0 -3
  685. package/src/domain/usecases/adapter-interfaces/ProcessSignalRepository.ts +0 -5
  686. package/src/domain/usecases/adapter-interfaces/ProjectRepository.ts +0 -29
  687. package/src/domain/usecases/adapter-interfaces/RateLimitCacheRepository.ts +0 -10
  688. package/src/domain/usecases/adapter-interfaces/RefusalTailStatusProvider.ts +0 -5
  689. package/src/domain/usecases/adapter-interfaces/SessionAssistantTurnsRepository.ts +0 -6
  690. package/src/domain/usecases/adapter-interfaces/SessionDegenerationCooldownStateRepository.ts +0 -4
  691. package/src/domain/usecases/adapter-interfaces/SessionOutputActivityRepository.ts +0 -7
  692. package/src/domain/usecases/adapter-interfaces/SessionRecordReader.ts +0 -3
  693. package/src/domain/usecases/adapter-interfaces/SessionSubAgentActivityRepository.ts +0 -8
  694. package/src/domain/usecases/adapter-interfaces/SilentSessionCandidateStateRepository.ts +0 -10
  695. package/src/domain/usecases/adapter-interfaces/SilentSessionHubTaskStatusCacheRepository.ts +0 -20
  696. package/src/domain/usecases/adapter-interfaces/SilentSessionMessageComposer.ts +0 -18
  697. package/src/domain/usecases/adapter-interfaces/SilentSessionNotificationRepository.ts +0 -6
  698. package/src/domain/usecases/adapter-interfaces/SlackRepository.ts +0 -20
  699. package/src/domain/usecases/adapter-interfaces/Sleeper.ts +0 -3
  700. package/src/domain/usecases/adapter-interfaces/SpreadsheetRepository.ts +0 -18
  701. package/src/domain/usecases/adapter-interfaces/StatusDefaultRepository.ts +0 -5
  702. package/src/domain/usecases/adapter-interfaces/SubAgentLivenessResolver.ts +0 -6
  703. package/src/domain/usecases/adapter-interfaces/SubAgentProcessLister.ts +0 -8
  704. package/src/domain/usecases/adapter-interfaces/SubAgentSilentSecondsResolver.ts +0 -3
  705. package/src/domain/usecases/adapter-interfaces/SubAgentTranscriptDirectoryResolver.ts +0 -6
  706. package/src/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.ts +0 -9
  707. package/src/domain/usecases/adapter-interfaces/TmuxSessionRepository.ts +0 -20
  708. package/src/domain/usecases/adapter-interfaces/TokenExhaustionHandoverStateRepository.ts +0 -6
  709. package/src/domain/usecases/adapter-interfaces/TokenRateLimitSnapshotRepository.ts +0 -22
  710. package/src/domain/usecases/adapter-interfaces/WebhookRepository.ts +0 -3
  711. package/src/domain/usecases/agentReportPrefix.ts +0 -1
  712. package/src/domain/usecases/autoStatusCheckComments.ts +0 -1
  713. package/src/domain/usecases/console/.gitkeep +0 -0
  714. package/src/domain/usecases/console/GenerateConsoleListsUseCase.test.ts +0 -887
  715. package/src/domain/usecases/console/GenerateConsoleListsUseCase.ts +0 -368
  716. package/src/domain/usecases/dashboard/ComposeDashboardUseCase.test.ts +0 -654
  717. package/src/domain/usecases/dashboard/ComposeDashboardUseCase.ts +0 -318
  718. package/src/domain/usecases/dashboard/DashboardProjectCode.test.ts +0 -34
  719. package/src/domain/usecases/dashboard/DashboardProjectCode.ts +0 -27
  720. package/src/domain/usecases/dashboard/GenerateDashboardRowUseCase.test.ts +0 -160
  721. package/src/domain/usecases/dashboard/GenerateDashboardRowUseCase.ts +0 -69
  722. package/src/domain/usecases/dashboard/GenerateTokenStatusUseCase.test.ts +0 -362
  723. package/src/domain/usecases/dashboard/GenerateTokenStatusUseCase.ts +0 -234
  724. package/src/domain/usecases/ensureAgentOptionAndGetId.ts +0 -47
  725. package/src/domain/usecases/extractFencedJsonBlocks.test.ts +0 -40
  726. package/src/domain/usecases/extractFencedJsonBlocks.ts +0 -21
  727. package/src/domain/usecases/extractNextStepAgent.test.ts +0 -58
  728. package/src/domain/usecases/extractNextStepAgent.ts +0 -18
  729. package/src/domain/usecases/extractNextStepAgentFromComments.ts +0 -13
  730. package/src/domain/usecases/findLastAgentReport.test.ts +0 -121
  731. package/src/domain/usecases/findLastAgentReport.ts +0 -14
  732. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.test.ts +0 -339
  733. package/src/domain/usecases/intmux/GenerateInTmuxByHumanDataUseCase.ts +0 -188
  734. package/src/domain/usecases/intmux/InTmuxByHumanSessionReconcileUseCase.test.ts +0 -389
  735. package/src/domain/usecases/intmux/InTmuxByHumanSessionReconcileUseCase.ts +0 -103
  736. package/src/domain/usecases/intmux/OwnerCallFile.test.ts +0 -184
  737. package/src/domain/usecases/intmux/OwnerCallFile.ts +0 -80
  738. package/src/domain/usecases/isAgentReportBody.test.ts +0 -108
  739. package/src/domain/usecases/isAgentReportBody.ts +0 -52
  740. package/src/domain/usecases/isAuthorAuthorizedForAutoStatusCheck.ts +0 -12
  741. package/src/domain/usecases/isHumanComment.test.ts +0 -77
  742. package/src/domain/usecases/isHumanComment.ts +0 -23
  743. package/src/domain/usecases/isRecord.ts +0 -2
  744. package/src/domain/usecases/issueReactivationTriggerIsPending.test.ts +0 -541
  745. package/src/domain/usecases/issueReactivationTriggerIsPending.ts +0 -25
  746. package/src/domain/usecases/nextStepAgentDispatchRepeatedMessage.ts +0 -2
  747. package/src/domain/usecases/normalizeReportBody.test.ts +0 -24
  748. package/src/domain/usecases/normalizeReportBody.ts +0 -2
  749. package/src/domain/usecases/resolveAllowedIssueAuthors.test.ts +0 -51
  750. package/src/domain/usecases/resolveAllowedIssueAuthors.ts +0 -6
  751. package/src/domain/usecases/resolveLabelsAsLlmAgentName.test.ts +0 -42
  752. package/src/domain/usecases/resolveLabelsAsLlmAgentName.ts +0 -6
  753. package/src/domain/usecases/resolveLabelsNotRequiringPullRequest.test.ts +0 -33
  754. package/src/domain/usecases/resolveLabelsNotRequiringPullRequest.ts +0 -7
  755. package/src/domain/usecases/resolveNextStepAgentDispatchRepetition.test.ts +0 -337
  756. package/src/domain/usecases/resolveNextStepAgentDispatchRepetition.ts +0 -133
  757. package/src/domain/usecases/silentSessionReminderSentinel.ts +0 -9
  758. package/src/domain/usecases/triagerAgentName.ts +0 -4
  759. package/src/domain/usecases/utils.test.ts +0 -35
  760. package/src/domain/usecases/utils.ts +0 -6
  761. package/src/index.test.ts +0 -8
  762. package/src/index.ts +0 -10
  763. package/src/releaseConfig.test.ts +0 -40
  764. package/tsconfig.build.json +0 -18
  765. package/tsconfig.json +0 -25
  766. package/types/adapter/entry-points/handlers/resolveUnansweredOwnerCalls.d.ts +0 -13
  767. package/types/adapter/entry-points/handlers/resolveUnansweredOwnerCalls.d.ts.map +0 -1
  768. package/types/adapter/repositories/FileSystemSilentSessionNotifiedStateRepository.d.ts +0 -16
  769. package/types/adapter/repositories/FileSystemSilentSessionNotifiedStateRepository.d.ts.map +0 -1
  770. package/types/adapter/repositories/issue/issueTimelineUtils.d.ts +0 -12
  771. package/types/adapter/repositories/issue/issueTimelineUtils.d.ts.map +0 -1
  772. package/types/domain/entities/UnansweredOwnerCall.d.ts +0 -5
  773. package/types/domain/entities/UnansweredOwnerCall.d.ts.map +0 -1
  774. package/types/domain/entities/WorkingTime.d.ts +0 -8
  775. package/types/domain/entities/WorkingTime.d.ts.map +0 -1
  776. package/types/domain/usecases/ChangeStatusLongInReviewIssueUseCase.d.ts +0 -17
  777. package/types/domain/usecases/ChangeStatusLongInReviewIssueUseCase.d.ts.map +0 -1
  778. package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts +0 -23
  779. package/types/domain/usecases/ConvertCheckboxToIssueInStoryIssueUseCase.d.ts.map +0 -1
  780. package/types/domain/usecases/GenerateWorkingTimeReportUseCase.d.ts +0 -50
  781. package/types/domain/usecases/GenerateWorkingTimeReportUseCase.d.ts.map +0 -1
  782. package/types/domain/usecases/TriagerApprovalDispatchUseCase.d.ts +0 -15
  783. package/types/domain/usecases/TriagerApprovalDispatchUseCase.d.ts.map +0 -1
  784. package/types/domain/usecases/adapter-interfaces/SilentSessionNotifiedStateRepository.d.ts +0 -11
  785. package/types/domain/usecases/adapter-interfaces/SilentSessionNotifiedStateRepository.d.ts.map +0 -1
  786. package/types/domain/usecases/awaitingOwnerApprovalMessage.d.ts +0 -3
  787. package/types/domain/usecases/awaitingOwnerApprovalMessage.d.ts.map +0 -1
  788. package/types/domain/usecases/findLastAgentDeclaringReport.d.ts +0 -5
  789. package/types/domain/usecases/findLastAgentDeclaringReport.d.ts.map +0 -1
  790. package/types/domain/usecases/isPullRequestDeclaredUnnecessary.d.ts +0 -5
  791. package/types/domain/usecases/isPullRequestDeclaredUnnecessary.d.ts.map +0 -1
  792. package/types/domain/usecases/isWaitingForOwnerApproval.d.ts +0 -2
  793. package/types/domain/usecases/isWaitingForOwnerApproval.d.ts.map +0 -1
  794. package/types/domain/usecases/returnedToAwaitingWorkspaceMessage.d.ts +0 -3
  795. package/types/domain/usecases/returnedToAwaitingWorkspaceMessage.d.ts.map +0 -1
@@ -1,2069 +0,0 @@
1
- import {
2
- NotifySilentLiveSessionsUseCase,
3
- HubTaskStatusResolver,
4
- parseHubTaskIssueUrlFromSessionName,
5
- isGitHubIssueOrPullRequestSessionName,
6
- DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
7
- DEFAULT_UNANSWERED_OWNER_CALL_GRACE_SECONDS,
8
- DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
9
- DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
10
- DEFAULT_NOTIFICATION_STAGGER_SECONDS,
11
- DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS,
12
- DEFAULT_HUB_TASK_STATUS_CACHE_TTL_SECONDS,
13
- } from './NotifySilentLiveSessionsUseCase';
14
- import { Issue } from '../entities/Issue';
15
- import { LiveSessionProcessSnapshotProvider } from './adapter-interfaces/LiveSessionProcessSnapshotProvider';
16
- import { InteractiveLiveSessionTranscriptResolver } from './adapter-interfaces/InteractiveLiveSessionTranscriptResolver';
17
- import { SessionOutputActivityRepository } from './adapter-interfaces/SessionOutputActivityRepository';
18
- import { SessionSubAgentActivityRepository } from './adapter-interfaces/SessionSubAgentActivityRepository';
19
- import { OwnerCallStatusProvider } from './adapter-interfaces/OwnerCallStatusProvider';
20
- import { RefusalTailStatusProvider } from './adapter-interfaces/RefusalTailStatusProvider';
21
- import { SilentSessionNotificationRepository } from './adapter-interfaces/SilentSessionNotificationRepository';
22
- import { SilentSessionCandidateStateRepository } from './adapter-interfaces/SilentSessionCandidateStateRepository';
23
- import { SilentSessionHubTaskStatusCacheRepository } from './adapter-interfaces/SilentSessionHubTaskStatusCacheRepository';
24
- import { SilentSessionMessageComposer } from './adapter-interfaces/SilentSessionMessageComposer';
25
- import { Sleeper } from './adapter-interfaces/Sleeper';
26
- import { SubAgentActivity } from '../entities/LiveSessionActivitySnapshot';
27
- import { LiveSessionProcessSnapshot } from '../entities/LiveSessionProcessSnapshot';
28
- import { InteractiveLiveSession } from '../entities/InteractiveLiveSession';
29
-
30
- type Mocked<T> = jest.Mocked<T> & jest.MockedObject<T>;
31
-
32
- const MAIN_STALLED_SECTION = 'MAIN_STALLED_SECTION';
33
- const MAIN_STALLED_STALE_OWNER_CALL_SECTION =
34
- 'MAIN_STALLED_STALE_OWNER_CALL_SECTION';
35
- const SUBAGENT_SECTION = 'SUBAGENT_SECTION';
36
- const SUBAGENT_UNCONSUMED_RESULT_SECTION = 'SUBAGENT_UNCONSUMED_RESULT_SECTION';
37
-
38
- class EveryNameRecentSet extends Set<string> {
39
- override has = (): boolean => true;
40
- }
41
-
42
- const everyNameRecentSet = (): Set<string> => new EveryNameRecentSet();
43
-
44
- describe('NotifySilentLiveSessionsUseCase', () => {
45
- let useCase: NotifySilentLiveSessionsUseCase;
46
- let mockSnapshotProvider: Mocked<LiveSessionProcessSnapshotProvider>;
47
- let mockTranscriptResolver: Mocked<InteractiveLiveSessionTranscriptResolver>;
48
- let mockSessionOutputActivityRepository: Mocked<SessionOutputActivityRepository>;
49
- let mockSubAgentActivityRepository: Mocked<SessionSubAgentActivityRepository>;
50
- let mockOwnerCallStatusProvider: Mocked<OwnerCallStatusProvider>;
51
- let mockNotificationRepository: Mocked<SilentSessionNotificationRepository>;
52
- let mockCandidateStateRepository: Mocked<SilentSessionCandidateStateRepository>;
53
- let mockMessageComposer: Mocked<SilentSessionMessageComposer>;
54
- let mockSleeper: Mocked<Sleeper>;
55
- let mockHubTaskStatusResolver: Mocked<HubTaskStatusResolver>;
56
- let mockHubTaskStatusCacheRepository: Mocked<SilentSessionHubTaskStatusCacheRepository>;
57
- let mockRefusalTailStatusProvider: Mocked<RefusalTailStatusProvider>;
58
- const now = new Date('2026-06-26T00:00:00Z');
59
- const nowEpochSeconds = Math.floor(now.getTime() / 1000);
60
- const GITHUB_SESSION = 'https_//github_com/HiromiShikata/repo/issues/42';
61
- const GITHUB_SESSION_ALPHA =
62
- 'https_//github_com/HiromiShikata/repo/issues/100';
63
- const GITHUB_SESSION_BRAVO =
64
- 'https_//github_com/HiromiShikata/repo/issues/200';
65
-
66
- const runParams = (
67
- overrides?: Partial<{
68
- activeHubTaskStatus: string | null;
69
- candidateDebounceRecencyWindowSeconds: number;
70
- hubTaskStatusCacheTtlSeconds: number;
71
- now: Date;
72
- }>,
73
- ): {
74
- mainSilentThresholdSeconds: number;
75
- unansweredOwnerCallGraceSeconds: number;
76
- subAgentSilentThresholdSeconds: number;
77
- subAgentRunningThresholdSeconds: number;
78
- staggerSeconds: number;
79
- candidateDebounceRecencyWindowSeconds: number;
80
- activeHubTaskStatus: string | null;
81
- hubTaskStatusCacheTtlSeconds: number;
82
- now: Date;
83
- } => ({
84
- mainSilentThresholdSeconds: DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
85
- unansweredOwnerCallGraceSeconds:
86
- DEFAULT_UNANSWERED_OWNER_CALL_GRACE_SECONDS,
87
- subAgentSilentThresholdSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
88
- subAgentRunningThresholdSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
89
- staggerSeconds: DEFAULT_NOTIFICATION_STAGGER_SECONDS,
90
- candidateDebounceRecencyWindowSeconds:
91
- DEFAULT_CANDIDATE_DEBOUNCE_RECENCY_WINDOW_SECONDS,
92
- activeHubTaskStatus: null,
93
- hubTaskStatusCacheTtlSeconds: DEFAULT_HUB_TASK_STATUS_CACHE_TTL_SECONDS,
94
- now,
95
- ...overrides,
96
- });
97
-
98
- const emptySnapshot: LiveSessionProcessSnapshot = {
99
- sessions: [],
100
- processes: [],
101
- };
102
-
103
- const sessionFor = (sessionName: string): InteractiveLiveSession => ({
104
- sessionName,
105
- sessionId: `${sessionName}-uuid`,
106
- candidateSessionIds: [`${sessionName}-uuid`],
107
- configDir: `/config/${sessionName}`,
108
- });
109
-
110
- // The use case derives interactive sessions from the snapshot via the embedded
111
- // pure resolver. To keep these tests focused on the orchestration, the
112
- // snapshot is shaped so that the pure resolver yields exactly the named
113
- // interactive sessions: one pane with a single claude child carrying a session
114
- // id and config directory.
115
- const snapshotWithSessions = (
116
- sessionNames: string[],
117
- ): LiveSessionProcessSnapshot => {
118
- const sessions = sessionNames.map((sessionName, index) => ({
119
- sessionName,
120
- panePids: [100 + index * 10],
121
- }));
122
- const processes = sessionNames.map((sessionName, index) => ({
123
- pid: 101 + index * 10,
124
- ppid: 100 + index * 10,
125
- commandLine: `claude --name ${sessionName}`,
126
- sessionId: `${sessionName}-uuid`,
127
- currentSessionId: `${sessionName}-uuid`,
128
- configDir: `/config/${sessionName}`,
129
- }));
130
- return { sessions, processes };
131
- };
132
-
133
- const transcriptMapFor = (sessionNames: string[]): Map<string, string> =>
134
- new Map(
135
- sessionNames.map((sessionName) => [
136
- sessionName,
137
- `/config/${sessionName}/projects/-home-user/${sessionName}-uuid.jsonl`,
138
- ]),
139
- );
140
-
141
- beforeEach(() => {
142
- jest.resetAllMocks();
143
- jest.spyOn(console, 'log').mockImplementation(() => undefined);
144
- mockSnapshotProvider = {
145
- getSnapshot: jest.fn().mockResolvedValue(emptySnapshot),
146
- };
147
- mockTranscriptResolver = {
148
- resolveTranscriptPaths: jest.fn().mockReturnValue(new Map()),
149
- };
150
- mockSessionOutputActivityRepository = {
151
- listSessionOutputActivities: jest.fn().mockResolvedValue([]),
152
- };
153
- mockSubAgentActivityRepository = {
154
- listSubAgentActivitiesBySessionName: jest
155
- .fn()
156
- .mockResolvedValue(new Map<string, SubAgentActivity[]>()),
157
- };
158
- mockOwnerCallStatusProvider = {
159
- listUnansweredOwnerCallEpochSecondsBySessionName: jest
160
- .fn()
161
- .mockResolvedValue(new Map<string, number>()),
162
- };
163
- mockNotificationRepository = {
164
- sendSelfCheckNotification: jest.fn().mockResolvedValue(undefined),
165
- };
166
- mockCandidateStateRepository = {
167
- loadRecentCandidateSessionNames: jest
168
- .fn()
169
- .mockResolvedValue(everyNameRecentSet()),
170
- saveCandidateSessionNames: jest.fn().mockResolvedValue(undefined),
171
- };
172
- mockMessageComposer = {
173
- composeMainStalledSection: jest
174
- .fn()
175
- .mockReturnValue(MAIN_STALLED_SECTION),
176
- composeMainStalledWithStaleOwnerCallSection: jest
177
- .fn()
178
- .mockReturnValue(MAIN_STALLED_STALE_OWNER_CALL_SECTION),
179
- composeSubAgentSection: jest.fn().mockReturnValue(SUBAGENT_SECTION),
180
- composeSubAgentUnconsumedResultSection: jest
181
- .fn()
182
- .mockReturnValue(SUBAGENT_UNCONSUMED_RESULT_SECTION),
183
- };
184
- mockSleeper = {
185
- sleep: jest.fn().mockResolvedValue(undefined),
186
- };
187
- mockHubTaskStatusResolver = {
188
- getIssueByUrl: jest.fn().mockResolvedValue(null),
189
- };
190
- mockHubTaskStatusCacheRepository = {
191
- loadHubTaskStatus: jest.fn().mockResolvedValue(null),
192
- saveHubTaskStatus: jest.fn().mockResolvedValue(undefined),
193
- };
194
- mockRefusalTailStatusProvider = {
195
- listRefusalTailedSessionNames: jest
196
- .fn()
197
- .mockResolvedValue(new Set<string>()),
198
- };
199
- useCase = new NotifySilentLiveSessionsUseCase(
200
- mockSnapshotProvider,
201
- mockTranscriptResolver,
202
- mockSessionOutputActivityRepository,
203
- mockSubAgentActivityRepository,
204
- mockOwnerCallStatusProvider,
205
- mockNotificationRepository,
206
- mockCandidateStateRepository,
207
- mockMessageComposer,
208
- mockSleeper,
209
- mockHubTaskStatusResolver,
210
- mockHubTaskStatusCacheRepository,
211
- mockRefusalTailStatusProvider,
212
- );
213
- });
214
-
215
- const issueFor = (overrides: Partial<Issue>): Issue => ({
216
- nameWithOwner: 'HiromiShikata/repo',
217
- number: 42,
218
- title: 'Hub task',
219
- state: 'OPEN',
220
- status: 'In tmux',
221
- story: null,
222
- nextActionDate: null,
223
- nextActionHour: null,
224
- estimationMinutes: null,
225
- dependedIssueUrls: [],
226
- completionDate50PercentConfidence: null,
227
- url: 'https://github.com/HiromiShikata/repo/issues/42',
228
- assignees: [],
229
- labels: [],
230
- org: 'HiromiShikata',
231
- repo: 'repo',
232
- body: '',
233
- itemId: 'item-id',
234
- isPr: false,
235
- isInProgress: false,
236
- isClosed: false,
237
- createdAt: now,
238
- author: 'HiromiShikata',
239
- closingIssueReferenceUrls: [],
240
- agent: null,
241
- stateReason: null,
242
- ...overrides,
243
- });
244
-
245
- const setupSilentMainSession = (sessionName: string): void => {
246
- setupLiveInteractiveSession(sessionName);
247
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
248
- [
249
- {
250
- sessionName,
251
- lastOutputEpochSeconds:
252
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
253
- },
254
- ],
255
- );
256
- };
257
-
258
- const setupLiveInteractiveSession = (sessionName: string): void => {
259
- mockSnapshotProvider.getSnapshot.mockResolvedValue(
260
- snapshotWithSessions([sessionName]),
261
- );
262
- mockTranscriptResolver.resolveTranscriptPaths.mockReturnValue(
263
- transcriptMapFor([sessionName]),
264
- );
265
- };
266
-
267
- it('exposes the default thresholds as named constants', () => {
268
- expect(DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS).toBe(600);
269
- expect(DEFAULT_UNANSWERED_OWNER_CALL_GRACE_SECONDS).toBe(3600);
270
- expect(DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS).toBe(300);
271
- expect(DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS).toBe(900);
272
- expect(DEFAULT_NOTIFICATION_STAGGER_SECONDS).toBe(25);
273
- });
274
-
275
- it('notifies a session whose name encodes a github.com issue URL', async () => {
276
- setupLiveInteractiveSession(GITHUB_SESSION);
277
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
278
- [
279
- {
280
- sessionName: GITHUB_SESSION,
281
- lastOutputEpochSeconds:
282
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
283
- },
284
- ],
285
- );
286
-
287
- await useCase.run(runParams());
288
-
289
- expect(mockMessageComposer.composeMainStalledSection).toHaveBeenCalledWith(
290
- DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
291
- );
292
- expect(
293
- mockNotificationRepository.sendSelfCheckNotification,
294
- ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
295
- });
296
-
297
- it('notifies a session whose name encodes a github.com pull-request URL', async () => {
298
- const pullRequestSession = 'https_//github_com/HiromiShikata/repo/pull/77';
299
- setupLiveInteractiveSession(pullRequestSession);
300
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
301
- [
302
- {
303
- sessionName: pullRequestSession,
304
- lastOutputEpochSeconds:
305
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
306
- },
307
- ],
308
- );
309
-
310
- await useCase.run(runParams());
311
-
312
- expect(
313
- mockNotificationRepository.sendSelfCheckNotification,
314
- ).toHaveBeenCalledWith(pullRequestSession, MAIN_STALLED_SECTION);
315
- });
316
-
317
- it('excludes a non-github-named session that has no resolvable transcript so it is never notified', async () => {
318
- mockSnapshotProvider.getSnapshot.mockResolvedValue(
319
- snapshotWithSessions(['workbench']),
320
- );
321
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
322
- [
323
- {
324
- sessionName: 'workbench',
325
- lastOutputEpochSeconds:
326
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
327
- },
328
- ],
329
- );
330
-
331
- await useCase.run(runParams());
332
-
333
- expect(mockTranscriptResolver.resolveTranscriptPaths).toHaveBeenCalledWith([
334
- sessionFor('workbench'),
335
- ]);
336
- expect(
337
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName,
338
- ).toHaveBeenCalledWith([], new Map());
339
- expect(
340
- mockMessageComposer.composeMainStalledSection,
341
- ).not.toHaveBeenCalled();
342
- expect(
343
- mockNotificationRepository.sendSelfCheckNotification,
344
- ).not.toHaveBeenCalled();
345
- });
346
-
347
- it('monitors the github-named session and excludes a non-github-named session that has no resolvable transcript', async () => {
348
- mockSnapshotProvider.getSnapshot.mockResolvedValue(
349
- snapshotWithSessions([GITHUB_SESSION, 'orchestrator']),
350
- );
351
- mockTranscriptResolver.resolveTranscriptPaths.mockReturnValue(
352
- transcriptMapFor([GITHUB_SESSION]),
353
- );
354
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
355
- [
356
- {
357
- sessionName: GITHUB_SESSION,
358
- lastOutputEpochSeconds:
359
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
360
- },
361
- {
362
- sessionName: 'orchestrator',
363
- lastOutputEpochSeconds:
364
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
365
- },
366
- ],
367
- );
368
-
369
- await useCase.run(runParams());
370
-
371
- expect(mockTranscriptResolver.resolveTranscriptPaths).toHaveBeenCalledWith([
372
- sessionFor(GITHUB_SESSION),
373
- sessionFor('orchestrator'),
374
- ]);
375
- expect(
376
- mockNotificationRepository.sendSelfCheckNotification,
377
- ).toHaveBeenCalledTimes(1);
378
- expect(
379
- mockNotificationRepository.sendSelfCheckNotification,
380
- ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
381
- });
382
-
383
- it('passes the resolved transcript paths to the output and owner-call providers', async () => {
384
- setupLiveInteractiveSession(GITHUB_SESSION);
385
-
386
- await useCase.run(runParams());
387
-
388
- const expectedMap = transcriptMapFor([GITHUB_SESSION]);
389
- expect(
390
- mockSessionOutputActivityRepository.listSessionOutputActivities,
391
- ).toHaveBeenCalledWith(expectedMap);
392
- expect(
393
- mockOwnerCallStatusProvider.listUnansweredOwnerCallEpochSecondsBySessionName,
394
- ).toHaveBeenCalledWith(expectedMap);
395
- expect(
396
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName,
397
- ).toHaveBeenCalledWith([GITHUB_SESSION], expectedMap);
398
- });
399
-
400
- it('suppresses the stalled section and sends nothing while the latest owner call is unanswered', async () => {
401
- setupSilentMainSession(GITHUB_SESSION);
402
- mockOwnerCallStatusProvider.listUnansweredOwnerCallEpochSecondsBySessionName.mockResolvedValue(
403
- new Map([
404
- [
405
- GITHUB_SESSION,
406
- nowEpochSeconds - DEFAULT_UNANSWERED_OWNER_CALL_GRACE_SECONDS + 1,
407
- ],
408
- ]),
409
- );
410
-
411
- await useCase.run(runParams());
412
-
413
- expect(
414
- mockMessageComposer.composeMainStalledSection,
415
- ).not.toHaveBeenCalled();
416
- expect(
417
- mockMessageComposer.composeMainStalledWithStaleOwnerCallSection,
418
- ).not.toHaveBeenCalled();
419
- expect(
420
- mockNotificationRepository.sendSelfCheckNotification,
421
- ).not.toHaveBeenCalled();
422
- });
423
-
424
- it('suppresses the reminder even when the unanswered owner call is far older than the former grace period (10 hours)', async () => {
425
- setupSilentMainSession(GITHUB_SESSION);
426
- mockOwnerCallStatusProvider.listUnansweredOwnerCallEpochSecondsBySessionName.mockResolvedValue(
427
- new Map([[GITHUB_SESSION, nowEpochSeconds - 10 * 60 * 60]]),
428
- );
429
-
430
- await useCase.run(runParams());
431
-
432
- expect(
433
- mockMessageComposer.composeMainStalledWithStaleOwnerCallSection,
434
- ).not.toHaveBeenCalled();
435
- expect(
436
- mockMessageComposer.composeMainStalledSection,
437
- ).not.toHaveBeenCalled();
438
- expect(
439
- mockNotificationRepository.sendSelfCheckNotification,
440
- ).not.toHaveBeenCalled();
441
- expect(
442
- mockCandidateStateRepository.saveCandidateSessionNames,
443
- ).toHaveBeenCalledWith({
444
- sessionNames: [],
445
- now,
446
- });
447
- });
448
-
449
- it('suppresses the reminder at exactly the former grace-period age instead of firing the stale-owner-call section', async () => {
450
- setupSilentMainSession(GITHUB_SESSION);
451
- mockOwnerCallStatusProvider.listUnansweredOwnerCallEpochSecondsBySessionName.mockResolvedValue(
452
- new Map([
453
- [
454
- GITHUB_SESSION,
455
- nowEpochSeconds - DEFAULT_UNANSWERED_OWNER_CALL_GRACE_SECONDS,
456
- ],
457
- ]),
458
- );
459
-
460
- await useCase.run(runParams());
461
-
462
- expect(
463
- mockMessageComposer.composeMainStalledWithStaleOwnerCallSection,
464
- ).not.toHaveBeenCalled();
465
- expect(
466
- mockMessageComposer.composeMainStalledSection,
467
- ).not.toHaveBeenCalled();
468
- expect(
469
- mockNotificationRepository.sendSelfCheckNotification,
470
- ).not.toHaveBeenCalled();
471
- });
472
-
473
- it('does not send anything when the owner call is old and the main output is not silent past the threshold', async () => {
474
- setupLiveInteractiveSession(GITHUB_SESSION);
475
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
476
- [
477
- {
478
- sessionName: GITHUB_SESSION,
479
- lastOutputEpochSeconds:
480
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS + 1,
481
- },
482
- ],
483
- );
484
- mockOwnerCallStatusProvider.listUnansweredOwnerCallEpochSecondsBySessionName.mockResolvedValue(
485
- new Map([
486
- [
487
- GITHUB_SESSION,
488
- nowEpochSeconds - DEFAULT_UNANSWERED_OWNER_CALL_GRACE_SECONDS,
489
- ],
490
- ]),
491
- );
492
-
493
- await useCase.run(runParams());
494
-
495
- expect(
496
- mockNotificationRepository.sendSelfCheckNotification,
497
- ).not.toHaveBeenCalled();
498
- });
499
-
500
- it('sends the main stalled section when the session is silent past the threshold and not waiting on the owner', async () => {
501
- setupLiveInteractiveSession(GITHUB_SESSION);
502
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
503
- [
504
- {
505
- sessionName: GITHUB_SESSION,
506
- lastOutputEpochSeconds:
507
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
508
- },
509
- ],
510
- );
511
- mockOwnerCallStatusProvider.listUnansweredOwnerCallEpochSecondsBySessionName.mockResolvedValue(
512
- new Map<string, number>(),
513
- );
514
-
515
- await useCase.run(runParams());
516
-
517
- expect(mockMessageComposer.composeMainStalledSection).toHaveBeenCalledWith(
518
- DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
519
- );
520
- expect(
521
- mockMessageComposer.composeMainStalledWithStaleOwnerCallSection,
522
- ).not.toHaveBeenCalled();
523
- expect(
524
- mockNotificationRepository.sendSelfCheckNotification,
525
- ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
526
- });
527
-
528
- it('sends the main stalled section for a session silent past the threshold regardless of any in-progress tool call, because apparent busyness never suppresses the reminder', async () => {
529
- setupLiveInteractiveSession(GITHUB_SESSION);
530
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
531
- [
532
- {
533
- sessionName: GITHUB_SESSION,
534
- lastOutputEpochSeconds:
535
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
536
- },
537
- ],
538
- );
539
- mockOwnerCallStatusProvider.listUnansweredOwnerCallEpochSecondsBySessionName.mockResolvedValue(
540
- new Map<string, number>(),
541
- );
542
-
543
- await useCase.run(runParams());
544
-
545
- expect(mockMessageComposer.composeMainStalledSection).toHaveBeenCalledWith(
546
- DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
547
- );
548
- expect(
549
- mockNotificationRepository.sendSelfCheckNotification,
550
- ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
551
- });
552
-
553
- it('does not send the main stalled section when output is within the threshold', async () => {
554
- setupLiveInteractiveSession(GITHUB_SESSION);
555
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
556
- [
557
- {
558
- sessionName: GITHUB_SESSION,
559
- lastOutputEpochSeconds:
560
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS + 1,
561
- },
562
- ],
563
- );
564
-
565
- await useCase.run(runParams());
566
-
567
- expect(
568
- mockNotificationRepository.sendSelfCheckNotification,
569
- ).not.toHaveBeenCalled();
570
- });
571
-
572
- it('sends the sub-agent section when a sub-agent exceeds the silent threshold', async () => {
573
- setupLiveInteractiveSession(GITHUB_SESSION);
574
- const subAgents: SubAgentActivity[] = [
575
- {
576
- label: 'sub-process-1',
577
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
578
- runningSeconds: 60,
579
- waitingOnExternalProcess: false,
580
- finishedResultUnconsumed: false,
581
- },
582
- ];
583
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName.mockResolvedValue(
584
- new Map([[GITHUB_SESSION, subAgents]]),
585
- );
586
-
587
- await useCase.run(runParams());
588
-
589
- expect(mockMessageComposer.composeSubAgentSection).toHaveBeenCalledWith({
590
- idleSubAgents: subAgents,
591
- longRunningSubAgents: [],
592
- });
593
- expect(
594
- mockNotificationRepository.sendSelfCheckNotification,
595
- ).toHaveBeenCalledWith(GITHUB_SESSION, SUBAGENT_SECTION);
596
- });
597
-
598
- it('applies a configured running threshold when selecting long-running sub-agents', async () => {
599
- setupLiveInteractiveSession(GITHUB_SESSION);
600
- const subAgents: SubAgentActivity[] = [
601
- {
602
- label: 'sub-process-1',
603
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
604
- runningSeconds: 600,
605
- waitingOnExternalProcess: false,
606
- finishedResultUnconsumed: false,
607
- },
608
- ];
609
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName.mockResolvedValue(
610
- new Map([[GITHUB_SESSION, subAgents]]),
611
- );
612
-
613
- await useCase.run({
614
- ...runParams(),
615
- subAgentRunningThresholdSeconds: 600,
616
- });
617
-
618
- expect(mockMessageComposer.composeSubAgentSection).toHaveBeenCalledWith({
619
- idleSubAgents: subAgents,
620
- longRunningSubAgents: subAgents,
621
- });
622
- });
623
-
624
- it('reports a sub-agent past the running threshold that produced output moments ago', async () => {
625
- setupLiveInteractiveSession(GITHUB_SESSION);
626
- const subAgents: SubAgentActivity[] = [
627
- {
628
- label: 'sub-process-1',
629
- silentSeconds: 10,
630
- runningSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
631
- waitingOnExternalProcess: false,
632
- finishedResultUnconsumed: false,
633
- },
634
- ];
635
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName.mockResolvedValue(
636
- new Map([[GITHUB_SESSION, subAgents]]),
637
- );
638
-
639
- await useCase.run(runParams());
640
-
641
- expect(mockMessageComposer.composeSubAgentSection).toHaveBeenCalledWith({
642
- idleSubAgents: [],
643
- longRunningSubAgents: subAgents,
644
- });
645
- expect(
646
- mockNotificationRepository.sendSelfCheckNotification,
647
- ).toHaveBeenCalledWith(GITHUB_SESSION, SUBAGENT_SECTION);
648
- });
649
-
650
- it('excludes an owner-handover spawn from selection so no notification is sent', async () => {
651
- mockSnapshotProvider.getSnapshot.mockResolvedValue({
652
- sessions: [{ sessionName: 'aw-host', panePids: [100] }],
653
- processes: [
654
- {
655
- pid: 101,
656
- ppid: 100,
657
- commandLine:
658
- 'claude --verbose -p Take ownership of https://example.com/issues/1 and finish it',
659
- sessionId: 'aw-uuid',
660
- currentSessionId: 'aw-uuid',
661
- configDir: '/config/aw',
662
- },
663
- ],
664
- });
665
-
666
- await useCase.run(runParams());
667
-
668
- expect(mockTranscriptResolver.resolveTranscriptPaths).toHaveBeenCalledWith(
669
- [],
670
- );
671
- expect(
672
- mockNotificationRepository.sendSelfCheckNotification,
673
- ).not.toHaveBeenCalled();
674
- });
675
-
676
- it('does nothing when there are no live interactive sessions', async () => {
677
- await useCase.run(runParams());
678
-
679
- expect(
680
- mockNotificationRepository.sendSelfCheckNotification,
681
- ).not.toHaveBeenCalled();
682
- });
683
-
684
- describe('role-named resident leader and PM agent sessions', () => {
685
- it('reminds a role-named leader agent session that has a resolvable transcript and is silent past the threshold', async () => {
686
- setupLiveInteractiveSession('secretary');
687
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
688
- [
689
- {
690
- sessionName: 'secretary',
691
- lastOutputEpochSeconds:
692
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
693
- },
694
- ],
695
- );
696
-
697
- await useCase.run(runParams());
698
-
699
- expect(
700
- mockMessageComposer.composeMainStalledSection,
701
- ).toHaveBeenCalledWith(DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS);
702
- expect(
703
- mockNotificationRepository.sendSelfCheckNotification,
704
- ).toHaveBeenCalledWith('secretary', MAIN_STALLED_SECTION);
705
- });
706
-
707
- it('excludes a non-agent interactive session with no resolvable transcript (for example a viewer named sso_login)', async () => {
708
- mockSnapshotProvider.getSnapshot.mockResolvedValue(
709
- snapshotWithSessions(['sso_login']),
710
- );
711
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
712
- [
713
- {
714
- sessionName: 'sso_login',
715
- lastOutputEpochSeconds:
716
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
717
- },
718
- ],
719
- );
720
-
721
- await useCase.run(runParams());
722
-
723
- expect(
724
- mockTranscriptResolver.resolveTranscriptPaths,
725
- ).toHaveBeenCalledWith([sessionFor('sso_login')]);
726
- expect(
727
- mockMessageComposer.composeMainStalledSection,
728
- ).not.toHaveBeenCalled();
729
- expect(
730
- mockNotificationRepository.sendSelfCheckNotification,
731
- ).not.toHaveBeenCalled();
732
- });
733
-
734
- it('reminds both a github-named session and a role-named leader session in the same cycle', async () => {
735
- mockSnapshotProvider.getSnapshot.mockResolvedValue(
736
- snapshotWithSessions([GITHUB_SESSION, 'app']),
737
- );
738
- mockTranscriptResolver.resolveTranscriptPaths.mockReturnValue(
739
- transcriptMapFor([GITHUB_SESSION, 'app']),
740
- );
741
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
742
- [
743
- {
744
- sessionName: GITHUB_SESSION,
745
- lastOutputEpochSeconds:
746
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
747
- },
748
- {
749
- sessionName: 'app',
750
- lastOutputEpochSeconds:
751
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
752
- },
753
- ],
754
- );
755
-
756
- await useCase.run(runParams());
757
-
758
- expect(
759
- mockNotificationRepository.sendSelfCheckNotification,
760
- ).toHaveBeenCalledTimes(2);
761
- expect(
762
- mockNotificationRepository.sendSelfCheckNotification,
763
- ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
764
- expect(
765
- mockNotificationRepository.sendSelfCheckNotification,
766
- ).toHaveBeenCalledWith('app', MAIN_STALLED_SECTION);
767
- });
768
-
769
- it('parks a role-named leader session while its latest owner call is unanswered', async () => {
770
- setupLiveInteractiveSession('acmepm');
771
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
772
- [
773
- {
774
- sessionName: 'acmepm',
775
- lastOutputEpochSeconds:
776
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
777
- },
778
- ],
779
- );
780
- mockOwnerCallStatusProvider.listUnansweredOwnerCallEpochSecondsBySessionName.mockResolvedValue(
781
- new Map([['acmepm', nowEpochSeconds - 60]]),
782
- );
783
-
784
- await useCase.run(runParams());
785
-
786
- expect(
787
- mockMessageComposer.composeMainStalledSection,
788
- ).not.toHaveBeenCalled();
789
- expect(
790
- mockNotificationRepository.sendSelfCheckNotification,
791
- ).not.toHaveBeenCalled();
792
- });
793
- });
794
-
795
- it('re-notifies a session after its silent episode resolves and a new one begins', async () => {
796
- setupLiveInteractiveSession(GITHUB_SESSION);
797
- const stalled = [
798
- {
799
- sessionName: GITHUB_SESSION,
800
- lastOutputEpochSeconds:
801
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
802
- },
803
- ];
804
- const active = [
805
- {
806
- sessionName: GITHUB_SESSION,
807
- lastOutputEpochSeconds: nowEpochSeconds,
808
- },
809
- ];
810
-
811
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
812
- stalled,
813
- );
814
- await useCase.run(runParams());
815
- expect(
816
- mockNotificationRepository.sendSelfCheckNotification,
817
- ).toHaveBeenCalledTimes(1);
818
-
819
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
820
- active,
821
- );
822
- await useCase.run(runParams());
823
- expect(
824
- mockNotificationRepository.sendSelfCheckNotification,
825
- ).toHaveBeenCalledTimes(1);
826
-
827
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
828
- stalled,
829
- );
830
- await useCase.run(runParams());
831
- expect(
832
- mockNotificationRepository.sendSelfCheckNotification,
833
- ).toHaveBeenCalledTimes(2);
834
- });
835
-
836
- describe('two-consecutive-cycle debounce', () => {
837
- const setupSilentGithubSession = (): void => {
838
- setupLiveInteractiveSession(GITHUB_SESSION);
839
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
840
- [
841
- {
842
- sessionName: GITHUB_SESSION,
843
- lastOutputEpochSeconds:
844
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
845
- },
846
- ],
847
- );
848
- };
849
-
850
- it('does not notify a session that is a candidate in only one cycle', async () => {
851
- setupSilentGithubSession();
852
- mockCandidateStateRepository.loadRecentCandidateSessionNames.mockResolvedValue(
853
- new Set<string>(),
854
- );
855
-
856
- await useCase.run(runParams());
857
-
858
- expect(
859
- mockNotificationRepository.sendSelfCheckNotification,
860
- ).not.toHaveBeenCalled();
861
- });
862
-
863
- it('records the current candidate set so a first-cycle candidate is remembered for the next cycle', async () => {
864
- setupSilentGithubSession();
865
- mockCandidateStateRepository.loadRecentCandidateSessionNames.mockResolvedValue(
866
- new Set<string>(),
867
- );
868
-
869
- await useCase.run(runParams());
870
-
871
- expect(
872
- mockCandidateStateRepository.saveCandidateSessionNames,
873
- ).toHaveBeenCalledWith({ sessionNames: [GITHUB_SESSION], now });
874
- });
875
-
876
- it('notifies a session that is a candidate in two consecutive cycles on the second cycle', async () => {
877
- setupSilentGithubSession();
878
- const previousCandidates = new Set<string>();
879
- mockCandidateStateRepository.loadRecentCandidateSessionNames.mockImplementation(
880
- async () => new Set(previousCandidates),
881
- );
882
- mockCandidateStateRepository.saveCandidateSessionNames.mockImplementation(
883
- async ({ sessionNames }) => {
884
- previousCandidates.clear();
885
- for (const sessionName of sessionNames) {
886
- previousCandidates.add(sessionName);
887
- }
888
- },
889
- );
890
-
891
- await useCase.run(runParams());
892
- expect(
893
- mockNotificationRepository.sendSelfCheckNotification,
894
- ).not.toHaveBeenCalled();
895
-
896
- await useCase.run(runParams());
897
- expect(
898
- mockNotificationRepository.sendSelfCheckNotification,
899
- ).toHaveBeenCalledTimes(1);
900
- expect(
901
- mockNotificationRepository.sendSelfCheckNotification,
902
- ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
903
- });
904
-
905
- it('suppresses the owner-reply-race candidate that was not a candidate in the previous cycle', async () => {
906
- setupSilentGithubSession();
907
- mockCandidateStateRepository.loadRecentCandidateSessionNames.mockResolvedValue(
908
- new Set<string>(),
909
- );
910
-
911
- await useCase.run(runParams());
912
-
913
- expect(
914
- mockNotificationRepository.sendSelfCheckNotification,
915
- ).not.toHaveBeenCalled();
916
- expect(
917
- mockMessageComposer.composeMainStalledSection,
918
- ).toHaveBeenCalledWith(DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS);
919
- });
920
-
921
- it('loads the previous candidate set using the configured recency window', async () => {
922
- setupSilentGithubSession();
923
-
924
- await useCase.run(
925
- runParams({ candidateDebounceRecencyWindowSeconds: 900 }),
926
- );
927
-
928
- expect(
929
- mockCandidateStateRepository.loadRecentCandidateSessionNames,
930
- ).toHaveBeenCalledWith({ now, recencyWindowSeconds: 900 });
931
- });
932
- });
933
-
934
- describe('repeated delivery while a session stays silent', () => {
935
- const setupSilentGithubSession = (): void => {
936
- setupLiveInteractiveSession(GITHUB_SESSION);
937
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
938
- [
939
- {
940
- sessionName: GITHUB_SESSION,
941
- lastOutputEpochSeconds:
942
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
943
- },
944
- ],
945
- );
946
- };
947
-
948
- it('sends the reminder again on the next cycle to a session that is still silent', async () => {
949
- setupSilentGithubSession();
950
-
951
- await useCase.run(runParams());
952
- await useCase.run(runParams());
953
-
954
- expect(
955
- mockNotificationRepository.sendSelfCheckNotification,
956
- ).toHaveBeenCalledTimes(2);
957
- expect(
958
- mockNotificationRepository.sendSelfCheckNotification,
959
- ).toHaveBeenNthCalledWith(1, GITHUB_SESSION, MAIN_STALLED_SECTION);
960
- expect(
961
- mockNotificationRepository.sendSelfCheckNotification,
962
- ).toHaveBeenNthCalledWith(2, GITHUB_SESSION, MAIN_STALLED_SECTION);
963
- });
964
-
965
- it('sends the reminder for a silent session even when its main REPL is mid-turn, because apparent busyness no longer defers delivery', async () => {
966
- setupSilentGithubSession();
967
-
968
- await useCase.run(runParams());
969
-
970
- expect(
971
- mockNotificationRepository.sendSelfCheckNotification,
972
- ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
973
- });
974
-
975
- it('keeps sending the reminder on every consecutive cycle the session stays silent', async () => {
976
- setupSilentGithubSession();
977
-
978
- await useCase.run(runParams());
979
- await useCase.run(runParams());
980
- await useCase.run(runParams());
981
- await useCase.run(runParams());
982
- await useCase.run(runParams());
983
-
984
- expect(
985
- mockNotificationRepository.sendSelfCheckNotification,
986
- ).toHaveBeenCalledTimes(5);
987
- });
988
- });
989
-
990
- describe('sub-agent state-based reminder judgment', () => {
991
- const hungSubAgent = (label: string): SubAgentActivity => ({
992
- label,
993
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
994
- runningSeconds: 60,
995
- waitingOnExternalProcess: false,
996
- finishedResultUnconsumed: false,
997
- });
998
- const waitingSubAgent = (label: string): SubAgentActivity => ({
999
- label,
1000
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
1001
- runningSeconds: 60,
1002
- waitingOnExternalProcess: true,
1003
- finishedResultUnconsumed: false,
1004
- });
1005
- const quietLongRunningSubAgent = (
1006
- label: string,
1007
- waitingOnExternalProcess: boolean,
1008
- ): SubAgentActivity => ({
1009
- label,
1010
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
1011
- runningSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
1012
- waitingOnExternalProcess,
1013
- finishedResultUnconsumed: false,
1014
- });
1015
- const producingLongRunningSubAgent = (label: string): SubAgentActivity => ({
1016
- label,
1017
- silentSeconds: 30,
1018
- runningSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
1019
- waitingOnExternalProcess: false,
1020
- finishedResultUnconsumed: false,
1021
- });
1022
-
1023
- const setupSubAgents = (subAgents: SubAgentActivity[]): void => {
1024
- setupLiveInteractiveSession(GITHUB_SESSION);
1025
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName.mockResolvedValue(
1026
- new Map([[GITHUB_SESSION, subAgents]]),
1027
- );
1028
- };
1029
-
1030
- it('reports every long-running sub-agent on runtime alone, whether it keeps producing output or waits on an external process', async () => {
1031
- setupSubAgents([
1032
- producingLongRunningSubAgent('sub-process-producing-output'),
1033
- quietLongRunningSubAgent('sub-process-waiting-on-external', true),
1034
- ]);
1035
-
1036
- await useCase.run(runParams());
1037
-
1038
- expect(mockMessageComposer.composeSubAgentSection).toHaveBeenCalledWith({
1039
- idleSubAgents: [],
1040
- longRunningSubAgents: [
1041
- producingLongRunningSubAgent('sub-process-producing-output'),
1042
- quietLongRunningSubAgent('sub-process-waiting-on-external', true),
1043
- ],
1044
- });
1045
- expect(
1046
- mockNotificationRepository.sendSelfCheckNotification,
1047
- ).toHaveBeenCalledWith(GITHUB_SESSION, SUBAGENT_SECTION);
1048
- });
1049
-
1050
- it('never selects a waiting sub-agent as a silent-reminder candidate', async () => {
1051
- setupSubAgents([waitingSubAgent('sub-process-1')]);
1052
-
1053
- await useCase.run(runParams());
1054
-
1055
- expect(mockMessageComposer.composeSubAgentSection).not.toHaveBeenCalled();
1056
- expect(
1057
- mockNotificationRepository.sendSelfCheckNotification,
1058
- ).not.toHaveBeenCalled();
1059
- });
1060
-
1061
- it('notifies a hung sub-agent whose in-flight tool has no live process', async () => {
1062
- setupSubAgents([hungSubAgent('sub-process-1')]);
1063
-
1064
- await useCase.run(runParams());
1065
-
1066
- expect(mockMessageComposer.composeSubAgentSection).toHaveBeenCalledWith({
1067
- idleSubAgents: [hungSubAgent('sub-process-1')],
1068
- longRunningSubAgents: [],
1069
- });
1070
- expect(
1071
- mockNotificationRepository.sendSelfCheckNotification,
1072
- ).toHaveBeenCalledWith(GITHUB_SESSION, SUBAGENT_SECTION);
1073
- });
1074
-
1075
- it('notifies a hung sub-agent again on every cycle it stays hung', async () => {
1076
- setupSubAgents([hungSubAgent('sub-process-1')]);
1077
-
1078
- await useCase.run(runParams());
1079
- await useCase.run(runParams());
1080
-
1081
- expect(
1082
- mockNotificationRepository.sendSelfCheckNotification,
1083
- ).toHaveBeenCalledTimes(2);
1084
- });
1085
-
1086
- const unconsumedResultSubAgent = (label: string): SubAgentActivity => ({
1087
- label,
1088
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
1089
- runningSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS + 60,
1090
- waitingOnExternalProcess: false,
1091
- finishedResultUnconsumed: true,
1092
- });
1093
- const justFinishedSubAgent = (label: string): SubAgentActivity => ({
1094
- label,
1095
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS - 1,
1096
- runningSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS + 60,
1097
- waitingOnExternalProcess: false,
1098
- finishedResultUnconsumed: true,
1099
- });
1100
-
1101
- const setupRecentlyProducingMainSession = (sessionName: string): void => {
1102
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
1103
- [{ sessionName, lastOutputEpochSeconds: nowEpochSeconds - 60 }],
1104
- );
1105
- };
1106
-
1107
- it('notifies a session whose finished sub-agent result stayed unconsumed past the threshold while the main session keeps producing output', async () => {
1108
- setupSubAgents([unconsumedResultSubAgent('agent-aaabbbbcccc30001')]);
1109
- setupRecentlyProducingMainSession(GITHUB_SESSION);
1110
-
1111
- await useCase.run(runParams());
1112
-
1113
- expect(
1114
- mockMessageComposer.composeSubAgentUnconsumedResultSection,
1115
- ).toHaveBeenCalledWith([
1116
- unconsumedResultSubAgent('agent-aaabbbbcccc30001'),
1117
- ]);
1118
- expect(
1119
- mockNotificationRepository.sendSelfCheckNotification,
1120
- ).toHaveBeenCalledWith(
1121
- GITHUB_SESSION,
1122
- SUBAGENT_UNCONSUMED_RESULT_SECTION,
1123
- );
1124
- });
1125
-
1126
- it('never selects a finished sub-agent whose result has been unconsumed for less than the threshold', async () => {
1127
- setupSubAgents([justFinishedSubAgent('agent-aaabbbbcccc30002')]);
1128
- setupRecentlyProducingMainSession(GITHUB_SESSION);
1129
-
1130
- await useCase.run(runParams());
1131
-
1132
- expect(
1133
- mockMessageComposer.composeSubAgentUnconsumedResultSection,
1134
- ).not.toHaveBeenCalled();
1135
- expect(
1136
- mockNotificationRepository.sendSelfCheckNotification,
1137
- ).not.toHaveBeenCalled();
1138
- });
1139
-
1140
- it('never selects a still-working idle sub-agent as an unconsumed result', async () => {
1141
- setupSubAgents([hungSubAgent('sub-process-1')]);
1142
-
1143
- await useCase.run(runParams());
1144
-
1145
- expect(
1146
- mockMessageComposer.composeSubAgentUnconsumedResultSection,
1147
- ).not.toHaveBeenCalled();
1148
- expect(mockMessageComposer.composeSubAgentSection).toHaveBeenCalledWith({
1149
- idleSubAgents: [hungSubAgent('sub-process-1')],
1150
- longRunningSubAgents: [],
1151
- });
1152
- });
1153
-
1154
- it('keeps an unconsumed finished sub-agent out of the idle and long-running sections', async () => {
1155
- setupSubAgents([unconsumedResultSubAgent('agent-aaabbbbcccc30003')]);
1156
-
1157
- await useCase.run(runParams());
1158
-
1159
- expect(mockMessageComposer.composeSubAgentSection).not.toHaveBeenCalled();
1160
- });
1161
-
1162
- it('delivers the idle section and the unconsumed-result section together when both conditions hold', async () => {
1163
- setupSubAgents([
1164
- hungSubAgent('sub-process-1'),
1165
- unconsumedResultSubAgent('agent-aaabbbbcccc30004'),
1166
- ]);
1167
-
1168
- await useCase.run(runParams());
1169
-
1170
- expect(
1171
- mockNotificationRepository.sendSelfCheckNotification,
1172
- ).toHaveBeenCalledWith(
1173
- GITHUB_SESSION,
1174
- `${SUBAGENT_SECTION}\n\n${SUBAGENT_UNCONSUMED_RESULT_SECTION}`,
1175
- );
1176
- });
1177
-
1178
- it('reports a waiting long-running sub-agent as long-running while keeping it out of the idle section', async () => {
1179
- setupSubAgents([quietLongRunningSubAgent('sub-process-1', true)]);
1180
-
1181
- await useCase.run(runParams());
1182
-
1183
- expect(mockMessageComposer.composeSubAgentSection).toHaveBeenCalledWith({
1184
- idleSubAgents: [],
1185
- longRunningSubAgents: [quietLongRunningSubAgent('sub-process-1', true)],
1186
- });
1187
- expect(
1188
- mockNotificationRepository.sendSelfCheckNotification,
1189
- ).toHaveBeenCalledWith(GITHUB_SESSION, SUBAGENT_SECTION);
1190
- });
1191
-
1192
- it('never selects a producing sub-agent that is one second short of the running threshold', async () => {
1193
- setupSubAgents([
1194
- {
1195
- ...producingLongRunningSubAgent('sub-process-1'),
1196
- runningSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS - 1,
1197
- },
1198
- ]);
1199
-
1200
- await useCase.run(runParams());
1201
-
1202
- expect(mockMessageComposer.composeSubAgentSection).not.toHaveBeenCalled();
1203
- expect(
1204
- mockNotificationRepository.sendSelfCheckNotification,
1205
- ).not.toHaveBeenCalled();
1206
- });
1207
-
1208
- it('includes a quiet long-running sub-agent in both the idle and long-running sections', async () => {
1209
- setupSubAgents([quietLongRunningSubAgent('sub-process-1', false)]);
1210
-
1211
- await useCase.run(runParams());
1212
-
1213
- expect(mockMessageComposer.composeSubAgentSection).toHaveBeenCalledWith({
1214
- idleSubAgents: [quietLongRunningSubAgent('sub-process-1', false)],
1215
- longRunningSubAgents: [
1216
- quietLongRunningSubAgent('sub-process-1', false),
1217
- ],
1218
- });
1219
- expect(
1220
- mockNotificationRepository.sendSelfCheckNotification,
1221
- ).toHaveBeenCalledWith(GITHUB_SESSION, SUBAGENT_SECTION);
1222
- });
1223
-
1224
- it('notifies a quiet long-running sub-agent again on every cycle while still evaluating it every cycle', async () => {
1225
- setupSubAgents([quietLongRunningSubAgent('sub-process-1', false)]);
1226
-
1227
- await useCase.run(runParams());
1228
- await useCase.run(runParams());
1229
-
1230
- expect(
1231
- mockNotificationRepository.sendSelfCheckNotification,
1232
- ).toHaveBeenCalledTimes(2);
1233
- expect(
1234
- mockMessageComposer.composeSubAgentSection,
1235
- ).toHaveBeenNthCalledWith(2, {
1236
- idleSubAgents: [quietLongRunningSubAgent('sub-process-1', false)],
1237
- longRunningSubAgents: [
1238
- quietLongRunningSubAgent('sub-process-1', false),
1239
- ],
1240
- });
1241
- });
1242
-
1243
- it('defers a first-cycle long-running candidate until it persists into the next cycle', async () => {
1244
- setupSubAgents([quietLongRunningSubAgent('sub-process-1', false)]);
1245
- mockCandidateStateRepository.loadRecentCandidateSessionNames.mockResolvedValue(
1246
- new Set<string>(),
1247
- );
1248
-
1249
- await useCase.run(runParams());
1250
-
1251
- expect(
1252
- mockNotificationRepository.sendSelfCheckNotification,
1253
- ).not.toHaveBeenCalled();
1254
- expect(
1255
- mockCandidateStateRepository.saveCandidateSessionNames,
1256
- ).toHaveBeenCalledWith({ sessionNames: [GITHUB_SESSION], now });
1257
- });
1258
-
1259
- it('stops notifying once the long-running sub-agent drops out of the activity snapshot', async () => {
1260
- setupSubAgents([quietLongRunningSubAgent('sub-process-1', false)]);
1261
-
1262
- await useCase.run(runParams());
1263
- expect(
1264
- mockNotificationRepository.sendSelfCheckNotification,
1265
- ).toHaveBeenCalledTimes(1);
1266
-
1267
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName.mockResolvedValue(
1268
- new Map<string, SubAgentActivity[]>(),
1269
- );
1270
- await useCase.run(runParams());
1271
-
1272
- expect(
1273
- mockNotificationRepository.sendSelfCheckNotification,
1274
- ).toHaveBeenCalledTimes(1);
1275
- });
1276
- });
1277
-
1278
- it('sends to multiple sessions sequentially with a stagger delay between sends', async () => {
1279
- mockSnapshotProvider.getSnapshot.mockResolvedValue(
1280
- snapshotWithSessions([GITHUB_SESSION_ALPHA, GITHUB_SESSION_BRAVO]),
1281
- );
1282
- mockTranscriptResolver.resolveTranscriptPaths.mockReturnValue(
1283
- transcriptMapFor([GITHUB_SESSION_ALPHA, GITHUB_SESSION_BRAVO]),
1284
- );
1285
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
1286
- [
1287
- {
1288
- sessionName: GITHUB_SESSION_ALPHA,
1289
- lastOutputEpochSeconds:
1290
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
1291
- },
1292
- {
1293
- sessionName: GITHUB_SESSION_BRAVO,
1294
- lastOutputEpochSeconds:
1295
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
1296
- },
1297
- ],
1298
- );
1299
-
1300
- const callOrder: string[] = [];
1301
- mockNotificationRepository.sendSelfCheckNotification.mockImplementation(
1302
- async (sessionName) => {
1303
- callOrder.push(`send:${sessionName}`);
1304
- },
1305
- );
1306
- mockSleeper.sleep.mockImplementation(async () => {
1307
- callOrder.push('sleep');
1308
- });
1309
-
1310
- await useCase.run(runParams());
1311
-
1312
- expect(callOrder).toEqual([
1313
- `send:${GITHUB_SESSION_ALPHA}`,
1314
- 'sleep',
1315
- `send:${GITHUB_SESSION_BRAVO}`,
1316
- ]);
1317
- expect(mockSleeper.sleep).toHaveBeenCalledTimes(1);
1318
- expect(mockSleeper.sleep).toHaveBeenCalledWith(
1319
- DEFAULT_NOTIFICATION_STAGGER_SECONDS * 1000,
1320
- );
1321
- });
1322
-
1323
- it('does not suppress errors raised while sending a notification', async () => {
1324
- setupLiveInteractiveSession(GITHUB_SESSION);
1325
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
1326
- [
1327
- {
1328
- sessionName: GITHUB_SESSION,
1329
- lastOutputEpochSeconds:
1330
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
1331
- },
1332
- ],
1333
- );
1334
- mockNotificationRepository.sendSelfCheckNotification.mockRejectedValue(
1335
- new Error('send-keys failed'),
1336
- );
1337
-
1338
- await expect(useCase.run(runParams())).rejects.toThrow('send-keys failed');
1339
- });
1340
-
1341
- describe('hub-task active-status pre-send gate', () => {
1342
- const HUB_TASK_SESSION = 'https://github.com/HiromiShikata/repo/issues/42';
1343
- const ACTIVE_STATUS = 'In tmux';
1344
-
1345
- it('sends when the hub task is open and in the active status', async () => {
1346
- setupSilentMainSession(HUB_TASK_SESSION);
1347
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
1348
- issueFor({
1349
- url: HUB_TASK_SESSION,
1350
- state: 'OPEN',
1351
- status: ACTIVE_STATUS,
1352
- }),
1353
- );
1354
-
1355
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1356
-
1357
- expect(mockHubTaskStatusResolver.getIssueByUrl).toHaveBeenCalledWith(
1358
- HUB_TASK_SESSION,
1359
- );
1360
- expect(
1361
- mockNotificationRepository.sendSelfCheckNotification,
1362
- ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
1363
- });
1364
-
1365
- it('skips when the hub task status differs from the active status', async () => {
1366
- setupSilentMainSession(HUB_TASK_SESSION);
1367
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
1368
- issueFor({ url: HUB_TASK_SESSION, state: 'OPEN', status: 'Todo' }),
1369
- );
1370
-
1371
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1372
-
1373
- expect(
1374
- mockNotificationRepository.sendSelfCheckNotification,
1375
- ).not.toHaveBeenCalled();
1376
- });
1377
-
1378
- it('skips when the hub task issue is closed', async () => {
1379
- setupSilentMainSession(HUB_TASK_SESSION);
1380
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
1381
- issueFor({
1382
- url: HUB_TASK_SESSION,
1383
- state: 'CLOSED',
1384
- status: ACTIVE_STATUS,
1385
- isClosed: true,
1386
- }),
1387
- );
1388
-
1389
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1390
-
1391
- expect(
1392
- mockNotificationRepository.sendSelfCheckNotification,
1393
- ).not.toHaveBeenCalled();
1394
- });
1395
-
1396
- it('does not consult the hub-task resolver for a role-named leader session that has no hub task URL, and still reminds it', async () => {
1397
- setupSilentMainSession('tdpm-cli');
1398
-
1399
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1400
-
1401
- expect(mockHubTaskStatusResolver.getIssueByUrl).not.toHaveBeenCalled();
1402
- expect(
1403
- mockNotificationRepository.sendSelfCheckNotification,
1404
- ).toHaveBeenCalledWith('tdpm-cli', MAIN_STALLED_SECTION);
1405
- });
1406
-
1407
- it('does not call the resolver at all when the active status is unconfigured', async () => {
1408
- setupSilentMainSession(HUB_TASK_SESSION);
1409
-
1410
- await useCase.run(runParams({ activeHubTaskStatus: null }));
1411
-
1412
- expect(mockHubTaskStatusResolver.getIssueByUrl).not.toHaveBeenCalled();
1413
- expect(
1414
- mockNotificationRepository.sendSelfCheckNotification,
1415
- ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
1416
- });
1417
-
1418
- it('fails open and logs a warning when status resolution throws', async () => {
1419
- setupSilentMainSession(HUB_TASK_SESSION);
1420
- const warnSpy = jest
1421
- .spyOn(console, 'warn')
1422
- .mockImplementation(() => undefined);
1423
- mockHubTaskStatusResolver.getIssueByUrl.mockRejectedValue(
1424
- new Error('GitHub API timeout'),
1425
- );
1426
-
1427
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1428
-
1429
- expect(
1430
- mockNotificationRepository.sendSelfCheckNotification,
1431
- ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
1432
- expect(warnSpy).toHaveBeenCalledWith(
1433
- expect.stringContaining('fail-open'),
1434
- );
1435
- warnSpy.mockRestore();
1436
- });
1437
-
1438
- it('fails open with a distinct no-cache warning when the hub task is not a resolvable tracked task and no cached status exists', async () => {
1439
- setupSilentMainSession(HUB_TASK_SESSION);
1440
- const warnSpy = jest
1441
- .spyOn(console, 'warn')
1442
- .mockImplementation(() => undefined);
1443
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(null);
1444
-
1445
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1446
-
1447
- expect(
1448
- mockNotificationRepository.sendSelfCheckNotification,
1449
- ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
1450
- expect(warnSpy).toHaveBeenCalledWith(
1451
- expect.stringContaining('no cached status'),
1452
- );
1453
- expect(warnSpy).toHaveBeenCalledWith(
1454
- expect.stringContaining('fail-open'),
1455
- );
1456
- warnSpy.mockRestore();
1457
- });
1458
-
1459
- it('gates on the real tmux session-name form by resolving its canonical issue URL', async () => {
1460
- const REAL_TMUX_SESSION =
1461
- 'https_//github_com/HiromiShikata/repo/issues/2355';
1462
- const CANONICAL_ISSUE_URL =
1463
- 'https://github.com/HiromiShikata/repo/issues/2355';
1464
- setupSilentMainSession(REAL_TMUX_SESSION);
1465
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
1466
- issueFor({
1467
- url: CANONICAL_ISSUE_URL,
1468
- state: 'OPEN',
1469
- status: ACTIVE_STATUS,
1470
- }),
1471
- );
1472
-
1473
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1474
-
1475
- expect(mockHubTaskStatusResolver.getIssueByUrl).toHaveBeenCalledWith(
1476
- CANONICAL_ISSUE_URL,
1477
- );
1478
- expect(
1479
- mockNotificationRepository.sendSelfCheckNotification,
1480
- ).toHaveBeenCalledWith(REAL_TMUX_SESSION, MAIN_STALLED_SECTION);
1481
- });
1482
-
1483
- it('skips the real tmux session-name form when its canonical hub task is no longer active', async () => {
1484
- const REAL_TMUX_SESSION =
1485
- 'https_//github_com/HiromiShikata/repo/issues/2355';
1486
- const CANONICAL_ISSUE_URL =
1487
- 'https://github.com/HiromiShikata/repo/issues/2355';
1488
- setupSilentMainSession(REAL_TMUX_SESSION);
1489
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
1490
- issueFor({
1491
- url: CANONICAL_ISSUE_URL,
1492
- state: 'OPEN',
1493
- status: 'Todo',
1494
- }),
1495
- );
1496
-
1497
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1498
-
1499
- expect(mockHubTaskStatusResolver.getIssueByUrl).toHaveBeenCalledWith(
1500
- CANONICAL_ISSUE_URL,
1501
- );
1502
- expect(
1503
- mockNotificationRepository.sendSelfCheckNotification,
1504
- ).not.toHaveBeenCalled();
1505
- });
1506
-
1507
- it('fails open without throwing for a real tmux session-name form whose repository is unresolvable and has no cached status', async () => {
1508
- const REAL_TMUX_SESSION =
1509
- 'https_//github_com/example-org/example-repo/issues/2350';
1510
- const CANONICAL_ISSUE_URL =
1511
- 'https://github.com/example-org/example-repo/issues/2350';
1512
- setupSilentMainSession(REAL_TMUX_SESSION);
1513
- const warnSpy = jest
1514
- .spyOn(console, 'warn')
1515
- .mockImplementation(() => undefined);
1516
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(null);
1517
-
1518
- await expect(
1519
- useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS })),
1520
- ).resolves.toBeUndefined();
1521
-
1522
- expect(mockHubTaskStatusResolver.getIssueByUrl).toHaveBeenCalledWith(
1523
- CANONICAL_ISSUE_URL,
1524
- );
1525
- expect(
1526
- mockNotificationRepository.sendSelfCheckNotification,
1527
- ).toHaveBeenCalledWith(REAL_TMUX_SESSION, MAIN_STALLED_SECTION);
1528
- expect(warnSpy).toHaveBeenCalledWith(
1529
- expect.stringContaining('no cached status'),
1530
- );
1531
- warnSpy.mockRestore();
1532
- });
1533
-
1534
- it('suppresses a resolved CLOSED hub task and writes the resolved status to the cache', async () => {
1535
- setupSilentMainSession(HUB_TASK_SESSION);
1536
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
1537
- issueFor({
1538
- url: HUB_TASK_SESSION,
1539
- state: 'CLOSED',
1540
- status: ACTIVE_STATUS,
1541
- isClosed: true,
1542
- }),
1543
- );
1544
-
1545
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1546
-
1547
- expect(
1548
- mockNotificationRepository.sendSelfCheckNotification,
1549
- ).not.toHaveBeenCalled();
1550
- expect(
1551
- mockHubTaskStatusCacheRepository.saveHubTaskStatus,
1552
- ).toHaveBeenCalledWith({
1553
- url: HUB_TASK_SESSION,
1554
- state: 'CLOSED',
1555
- status: ACTIVE_STATUS,
1556
- now,
1557
- });
1558
- });
1559
-
1560
- it('suppresses a resolved Done (non-active project status) hub task', async () => {
1561
- setupSilentMainSession(HUB_TASK_SESSION);
1562
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
1563
- issueFor({ url: HUB_TASK_SESSION, state: 'OPEN', status: 'Done' }),
1564
- );
1565
-
1566
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1567
-
1568
- expect(
1569
- mockNotificationRepository.sendSelfCheckNotification,
1570
- ).not.toHaveBeenCalled();
1571
- });
1572
-
1573
- it('sends a resolved active hub task and writes its status to the cache', async () => {
1574
- setupSilentMainSession(HUB_TASK_SESSION);
1575
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
1576
- issueFor({
1577
- url: HUB_TASK_SESSION,
1578
- state: 'OPEN',
1579
- status: ACTIVE_STATUS,
1580
- }),
1581
- );
1582
-
1583
- await useCase.run(runParams({ activeHubTaskStatus: ACTIVE_STATUS }));
1584
-
1585
- expect(
1586
- mockNotificationRepository.sendSelfCheckNotification,
1587
- ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
1588
- expect(
1589
- mockHubTaskStatusCacheRepository.saveHubTaskStatus,
1590
- ).toHaveBeenCalledWith({
1591
- url: HUB_TASK_SESSION,
1592
- state: 'OPEN',
1593
- status: ACTIVE_STATUS,
1594
- now,
1595
- });
1596
- });
1597
-
1598
- it('decides from a fresh cached entry without consulting the resolver', async () => {
1599
- setupSilentMainSession(HUB_TASK_SESSION);
1600
- mockHubTaskStatusCacheRepository.loadHubTaskStatus.mockResolvedValue({
1601
- url: HUB_TASK_SESSION,
1602
- state: 'OPEN',
1603
- status: ACTIVE_STATUS,
1604
- recordedEpochSeconds: nowEpochSeconds - 60,
1605
- });
1606
-
1607
- await useCase.run(
1608
- runParams({
1609
- activeHubTaskStatus: ACTIVE_STATUS,
1610
- hubTaskStatusCacheTtlSeconds: 300,
1611
- }),
1612
- );
1613
-
1614
- expect(mockHubTaskStatusResolver.getIssueByUrl).not.toHaveBeenCalled();
1615
- expect(
1616
- mockHubTaskStatusCacheRepository.saveHubTaskStatus,
1617
- ).not.toHaveBeenCalled();
1618
- expect(
1619
- mockNotificationRepository.sendSelfCheckNotification,
1620
- ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
1621
- });
1622
-
1623
- it('suppresses from a fresh cached closed entry without consulting the resolver', async () => {
1624
- setupSilentMainSession(HUB_TASK_SESSION);
1625
- mockHubTaskStatusCacheRepository.loadHubTaskStatus.mockResolvedValue({
1626
- url: HUB_TASK_SESSION,
1627
- state: 'CLOSED',
1628
- status: ACTIVE_STATUS,
1629
- recordedEpochSeconds: nowEpochSeconds - 60,
1630
- });
1631
-
1632
- await useCase.run(
1633
- runParams({
1634
- activeHubTaskStatus: ACTIVE_STATUS,
1635
- hubTaskStatusCacheTtlSeconds: 300,
1636
- }),
1637
- );
1638
-
1639
- expect(mockHubTaskStatusResolver.getIssueByUrl).not.toHaveBeenCalled();
1640
- expect(
1641
- mockNotificationRepository.sendSelfCheckNotification,
1642
- ).not.toHaveBeenCalled();
1643
- });
1644
-
1645
- it('re-resolves when the cached entry is older than the configured time-to-live', async () => {
1646
- setupSilentMainSession(HUB_TASK_SESSION);
1647
- mockHubTaskStatusCacheRepository.loadHubTaskStatus.mockResolvedValue({
1648
- url: HUB_TASK_SESSION,
1649
- state: 'OPEN',
1650
- status: ACTIVE_STATUS,
1651
- recordedEpochSeconds: nowEpochSeconds - 600,
1652
- });
1653
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(
1654
- issueFor({
1655
- url: HUB_TASK_SESSION,
1656
- state: 'OPEN',
1657
- status: ACTIVE_STATUS,
1658
- }),
1659
- );
1660
-
1661
- await useCase.run(
1662
- runParams({
1663
- activeHubTaskStatus: ACTIVE_STATUS,
1664
- hubTaskStatusCacheTtlSeconds: 300,
1665
- }),
1666
- );
1667
-
1668
- expect(mockHubTaskStatusResolver.getIssueByUrl).toHaveBeenCalledWith(
1669
- HUB_TASK_SESSION,
1670
- );
1671
- expect(
1672
- mockNotificationRepository.sendSelfCheckNotification,
1673
- ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
1674
- });
1675
-
1676
- it('falls back to an expired cached active entry and still sends when live resolution returns null', async () => {
1677
- setupSilentMainSession(HUB_TASK_SESSION);
1678
- mockHubTaskStatusCacheRepository.loadHubTaskStatus.mockResolvedValue({
1679
- url: HUB_TASK_SESSION,
1680
- state: 'OPEN',
1681
- status: ACTIVE_STATUS,
1682
- recordedEpochSeconds: nowEpochSeconds - 600,
1683
- });
1684
- mockHubTaskStatusResolver.getIssueByUrl.mockResolvedValue(null);
1685
-
1686
- await useCase.run(
1687
- runParams({
1688
- activeHubTaskStatus: ACTIVE_STATUS,
1689
- hubTaskStatusCacheTtlSeconds: 300,
1690
- }),
1691
- );
1692
-
1693
- expect(
1694
- mockNotificationRepository.sendSelfCheckNotification,
1695
- ).toHaveBeenCalledWith(HUB_TASK_SESSION, MAIN_STALLED_SECTION);
1696
- });
1697
-
1698
- it('falls back to an expired cached closed entry and suppresses when live resolution throws', async () => {
1699
- setupSilentMainSession(HUB_TASK_SESSION);
1700
- const warnSpy = jest
1701
- .spyOn(console, 'warn')
1702
- .mockImplementation(() => undefined);
1703
- mockHubTaskStatusCacheRepository.loadHubTaskStatus.mockResolvedValue({
1704
- url: HUB_TASK_SESSION,
1705
- state: 'CLOSED',
1706
- status: ACTIVE_STATUS,
1707
- recordedEpochSeconds: nowEpochSeconds - 600,
1708
- });
1709
- mockHubTaskStatusResolver.getIssueByUrl.mockRejectedValue(
1710
- new Error('GraphQL rate limit'),
1711
- );
1712
-
1713
- await useCase.run(
1714
- runParams({
1715
- activeHubTaskStatus: ACTIVE_STATUS,
1716
- hubTaskStatusCacheTtlSeconds: 300,
1717
- }),
1718
- );
1719
-
1720
- expect(
1721
- mockNotificationRepository.sendSelfCheckNotification,
1722
- ).not.toHaveBeenCalled();
1723
- expect(warnSpy).toHaveBeenCalledWith(
1724
- expect.stringContaining('expired cached status'),
1725
- );
1726
- warnSpy.mockRestore();
1727
- });
1728
-
1729
- it('parses a clean github.com issue URL session name and rejects non-github names', () => {
1730
- expect(parseHubTaskIssueUrlFromSessionName(HUB_TASK_SESSION)).toBe(
1731
- HUB_TASK_SESSION,
1732
- );
1733
- expect(parseHubTaskIssueUrlFromSessionName('workbench')).toBeNull();
1734
- expect(
1735
- parseHubTaskIssueUrlFromSessionName(
1736
- 'https://example.com/HiromiShikata/repo/issues/42',
1737
- ),
1738
- ).toBeNull();
1739
- });
1740
-
1741
- it('parses the real tmux session-name form produced by toTmuxSessionName for an issue', () => {
1742
- expect(
1743
- parseHubTaskIssueUrlFromSessionName(
1744
- 'https_//github_com/HiromiShikata/repo/issues/2355',
1745
- ),
1746
- ).toBe('https://github.com/HiromiShikata/repo/issues/2355');
1747
- });
1748
-
1749
- it('parses the real tmux session-name form for a pull request', () => {
1750
- expect(
1751
- parseHubTaskIssueUrlFromSessionName(
1752
- 'https_//github_com/HiromiShikata/repo/pull/2474',
1753
- ),
1754
- ).toBe('https://github.com/HiromiShikata/repo/pull/2474');
1755
- });
1756
-
1757
- it('accepts a clean github.com pull URL session name', () => {
1758
- expect(
1759
- parseHubTaskIssueUrlFromSessionName(
1760
- 'https://github.com/HiromiShikata/repo/pull/42',
1761
- ),
1762
- ).toBe('https://github.com/HiromiShikata/repo/pull/42');
1763
- });
1764
-
1765
- it('rejects an encoded non-github host or a non-issue/pull path', () => {
1766
- expect(
1767
- parseHubTaskIssueUrlFromSessionName(
1768
- 'https_//example_com/HiromiShikata/repo/issues/42',
1769
- ),
1770
- ).toBeNull();
1771
- expect(
1772
- parseHubTaskIssueUrlFromSessionName(
1773
- 'https_//github_com/HiromiShikata/repo/discussions/42',
1774
- ),
1775
- ).toBeNull();
1776
- });
1777
- });
1778
-
1779
- describe('refusal-tailed session gating', () => {
1780
- it('excludes a main-stalled session whose last assistant turn is a refusal and logs one skip line', async () => {
1781
- setupSilentMainSession(GITHUB_SESSION);
1782
- mockRefusalTailStatusProvider.listRefusalTailedSessionNames.mockResolvedValue(
1783
- new Set([GITHUB_SESSION]),
1784
- );
1785
-
1786
- await useCase.run(runParams());
1787
-
1788
- expect(
1789
- mockMessageComposer.composeMainStalledSection,
1790
- ).not.toHaveBeenCalled();
1791
- expect(
1792
- mockNotificationRepository.sendSelfCheckNotification,
1793
- ).not.toHaveBeenCalled();
1794
- const skipLines = jest
1795
- .mocked(console.log)
1796
- .mock.calls.filter(
1797
- (call) =>
1798
- typeof call[0] === 'string' &&
1799
- call[0].includes('last assistant turn was a model refusal'),
1800
- );
1801
- expect(skipLines).toEqual([
1802
- [
1803
- `Skipping ${GITHUB_SESSION}: last assistant turn was a model refusal; suppressing reminders until a non-refusal turn appears.`,
1804
- ],
1805
- ]);
1806
- });
1807
-
1808
- it('excludes a refusal-tailed session from the sub-agent reminder branch as well', async () => {
1809
- setupLiveInteractiveSession(GITHUB_SESSION);
1810
- const subAgents: SubAgentActivity[] = [
1811
- {
1812
- label: 'sub-process-1',
1813
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
1814
- runningSeconds: 60,
1815
- waitingOnExternalProcess: false,
1816
- finishedResultUnconsumed: false,
1817
- },
1818
- ];
1819
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName.mockResolvedValue(
1820
- new Map([[GITHUB_SESSION, subAgents]]),
1821
- );
1822
- mockRefusalTailStatusProvider.listRefusalTailedSessionNames.mockResolvedValue(
1823
- new Set([GITHUB_SESSION]),
1824
- );
1825
-
1826
- await useCase.run(runParams());
1827
-
1828
- expect(mockMessageComposer.composeSubAgentSection).not.toHaveBeenCalled();
1829
- expect(
1830
- mockNotificationRepository.sendSelfCheckNotification,
1831
- ).not.toHaveBeenCalled();
1832
- expect(
1833
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName,
1834
- ).toHaveBeenCalledWith([], transcriptMapFor([GITHUB_SESSION]));
1835
- });
1836
-
1837
- it('passes the resolved transcript paths to the refusal-tail provider', async () => {
1838
- setupSilentMainSession(GITHUB_SESSION);
1839
-
1840
- await useCase.run(runParams());
1841
-
1842
- expect(
1843
- mockRefusalTailStatusProvider.listRefusalTailedSessionNames,
1844
- ).toHaveBeenCalledWith(transcriptMapFor([GITHUB_SESSION]));
1845
- });
1846
-
1847
- it('notifies a session again once the provider stops reporting it (a non-refusal turn followed the refusal)', async () => {
1848
- setupSilentMainSession(GITHUB_SESSION);
1849
- mockRefusalTailStatusProvider.listRefusalTailedSessionNames.mockResolvedValue(
1850
- new Set<string>(),
1851
- );
1852
-
1853
- await useCase.run(runParams());
1854
-
1855
- expect(
1856
- mockNotificationRepository.sendSelfCheckNotification,
1857
- ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
1858
- });
1859
-
1860
- it('excludes only the refusal-tailed session when mixed with a healthy stalled session', async () => {
1861
- mockSnapshotProvider.getSnapshot.mockResolvedValue(
1862
- snapshotWithSessions([GITHUB_SESSION_ALPHA, GITHUB_SESSION_BRAVO]),
1863
- );
1864
- mockTranscriptResolver.resolveTranscriptPaths.mockReturnValue(
1865
- transcriptMapFor([GITHUB_SESSION_ALPHA, GITHUB_SESSION_BRAVO]),
1866
- );
1867
- mockSessionOutputActivityRepository.listSessionOutputActivities.mockResolvedValue(
1868
- [
1869
- {
1870
- sessionName: GITHUB_SESSION_ALPHA,
1871
- lastOutputEpochSeconds:
1872
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
1873
- },
1874
- {
1875
- sessionName: GITHUB_SESSION_BRAVO,
1876
- lastOutputEpochSeconds:
1877
- nowEpochSeconds - DEFAULT_MAIN_SILENT_THRESHOLD_SECONDS,
1878
- },
1879
- ],
1880
- );
1881
- mockRefusalTailStatusProvider.listRefusalTailedSessionNames.mockResolvedValue(
1882
- new Set([GITHUB_SESSION_ALPHA]),
1883
- );
1884
-
1885
- await useCase.run(runParams());
1886
-
1887
- expect(
1888
- mockNotificationRepository.sendSelfCheckNotification,
1889
- ).toHaveBeenCalledTimes(1);
1890
- expect(
1891
- mockNotificationRepository.sendSelfCheckNotification,
1892
- ).toHaveBeenCalledWith(GITHUB_SESSION_BRAVO, MAIN_STALLED_SECTION);
1893
- });
1894
-
1895
- it('keeps the existing behavior when no refusal-tail provider is configured', async () => {
1896
- const useCaseWithoutProvider = new NotifySilentLiveSessionsUseCase(
1897
- mockSnapshotProvider,
1898
- mockTranscriptResolver,
1899
- mockSessionOutputActivityRepository,
1900
- mockSubAgentActivityRepository,
1901
- mockOwnerCallStatusProvider,
1902
- mockNotificationRepository,
1903
- mockCandidateStateRepository,
1904
- mockMessageComposer,
1905
- mockSleeper,
1906
- mockHubTaskStatusResolver,
1907
- mockHubTaskStatusCacheRepository,
1908
- );
1909
- setupSilentMainSession(GITHUB_SESSION);
1910
-
1911
- await useCaseWithoutProvider.run(runParams());
1912
-
1913
- expect(
1914
- mockNotificationRepository.sendSelfCheckNotification,
1915
- ).toHaveBeenCalledWith(GITHUB_SESSION, MAIN_STALLED_SECTION);
1916
- });
1917
- });
1918
-
1919
- describe('per-send observability log line', () => {
1920
- const notifiedLogLines = (): string[] =>
1921
- jest
1922
- .mocked(console.log)
1923
- .mock.calls.map((call): unknown => call[0])
1924
- .filter(
1925
- (line): line is string =>
1926
- typeof line === 'string' && line.startsWith('Notified '),
1927
- );
1928
-
1929
- it('logs the timestamp and the main-stalled section type on a main-stall send', async () => {
1930
- setupSilentMainSession(GITHUB_SESSION);
1931
-
1932
- await useCase.run(runParams());
1933
-
1934
- expect(notifiedLogLines()).toEqual([
1935
- `Notified ${GITHUB_SESSION} at=${now.toISOString()} sections=[main-stalled]`,
1936
- ]);
1937
- });
1938
-
1939
- it('logs sub-agent section types with their sub-agent labels', async () => {
1940
- setupLiveInteractiveSession(GITHUB_SESSION);
1941
- const idleOnlySubAgent: SubAgentActivity = {
1942
- label: 'agent-idle-1',
1943
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
1944
- runningSeconds: 60,
1945
- waitingOnExternalProcess: false,
1946
- finishedResultUnconsumed: false,
1947
- };
1948
- const quietLongRunningSubAgent: SubAgentActivity = {
1949
- label: 'agent-long-1',
1950
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
1951
- runningSeconds: DEFAULT_SUBAGENT_RUNNING_THRESHOLD_SECONDS,
1952
- waitingOnExternalProcess: false,
1953
- finishedResultUnconsumed: false,
1954
- };
1955
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName.mockResolvedValue(
1956
- new Map([
1957
- [GITHUB_SESSION, [idleOnlySubAgent, quietLongRunningSubAgent]],
1958
- ]),
1959
- );
1960
-
1961
- await useCase.run(runParams());
1962
-
1963
- expect(notifiedLogLines()).toEqual([
1964
- `Notified ${GITHUB_SESSION} at=${now.toISOString()} sections=[sub-agent-idle:agent-idle-1,sub-agent-idle:agent-long-1,sub-agent-long-running:agent-long-1]`,
1965
- ]);
1966
- });
1967
-
1968
- it('logs both the main-stalled and sub-agent section types on a combined send', async () => {
1969
- setupSilentMainSession(GITHUB_SESSION);
1970
- mockSubAgentActivityRepository.listSubAgentActivitiesBySessionName.mockResolvedValue(
1971
- new Map([
1972
- [
1973
- GITHUB_SESSION,
1974
- [
1975
- {
1976
- label: 'agent-idle-1',
1977
- silentSeconds: DEFAULT_SUBAGENT_SILENT_THRESHOLD_SECONDS,
1978
- runningSeconds: 60,
1979
- waitingOnExternalProcess: false,
1980
- finishedResultUnconsumed: false,
1981
- },
1982
- ],
1983
- ],
1984
- ]),
1985
- );
1986
-
1987
- await useCase.run(runParams());
1988
-
1989
- expect(notifiedLogLines()).toEqual([
1990
- `Notified ${GITHUB_SESSION} at=${now.toISOString()} sections=[main-stalled,sub-agent-idle:agent-idle-1]`,
1991
- ]);
1992
- });
1993
- });
1994
-
1995
- describe('isGitHubIssueOrPullRequestSessionName', () => {
1996
- it('accepts the encoded form of a github.com issue URL session name', () => {
1997
- expect(
1998
- isGitHubIssueOrPullRequestSessionName(
1999
- 'https_//github_com/HiromiShikata/repo/issues/42',
2000
- ),
2001
- ).toBe(true);
2002
- });
2003
-
2004
- it('accepts the encoded form of a github.com pull-request URL session name', () => {
2005
- expect(
2006
- isGitHubIssueOrPullRequestSessionName(
2007
- 'https_//github_com/HiromiShikata/repo/pull/77',
2008
- ),
2009
- ).toBe(true);
2010
- });
2011
-
2012
- it('accepts the raw form of a github.com issue and pull-request URL session name', () => {
2013
- expect(
2014
- isGitHubIssueOrPullRequestSessionName(
2015
- 'https://github.com/HiromiShikata/repo/issues/42',
2016
- ),
2017
- ).toBe(true);
2018
- expect(
2019
- isGitHubIssueOrPullRequestSessionName(
2020
- 'https://github.com/HiromiShikata/repo/pull/77',
2021
- ),
2022
- ).toBe(true);
2023
- });
2024
-
2025
- it('rejects a plain orchestrator-style session name', () => {
2026
- expect(isGitHubIssueOrPullRequestSessionName('workbench')).toBe(false);
2027
- expect(isGitHubIssueOrPullRequestSessionName('orchestrator')).toBe(false);
2028
- expect(isGitHubIssueOrPullRequestSessionName('aw-host')).toBe(false);
2029
- });
2030
-
2031
- it('rejects a non-github host even in the encoded form', () => {
2032
- expect(
2033
- isGitHubIssueOrPullRequestSessionName(
2034
- 'https_//example_com/HiromiShikata/repo/issues/42',
2035
- ),
2036
- ).toBe(false);
2037
- });
2038
-
2039
- it('rejects a github.com session name that is neither an issue nor a pull request', () => {
2040
- expect(
2041
- isGitHubIssueOrPullRequestSessionName(
2042
- 'https_//github_com/HiromiShikata/repo',
2043
- ),
2044
- ).toBe(false);
2045
- expect(
2046
- isGitHubIssueOrPullRequestSessionName(
2047
- 'https_//github_com/HiromiShikata/repo/discussions/42',
2048
- ),
2049
- ).toBe(false);
2050
- });
2051
-
2052
- it('rejects a github.com issue URL whose trailing segment is not a number', () => {
2053
- expect(
2054
- isGitHubIssueOrPullRequestSessionName(
2055
- 'https_//github_com/HiromiShikata/repo/issues/new',
2056
- ),
2057
- ).toBe(false);
2058
- });
2059
- });
2060
-
2061
- it('uses the session entity helper for type completeness', () => {
2062
- expect(sessionFor('workbench')).toEqual({
2063
- sessionName: 'workbench',
2064
- sessionId: 'workbench-uuid',
2065
- candidateSessionIds: ['workbench-uuid'],
2066
- configDir: '/config/workbench',
2067
- });
2068
- });
2069
- });