switchroom 0.18.31 → 0.18.33

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 (159) hide show
  1. package/dist/agent-scheduler/index.js +4 -2
  2. package/dist/auth-broker/index.js +21 -3
  3. package/dist/cli/notion-write-pretool.mjs +4 -2
  4. package/dist/cli/switchroom.js +1410 -852
  5. package/dist/host-control/main.js +22 -4
  6. package/dist/vault/approvals/kernel-server.js +21 -3
  7. package/dist/vault/broker/server.js +48 -4
  8. package/package.json +4 -3
  9. package/profiles/_base/start.sh.hbs +148 -23
  10. package/telegram-plugin/dist/gateway/gateway.js +62726 -58282
  11. package/telegram-plugin/gateway/agent-button-callback-handler.ts +237 -0
  12. package/telegram-plugin/gateway/ask-callback-handler.ts +92 -0
  13. package/telegram-plugin/gateway/attachment-message-handlers.ts +152 -0
  14. package/telegram-plugin/gateway/backstop-delivery.ts +223 -23
  15. package/telegram-plugin/gateway/boot-card.ts +169 -1
  16. package/telegram-plugin/gateway/bot-commands-model-effort.ts +209 -0
  17. package/telegram-plugin/gateway/bot-commands-start-info.ts +108 -0
  18. package/telegram-plugin/gateway/callback-query-handlers.ts +124 -0
  19. package/telegram-plugin/gateway/captured-answer-resume.ts +259 -0
  20. package/telegram-plugin/gateway/card-approval-keyboards.test.ts +28 -0
  21. package/telegram-plugin/gateway/card-tool-handlers.ts +639 -0
  22. package/telegram-plugin/gateway/checklist-message-handler.ts +107 -0
  23. package/telegram-plugin/gateway/delivery-confirm-wiring.ts +133 -0
  24. package/telegram-plugin/gateway/disconnect-flush.ts +6 -44
  25. package/telegram-plugin/gateway/gateway-import-clean.test.ts +188 -0
  26. package/telegram-plugin/gateway/gateway.ts +6403 -13456
  27. package/telegram-plugin/gateway/inbound-delivery-machine-dispatch.ts +7 -15
  28. package/telegram-plugin/gateway/inbound-delivery-machine-shadow.ts +35 -68
  29. package/telegram-plugin/gateway/inbound-interceptors.ts +1133 -0
  30. package/telegram-plugin/gateway/inbound-router.ts +400 -0
  31. package/telegram-plugin/gateway/liveness-wiring.ts +440 -0
  32. package/telegram-plugin/gateway/media-message-handlers.ts +256 -0
  33. package/telegram-plugin/gateway/mental-model-propose-card.ts +16 -0
  34. package/telegram-plugin/gateway/model-command.ts +23 -0
  35. package/telegram-plugin/gateway/narrative-lane.ts +865 -0
  36. package/telegram-plugin/gateway/obligation-ledger.ts +42 -0
  37. package/telegram-plugin/gateway/obligation-store.ts +37 -1
  38. package/telegram-plugin/gateway/obligation-wiring.ts +333 -0
  39. package/telegram-plugin/gateway/outbound-send-path.ts +2012 -0
  40. package/telegram-plugin/gateway/photo-message-handler.ts +80 -0
  41. package/telegram-plugin/gateway/pinned-message-handler.ts +86 -0
  42. package/telegram-plugin/gateway/secret-request-card.test.ts +46 -0
  43. package/telegram-plugin/gateway/secret-request-card.ts +45 -0
  44. package/telegram-plugin/gateway/stream-render.ts +2166 -0
  45. package/telegram-plugin/gateway/turn-end.ts +606 -0
  46. package/telegram-plugin/gateway/turn-start-surfaces.ts +298 -0
  47. package/telegram-plugin/gateway/vault-request-access-card.ts +16 -0
  48. package/telegram-plugin/gateway/vault-request-save-card.test.ts +49 -0
  49. package/telegram-plugin/gateway/vault-request-save-card.ts +52 -0
  50. package/telegram-plugin/gateway/voice-message-handler.ts +123 -0
  51. package/telegram-plugin/gateway/voice-ondemand-callback-handler.ts +204 -0
  52. package/telegram-plugin/gateway/worker-feed-dispatch.ts +40 -0
  53. package/telegram-plugin/narrative-dedup.ts +24 -1
  54. package/telegram-plugin/narrative-flush.ts +2 -2
  55. package/telegram-plugin/pending-user-notice.ts +59 -13
  56. package/telegram-plugin/render/render.ts +25 -1
  57. package/telegram-plugin/status-no-truncate.ts +13 -0
  58. package/telegram-plugin/subagent-watcher.ts +297 -31
  59. package/telegram-plugin/tests/activity-card-wiring.test.ts +8 -3
  60. package/telegram-plugin/tests/activity-ever-opened-sticky.test.ts +18 -3
  61. package/telegram-plugin/tests/agent-button-callback-handler.test.ts +149 -0
  62. package/telegram-plugin/tests/ask-callback-handler.test.ts +118 -0
  63. package/telegram-plugin/tests/attachment-message-handlers.test.ts +135 -0
  64. package/telegram-plugin/tests/backstop-delivery.test.ts +167 -0
  65. package/telegram-plugin/tests/backstop-readback-probe.test.ts +144 -0
  66. package/telegram-plugin/tests/boot-card-routing.test.ts +139 -0
  67. package/telegram-plugin/tests/bot-commands-model-effort.test.ts +189 -0
  68. package/telegram-plugin/tests/bot-commands-start-info.test.ts +240 -0
  69. package/telegram-plugin/tests/buffer-gate-broadened.test.ts +28 -9
  70. package/telegram-plugin/tests/busy-ack-wiring.test.ts +6 -1
  71. package/telegram-plugin/tests/button-tap-turn-gated.test.ts +21 -12
  72. package/telegram-plugin/tests/callback-query-handlers.test.ts +101 -0
  73. package/telegram-plugin/tests/captured-answer-resume.test.ts +358 -0
  74. package/telegram-plugin/tests/card-tool-handlers.test.ts +497 -0
  75. package/telegram-plugin/tests/catch-all-unhandled-message.test.ts +5 -2
  76. package/telegram-plugin/tests/checklist-message-handler.test.ts +160 -0
  77. package/telegram-plugin/tests/emission-authority-facade.test.ts +76 -29
  78. package/telegram-plugin/tests/emission-authority-ping-gate.test.ts +4 -1
  79. package/telegram-plugin/tests/emission-determinism-wiring.test.ts +45 -16
  80. package/telegram-plugin/tests/feed-heartbeat-liveness-open.test.ts +30 -7
  81. package/telegram-plugin/tests/gateway-boot-side-effect-gating.test.ts +270 -0
  82. package/telegram-plugin/tests/gateway-boot-smoke.test.ts +150 -0
  83. package/telegram-plugin/tests/gateway-bot-construction-deferral.test.ts +251 -0
  84. package/telegram-plugin/tests/gateway-disconnect-flush.test.ts +5 -128
  85. package/telegram-plugin/tests/gateway-handler-registration-wiring.test.ts +299 -0
  86. package/telegram-plugin/tests/gateway-loopback-paste-redact.test.ts +44 -29
  87. package/telegram-plugin/tests/gateway-outbound-redact.test.ts +18 -5
  88. package/telegram-plugin/tests/gateway-request-secret.test.ts +7 -3
  89. package/telegram-plugin/tests/gateway-secret-detect.test.ts +20 -10
  90. package/telegram-plugin/tests/gateway-session-model-relaunch.test.ts +8 -2
  91. package/telegram-plugin/tests/inbound-delivery-cutover-flip.test.ts +54 -150
  92. package/telegram-plugin/tests/inbound-delivery-cutover-gate.test.ts +10 -14
  93. package/telegram-plugin/tests/inbound-delivery-dispatch-equivalence.test.ts +6 -7
  94. package/telegram-plugin/tests/inbound-delivery-machine-dispatch.test.ts +0 -16
  95. package/telegram-plugin/tests/inbound-emit-after-intercepts.test.ts +18 -7
  96. package/telegram-plugin/tests/inbound-message-types.test.ts +52 -16
  97. package/telegram-plugin/tests/litellm-proxy-auth-misconfig.test.ts +69 -14
  98. package/telegram-plugin/tests/media-message-handlers.test.ts +276 -0
  99. package/telegram-plugin/tests/mental-model-propose-callback-gate.test.ts +8 -4
  100. package/telegram-plugin/tests/model-command.test.ts +30 -0
  101. package/telegram-plugin/tests/multitopic-routing-wiring.test.ts +36 -12
  102. package/telegram-plugin/tests/narrative-dedup.test.ts +32 -0
  103. package/telegram-plugin/tests/narrative-flush.test.ts +6 -2
  104. package/telegram-plugin/tests/narrative-lane-golden.test.ts +458 -0
  105. package/telegram-plugin/tests/no-reply-bounded-drain.test.ts +14 -3
  106. package/telegram-plugin/tests/obligation-ledger.test.ts +40 -0
  107. package/telegram-plugin/tests/obligation-store.test.ts +43 -0
  108. package/telegram-plugin/tests/pending-card-durability-wiring.test.ts +18 -8
  109. package/telegram-plugin/tests/per-topic-current-turn.test.ts +32 -8
  110. package/telegram-plugin/tests/permission-no-repeat-wiring.test.ts +9 -6
  111. package/telegram-plugin/tests/photo-message-handler.test.ts +114 -0
  112. package/telegram-plugin/tests/photo-reroute-wiring.test.ts +5 -2
  113. package/telegram-plugin/tests/pinned-message-handler.test.ts +108 -0
  114. package/telegram-plugin/tests/render/render.test.ts +42 -0
  115. package/telegram-plugin/tests/reply-terminal-reaction.test.ts +6 -2
  116. package/telegram-plugin/tests/secret-detect-delete-must-surface-failures.test.ts +8 -4
  117. package/telegram-plugin/tests/secret-detect-fail-closed.test.ts +38 -28
  118. package/telegram-plugin/tests/secret-detect-oauth-code.test.ts +31 -20
  119. package/telegram-plugin/tests/send-reply-golden.test.ts +571 -0
  120. package/telegram-plugin/tests/silence-liveness-wiring.test.ts +22 -8
  121. package/telegram-plugin/tests/status-pin-service-message-suppression.test.ts +42 -49
  122. package/telegram-plugin/tests/stop-command.test.ts +22 -12
  123. package/telegram-plugin/tests/stream-render-golden.test.ts +424 -0
  124. package/telegram-plugin/tests/subagent-watcher-boot-skip-dead.test.ts +218 -0
  125. package/telegram-plugin/tests/subagent-watcher-resume-reregister.test.ts +305 -0
  126. package/telegram-plugin/tests/subagent-watcher-resurrection.test.ts +32 -0
  127. package/telegram-plugin/tests/subagent-watcher.test.ts +35 -3
  128. package/telegram-plugin/tests/turn-end-gate-backstop.test.ts +8 -12
  129. package/telegram-plugin/tests/turn-flush-safety.test.ts +191 -11
  130. package/telegram-plugin/tests/turn-flush-suppression-wiring.test.ts +117 -0
  131. package/telegram-plugin/tests/vault-approval-posture.test.ts +8 -2
  132. package/telegram-plugin/tests/vault-grant-inbound-builders.test.ts +2 -2
  133. package/telegram-plugin/tests/vault-grant-union.test.ts +4 -1
  134. package/telegram-plugin/tests/vault-key-regex-allows-slash.test.ts +16 -5
  135. package/telegram-plugin/tests/vault-request-access-tool.test.ts +10 -5
  136. package/telegram-plugin/tests/vault-request-access-unlock-resume.test.ts +4 -1
  137. package/telegram-plugin/tests/vault-subcommands.test.ts +6 -1
  138. package/telegram-plugin/tests/voice-message-handler.test.ts +111 -0
  139. package/telegram-plugin/tests/voice-ondemand-callback-handler.test.ts +140 -0
  140. package/telegram-plugin/tests/worker-activity-feed.test.ts +86 -19
  141. package/telegram-plugin/tests/worker-feed-coalesce.test.ts +236 -20
  142. package/telegram-plugin/tests/worker-feed-resume-guard.test.ts +86 -0
  143. package/telegram-plugin/tool-activity-summary.ts +110 -38
  144. package/telegram-plugin/turn-flush-safety.ts +80 -14
  145. package/telegram-plugin/uat/restart-capability.ts +76 -0
  146. package/telegram-plugin/uat/scenarios/bg-sub-agent-dispatch-dm.test.ts +14 -4
  147. package/telegram-plugin/uat/scenarios/bridge-flap-resilience-dm.test.ts +11 -1
  148. package/telegram-plugin/uat/scenarios/cross-turn-pending-progress-dm.test.ts +19 -2
  149. package/telegram-plugin/uat/scenarios/jtbd-always-on-after-restart-dm.test.ts +6 -12
  150. package/telegram-plugin/uat/scenarios/jtbd-deliberate-restart-resumes-dm.test.ts +6 -12
  151. package/telegram-plugin/uat/scenarios/jtbd-interrupted-turn-resumes-dm.test.ts +6 -12
  152. package/telegram-plugin/uat/scenarios/jtbd-multipart-render-dm.test.ts +47 -13
  153. package/telegram-plugin/worker-activity-feed.ts +34 -4
  154. package/telegram-plugin/gateway/busy-key-reaper.ts +0 -113
  155. package/telegram-plugin/gateway/gate-parity-probe.ts +0 -102
  156. package/telegram-plugin/tests/busy-key-reaper.test.ts +0 -192
  157. package/telegram-plugin/tests/fixtures/cutover-killswitch-probe.ts +0 -75
  158. package/telegram-plugin/tests/gate-parity-probe.test.ts +0 -171
  159. package/telegram-plugin/tests/parallel-turns-deadlock-fix.test.ts +0 -217
@@ -98,10 +98,12 @@ describe('anthropic_oauth_code pattern — Channel A', () => {
98
98
  // ─── Channel B — context rule structural tests ────────────────────────────────
99
99
 
100
100
  describe('auth-flow context rule — Channel B (structural wiring in gateway.ts)', () => {
101
- const src = readFileSync(
102
- new URL('../gateway/gateway.ts', import.meta.url),
103
- 'utf8',
104
- )
101
+ const src =
102
+ readFileSync(new URL('../gateway/gateway.ts', import.meta.url), 'utf8') +
103
+ '\n' +
104
+ // P7 PR-9 (#2996): the secret-detect pipeline intercept moved verbatim
105
+ // into gateway/inbound-interceptors.ts (interceptSecretDetectPipeline).
106
+ readFileSync(new URL('../gateway/inbound-interceptors.ts', import.meta.url), 'utf8')
105
107
 
106
108
  it('declares awaitingAuthCodeAt map and AUTH_CODE_CONTEXT_TTL_MS constant', () => {
107
109
  expect(src).toMatch(/const awaitingAuthCodeAt = new Map<string, number>/)
@@ -121,7 +123,7 @@ describe('auth-flow context rule — Channel B (structural wiring in gateway.ts)
121
123
 
122
124
  it('clears awaitingAuthCodeAt (delete) in the inbound handler when the flag is active', () => {
123
125
  // The inbound handler must call delete after reading the flag
124
- expect(src).toMatch(/awaitingAuthCodeAt\.delete\(chat_id\)/)
126
+ expect(src).toMatch(/awaitingAuthCodeAt\.delete\((?:p\.)?chat_id\)/)
125
127
  })
126
128
 
127
129
  it('checks isAuthFlowContext in the secret-detect block (passphrase path)', () => {
@@ -145,8 +147,9 @@ describe('auth-flow context rule — Channel B (structural wiring in gateway.ts)
145
147
  })
146
148
 
147
149
  it('reaps awaitingAuthCodeAt in the TTL reaper alongside other pending-state maps', () => {
148
- // The pendingStateReaper interval must sweep expired auth-code-context entries
149
- const reaperIdx = src.indexOf('pendingStateReaper = setInterval')
150
+ // The pendingStateReaper interval must sweep expired auth-code-context entries.
151
+ // Anchor tolerates the #2996 P0c `isGatewayMain ? setInterval(...)` boot gate.
152
+ const reaperIdx = src.indexOf('pendingStateReaper = ')
150
153
  expect(reaperIdx).toBeGreaterThan(0)
151
154
  const reaperBlock = src.slice(reaperIdx, reaperIdx + 800)
152
155
  expect(reaperBlock).toMatch(/awaitingAuthCodeAt/)
@@ -154,7 +157,9 @@ describe('auth-flow context rule — Channel B (structural wiring in gateway.ts)
154
157
  })
155
158
 
156
159
  it('auth-flow context rule sits BEFORE recordInbound() and broadcast()', () => {
157
- const contextIdx = src.indexOf('isAuthFlowContext')
160
+ // P7 PR-9: the context rule lives inside interceptSecretDetectPipeline;
161
+ // its gateway CALL SITE is the ordering anchor against the sinks.
162
+ const contextIdx = src.indexOf('await interceptSecretDetectPipeline(')
158
163
  const recordIdx = src.indexOf('recordInbound(', contextIdx)
159
164
  const broadcastIdx = src.indexOf('ipcServer.broadcast(inboundMsg)', contextIdx)
160
165
  expect(contextIdx).toBeGreaterThan(0)
@@ -190,8 +195,12 @@ describe('anthropic_oauth_code pattern — URL false-positive regression', () =>
190
195
  // Test 2: Blocker 1 sequencing — structural check that deleteMessage is called
191
196
  // inside the pendingReauthFlows intercept path, before setMessageReaction.
192
197
  describe('pendingReauthFlows intercept — deleteMessage sequencing (Blocker 1)', () => {
198
+ // P7 PR-7 (#2996): the reauth intercept body moved verbatim into
199
+ // gateway/inbound-interceptors.ts (interceptReauth); the redaction is the
200
+ // injected deps.redactAuthCode closure over redactAuthCodeMessage +
201
+ // redactAuthCodeApi (bound in gateway.ts). Same pins, new file owner.
193
202
  const src = readFileSync(
194
- new URL('../gateway/gateway.ts', import.meta.url),
203
+ new URL('../gateway/inbound-interceptors.ts', import.meta.url),
195
204
  'utf8',
196
205
  )
197
206
 
@@ -201,7 +210,7 @@ describe('pendingReauthFlows intercept — deleteMessage sequencing (Blocker 1)'
201
210
  // `setMessageReaction(...)` literals, but #488 consolidated all 6
202
211
  // auth-code paste paths through `redactAuthCodeMessage`. The pin
203
212
  // is now: the intercept block must call the helper.
204
- const interceptIdx = src.indexOf('// Auth-code intercept')
213
+ const interceptIdx = src.indexOf('export async function interceptReauth(')
205
214
  expect(interceptIdx).toBeGreaterThan(0)
206
215
 
207
216
  // Find the end of this intercept block — the next blank line after
@@ -214,7 +223,7 @@ describe('pendingReauthFlows intercept — deleteMessage sequencing (Blocker 1)'
214
223
  // (optionally cast, #623), now the gated `redactAuthCodeApi` adapter whose
215
224
  // reaction routes through the send gate + flood breaker (#3155). `msgId`
216
225
  // may be narrowed (`msgId ?? null`).
217
- expect(window).toMatch(/redactAuthCodeMessage\((?:bot\.api|redactAuthCodeApi)(?:\s+as\s+\w+)?,\s*chat_id,\s*msgId(?:\s*\?\?\s*null)?(?:,\s*[^)]+)?\)/)
226
+ expect(window).toMatch(/deps\.redactAuthCode\(p\.chat_id,\s*p\.msgId(?:\s*\?\?\s*null)?\)/)
218
227
  })
219
228
 
220
229
  it('redaction lands AFTER the success/error reply renders', () => {
@@ -223,10 +232,10 @@ describe('pendingReauthFlows intercept — deleteMessage sequencing (Blocker 1)'
223
232
  // even if their original message disappears mid-render. Same
224
233
  // ordering the helper preserves — fire-and-forget redaction
225
234
  // happens after `await switchroomReply(...)`.
226
- const interceptIdx = src.indexOf('// Auth-code intercept')
235
+ const interceptIdx = src.indexOf('export async function interceptReauth(')
227
236
  const window = src.slice(interceptIdx, interceptIdx + 2000)
228
- const replyIdx = window.indexOf('switchroomReply(ctx,')
229
- const redactIdx = window.indexOf('redactAuthCodeMessage(')
237
+ const replyIdx = window.indexOf('deps.switchroomReply(')
238
+ const redactIdx = window.indexOf('deps.redactAuthCode(')
230
239
  expect(replyIdx).toBeGreaterThan(0)
231
240
  expect(redactIdx).toBeGreaterThan(0)
232
241
  expect(replyIdx).toBeLessThan(redactIdx)
@@ -236,10 +245,12 @@ describe('pendingReauthFlows intercept — deleteMessage sequencing (Blocker 1)'
236
245
  // Test 3: Flag consumption — awaitingAuthCodeAt is NOT cleared on a non-detection
237
246
  // inbound (a stray "ok" within the 5-min window should not disarm Channel B).
238
247
  describe('awaitingAuthCodeAt flag — consumption only on actual detection', () => {
239
- const src = readFileSync(
240
- new URL('../gateway/gateway.ts', import.meta.url),
241
- 'utf8',
242
- )
248
+ const src =
249
+ readFileSync(new URL('../gateway/gateway.ts', import.meta.url), 'utf8') +
250
+ '\n' +
251
+ // P7 PR-9 (#2996): the secret-detect pipeline intercept moved verbatim
252
+ // into gateway/inbound-interceptors.ts (interceptSecretDetectPipeline).
253
+ readFileSync(new URL('../gateway/inbound-interceptors.ts', import.meta.url), 'utf8')
243
254
 
244
255
  it('delete(chat_id) does NOT appear at the top of the isAuthFlowContext block (no early consume)', () => {
245
256
  // The old bug: delete fired unconditionally inside `if (isAuthFlowContext)`.
@@ -260,7 +271,7 @@ describe('awaitingAuthCodeAt flag — consumption only on actual detection', ()
260
271
  expect(fallbackIdx).toBeGreaterThan(0)
261
272
  // Within 400 chars after the comment, delete must appear
262
273
  const window = src.slice(fallbackIdx, fallbackIdx + 400)
263
- expect(window).toMatch(/awaitingAuthCodeAt\.delete\(chat_id\)/)
274
+ expect(window).toMatch(/(?:deps\.)?awaitingAuthCodeAt\.delete\((?:p\.)?chat_id\)/)
264
275
  })
265
276
 
266
277
  it('awaitingAuthCodeAt.delete appears inside the no-passphrase hasHigh branch', () => {
@@ -271,7 +282,7 @@ describe('awaitingAuthCodeAt flag — consumption only on actual detection', ()
271
282
  const window = src.slice(noPpIdx, noPpIdx + 1200)
272
283
  // Conditional consume: only fires if isAuthFlowContext
273
284
  expect(window).toMatch(/if \(isAuthFlowContext\)/)
274
- expect(window).toMatch(/awaitingAuthCodeAt\.delete\(chat_id\)/)
285
+ expect(window).toMatch(/(?:deps\.)?awaitingAuthCodeAt\.delete\((?:p\.)?chat_id\)/)
275
286
  })
276
287
  })
277
288