switchroom 0.15.45 → 0.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/agent-scheduler/index.js +122 -88
  2. package/dist/auth-broker/index.js +463 -177
  3. package/dist/cli/autoaccept-poll.js +4842 -35
  4. package/dist/cli/drive-write-pretool.mjs +17 -14
  5. package/dist/cli/notion-write-pretool.mjs +117 -86
  6. package/dist/cli/self-improve-apply-guard-pretool.mjs +626 -0
  7. package/dist/cli/self-improve-stop.mjs +428 -0
  8. package/dist/cli/skill-validate-pretool.mjs +72 -72
  9. package/dist/cli/switchroom.js +3158 -1178
  10. package/dist/host-control/main.js +2833 -355
  11. package/dist/vault/approvals/kernel-server.js +7479 -7439
  12. package/dist/vault/broker/server.js +11312 -11272
  13. package/examples/minimal.yaml +1 -0
  14. package/examples/switchroom.yaml +1 -0
  15. package/package.json +3 -3
  16. package/profiles/_base/start.sh.hbs +88 -1
  17. package/profiles/_shared/execution-discipline.md.hbs +18 -0
  18. package/profiles/default/CLAUDE.md.hbs +0 -19
  19. package/telegram-plugin/.claude-plugin/plugin.json +2 -2
  20. package/telegram-plugin/answer-stream-flag.ts +12 -49
  21. package/telegram-plugin/answer-stream.ts +5 -150
  22. package/telegram-plugin/auth-snapshot-format.ts +280 -48
  23. package/telegram-plugin/auto-fallback-fleet.ts +44 -1
  24. package/telegram-plugin/context-exhaustion.ts +12 -0
  25. package/telegram-plugin/demo-mask.ts +154 -0
  26. package/telegram-plugin/dist/bridge/bridge.js +167 -124
  27. package/telegram-plugin/dist/gateway/gateway.js +3039 -1159
  28. package/telegram-plugin/dist/server.js +215 -172
  29. package/telegram-plugin/docs/waiting-ux-spec.md +2 -2
  30. package/telegram-plugin/draft-stream.ts +47 -410
  31. package/telegram-plugin/final-answer-detect.ts +17 -12
  32. package/telegram-plugin/fleet-fallback-resume.ts +131 -0
  33. package/telegram-plugin/format.ts +56 -19
  34. package/telegram-plugin/gateway/auth-add-flow.ts +332 -127
  35. package/telegram-plugin/gateway/auth-broker-client.ts +2 -2
  36. package/telegram-plugin/gateway/auth-command.ts +70 -14
  37. package/telegram-plugin/gateway/clean-shutdown-marker.ts +44 -0
  38. package/telegram-plugin/gateway/config-approval-handler.test.ts +91 -4
  39. package/telegram-plugin/gateway/config-approval-handler.ts +94 -13
  40. package/telegram-plugin/gateway/current-turn-map.ts +188 -0
  41. package/telegram-plugin/gateway/disconnect-flush.ts +3 -1
  42. package/telegram-plugin/gateway/effort-command.ts +8 -3
  43. package/telegram-plugin/gateway/emission-authority.ts +369 -0
  44. package/telegram-plugin/gateway/feed-open-gate.ts +292 -0
  45. package/telegram-plugin/gateway/gateway.ts +1837 -291
  46. package/telegram-plugin/gateway/inject-handler.test.ts +2 -1
  47. package/telegram-plugin/gateway/ms365-write-approval.test.ts +4 -4
  48. package/telegram-plugin/gateway/represent-guard.ts +72 -0
  49. package/telegram-plugin/gateway/status-surface-log.test.ts +5 -4
  50. package/telegram-plugin/gateway/status-surface-log.ts +14 -3
  51. package/telegram-plugin/history.ts +33 -11
  52. package/telegram-plugin/hooks/repo-context-pretool.mjs +26 -0
  53. package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +5 -0
  54. package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +8 -0
  55. package/telegram-plugin/hooks/tool-label-pretool.mjs +39 -15
  56. package/telegram-plugin/issues-card.ts +4 -0
  57. package/telegram-plugin/model-unavailable.ts +124 -0
  58. package/telegram-plugin/narrative-dedup.ts +69 -0
  59. package/telegram-plugin/over-ping-safety-net.ts +70 -4
  60. package/telegram-plugin/package.json +3 -3
  61. package/telegram-plugin/pending-work-progress.ts +12 -0
  62. package/telegram-plugin/permission-rule.ts +32 -5
  63. package/telegram-plugin/permission-title.ts +152 -9
  64. package/telegram-plugin/quota-check.ts +13 -0
  65. package/telegram-plugin/quota-watch.ts +135 -7
  66. package/telegram-plugin/registry/turns-schema.test.ts +24 -0
  67. package/telegram-plugin/registry/turns-schema.ts +9 -0
  68. package/telegram-plugin/runtime-metrics.ts +13 -0
  69. package/telegram-plugin/session-tail.ts +96 -11
  70. package/telegram-plugin/silence-poke.ts +170 -24
  71. package/telegram-plugin/slot-banner-driver.ts +3 -0
  72. package/telegram-plugin/status-no-truncate.ts +44 -0
  73. package/telegram-plugin/status-reactions.ts +20 -3
  74. package/telegram-plugin/stream-controller.ts +4 -23
  75. package/telegram-plugin/stream-reply-handler.ts +6 -24
  76. package/telegram-plugin/streaming-metrics.ts +91 -0
  77. package/telegram-plugin/subagent-watcher.ts +212 -66
  78. package/telegram-plugin/tests/activity-ever-opened-sticky.test.ts +47 -0
  79. package/telegram-plugin/tests/answer-stream-dedup.test.ts +9 -26
  80. package/telegram-plugin/tests/answer-stream-flag.test.ts +25 -58
  81. package/telegram-plugin/tests/answer-stream-silent-markers.test.ts +41 -51
  82. package/telegram-plugin/tests/answer-stream.test.ts +2 -411
  83. package/telegram-plugin/tests/auth-add-flow.test.ts +488 -253
  84. package/telegram-plugin/tests/auth-command-format2.test.ts +71 -1
  85. package/telegram-plugin/tests/auth-snapshot-format.test.ts +376 -6
  86. package/telegram-plugin/tests/auto-fallback-fleet.test.ts +120 -0
  87. package/telegram-plugin/tests/cross-turn-card-gate.test.ts +424 -0
  88. package/telegram-plugin/tests/demo-mask.test.ts +127 -0
  89. package/telegram-plugin/tests/draft-stream.test.ts +0 -827
  90. package/telegram-plugin/tests/emission-authority-card-drain-gate.test.ts +236 -0
  91. package/telegram-plugin/tests/emission-authority-facade.test.ts +488 -0
  92. package/telegram-plugin/tests/emission-authority-open-gate.test.ts +179 -0
  93. package/telegram-plugin/tests/emission-authority-ping-gate.test.ts +395 -0
  94. package/telegram-plugin/tests/emission-determinism-wiring.test.ts +177 -0
  95. package/telegram-plugin/tests/feed-heartbeat-liveness-open.test.ts +146 -0
  96. package/telegram-plugin/tests/feed-open-gate.test.ts +259 -0
  97. package/telegram-plugin/tests/feed-survival.test.ts +526 -0
  98. package/telegram-plugin/tests/fleet-fallback-resume.test.ts +197 -0
  99. package/telegram-plugin/tests/gateway-clean-shutdown-marker.test.ts +117 -0
  100. package/telegram-plugin/tests/gateway-no-reply-single-emit.test.ts +4 -11
  101. package/telegram-plugin/tests/history.test.ts +60 -0
  102. package/telegram-plugin/tests/model-unavailable.test.ts +118 -0
  103. package/telegram-plugin/tests/narrative-dedup.test.ts +118 -0
  104. package/telegram-plugin/tests/orphaned-reply-rearm.test.ts +285 -0
  105. package/telegram-plugin/tests/over-ping-final-answer-decoupling.test.ts +194 -0
  106. package/telegram-plugin/tests/over-ping-safety-net.test.ts +2 -2
  107. package/telegram-plugin/tests/per-topic-current-turn.test.ts +373 -0
  108. package/telegram-plugin/tests/permission-card-origin-kill-switch.test.ts +42 -0
  109. package/telegram-plugin/tests/permission-rule.test.ts +17 -0
  110. package/telegram-plugin/tests/permission-title.test.ts +206 -17
  111. package/telegram-plugin/tests/quota-watch.test.ts +252 -9
  112. package/telegram-plugin/tests/reply-terminal-reaction.test.ts +6 -1
  113. package/telegram-plugin/tests/repo-context-pretool.test.ts +62 -0
  114. package/telegram-plugin/tests/represent-guard.test.ts +162 -0
  115. package/telegram-plugin/tests/session-tail.test.ts +147 -3
  116. package/telegram-plugin/tests/silence-liveness-wiring.test.ts +18 -0
  117. package/telegram-plugin/tests/status-card-budget-parity.test.ts +72 -0
  118. package/telegram-plugin/tests/status-surface-log.test.ts +146 -0
  119. package/telegram-plugin/tests/subagent-watcher-clip-narrative.test.ts +58 -0
  120. package/telegram-plugin/tests/subagent-watcher-parent-turn-key.test.ts +102 -0
  121. package/telegram-plugin/tests/subagent-watcher-workflow-visibility.test.ts +225 -0
  122. package/telegram-plugin/tests/subagent-watcher.test.ts +147 -0
  123. package/telegram-plugin/tests/telegram-activity-visibility-integration.test.ts +597 -0
  124. package/telegram-plugin/tests/telegram-format.test.ts +101 -6
  125. package/telegram-plugin/tests/tool-activity-summary.test.ts +550 -15
  126. package/telegram-plugin/tests/tool-label-pretool.test.ts +73 -0
  127. package/telegram-plugin/tests/tool-label-sidecar.test.ts +44 -0
  128. package/telegram-plugin/tests/tool-labels.test.ts +67 -0
  129. package/telegram-plugin/tests/turn-liveness-floor.test.ts +196 -0
  130. package/telegram-plugin/tests/turn-liveness-invariant.test.ts +340 -0
  131. package/telegram-plugin/tests/welcome-text.test.ts +32 -3
  132. package/telegram-plugin/tests/worker-activity-feed.test.ts +470 -22
  133. package/telegram-plugin/tool-activity-summary.ts +375 -58
  134. package/telegram-plugin/turn-liveness-floor.ts +240 -0
  135. package/telegram-plugin/uat/assertions.ts +115 -0
  136. package/telegram-plugin/uat/driver.ts +68 -0
  137. package/telegram-plugin/uat/scenarios/bg-sub-agent-dispatch-dm.test.ts +119 -133
  138. package/telegram-plugin/uat/scenarios/jtbd-answer-pings.test.ts +94 -0
  139. package/telegram-plugin/uat/scenarios/jtbd-cross-turn-card-dm.test.ts +109 -0
  140. package/telegram-plugin/uat/scenarios/jtbd-foreground-feed-thinkgap-dm.test.ts +478 -0
  141. package/telegram-plugin/uat/scenarios/jtbd-foreground-feed-visibility-dm.test.ts +396 -0
  142. package/telegram-plugin/uat/scenarios/jtbd-liveness-feed-open-dm.test.ts +202 -0
  143. package/telegram-plugin/uat/scenarios/jtbd-reply-is-last-dm.test.ts +202 -0
  144. package/telegram-plugin/uat/scenarios/reactions-dm.test.ts +93 -87
  145. package/telegram-plugin/welcome-text.ts +13 -1
  146. package/telegram-plugin/worker-activity-feed.ts +157 -82
  147. package/telegram-plugin/draft-transport.ts +0 -122
  148. package/telegram-plugin/tests/draft-retirement-wiring.test.ts +0 -82
  149. package/telegram-plugin/tests/draft-transport.test.ts +0 -211
@@ -0,0 +1,154 @@
1
+ /**
2
+ * demo-mask — PII masking for the `demo` suffix on Telegram status
3
+ * commands (`/usage demo`, `/auth demo`, `/status demo`, `/whoami demo`).
4
+ *
5
+ * Purpose: when an operator records a screen-recording / screenshot of a
6
+ * status command, a trailing `demo` token masks the MUST-MASK PII tier so
7
+ * real account emails, the operator's Telegram handle/id, and live vault key
8
+ * names never end up in a published clip. This is per-command and opt-in —
9
+ * the default output is unchanged and still shows the real values.
10
+ *
11
+ * Scope is deliberately narrow (the MUST-MASK tier only):
12
+ * 1. Email addresses (account labels) → maskEmail
13
+ * 2. Telegram username / sender id → maskUsername
14
+ * 3. Vault key names → maskVaultKey
15
+ *
16
+ * Explicitly OUT of scope (NOT masked): agent names, MCP server names,
17
+ * model ids, host paths, fleet topology. Those are not PII and masking
18
+ * them would make a demo recording confusingly unrepresentative.
19
+ *
20
+ * Determinism contract: every function is a pure-ish mapping with a
21
+ * process-lifetime stable cache. The SAME input always maps to the SAME
22
+ * masked output within a process; DISTINCT inputs map to DISTINCT outputs
23
+ * (within the size of each pool — pools are large enough for realistic
24
+ * fleets, and overflow falls back to a stable suffixed form so distinctness
25
+ * still holds). The mapping is intentionally NOT stable across process
26
+ * restarts — it does not need to be, and a per-process map keeps the module
27
+ * dependency-free (no persisted state, no hashing of secrets to disk).
28
+ */
29
+
30
+ // ── stable assignment helper ─────────────────────────────────────────
31
+
32
+ /**
33
+ * Assign a stable masked value for `input` using a per-pool Map. The first
34
+ * time an input is seen it claims the next pool entry (or a deterministic
35
+ * overflow form once the pool is exhausted); subsequent calls return the
36
+ * same value. Distinct inputs never collide.
37
+ */
38
+ function stableAssign(
39
+ input: string,
40
+ cache: Map<string, string>,
41
+ pool: readonly string[],
42
+ overflow: (index: number) => string,
43
+ ): string {
44
+ const existing = cache.get(input);
45
+ if (existing !== undefined) return existing;
46
+ const index = cache.size;
47
+ const value = index < pool.length ? pool[index]! : overflow(index);
48
+ cache.set(input, value);
49
+ return value;
50
+ }
51
+
52
+ // ── emails ───────────────────────────────────────────────────────────
53
+
54
+ /**
55
+ * Fixed pool of realistic fake emails. Named after computing pioneers so a
56
+ * demo clip reads naturally without exposing the operator's real accounts.
57
+ * All on `example.com` (RFC 2606 reserved — guaranteed not a real inbox).
58
+ */
59
+ const EMAIL_POOL: readonly string[] = [
60
+ 'ada@example.com',
61
+ 'grace@example.com',
62
+ 'linus@example.com',
63
+ 'hopper@example.com',
64
+ 'turing@example.com',
65
+ 'lovelace@example.com',
66
+ 'dijkstra@example.com',
67
+ 'knuth@example.com',
68
+ 'ritchie@example.com',
69
+ 'torvalds@example.com',
70
+ ];
71
+
72
+ const emailCache = new Map<string, string>();
73
+
74
+ /**
75
+ * Map an account label to a stable realistic fake.
76
+ *
77
+ * Email-shaped labels map to the email pool. A non-email label (some
78
+ * operators use a plain nickname as an account label) still gets a stable
79
+ * fake email — masking a label that MIGHT carry a name to an obviously-fake
80
+ * address is the safe choice for a recording.
81
+ */
82
+ export function maskEmail(label: string): string {
83
+ return stableAssign(
84
+ label,
85
+ emailCache,
86
+ EMAIL_POOL,
87
+ (i) => `demo${i + 1}@example.com`,
88
+ );
89
+ }
90
+
91
+ // ── telegram username / sender id ────────────────────────────────────
92
+
93
+ /**
94
+ * Fixed pool of fake Telegram handles. First input → `@demo_user`, second
95
+ * distinct input → `@demo_user2`, etc., so a recording shows a believable
96
+ * handle and a second account (if any) stays distinct.
97
+ */
98
+ const USERNAME_POOL: readonly string[] = [
99
+ '@demo_user',
100
+ '@demo_user2',
101
+ '@demo_user3',
102
+ '@demo_user4',
103
+ '@demo_user5',
104
+ ];
105
+
106
+ const usernameCache = new Map<string, string>();
107
+
108
+ /**
109
+ * Map a `@handle` or a numeric sender id to a stable fake handle. The input
110
+ * may be `@realhandle` (when the user has a username) or a bare numeric id
111
+ * (when they don't) — both map into the same pool, so the masked output is
112
+ * always a `@demo_user…` handle regardless of the input shape. This also
113
+ * normalises the id case to a friendlier handle for the recording.
114
+ */
115
+ export function maskUsername(tag: string): string {
116
+ return stableAssign(
117
+ tag,
118
+ usernameCache,
119
+ USERNAME_POOL,
120
+ (i) => `@demo_user${i + 1}`,
121
+ );
122
+ }
123
+
124
+ // ── vault key names ──────────────────────────────────────────────────
125
+
126
+ const vaultKeyCache = new Map<string, string>();
127
+
128
+ /**
129
+ * Map a real vault key name (e.g. `coolify/api-token`, `github/token`) to a
130
+ * stable masked form (`demo/secret-1`, `demo/secret-2`, …). Keeps the
131
+ * `namespace/key` shape so a recording still reads like a real vault listing
132
+ * without revealing which services the operator has wired.
133
+ */
134
+ export function maskVaultKey(name: string): string {
135
+ return stableAssign(
136
+ name,
137
+ vaultKeyCache,
138
+ [],
139
+ (i) => `demo/secret-${i + 1}`,
140
+ );
141
+ }
142
+
143
+ // ── test-only reset ──────────────────────────────────────────────────
144
+
145
+ /**
146
+ * Clear all stable-assignment caches. Test-only — lets a test assert the
147
+ * pool-ordering from a known-empty state without cross-test contamination.
148
+ * Not used by production code paths.
149
+ */
150
+ export function __resetDemoMaskCachesForTest(): void {
151
+ emailCache.clear();
152
+ usernameCache.clear();
153
+ vaultKeyCache.clear();
154
+ }