switchroom 0.7.15 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/README.md +51 -59
  2. package/bin/run-hook.sh +27 -11
  3. package/bin/timezone-hook.sh +9 -7
  4. package/dist/agent-scheduler/index.js +410 -133
  5. package/dist/auth-broker/index.js +13932 -0
  6. package/dist/cli/switchroom.js +26937 -5601
  7. package/dist/host-control/main.js +12702 -0
  8. package/dist/vault/approvals/kernel-server.js +467 -184
  9. package/dist/vault/broker/server.js +1430 -724
  10. package/examples/minimal.yaml +63 -0
  11. package/examples/personal-google-workspace-mcp/.env.example +34 -0
  12. package/examples/personal-google-workspace-mcp/README.md +194 -0
  13. package/examples/personal-google-workspace-mcp/compose.yaml +66 -0
  14. package/examples/switchroom.yaml +220 -0
  15. package/package.json +7 -4
  16. package/profiles/_base/settings.json.hbs +20 -5
  17. package/profiles/_base/start.sh.hbs +16 -3
  18. package/profiles/_shared/agent-self-service.md.hbs +126 -0
  19. package/profiles/_shared/telegram-style.md.hbs +20 -90
  20. package/profiles/_shared/vault-protocol.md.hbs +68 -0
  21. package/profiles/default/CLAUDE.md +50 -96
  22. package/profiles/default/CLAUDE.md.hbs +36 -6
  23. package/profiles/default/workspace/SOUL.md.hbs +12 -5
  24. package/skills/buildkite-agent-infrastructure/SKILL.md +30 -11
  25. package/skills/buildkite-agent-runtime/SKILL.md +44 -11
  26. package/skills/buildkite-api/SKILL.md +31 -8
  27. package/skills/buildkite-cli/SKILL.md +27 -9
  28. package/skills/buildkite-migration/SKILL.md +22 -9
  29. package/skills/buildkite-pipelines/SKILL.md +26 -9
  30. package/skills/buildkite-secure-delivery/SKILL.md +23 -9
  31. package/skills/buildkite-test-engine/SKILL.md +25 -8
  32. package/skills/docx/SKILL.md +1 -1
  33. package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-313.pyc +0 -0
  34. package/skills/docx/scripts/office/validators/__pycache__/base.cpython-313.pyc +0 -0
  35. package/skills/file-bug/SKILL.md +34 -6
  36. package/skills/humanizer/SKILL.md +15 -0
  37. package/skills/humanizer-calibrate/SKILL.md +7 -1
  38. package/skills/mcp-builder/SKILL.md +1 -1
  39. package/skills/pdf/SKILL.md +1 -1
  40. package/skills/pptx/SKILL.md +1 -1
  41. package/skills/skill-creator/SKILL.md +21 -1
  42. package/skills/skill-creator/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
  43. package/skills/skill-creator/scripts/__pycache__/generate_report.cpython-313.pyc +0 -0
  44. package/skills/skill-creator/scripts/__pycache__/improve_description.cpython-313.pyc +0 -0
  45. package/skills/skill-creator/scripts/__pycache__/run_eval.cpython-313.pyc +0 -0
  46. package/skills/skill-creator/scripts/__pycache__/run_loop.cpython-313.pyc +0 -0
  47. package/skills/skill-creator/scripts/__pycache__/utils.cpython-313.pyc +0 -0
  48. package/skills/switchroom-cli/SKILL.md +63 -64
  49. package/skills/switchroom-health/SKILL.md +23 -10
  50. package/skills/switchroom-install/SKILL.md +3 -3
  51. package/skills/switchroom-manage/SKILL.md +26 -19
  52. package/skills/switchroom-runtime/SKILL.md +191 -0
  53. package/skills/switchroom-status/SKILL.md +27 -2
  54. package/skills/telegram-test-harness/SKILL.md +3 -0
  55. package/skills/token-helpers/SKILL.md +24 -1
  56. package/skills/webapp-testing/SKILL.md +31 -1
  57. package/skills/xlsx/SKILL.md +1 -1
  58. package/telegram-plugin/admin-commands/index.ts +7 -5
  59. package/telegram-plugin/analytics-posthog.ts +191 -0
  60. package/telegram-plugin/bridge/bridge.ts +69 -0
  61. package/telegram-plugin/bridge/ipc-client.ts +4 -1
  62. package/telegram-plugin/dist/bridge/bridge.js +194 -119
  63. package/telegram-plugin/dist/gateway/gateway.js +23611 -19671
  64. package/telegram-plugin/dist/server.js +245 -189
  65. package/telegram-plugin/first-paint.ts +3 -24
  66. package/telegram-plugin/gateway/auth-add-flow.ts +326 -0
  67. package/telegram-plugin/gateway/auth-broker-client.ts +75 -0
  68. package/telegram-plugin/gateway/auth-command.ts +794 -0
  69. package/telegram-plugin/gateway/auth-line.ts +123 -0
  70. package/telegram-plugin/gateway/boot-card.ts +169 -40
  71. package/telegram-plugin/gateway/boot-issue-cache.ts +308 -0
  72. package/telegram-plugin/gateway/boot-probes.ts +166 -123
  73. package/telegram-plugin/gateway/boot-reason.ts +41 -7
  74. package/telegram-plugin/gateway/boot-version.ts +66 -0
  75. package/telegram-plugin/gateway/gateway.ts +3499 -1885
  76. package/telegram-plugin/gateway/hostd-dispatch.ts +117 -0
  77. package/telegram-plugin/gateway/ipc-protocol.ts +18 -0
  78. package/telegram-plugin/gateway/pending-inbound-buffer.ts +106 -0
  79. package/telegram-plugin/gateway/quarantine.ts +69 -0
  80. package/telegram-plugin/gateway/quota-cache.ts +9 -4
  81. package/telegram-plugin/gateway/reaction-trigger.ts +401 -0
  82. package/telegram-plugin/gateway/recent-denials.test.ts +103 -0
  83. package/telegram-plugin/gateway/recent-denials.ts +77 -0
  84. package/telegram-plugin/gateway/startup-network-retry.ts +109 -31
  85. package/telegram-plugin/gateway/vault-grant-inbound-builders.ts +125 -0
  86. package/telegram-plugin/history.ts +91 -0
  87. package/telegram-plugin/hooks/hooks.json +10 -0
  88. package/telegram-plugin/hooks/sandbox-hint-posttool.mjs +130 -0
  89. package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +19 -2
  90. package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +22 -2
  91. package/telegram-plugin/hooks/tool-label-pretool.mjs +11 -0
  92. package/telegram-plugin/hooks/wedge-detect-posttool.mjs +303 -0
  93. package/telegram-plugin/inbound-classifier.ts +50 -0
  94. package/telegram-plugin/inline-keyboard-callbacks.ts +136 -0
  95. package/telegram-plugin/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  96. package/telegram-plugin/package.json +4 -2
  97. package/telegram-plugin/permission-rule.ts +51 -0
  98. package/telegram-plugin/permission-title.ts +56 -0
  99. package/telegram-plugin/quota-check.ts +19 -41
  100. package/telegram-plugin/registry/reaper.ts +223 -0
  101. package/telegram-plugin/retry-api-call.ts +80 -0
  102. package/telegram-plugin/runtime-metrics.ts +177 -0
  103. package/telegram-plugin/scripts/build.mjs +0 -1
  104. package/telegram-plugin/secret-detect/index.ts +24 -0
  105. package/telegram-plugin/secret-detect/vault-error.test.ts +64 -12
  106. package/telegram-plugin/secret-detect/vault-error.ts +78 -11
  107. package/telegram-plugin/secret-detect/vault-write.ts +14 -2
  108. package/telegram-plugin/server.js +41795 -0
  109. package/telegram-plugin/session-tail.ts +6 -1
  110. package/telegram-plugin/shared/bot-runtime.ts +5 -4
  111. package/telegram-plugin/silence-poke.ts +420 -0
  112. package/telegram-plugin/silent-end.ts +174 -0
  113. package/telegram-plugin/stream-controller.ts +13 -0
  114. package/telegram-plugin/stream-reply-handler.ts +7 -0
  115. package/telegram-plugin/subagent-watcher.ts +213 -4
  116. package/telegram-plugin/tests/auth-add-flow.test.ts +559 -0
  117. package/telegram-plugin/tests/auth-code-redact.test.ts +8 -4
  118. package/telegram-plugin/tests/auth-command-vernacular.test.ts +531 -0
  119. package/telegram-plugin/tests/boot-card-issue-dedup.test.ts +247 -0
  120. package/telegram-plugin/tests/boot-card-reason-to-render.test.ts +182 -0
  121. package/telegram-plugin/tests/boot-card-reason.test.ts +65 -2
  122. package/telegram-plugin/tests/boot-card-render.test.ts +146 -0
  123. package/telegram-plugin/tests/boot-card-silent-on-operator.test.ts +103 -0
  124. package/telegram-plugin/tests/boot-probes.test.ts +216 -10
  125. package/telegram-plugin/tests/boot-version-string.test.ts +0 -0
  126. package/telegram-plugin/tests/finalize-callback.test.ts +190 -0
  127. package/telegram-plugin/tests/gateway-message-validator.test.ts +26 -0
  128. package/telegram-plugin/tests/gateway-secret-detect.test.ts +12 -3
  129. package/telegram-plugin/tests/gateway-startup-network-retry.test.ts +104 -0
  130. package/telegram-plugin/tests/history-reaper.test.ts +378 -0
  131. package/telegram-plugin/tests/hostd-dispatch.test.ts +129 -0
  132. package/telegram-plugin/tests/inbound-classifier.test.ts +76 -0
  133. package/telegram-plugin/tests/inbound-message-types.test.ts +267 -0
  134. package/telegram-plugin/tests/issues-card.test.ts +49 -0
  135. package/telegram-plugin/tests/pending-inbound-buffer.test.ts +132 -0
  136. package/telegram-plugin/tests/permission-rule.test.ts +80 -1
  137. package/telegram-plugin/tests/permission-title.test.ts +31 -0
  138. package/telegram-plugin/tests/quota-check.test.ts +5 -35
  139. package/telegram-plugin/tests/races.test.ts +179 -0
  140. package/telegram-plugin/tests/reaction-trigger-flow.test.ts +353 -0
  141. package/telegram-plugin/tests/reaction-trigger.test.ts +397 -0
  142. package/telegram-plugin/tests/retry-api-call.test.ts +152 -1
  143. package/telegram-plugin/tests/runtime-metrics.test.ts +145 -0
  144. package/telegram-plugin/tests/sandbox-hint-posttool.test.ts +155 -0
  145. package/telegram-plugin/tests/secret-detect-delete-must-surface-failures.test.ts +133 -0
  146. package/telegram-plugin/tests/secret-detect-false-positives.test.ts +137 -0
  147. package/telegram-plugin/tests/silence-poke.test.ts +493 -0
  148. package/telegram-plugin/tests/silent-end.test.ts +206 -0
  149. package/telegram-plugin/tests/subagent-tracker-hooks.test.ts +107 -0
  150. package/telegram-plugin/tests/subagent-watcher-env-thresholds.test.ts +224 -0
  151. package/telegram-plugin/tests/subagent-watcher-stall-terminal.test.ts +316 -0
  152. package/telegram-plugin/tests/subagent-watcher.test.ts +263 -0
  153. package/telegram-plugin/tests/turn-signal-tracker.test.ts +81 -0
  154. package/telegram-plugin/tests/vault-approval-posture.test.ts +256 -0
  155. package/telegram-plugin/tests/vault-grant-auto-resume.test.ts +73 -0
  156. package/telegram-plugin/tests/vault-grant-inbound-builders.test.ts +226 -0
  157. package/telegram-plugin/tests/vault-grant-union.test.ts +130 -0
  158. package/telegram-plugin/tests/vault-key-regex-allows-slash.test.ts +140 -0
  159. package/telegram-plugin/tests/vault-posture-quarantine.test.ts +104 -0
  160. package/telegram-plugin/tests/vault-request-access-tool.test.ts +114 -0
  161. package/telegram-plugin/tests/vault-request-access-unlock-resume.test.ts +106 -0
  162. package/telegram-plugin/turn-signal-tracker.ts +100 -24
  163. package/telegram-plugin/uat/SETUP.md +210 -35
  164. package/telegram-plugin/uat/assertions.ts +264 -37
  165. package/telegram-plugin/uat/driver-info.ts +57 -0
  166. package/telegram-plugin/uat/driver.ts +590 -51
  167. package/telegram-plugin/uat/harness.ts +140 -94
  168. package/telegram-plugin/uat/load-env.test.ts +72 -0
  169. package/telegram-plugin/uat/load-env.ts +48 -0
  170. package/telegram-plugin/uat/login.ts +96 -53
  171. package/telegram-plugin/uat/runners/agent-self-sufficiency.ts +457 -0
  172. package/telegram-plugin/uat/runners/paraphrases.ts +231 -0
  173. package/telegram-plugin/uat/runners/report.ts +150 -0
  174. package/telegram-plugin/uat/runners/run-agent-self-sufficiency.sh +50 -0
  175. package/telegram-plugin/uat/runners/scorer.test.ts +196 -0
  176. package/telegram-plugin/uat/runners/scorer.ts +106 -0
  177. package/telegram-plugin/uat/runners/skill-coverage.test.ts +100 -0
  178. package/telegram-plugin/uat/runners/skill-coverage.ts +620 -0
  179. package/telegram-plugin/uat/scenarios/ask-user-button-tap-dm.test.ts +141 -0
  180. package/telegram-plugin/uat/scenarios/bg-sub-agent-dispatch-dm.test.ts +191 -0
  181. package/telegram-plugin/uat/scenarios/fuzz-extended-dm.test.ts +255 -0
  182. package/telegram-plugin/uat/scenarios/fuzz-human-style-dm.test.ts +275 -0
  183. package/telegram-plugin/uat/scenarios/fuzz-random-prompts-dm.test.ts +146 -0
  184. package/telegram-plugin/uat/scenarios/fuzz-status-ask-dm.test.ts +486 -0
  185. package/telegram-plugin/uat/scenarios/jtbd-interrupt-marker-dm.test.ts +67 -0
  186. package/telegram-plugin/uat/scenarios/jtbd-rapid-followup-dm.test.ts +100 -0
  187. package/telegram-plugin/uat/scenarios/jtbd-soft-commit-dm.test.ts +67 -0
  188. package/telegram-plugin/uat/scenarios/jtbd-status-query-dm.test.ts +49 -0
  189. package/telegram-plugin/uat/scenarios/location-inbound-dm.test.ts +65 -0
  190. package/telegram-plugin/uat/scenarios/midturn-silent-dm.test.ts +175 -0
  191. package/telegram-plugin/uat/scenarios/reactions-dm.test.ts +142 -0
  192. package/telegram-plugin/uat/scenarios/reactions-trigger-turn-dm.test.ts +96 -0
  193. package/telegram-plugin/uat/scenarios/secret-redaction-deletes-original-dm.test.ts +123 -0
  194. package/telegram-plugin/uat/scenarios/secret-redaction-no-false-positive-dm.test.ts +87 -0
  195. package/telegram-plugin/uat/scenarios/silence-poke-soft-dm.test.ts +155 -0
  196. package/telegram-plugin/uat/scenarios/silent-end-recovery-dm.test.ts +95 -0
  197. package/telegram-plugin/uat/scenarios/smoke-dm-reply.test.ts +57 -0
  198. package/telegram-plugin/uat/scenarios/subagent-watcher-no-rerun-dm.test.ts +135 -0
  199. package/telegram-plugin/uat/scenarios/vault-approval-posture-telegram-id-dm.test.ts +191 -0
  200. package/telegram-plugin/uat/scenarios/vault-audit-allow-dm.test.ts +108 -0
  201. package/telegram-plugin/uat/scenarios/vault-grant-auto-resume-dm.test.ts +121 -0
  202. package/telegram-plugin/uat/scenarios/vault-request-access-concurrent-dm.test.ts +161 -0
  203. package/telegram-plugin/uat/scenarios/vault-request-access-end-to-end-dm.test.ts +158 -0
  204. package/telegram-plugin/uat/scenarios/voice-inbound-dm.test.ts +65 -0
  205. package/telegram-plugin/vault-approval-posture.ts +42 -0
  206. package/telegram-plugin/welcome-text.ts +1 -0
  207. package/telegram-plugin/active-pins-sweep.ts +0 -204
  208. package/telegram-plugin/active-pins.ts +0 -146
  209. package/telegram-plugin/auth-dashboard.ts +0 -1104
  210. package/telegram-plugin/auth-slot-parser.ts +0 -497
  211. package/telegram-plugin/card-event-log.ts +0 -138
  212. package/telegram-plugin/dist/foreman/foreman.js +0 -31106
  213. package/telegram-plugin/docs/multi-agent-card-design.md +0 -847
  214. package/telegram-plugin/docs/pinned-progress-card-reliability.md +0 -144
  215. package/telegram-plugin/foreman/foreman-create-flow.ts +0 -202
  216. package/telegram-plugin/foreman/foreman-handlers.ts +0 -493
  217. package/telegram-plugin/foreman/foreman.ts +0 -1165
  218. package/telegram-plugin/foreman/setup-flow.ts +0 -345
  219. package/telegram-plugin/foreman/setup-state.ts +0 -239
  220. package/telegram-plugin/foreman/state.ts +0 -203
  221. package/telegram-plugin/pin-event-log.ts +0 -76
  222. package/telegram-plugin/progress-card-driver.ts +0 -2886
  223. package/telegram-plugin/progress-card-pin-manager.ts +0 -589
  224. package/telegram-plugin/progress-card-pin-watchdog.ts +0 -98
  225. package/telegram-plugin/progress-card.ts +0 -1409
  226. package/telegram-plugin/tests/HARNESS.md +0 -340
  227. package/telegram-plugin/tests/_progress-card-harness.ts +0 -109
  228. package/telegram-plugin/tests/active-pins-boot-reaper.test.ts +0 -211
  229. package/telegram-plugin/tests/active-pins-sweep.test.ts +0 -309
  230. package/telegram-plugin/tests/active-pins.test.ts +0 -187
  231. package/telegram-plugin/tests/auth-account-identity-surface.test.ts +0 -118
  232. package/telegram-plugin/tests/auth-dashboard-edge-cases.test.ts +0 -260
  233. package/telegram-plugin/tests/auth-dashboard-restart-flow.test.ts +0 -140
  234. package/telegram-plugin/tests/auth-dashboard-v3b.test.ts +0 -559
  235. package/telegram-plugin/tests/auth-dashboard.test.ts +0 -1045
  236. package/telegram-plugin/tests/auth-slot-commands.test.ts +0 -640
  237. package/telegram-plugin/tests/bg-agent-progress-card-757.test.ts +0 -201
  238. package/telegram-plugin/tests/boot-card-account-quota.test.ts +0 -137
  239. package/telegram-plugin/tests/card-event-log.test.ts +0 -145
  240. package/telegram-plugin/tests/first-paint.test.ts +0 -257
  241. package/telegram-plugin/tests/foreman-create-flow.test.ts +0 -359
  242. package/telegram-plugin/tests/foreman-handlers.test.ts +0 -347
  243. package/telegram-plugin/tests/foreman-state.test.ts +0 -164
  244. package/telegram-plugin/tests/foreman-write-ops.test.ts +0 -214
  245. package/telegram-plugin/tests/harness-ordering-invariants.test.ts +0 -243
  246. package/telegram-plugin/tests/pin-event-log.test.ts +0 -124
  247. package/telegram-plugin/tests/progress-card-api-failure-during-deferred.test.ts +0 -73
  248. package/telegram-plugin/tests/progress-card-close-paths-converge.test.ts +0 -272
  249. package/telegram-plugin/tests/progress-card-cross-turn.test.ts +0 -258
  250. package/telegram-plugin/tests/progress-card-delay-842.test.ts +0 -160
  251. package/telegram-plugin/tests/progress-card-dispose-preservepending.test.ts +0 -81
  252. package/telegram-plugin/tests/progress-card-draft-flag.test.ts +0 -80
  253. package/telegram-plugin/tests/progress-card-driver-eviction.test.ts +0 -215
  254. package/telegram-plugin/tests/progress-card-driver-fleet-shadow.test.ts +0 -123
  255. package/telegram-plugin/tests/progress-card-driver-force-complete-parent-done.test.ts +0 -76
  256. package/telegram-plugin/tests/progress-card-edit-timestamps-budget.test.ts +0 -62
  257. package/telegram-plugin/tests/progress-card-memory-bounds.test.ts +0 -84
  258. package/telegram-plugin/tests/progress-card-pin-failure-paths.test.ts +0 -139
  259. package/telegram-plugin/tests/progress-card-pin-manager.test.ts +0 -773
  260. package/telegram-plugin/tests/progress-card-pin-race-fast-turn.test.ts +0 -66
  261. package/telegram-plugin/tests/progress-card-pin-sidecar-partial-write.test.ts +0 -64
  262. package/telegram-plugin/tests/progress-card-pin-watchdog.test.ts +0 -190
  263. package/telegram-plugin/tests/progress-card-sigterm-pin-flush.test.ts +0 -146
  264. package/telegram-plugin/tests/real-gateway-f1-ladder-integrity.test.ts +0 -123
  265. package/telegram-plugin/tests/real-gateway-f2-instant-draft.test.ts +0 -82
  266. package/telegram-plugin/tests/real-gateway-f3-late-card.test.ts +0 -114
  267. package/telegram-plugin/tests/real-gateway-harness.ts +0 -699
  268. package/telegram-plugin/tests/real-gateway-i6-turn-flush-replay-dedup.test.ts +0 -313
  269. package/telegram-plugin/tests/real-gateway-ipc-lifecycle.test.ts +0 -299
  270. package/telegram-plugin/tests/real-gateway-spec.test.ts +0 -487
  271. package/telegram-plugin/tests/real-gateway.smoke.test.ts +0 -101
  272. package/telegram-plugin/tests/setup-flow.test.ts +0 -510
  273. package/telegram-plugin/tests/setup-state.test.ts +0 -146
  274. package/telegram-plugin/tests/sync-chat-running-subagents.test.ts +0 -116
  275. package/telegram-plugin/tests/turn-end-regressions.test.ts +0 -489
  276. package/telegram-plugin/tests/turn-flush-card-takeover.test.ts +0 -218
  277. package/telegram-plugin/tests/turn-flush-prose-recovery.test.ts +0 -78
  278. package/telegram-plugin/tests/two-zone-bg-carry-full-lifecycle.test.ts +0 -131
  279. package/telegram-plugin/tests/two-zone-bg-detection.test.ts +0 -120
  280. package/telegram-plugin/tests/two-zone-bg-done-when-all-terminal.test.ts +0 -116
  281. package/telegram-plugin/tests/two-zone-bg-early-turn-end.test.ts +0 -87
  282. package/telegram-plugin/tests/two-zone-bg-survives-next-turn.test.ts +0 -211
  283. package/telegram-plugin/tests/two-zone-card-cap.test.ts +0 -62
  284. package/telegram-plugin/tests/two-zone-card-fleet-row.test.ts +0 -101
  285. package/telegram-plugin/tests/two-zone-card-header-phases.test.ts +0 -78
  286. package/telegram-plugin/tests/two-zone-card-html-balance.test.ts +0 -110
  287. package/telegram-plugin/tests/two-zone-card-lifecycle.test.ts +0 -128
  288. package/telegram-plugin/tests/two-zone-card-sanitise.test.ts +0 -58
  289. package/telegram-plugin/tests/two-zone-card-snapshot.test.ts +0 -133
  290. package/telegram-plugin/tests/two-zone-concurrent-turns-isolation.test.ts +0 -155
  291. package/telegram-plugin/tests/two-zone-phasefor-precedence.test.ts +0 -117
  292. package/telegram-plugin/tests/two-zone-snapshot-extras.test.ts +0 -187
  293. package/telegram-plugin/tests/two-zone-stuck-edit-throttle.test.ts +0 -149
  294. package/telegram-plugin/tests/two-zone-stuck-header-escalation.test.ts +0 -101
  295. package/telegram-plugin/tests/two-zone-stuck-per-member.test.ts +0 -114
  296. package/telegram-plugin/tests/two-zone-stuck-recovery.test.ts +0 -105
  297. package/telegram-plugin/tests/waiting-ux-harness.ts +0 -381
  298. package/telegram-plugin/tests/waiting-ux.e2e.test.ts +0 -233
  299. package/telegram-plugin/turn-flush-prose-recovery.ts +0 -40
  300. package/telegram-plugin/two-zone-card.ts +0 -269
  301. package/telegram-plugin/uat/scenarios/smoke-clerk-reply.test.ts +0 -61
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: switchroom-install
3
- description: Install switchroom and its dependencies (docker, claude CLI, switchroom binary) on a fresh machine. Use for onboarding and first-time setup — when the user says 'install switchroom on this machine', 'set up switchroom for the first time', 'bootstrap switchroom from scratch', 'get switchroom running', 'how do I get started with switchroom', "I'm new to switchroom, where do I begin", or asks about switchroom dependencies or prerequisites. This is the onboarding entry point, not for managing existing agents.
3
+ description: Install switchroom and its dependencies (docker, claude CLI, switchroom binary) on a fresh machine. Use for onboarding and first-time setup — when the user says 'install switchroom on this machine', 'set up switchroom for the first time', 'bootstrap switchroom from scratch', 'get switchroom running', 'how do I get started with switchroom', "I'm new to switchroom, where do I begin", or asks about switchroom dependencies or prerequisites. This is the onboarding entry point, not for managing existing agents. Do NOT use when the user's message starts with "In switchroom agent management," — that prefix is a hard trigger for `switchroom-manage` even when the action mentions "reinstall my agents" or "set up my agents"; agent-management prefix means fleet operations on an already-installed switchroom, not first-time host bootstrap.
4
4
  ---
5
5
 
6
6
  # Install Switchroom
@@ -40,7 +40,7 @@ Only install what's missing. Check each first:
40
40
  command -v docker || echo "MISSING: docker"
41
41
  docker compose version >/dev/null 2>&1 || echo "MISSING: docker compose v2"
42
42
 
43
- # Claude Code CLI (needed for switchroom auth login)
43
+ # Claude Code CLI (used inside agent containers and for the initial OAuth flow)
44
44
  command -v claude || echo "MISSING: claude"
45
45
  ```
46
46
 
@@ -102,7 +102,7 @@ If `switchroom doctor` reports healthy and at least one agent is listed, install
102
102
 
103
103
  ### Optional follow-up: share one Anthropic account across multiple agents
104
104
 
105
- Once the first agent is up and authenticated, the user can promote that agent's auth to a global Anthropic account so additional agents share the same Pro/Max subscription without each running its own OAuth flow. See `switchroom-manage` (Anthropic accounts section) for the bootstrap flow. This is the path most users want when they add a second agent — flag it as soon as they ask "how do I add another agent?".
105
+ This is the default. One OAuth flow per Anthropic account, then every agent in the fleet inherits the fleet-wide active account no per-agent OAuth round. The auth-broker handles refresh and credential fanout automatically. See `switchroom-manage` (Anthropic accounts section) and `docs/auth.md` for the bootstrap flow. Flag this as soon as they ask "how do I add another agent?".
106
106
 
107
107
  ## What not to do
108
108
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: switchroom-manage
3
- description: Manage the fleet of switchroom agents from a Claude Code session add, create, remove, reinstall, reprovision, or lifecycle-control agents. Use when the user says 'add a new agent', 'add an agent to my setup', 'create a new agent', 'remove an agent', 'reinstall my agents', 'reprovision my agents', 'list my agents', 'manage my agents', or invokes `/switchroom`. This is the right skill for fleet-level changes (adding/removing agents) even when the phrasing includes 'install' or 'reinstall'use switchroom-install only for bootstrapping switchroom itself on a fresh machine.
3
+ description: Manage the fleet of switchroom agents on an already-bootstrapped installadding, creating, removing, listing, reinstalling, reprovisioning, or lifecycle-controlling agents. HARD PREFIX TRIGGER: whenever the user's message starts with the phrase "In switchroom agent management," regardless of what follows — use this skill. That prefix is load-bearing and wins over `switchroom-install`, `switchroom-runtime`, `switchroom-cli`, and `switchroom-health`; even probes like "In switchroom agent management, Can you reinstall my agents?", "In switchroom agent management, I need to reprovision my agents.", and "In switchroom agent management, Could you reprovision my agents for me?" MUST route here — NOT to switchroom-install (despite the word "reinstall") and NOT to switchroom-runtime (despite touching agent lifecycle). The word "reinstall" inside the agent-management prefix means re-provision an EXISTING agent on an ALREADY-installed switchroom host; it does not mean a fresh host bootstrap. Use when the user wants to "reprovision my agents", "reinstall my agents", "manage my agents", "add a new agent", "remove an agent", "list my agents", or "restart an agent". Triggers on phrasings including "I need to reprovision my agents.", "Could you reprovision my agents for me?", "Manage my agents, please.", "Can you reinstall my agents?", "I'd like to reinstall my agents.", "Help me list my agents.", "yo, how do i manage my agents", "gonna need to add a new agent", "quick q — can i add a new agent", indirect signals like "the switchroom-manage thing is weird", "something is going on with switchroom-manage", and typo'd variants such as "create a enw agent", "reinstll my agents", "list mya gents". Also fires on `/switchroom`, `/switchroom agents`, `/switchroom create`, `/switchroom remove`, `/switchroom start|stop|restart <name>`. Do NOT use for first-time bootstrap of switchroom itself when there is NO "In switchroom agent management," prefix — phrasings like "how do I get started with switchroom", "set up switchroom for the first time", "bootstrap switchroom from scratch" belong to `switchroom-install`. Do NOT use for per-agent snapshots or statusthat's `switchroom-status`. Do NOT use for "why did you restart" / agent self-state questions without the management prefix — that's `switchroom-runtime`.
4
4
  ---
5
5
 
6
6
  # Switchroom Agent Management
@@ -20,12 +20,12 @@ When the user invokes `/switchroom` or asks to add, create, remove, reinstall, r
20
20
  | `/switchroom stop <name>` | `switchroom agent stop <name>` |
21
21
  | `/switchroom restart <name>` | `switchroom restart <name>` |
22
22
  | `/switchroom reinstall <name>` or "reinstall my agents" | `switchroom apply && docker compose -p switchroom -f ~/.switchroom/compose/docker-compose.yml up -d` |
23
- | `/switchroom status` | `switchroom auth status` |
23
+ | `/switchroom status` | `switchroom auth show` |
24
24
  | `/switchroom memory <query>` | `switchroom memory search "<query>"` |
25
25
  | `/switchroom memory <query> --agent <name>` | `switchroom memory search "<query>" --agent <name>` |
26
26
  | `/switchroom vault list` | `switchroom vault list` |
27
27
  | `/switchroom topics` | `switchroom topics list` |
28
- | `/switchroom accounts` or "list anthropic accounts" | `switchroom auth account list` |
28
+ | `/switchroom accounts` or "list anthropic accounts" | `switchroom auth list` |
29
29
  | "share my Pro subscription across agents" / "add an Anthropic account" | See **Anthropic accounts** below |
30
30
 
31
31
  ### Add / create a new agent
@@ -38,30 +38,37 @@ When the user says "add a new agent", "add an agent to my switchroom setup", or
38
38
 
39
39
  ### Anthropic accounts (one OAuth, many agents)
40
40
 
41
- The new auth model treats the Anthropic account as the unit of authentication: one `claude setup-token` per account, then enable the account on however many agents you want. See `reference/share-auth-across-the-fleet.md` for the full design.
41
+ The auth model treats the Anthropic account as the unit of authentication: one OAuth flow per account, then every agent in the fleet inherits the fleet-wide active account. The `switchroom-auth-broker` daemon owns the refresh loop and is the sole writer of every `credentials.json`. See `docs/auth.md` for the operator guide and `reference/share-auth-across-the-fleet.md` for the design.
42
42
 
43
43
  **Bootstrap flow when the user wants to share one Pro/Max subscription across agents:**
44
44
 
45
- 1. Make sure at least one agent is already authenticated the per-agent way (existing `switchroom auth login <agent>` flow). This gives you a valid `.credentials.json` to lift from.
46
- 2. **Create the global account** by lifting the agent's credentials:
45
+ 1. **Add the account** (one OAuth flow, ever):
47
46
  ```bash
48
- switchroom auth account add work-pro --from-agent <existing-agent>
47
+ switchroom auth add work-pro --from-oauth
49
48
  ```
50
- 3. **Enable** the account on every agent that should share it:
49
+ Alternatively, seed from an already-authenticated agent's credentials: `switchroom auth add work-pro --from-agent <existing-agent>`.
50
+ 2. **Activate it fleet-wide:**
51
51
  ```bash
52
- switchroom auth enable work-pro <agent-1> <agent-2> ...
52
+ switchroom auth use work-pro
53
53
  ```
54
- This appends to `agents.<name>.auth.accounts` in `switchroom.yaml` and immediately fans out the credentials to each agent's `.claude/credentials.json`.
55
- 4. **Restart** the affected agents so claude picks up the new credentials.
54
+ This sets `auth.active: work-pro` in `switchroom.yaml`. Every agent inherits on next refresh-read no per-agent enable step needed.
55
+ 3. The broker fans out the credentials to each agent's `.claude/credentials.json` automatically. No manual restart required in the common case.
56
56
 
57
- Verify with `switchroom auth account list` — shows accounts, which agents use each, health, and expiry. Account-level quota and refresh state replaces the per-agent view: when one account hits its 5-hour cap, every agent on it is failed over together.
57
+ Verify with `switchroom auth list` — shows accounts, health, and which one is fleet-active. Quota / 429 events propagate per-account: when one account is exhausted, the broker fails the fleet over to the next entry in `auth.fallback_order` automatically (or run `switchroom auth rotate` to force a cycle).
58
58
 
59
- **Telegram parity**the same flow works from inside a chat:
59
+ **Edge caseper-agent override.** If one agent needs a different account than the fleet active (e.g. a personal-only experiment running on `personal-max`), use:
60
60
 
61
+ ```bash
62
+ switchroom auth agent override klanker personal-max
63
+ switchroom auth agent override klanker --clear # back to fleet active
61
64
  ```
62
- /auth login # current agent, existing slot flow
63
- /auth account add work-pro # lifts current agent → global account
64
- /auth enable work-pro <other-agent> # wires another agent to the same account
65
+
66
+ **Telegram parity** three commands from any agent's chat:
67
+
68
+ ```
69
+ /auth show # read-only fleet snapshot, open to any agent
70
+ /auth use work-pro # admin agents only
71
+ /auth rotate # admin agents only — cycle fallback_order
65
72
  ```
66
73
 
67
74
  ## Behavior
@@ -77,8 +84,8 @@ Switchroom commands:
77
84
  /switchroom start <name> Start an agent
78
85
  /switchroom stop <name> Stop an agent
79
86
  /switchroom restart <name> Restart an agent (drain by default)
80
- /switchroom status Show per-agent auth status
81
- /switchroom accounts List Anthropic accounts + which agents use each
87
+ /switchroom status Show fleet auth state (active account, agents, health)
88
+ /switchroom accounts List Anthropic accounts + health
82
89
  /switchroom memory <query> Search agent memory
83
90
  /switchroom vault list List vault secrets
84
91
  /switchroom topics List Telegram topics
@@ -86,5 +93,5 @@ Switchroom commands:
86
93
  Fleet operations (run directly, not via /switchroom <sub>):
87
94
  switchroom apply Reconcile + (re)write compose; bring up via `docker compose ... up -d`
88
95
  switchroom version Show versions + running agent health summary
89
- switchroom auth refresh-accounts Refresh OAuth tokens + fan out (cron entrypoint)
96
+ switchroom auth refresh Force a refresh tick (diagnostic; broker owns the loop)
90
97
  ```
@@ -0,0 +1,191 @@
1
+ ---
2
+ name: switchroom-runtime
3
+ description: |
4
+ Use ONLY when the user is asking the AGENT ITSELF about its own
5
+ runtime state in a specific runtime-context — i.e. the message
6
+ refers to an actual crash, restart, hand-off resume, or mid-turn
7
+ interrupt event. Required disambiguator: the prompt must reference
8
+ one of these runtime-specific signals — "why did you restart",
9
+ "did you crash", "you went away", "stop you mid-turn", "interrupt
10
+ you", "are you still there after the restart", "resume the
11
+ interrupted turn", "wake audit", "owed reply", "clean-shutdown"
12
+ — OR start with the hard-prefix "For switchroom runtime hand-offs,".
13
+ Also invoked on boot signals: SWITCHROOM_PENDING_TURN=true
14
+ (interrupted-turn resume) or sentinel file
15
+ $TELEGRAM_STATE_DIR/.wake-audit-pending (wake audit: scan for
16
+ owed replies, orphan sub-agents, stale todos before answering).
17
+ Triggers on phrasings like "Why did you restart, please.", "you
18
+ went away.", "can I stop you mid-turn.", "why did you restart.",
19
+ "how do I interrupt you", "did you crash?", indirect signals like
20
+ "the switchroom-runtime thing is weird", "something is going on
21
+ with switchroom-runtime", and typo'd variants such as "stil there
22
+ after restart?". Whenever the user's message starts with the
23
+ phrase "For switchroom runtime hand-offs," — regardless of what
24
+ follows — use this skill. Surface the audit trail from
25
+ clean-shutdown.json + container/journal logs.
26
+ CRITICAL NEGATIVE GUARD — bare terse pings like "still there?",
27
+ "any update?", "alive?", "you there?" are NOT sufficient on their
28
+ own; they only route here when they appear AFTER an unexplained
29
+ silence the agent should have explained (a real restart / crash
30
+ event), not as conversational opener. When unsure, do NOT fire.
31
+ Do NOT use for "reprovision my agents", "reinstall my agents",
32
+ "manage my agents", "add a new agent", "remove an agent" — those
33
+ are about the fleet, use `switchroom-manage`. Do NOT use when the
34
+ user's message starts with "In switchroom (the CLI),", "In
35
+ switchroom agent management,", or any other rival hard-prefix —
36
+ those prefixes win over this skill. Do NOT use for "sync my
37
+ config", "apply my config changes", "Please sync my config.",
38
+ "upgrade switchroom", "Upgrade switchroom, please.", "what version
39
+ is running", "what version", "apply my config", "check the
40
+ journal", "logs", "show me the logs" — those are CLI operations,
41
+ use `switchroom-cli`. Do NOT use for filing a bug or reporting an
42
+ issue on GitHub — that's `file-bug`. Do NOT use for "what's wrong"
43
+ / health-check style diagnostics — that's `switchroom-health`.
44
+ Do NOT use for normal Telegram conversation, formatting questions,
45
+ voice/sticker/Telegraph behavior, MCP tool questions, or persona /
46
+ voice / Execution-Bias rules — those live in your always-loaded
47
+ CLAUDE.md.
48
+ allowed-tools: Bash Read Grep
49
+ ---
50
+
51
+ # Switchroom Runtime Protocols
52
+
53
+ This skill holds the runtime protocols that fire on specific boot signals or user phrases. The always-loaded `CLAUDE.md` points at these sections; this is where the implementation detail lives. Each section is gated by a distinct trigger — jump to the one that fires.
54
+
55
+ ---
56
+
57
+ ## Resume protocol — interrupted turns
58
+
59
+ **Trigger:** the env var `SWITCHROOM_PENDING_TURN=true` is set when your session boots. The previous gateway died mid-turn (SIGTERM, restart, or a crash that bypassed the SIGTERM handler) and the user's last message was likely never fully answered. The accompanying env vars tell you what was in flight:
60
+
61
+ - `SWITCHROOM_PENDING_CHAT_ID` — the chat the interrupted turn belonged to
62
+ - `SWITCHROOM_PENDING_THREAD_ID` — the forum topic id (empty if not a forum)
63
+ - `SWITCHROOM_PENDING_USER_MSG_ID` — the inbound message_id that started the turn (you can quote-reply to it for context)
64
+ - `SWITCHROOM_PENDING_ENDED_VIA` — `restart` (user ran `switchroom agent restart`), `sigterm` (systemd/manual kill), `timeout` (watchdog), or `unknown` (crash before stamp)
65
+ - `SWITCHROOM_PENDING_STARTED_AT` — unix-ms when the turn started
66
+
67
+ **Your first action on a `SWITCHROOM_PENDING_TURN=true` boot must be to acknowledge the gap and confirm direction.** Don't silently pick up where you left off. The user has no way to know whether you remember what you were doing. Use `reply` with `accent: 'issue'` to make it obvious. Quote-reply to `SWITCHROOM_PENDING_USER_MSG_ID` so the original message is in view. Sample wording (adapt to the situation):
68
+
69
+ > ⚠️ Issue
70
+ >
71
+ > I was killed mid-turn. Looks like my previous shutdown was via `<endedVia>`. Don't have full context on what I'd already done. Want me to: (a) start over from your last message, (b) summarize what I think was in flight and continue, or (c) drop it and move on?
72
+
73
+ The env vars are one-shot (start.sh deletes the file after sourcing), so this prompt only fires on the immediately-following session, not every restart afterward. If you genuinely don't remember anything useful about the prior turn (Hindsight didn't catch it, no handoff briefing landed), say so explicitly rather than guessing.
74
+
75
+ If `SWITCHROOM_PENDING_TURN` is unset or empty, do nothing special: the previous turn ended cleanly.
76
+
77
+ ---
78
+
79
+ ## Wake audit — every fresh boot
80
+
81
+ **Trigger:** the sentinel file `$TELEGRAM_STATE_DIR/.wake-audit-pending` exists. `start.sh` drops it on every process boot. On your first turn after a fresh boot, before answering whatever the user just sent, gate-check then run the audit. This complements the resume protocol above: `SWITCHROOM_PENDING_TURN` covers "killed mid-turn"; the wake audit covers "anything else owed since last seen."
82
+
83
+ **Conversation-aware dedup.** start.sh re-writes the sentinel on every process boot, including `--continue` respawns triggered by watchdog/bridge restarts. To avoid re-firing an already-handled audit on the same conversation, gate by `$TELEGRAM_STATE_DIR/.wake-audit-last-completed`:
84
+
85
+ ```bash
86
+ # Step 0: is an audit pending?
87
+ [ -f "$TELEGRAM_STATE_DIR/.wake-audit-pending" ] || exit 0
88
+
89
+ # Step 1: have we already audited since the most recent user message?
90
+ # If `.wake-audit-last-completed` is newer than the latest inbound user
91
+ # message in any active topic, the audit was handled by a prior boot in
92
+ # this conversation. Clear the sentinel and skip.
93
+ # - Compare the marker mtime to the max user-message ts from
94
+ # `mcp__switchroom-telegram__get_recent_messages` across the topics
95
+ # you might owe a reply in.
96
+ # - If marker_mtime >= latest_user_msg_ts: rm -f the sentinel, exit.
97
+ ```
98
+
99
+ If you proceed past the gate, run all three checks:
100
+
101
+ 1. **Owed replies** (the most common "you forgot me" failure). Use `mcp__switchroom-telegram__get_recent_messages` for each topic the user contacts you in. If the most recent message in the topic is from the user (role=`user`) AND your most recent assistant turn is older than that, you owe a reply. Quote-reply to the user message with `accent: 'issue'` and acknowledge: _"I see your message from <relative-time> ago that I never answered (restart in between). Want me to handle it now?"_
102
+
103
+ 2. **Orphan sub-agents** (jobs the watchdog killed mid-flight). Run:
104
+ ```bash
105
+ find "$CLAUDE_CONFIG_DIR/projects" -path '*/subagents/*.jsonl' -mmin -1440 -print 2>/dev/null
106
+ ```
107
+ For each, check the LAST line. If it's not a terminal record (`type:result` / `type:final` / `subtype:end`), the sub-agent was killed before completing. Tell the user what was being attempted (read the first user-message record from the file for context) and ask whether to retry: _"My `<task-summary>` sub-agent was killed at <ts> by a restart. Want me to redispatch?"_
108
+
109
+ 3. **Open todos** (in-process work that never finished). Scan recent task state:
110
+ ```bash
111
+ find "$CLAUDE_CONFIG_DIR/tasks" -name '*.json' -mmin -1440 -print 2>/dev/null
112
+ ```
113
+ If any have items with `status: in_progress` whose mtime predates your session start, those are stale. Only mention them if relevant to the conversation. Don't recite the whole list.
114
+
115
+ **Idempotency**: after the audit (whether anything was found or not), stamp the dedup marker AND clear the sentinel:
116
+
117
+ ```bash
118
+ touch "$TELEGRAM_STATE_DIR/.wake-audit-last-completed"
119
+ rm -f "$TELEGRAM_STATE_DIR/.wake-audit-pending"
120
+ ```
121
+
122
+ The marker's mtime defines "audit complete for this conversation up to now". A future `--continue` respawn that finds the marker newer than the latest user message will skip the audit. The sentinel's absence means "audit complete for this process boot."
123
+
124
+ **Don't be noisy**: if all three checks come back clean, say nothing about the audit. Just answer whatever the user asked. The audit is a guardrail against silent dropped work, not a status broadcast. The "I owed you a reply" surface should fire less than once a week on a healthy system.
125
+
126
+ ---
127
+
128
+ ## "Why did you restart?" — read the audit trail
129
+
130
+ **Trigger:** the user asks something like "why did you restart?", "did you crash?", "you went away", "what happened earlier". The `SWITCHROOM_PENDING_*` env vars are one-shot (cleared by start.sh on first read), so by the time a user asks this, they're long gone. Don't answer from memory, don't say "no restart on my end". Three durable on-disk sources have the actual reason. Check them in order:
131
+
132
+ 1. **`$TELEGRAM_STATE_DIR/clean-shutdown.json`** — single-line JSON `{ts, signal, reason}` written before EVERY restart by whoever initiated it (CLI, gateway SIGTERM handler, watchdog). Fastest answer for "what was THIS boot's reason." Example: `cat "$TELEGRAM_STATE_DIR/clean-shutdown.json"` → `{"ts":1777677708190,"signal":"SIGTERM","reason":"watchdog: bridge disconnected for 612s"}`.
133
+
134
+ 2. **Container/unit history.** Under v0.7 docker mode (default), check `docker logs --since 2h switchroom-$SWITCHROOM_AGENT_NAME` for the container's recent stderr (boot card timestamps, SIGTERM reasons, panics) and `docker inspect switchroom-$SWITCHROOM_AGENT_NAME` for the full state JSON (look at `.State.StartedAt` for the last start time and `.State.RestartCount` for cumulative restarts). Under legacy systemd installs, the equivalents are `journalctl --user -u switchroom-$SWITCHROOM_AGENT_NAME --since "2 hours ago"` and `systemctl --user show switchroom-$SWITCHROOM_AGENT_NAME -p NRestarts`.
135
+
136
+ 3. **Watchdog audit log.** Under systemd, `journalctl --user -t switchroom-watchdog --since "2 hours ago"` (every watchdog action: `[restart] / [skip] / [detect] / [error]` with `agent=NAME reason=KIND threshold=Ns observed=Ns ...`). Under docker the watchdog is disabled (no NRestarts equivalent without the docker socket), so this source is silent. Fall back to `clean-shutdown.json` plus the container logs above.
137
+
138
+ Quote the `reason` field verbatim when answering. Don't paraphrase. If `clean-shutdown.json` is older than the unit's current uptime, it's stale and the new boot wasn't a clean shutdown (likely OOM or panic). Say that explicitly. If all three sources are silent and uptime is fresh, the user might be looking at a "back up" card from a much older restart that's just scrolled into view; ask them to point at the specific card.
139
+
140
+ ---
141
+
142
+ ## `!` interrupt marker — implementation detail
143
+
144
+ **Trigger:** the user asks how to stop you mid-turn AND you want to give more than the one-liner answer (which lives in your always-loaded prompt). The one-liner answer is: *"Start your message with `!` — it interrupts whatever I'm doing and treats the rest as a fresh request."*
145
+
146
+ Implementation detail:
147
+
148
+ The gateway treats a Telegram message starting with `!` (single bang, not `!!` or `!!!`) as a deliberate interrupt: SIGINT to the active turn, strip the `!`, deliver the rest as a fresh turn. Under tmux-default, the SIGINT is delivered via `tmux send-keys C-c` to whatever has focus in the agent's pane (typically the claude REPL, but if claude has spawned a child Bash for a tool call, the child gets the C-c, which usually matches operator intent). A cgroup-wide kill fallback (legacy systemd: `systemctl kill --signal=INT`) fires only if send-keys fails.
149
+
150
+ If the user sends `! actually never mind, do X instead`, you'll boot up and see `actually never mind, do X instead` with no record of what you were doing before. That's intentional.
151
+
152
+ Doubled `!!` (typo / emphasis) reaches you verbatim. Empty `!` gets a "Send your replacement instruction now" reply from the gateway and never reaches you. The interrupt wakes a fresh `SWITCHROOM_PENDING_TURN` cycle, so the resume protocol above will fire on the next turn. Keep that pairing in mind when acknowledging.
153
+
154
+ ---
155
+
156
+ ## "status?" / "still there?" — UX-failure signal
157
+
158
+ **Trigger:** the user sends a short, low-content message asking whether you're alive — "status?", "still there?", "any update?", "you working?". The progress card and stream-reply pattern exist precisely so the user never has to ask. When you see one of those messages, treat it as a defect signal: something about the in-flight turn made the user feel uncertain. The product expectation (per `reference/know-what-my-agent-is-doing.md`) is that this rate trends to zero.
159
+
160
+ Your response should:
161
+
162
+ 1. Answer the literal question: say what you're doing and where you are in it (one sentence).
163
+ 2. **Offer to file an RCA issue.** Something like _"Want me to file this as an RCA so the progress surface gets fixed?"_ If the user says yes, invoke the bundled `/file-bug` skill which handles the log-pull + RCA structure + `gh issue create --label incident-rca`.
164
+
165
+ Pre-emptively reach for `/file-bug` only when the user clearly indicates they want it filed. Don't auto-file from a single "status?". That creates noise. The offer-then-confirm shape is the right friction.
166
+
167
+ The companion telemetry already in place (`gateway.ts` logs every `status?` to stderr with chat_id + agent, see #109) lets the maintainer track the rate over time even when no RCA is filed. Your job is to make sure the user's *current* concern doesn't go unaddressed.
168
+
169
+ ---
170
+
171
+ ## Bash shell wedge — KillBash, then ask for restart
172
+
173
+ **Trigger:** you receive a tool-result preamble from the framework that says `[wedge-detect] N consecutive empty-result Bash calls`, OR you notice trivial Bash calls (`echo ok`, `true`, `ls`) returning exit-1 with empty stdout/stderr two or three times in a row.
174
+
175
+ This is **the persistent-shell wedge.** Claude Code keeps a single `bash` subprocess per session for state continuity (so `cd` carries across calls). When that shell's IO state desyncs (typically after a long-running or interrupted command like `npm test` that was `!`-interrupted) every subsequent Bash call comes back exit-1-empty. Even `true` fails. The wedge is sticky for the session.
176
+
177
+ **Do not retry the same command.** The shell is dead to you; loops just burn the user's time. Two recovery steps in order:
178
+
179
+ 1. **Try `KillBash`.** Claude Code exposes a `KillBash` tool that drops the wedged shell session; the next Bash call gets a fresh shell. This works in some wedge modes but not all (sentinel-parsing wedges sometimes don't release until a full session restart). Worth trying first because it's cheap.
180
+
181
+ 2. **Ask the user for `switchroom agent restart <self>`.** If `KillBash` didn't recover (next Bash call is still exit-1-empty), the persistent shell needs the whole `claude` process to restart. Tell the user on Telegram with `accent: 'issue'`:
182
+
183
+ > ⚠️ Issue
184
+ >
185
+ > My Bash shell is wedged. Every command including `true` returns exit-1 with empty output. Tried `KillBash`, didn't recover. Run `switchroom agent restart <self>` on the host to bounce me. State that survives the restart: Hindsight memory, handoff briefing, Telegram history. State that doesn't: anything I was about to write that's not yet on disk.
186
+
187
+ Adapt the wording.
188
+
189
+ **Triggering causes to avoid.** The wedge most often follows: (a) a long `npm test` / `bun test` run, (b) any command that was `!`-interrupted mid-flight, (c) heredoc-style commands the shell's stdin couldn't fully consume. Prevention: dispatch heavy test suites to a worker sub-agent (so the wedge dies with the worker) rather than running them in your own session, and use `run_in_background: true` for long jobs.
190
+
191
+ A sentinel file at `$TELEGRAM_STATE_DIR/wedge-detected.json` records the most recent wedge detection. Operators can `cat` it for forensic timestamps; you don't normally need to read it yourself.
@@ -1,6 +1,31 @@
1
1
  ---
2
2
  name: switchroom-status
3
- description: List running switchroom agents with their uptime, model, and per-agent state. Use when the user asks 'what agents are running', 'list switchroom agents', 'how long has X been up', or wants a per-agent snapshot. Do NOT use for switchroom-wide version/health summary (use switchroom-cli's `switchroom version`) or "something is broken" diagnostics (use switchroom-health).
3
+ description: >
4
+ List running switchroom agents with their uptime, model, and per-agent
5
+ state. Strictly the "what's running and for how long" snapshot — nothing
6
+ about install, restart, health, version, or update.
7
+ Triggers ONLY on natural phrasings about listing/snapshotting agents and
8
+ uptime, including: "Can you show me the fleet?", "Show me the fleet,
9
+ please.", "Let's list switchroom agents.",
10
+ "Let's how long has X been up.", "I need to how long has X been up.",
11
+ "I'd like to what's the uptime of each agent.",
12
+ "any way to list switchroom agents?",
13
+ "quick q — can i show me the fleet",
14
+ "pls per-agent snapshot", and typo'd variants like "per-agent snapshot",
15
+ "per-agents napshot", "list swtchroom agents".
16
+ Also fires on indirect signals like "how's the fleet doing",
17
+ "what's alive right now", "is anything running right now".
18
+ Do NOT use when the user is asking about anything OTHER than a running-
19
+ agent list / uptime snapshot. In particular:
20
+ - "fresh install / bootstrap / first-time setup" → `switchroom-install`.
21
+ - "start / stop / restart / crash / interrupt an agent",
22
+ "apply my config", "what version is running" → `switchroom-runtime`.
23
+ - "manage / add / remove / rename agents", "edit memory / SOUL.md /
24
+ CLAUDE.md", "set per-agent config" → `switchroom-manage`.
25
+ - "what's wrong / diagnose / health check / troubleshoot /
26
+ my agents are broken / something's wrong" → `switchroom-health`.
27
+ If the prompt is ambiguous between status and any of the above rivals,
28
+ do NOT fire — pick the rival.
4
29
  ---
5
30
 
6
31
  # Agent Status
@@ -58,7 +83,7 @@ assistant — running (2h 14m)
58
83
  model: claude-sonnet-4-6 collection: general
59
84
 
60
85
  dev — running (45m)
61
- model: claude-opus-4-6 collection: coding
86
+ model: claude-opus-4-7 collection: coding
62
87
 
63
88
  coach — stopped
64
89
  last run: 3 days ago
@@ -11,6 +11,9 @@ description: >
11
11
  bot-api.harness, GrammyError, e2e telegram, telegram regression
12
12
  test, or asks how to add a test for code that calls bot.api.* or
13
13
  handles incoming Telegram updates.
14
+ Do NOT use for live progress-card behavior or telegram-plugin runtime
15
+ questions — this is strictly for writing Bun tests under
16
+ `telegram-plugin/tests/`.
14
17
  ---
15
18
 
16
19
  # Telegram test harness (switchroom)
@@ -65,7 +65,30 @@ Other env:
65
65
  - `curl`
66
66
  - `jq`
67
67
  - `switchroom` on `PATH` (or pass `SWITCHROOM_CLI`)
68
- - `SWITCHROOM_VAULT_PASSPHRASE` exported so the CLI can unlock the vault non-interactively
68
+
69
+ ### Vault authentication
70
+
71
+ **Canonical: capability grant.** The CLI authenticates to the broker via the
72
+ agent's capability token at `~/.switchroom/agents/<agent>/.vault-token` (mode
73
+ 0600). Mint once with:
74
+
75
+ ```bash
76
+ switchroom vault grant <agent> \
77
+ --keys google-cal-refresh-token,google-cal-client-id,google-cal-client-secret \
78
+ --write google-cal-access-token \
79
+ --duration 30d
80
+ ```
81
+
82
+ The agent container's compose env sets `SWITCHROOM_AGENT_NAME` automatically;
83
+ standalone scripts must set it. The CLI reads the token transparently and
84
+ forwards it on every `get` / `set` call. See `docs/vault-security.md` for the
85
+ full model.
86
+
87
+ **Legacy: `SWITCHROOM_VAULT_PASSPHRASE`** (deprecated for agent-side use,
88
+ still honoured). Setting this env var puts the master passphrase in every
89
+ subprocess's environment, defeats the ACL model, and bypasses the broker's
90
+ audit log. A runtime deprecation warning is emitted when the env var is
91
+ consumed inside an agent sandbox.
69
92
 
70
93
  ## Exit codes
71
94
 
@@ -1,6 +1,36 @@
1
1
  ---
2
2
  name: webapp-testing
3
- description: Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
3
+ description: >
4
+ Toolkit for interacting with and testing local web applications using
5
+ Playwright. Use when the user wants to: spin up a local server and
6
+ test it, run a Playwright test, view browser logs, capture a browser
7
+ screenshot, click through a UI, automate a dashboard, snapshot a
8
+ frontend, or verify any frontend behaviour end-to-end. Triggers on
9
+ phrasings: "Please spin up a local server and test it.", "I'd like
10
+ to run a Playwright test.", "Can you run a Playwright test?", "Help
11
+ me view browser logs.", "capture a browser screenshot", "click
12
+ through my UI", "test the frontend", "Help me spin up a local server
13
+ and test it.", "Let's spin up a local server and test it.", "any way
14
+ to test the frontend?", "pls capture a browser screenshot", "gonna
15
+ need to test a local web app", and typo'd variants like "run a
16
+ Playwwright test", "capture a browesr screenshot", "test a local
17
+ web app". Whenever the user's message starts with the phrase "For
18
+ browser-based webapp testing with Playwright," — regardless of what
19
+ follows — use this skill.
20
+ Triggers on natural phrasings including: "Please spin up a local server
21
+ and test it.", "Help me spin up a local server and test it.",
22
+ "Let's spin up a local server and test it.", "I'd like to run a
23
+ Playwright test.", "Can you run a Playwright test?", "Help me view
24
+ browser logs.", "any way to test the frontend?", "pls capture a browser
25
+ screenshot", "gonna need to test a local web app", and typo'd variants
26
+ like "run a Playwwright test", "capture a browesr screenshot",
27
+ "test a local web app".
28
+ Also fires when the user says "click through my UI", "automate this
29
+ dashboard", "snapshot the frontend", or mentions Playwright, headless
30
+ Chromium, browser automation, frontend e2e tests, or a `localhost:<port>`
31
+ webapp that needs end-to-end exercise.
32
+ Do NOT use for Telegram Bot-API tests (`telegram-test-harness`),
33
+ CLI/unit tests (vitest under `tests/`), or non-web UI testing.
4
34
  license: Complete terms in LICENSE.txt
5
35
  ---
6
36
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: xlsx
3
- description: "Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like \"the xlsx in my downloads\") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved."
3
+ description: "Create, read, edit, or transform Excel and CSV spreadsheets (.xlsx, .xlsm, .csv, .tsv). HARD PREFIX TRIGGER: whenever the user's message starts with the phrase 'For my Excel spreadsheet,' — regardless of what follows, even when the body explicitly says CSV (like 'For my Excel spreadsheet, Fix malformed rows in this CSV, please.') — use this skill. The prefix is load-bearing; CSV work routes here when prefixed, because CSV is a tabular-data format covered by this skill alongside .xlsx/.xlsm/.tsv. Use any time a spreadsheet file is the primary input or output. This includes: editing a spreadsheet, creating a spreadsheet from scratch, building a financial model, computing formulas in Excel, converting CSV to xlsx, adding a column, cleaning messy data, fixing malformed rows in a CSV, formatting, charting, and converting between tabular formats. Triggers on phrasings: \"I'd like to edit a spreadsheet.\", 'Help me create a spreadsheet from scratch.', \"Let's build a financial model.\", 'Fix malformed rows in this CSV, please.', 'Fix malformed rows in this CSV.', 'compute formulas in Excel', 'convert CSV to xlsx', 'add a column', 'clean this messy data', 'Open this xlsx, please.', 'Compute formulas in Excel, please.', 'pls convert CSV to xlsx', 'pls add columns to a CSV', 'any way to fix malformed rows in this CSV?', and typo'd variants like 'build a finnacial model', 'fix malfored rows in this CSV', 'compute ormulas in Excel'. Also fires on indirect signals like 'this csv is a mess', 'the columns are all wrong in this sheet', 'I need to crunch some numbers in a sheet'. Trigger especially when the user references a spreadsheet file by name or path — even casually (like \"the xlsx in my downloads\") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document (`docx`), presentation (`pptx`), PDF (`pdf`), HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved."
4
4
  license: Proprietary. LICENSE.txt has complete terms
5
5
  ---
6
6
 
@@ -21,11 +21,13 @@
21
21
  * middleware (via `makeAdminCommandMiddleware`) BEFORE its bot.command() calls;
22
22
  * the middleware redirects to handleInbound when admin=false.
23
23
  *
24
- * Out of scope for Phase 1
25
- * ────────────────────────
26
- * `/create-agent` has a complex multi-turn state machine (persisted wizard
27
- * state across messages). It is intentionally NOT included here and remains
28
- * foreman/server-only until Phase 2 or later.
24
+ * Out of scope
25
+ * ────────────
26
+ * `/create-agent` is a multi-turn wizard for onboarding a new agent
27
+ * from Telegram. Not implemented operators run `switchroom agent
28
+ * add <name>` on the host. (The standalone foreman bot used to host
29
+ * this wizard; it was retired since the gateway-intercept model
30
+ * supersedes it.)
29
31
  */
30
32
 
31
33
  /**