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.
- package/README.md +51 -59
- package/bin/run-hook.sh +27 -11
- package/bin/timezone-hook.sh +9 -7
- package/dist/agent-scheduler/index.js +410 -133
- package/dist/auth-broker/index.js +13932 -0
- package/dist/cli/switchroom.js +26937 -5601
- package/dist/host-control/main.js +12702 -0
- package/dist/vault/approvals/kernel-server.js +467 -184
- package/dist/vault/broker/server.js +1430 -724
- package/examples/minimal.yaml +63 -0
- package/examples/personal-google-workspace-mcp/.env.example +34 -0
- package/examples/personal-google-workspace-mcp/README.md +194 -0
- package/examples/personal-google-workspace-mcp/compose.yaml +66 -0
- package/examples/switchroom.yaml +220 -0
- package/package.json +7 -4
- package/profiles/_base/settings.json.hbs +20 -5
- package/profiles/_base/start.sh.hbs +16 -3
- package/profiles/_shared/agent-self-service.md.hbs +126 -0
- package/profiles/_shared/telegram-style.md.hbs +20 -90
- package/profiles/_shared/vault-protocol.md.hbs +68 -0
- package/profiles/default/CLAUDE.md +50 -96
- package/profiles/default/CLAUDE.md.hbs +36 -6
- package/profiles/default/workspace/SOUL.md.hbs +12 -5
- package/skills/buildkite-agent-infrastructure/SKILL.md +30 -11
- package/skills/buildkite-agent-runtime/SKILL.md +44 -11
- package/skills/buildkite-api/SKILL.md +31 -8
- package/skills/buildkite-cli/SKILL.md +27 -9
- package/skills/buildkite-migration/SKILL.md +22 -9
- package/skills/buildkite-pipelines/SKILL.md +26 -9
- package/skills/buildkite-secure-delivery/SKILL.md +23 -9
- package/skills/buildkite-test-engine/SKILL.md +25 -8
- package/skills/docx/SKILL.md +1 -1
- package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/base.cpython-313.pyc +0 -0
- package/skills/file-bug/SKILL.md +34 -6
- package/skills/humanizer/SKILL.md +15 -0
- package/skills/humanizer-calibrate/SKILL.md +7 -1
- package/skills/mcp-builder/SKILL.md +1 -1
- package/skills/pdf/SKILL.md +1 -1
- package/skills/pptx/SKILL.md +1 -1
- package/skills/skill-creator/SKILL.md +21 -1
- package/skills/skill-creator/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/generate_report.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/improve_description.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/run_eval.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/run_loop.cpython-313.pyc +0 -0
- package/skills/skill-creator/scripts/__pycache__/utils.cpython-313.pyc +0 -0
- package/skills/switchroom-cli/SKILL.md +63 -64
- package/skills/switchroom-health/SKILL.md +23 -10
- package/skills/switchroom-install/SKILL.md +3 -3
- package/skills/switchroom-manage/SKILL.md +26 -19
- package/skills/switchroom-runtime/SKILL.md +191 -0
- package/skills/switchroom-status/SKILL.md +27 -2
- package/skills/telegram-test-harness/SKILL.md +3 -0
- package/skills/token-helpers/SKILL.md +24 -1
- package/skills/webapp-testing/SKILL.md +31 -1
- package/skills/xlsx/SKILL.md +1 -1
- package/telegram-plugin/admin-commands/index.ts +7 -5
- package/telegram-plugin/analytics-posthog.ts +191 -0
- package/telegram-plugin/bridge/bridge.ts +69 -0
- package/telegram-plugin/bridge/ipc-client.ts +4 -1
- package/telegram-plugin/dist/bridge/bridge.js +194 -119
- package/telegram-plugin/dist/gateway/gateway.js +23611 -19671
- package/telegram-plugin/dist/server.js +245 -189
- package/telegram-plugin/first-paint.ts +3 -24
- package/telegram-plugin/gateway/auth-add-flow.ts +326 -0
- package/telegram-plugin/gateway/auth-broker-client.ts +75 -0
- package/telegram-plugin/gateway/auth-command.ts +794 -0
- package/telegram-plugin/gateway/auth-line.ts +123 -0
- package/telegram-plugin/gateway/boot-card.ts +169 -40
- package/telegram-plugin/gateway/boot-issue-cache.ts +308 -0
- package/telegram-plugin/gateway/boot-probes.ts +166 -123
- package/telegram-plugin/gateway/boot-reason.ts +41 -7
- package/telegram-plugin/gateway/boot-version.ts +66 -0
- package/telegram-plugin/gateway/gateway.ts +3499 -1885
- package/telegram-plugin/gateway/hostd-dispatch.ts +117 -0
- package/telegram-plugin/gateway/ipc-protocol.ts +18 -0
- package/telegram-plugin/gateway/pending-inbound-buffer.ts +106 -0
- package/telegram-plugin/gateway/quarantine.ts +69 -0
- package/telegram-plugin/gateway/quota-cache.ts +9 -4
- package/telegram-plugin/gateway/reaction-trigger.ts +401 -0
- package/telegram-plugin/gateway/recent-denials.test.ts +103 -0
- package/telegram-plugin/gateway/recent-denials.ts +77 -0
- package/telegram-plugin/gateway/startup-network-retry.ts +109 -31
- package/telegram-plugin/gateway/vault-grant-inbound-builders.ts +125 -0
- package/telegram-plugin/history.ts +91 -0
- package/telegram-plugin/hooks/hooks.json +10 -0
- package/telegram-plugin/hooks/sandbox-hint-posttool.mjs +130 -0
- package/telegram-plugin/hooks/subagent-tracker-posttool.mjs +19 -2
- package/telegram-plugin/hooks/subagent-tracker-pretool.mjs +22 -2
- package/telegram-plugin/hooks/tool-label-pretool.mjs +11 -0
- package/telegram-plugin/hooks/wedge-detect-posttool.mjs +303 -0
- package/telegram-plugin/inbound-classifier.ts +50 -0
- package/telegram-plugin/inline-keyboard-callbacks.ts +136 -0
- package/telegram-plugin/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/telegram-plugin/package.json +4 -2
- package/telegram-plugin/permission-rule.ts +51 -0
- package/telegram-plugin/permission-title.ts +56 -0
- package/telegram-plugin/quota-check.ts +19 -41
- package/telegram-plugin/registry/reaper.ts +223 -0
- package/telegram-plugin/retry-api-call.ts +80 -0
- package/telegram-plugin/runtime-metrics.ts +177 -0
- package/telegram-plugin/scripts/build.mjs +0 -1
- package/telegram-plugin/secret-detect/index.ts +24 -0
- package/telegram-plugin/secret-detect/vault-error.test.ts +64 -12
- package/telegram-plugin/secret-detect/vault-error.ts +78 -11
- package/telegram-plugin/secret-detect/vault-write.ts +14 -2
- package/telegram-plugin/server.js +41795 -0
- package/telegram-plugin/session-tail.ts +6 -1
- package/telegram-plugin/shared/bot-runtime.ts +5 -4
- package/telegram-plugin/silence-poke.ts +420 -0
- package/telegram-plugin/silent-end.ts +174 -0
- package/telegram-plugin/stream-controller.ts +13 -0
- package/telegram-plugin/stream-reply-handler.ts +7 -0
- package/telegram-plugin/subagent-watcher.ts +213 -4
- package/telegram-plugin/tests/auth-add-flow.test.ts +559 -0
- package/telegram-plugin/tests/auth-code-redact.test.ts +8 -4
- package/telegram-plugin/tests/auth-command-vernacular.test.ts +531 -0
- package/telegram-plugin/tests/boot-card-issue-dedup.test.ts +247 -0
- package/telegram-plugin/tests/boot-card-reason-to-render.test.ts +182 -0
- package/telegram-plugin/tests/boot-card-reason.test.ts +65 -2
- package/telegram-plugin/tests/boot-card-render.test.ts +146 -0
- package/telegram-plugin/tests/boot-card-silent-on-operator.test.ts +103 -0
- package/telegram-plugin/tests/boot-probes.test.ts +216 -10
- package/telegram-plugin/tests/boot-version-string.test.ts +0 -0
- package/telegram-plugin/tests/finalize-callback.test.ts +190 -0
- package/telegram-plugin/tests/gateway-message-validator.test.ts +26 -0
- package/telegram-plugin/tests/gateway-secret-detect.test.ts +12 -3
- package/telegram-plugin/tests/gateway-startup-network-retry.test.ts +104 -0
- package/telegram-plugin/tests/history-reaper.test.ts +378 -0
- package/telegram-plugin/tests/hostd-dispatch.test.ts +129 -0
- package/telegram-plugin/tests/inbound-classifier.test.ts +76 -0
- package/telegram-plugin/tests/inbound-message-types.test.ts +267 -0
- package/telegram-plugin/tests/issues-card.test.ts +49 -0
- package/telegram-plugin/tests/pending-inbound-buffer.test.ts +132 -0
- package/telegram-plugin/tests/permission-rule.test.ts +80 -1
- package/telegram-plugin/tests/permission-title.test.ts +31 -0
- package/telegram-plugin/tests/quota-check.test.ts +5 -35
- package/telegram-plugin/tests/races.test.ts +179 -0
- package/telegram-plugin/tests/reaction-trigger-flow.test.ts +353 -0
- package/telegram-plugin/tests/reaction-trigger.test.ts +397 -0
- package/telegram-plugin/tests/retry-api-call.test.ts +152 -1
- package/telegram-plugin/tests/runtime-metrics.test.ts +145 -0
- package/telegram-plugin/tests/sandbox-hint-posttool.test.ts +155 -0
- package/telegram-plugin/tests/secret-detect-delete-must-surface-failures.test.ts +133 -0
- package/telegram-plugin/tests/secret-detect-false-positives.test.ts +137 -0
- package/telegram-plugin/tests/silence-poke.test.ts +493 -0
- package/telegram-plugin/tests/silent-end.test.ts +206 -0
- package/telegram-plugin/tests/subagent-tracker-hooks.test.ts +107 -0
- package/telegram-plugin/tests/subagent-watcher-env-thresholds.test.ts +224 -0
- package/telegram-plugin/tests/subagent-watcher-stall-terminal.test.ts +316 -0
- package/telegram-plugin/tests/subagent-watcher.test.ts +263 -0
- package/telegram-plugin/tests/turn-signal-tracker.test.ts +81 -0
- package/telegram-plugin/tests/vault-approval-posture.test.ts +256 -0
- package/telegram-plugin/tests/vault-grant-auto-resume.test.ts +73 -0
- package/telegram-plugin/tests/vault-grant-inbound-builders.test.ts +226 -0
- package/telegram-plugin/tests/vault-grant-union.test.ts +130 -0
- package/telegram-plugin/tests/vault-key-regex-allows-slash.test.ts +140 -0
- package/telegram-plugin/tests/vault-posture-quarantine.test.ts +104 -0
- package/telegram-plugin/tests/vault-request-access-tool.test.ts +114 -0
- package/telegram-plugin/tests/vault-request-access-unlock-resume.test.ts +106 -0
- package/telegram-plugin/turn-signal-tracker.ts +100 -24
- package/telegram-plugin/uat/SETUP.md +210 -35
- package/telegram-plugin/uat/assertions.ts +264 -37
- package/telegram-plugin/uat/driver-info.ts +57 -0
- package/telegram-plugin/uat/driver.ts +590 -51
- package/telegram-plugin/uat/harness.ts +140 -94
- package/telegram-plugin/uat/load-env.test.ts +72 -0
- package/telegram-plugin/uat/load-env.ts +48 -0
- package/telegram-plugin/uat/login.ts +96 -53
- package/telegram-plugin/uat/runners/agent-self-sufficiency.ts +457 -0
- package/telegram-plugin/uat/runners/paraphrases.ts +231 -0
- package/telegram-plugin/uat/runners/report.ts +150 -0
- package/telegram-plugin/uat/runners/run-agent-self-sufficiency.sh +50 -0
- package/telegram-plugin/uat/runners/scorer.test.ts +196 -0
- package/telegram-plugin/uat/runners/scorer.ts +106 -0
- package/telegram-plugin/uat/runners/skill-coverage.test.ts +100 -0
- package/telegram-plugin/uat/runners/skill-coverage.ts +620 -0
- package/telegram-plugin/uat/scenarios/ask-user-button-tap-dm.test.ts +141 -0
- package/telegram-plugin/uat/scenarios/bg-sub-agent-dispatch-dm.test.ts +191 -0
- package/telegram-plugin/uat/scenarios/fuzz-extended-dm.test.ts +255 -0
- package/telegram-plugin/uat/scenarios/fuzz-human-style-dm.test.ts +275 -0
- package/telegram-plugin/uat/scenarios/fuzz-random-prompts-dm.test.ts +146 -0
- package/telegram-plugin/uat/scenarios/fuzz-status-ask-dm.test.ts +486 -0
- package/telegram-plugin/uat/scenarios/jtbd-interrupt-marker-dm.test.ts +67 -0
- package/telegram-plugin/uat/scenarios/jtbd-rapid-followup-dm.test.ts +100 -0
- package/telegram-plugin/uat/scenarios/jtbd-soft-commit-dm.test.ts +67 -0
- package/telegram-plugin/uat/scenarios/jtbd-status-query-dm.test.ts +49 -0
- package/telegram-plugin/uat/scenarios/location-inbound-dm.test.ts +65 -0
- package/telegram-plugin/uat/scenarios/midturn-silent-dm.test.ts +175 -0
- package/telegram-plugin/uat/scenarios/reactions-dm.test.ts +142 -0
- package/telegram-plugin/uat/scenarios/reactions-trigger-turn-dm.test.ts +96 -0
- package/telegram-plugin/uat/scenarios/secret-redaction-deletes-original-dm.test.ts +123 -0
- package/telegram-plugin/uat/scenarios/secret-redaction-no-false-positive-dm.test.ts +87 -0
- package/telegram-plugin/uat/scenarios/silence-poke-soft-dm.test.ts +155 -0
- package/telegram-plugin/uat/scenarios/silent-end-recovery-dm.test.ts +95 -0
- package/telegram-plugin/uat/scenarios/smoke-dm-reply.test.ts +57 -0
- package/telegram-plugin/uat/scenarios/subagent-watcher-no-rerun-dm.test.ts +135 -0
- package/telegram-plugin/uat/scenarios/vault-approval-posture-telegram-id-dm.test.ts +191 -0
- package/telegram-plugin/uat/scenarios/vault-audit-allow-dm.test.ts +108 -0
- package/telegram-plugin/uat/scenarios/vault-grant-auto-resume-dm.test.ts +121 -0
- package/telegram-plugin/uat/scenarios/vault-request-access-concurrent-dm.test.ts +161 -0
- package/telegram-plugin/uat/scenarios/vault-request-access-end-to-end-dm.test.ts +158 -0
- package/telegram-plugin/uat/scenarios/voice-inbound-dm.test.ts +65 -0
- package/telegram-plugin/vault-approval-posture.ts +42 -0
- package/telegram-plugin/welcome-text.ts +1 -0
- package/telegram-plugin/active-pins-sweep.ts +0 -204
- package/telegram-plugin/active-pins.ts +0 -146
- package/telegram-plugin/auth-dashboard.ts +0 -1104
- package/telegram-plugin/auth-slot-parser.ts +0 -497
- package/telegram-plugin/card-event-log.ts +0 -138
- package/telegram-plugin/dist/foreman/foreman.js +0 -31106
- package/telegram-plugin/docs/multi-agent-card-design.md +0 -847
- package/telegram-plugin/docs/pinned-progress-card-reliability.md +0 -144
- package/telegram-plugin/foreman/foreman-create-flow.ts +0 -202
- package/telegram-plugin/foreman/foreman-handlers.ts +0 -493
- package/telegram-plugin/foreman/foreman.ts +0 -1165
- package/telegram-plugin/foreman/setup-flow.ts +0 -345
- package/telegram-plugin/foreman/setup-state.ts +0 -239
- package/telegram-plugin/foreman/state.ts +0 -203
- package/telegram-plugin/pin-event-log.ts +0 -76
- package/telegram-plugin/progress-card-driver.ts +0 -2886
- package/telegram-plugin/progress-card-pin-manager.ts +0 -589
- package/telegram-plugin/progress-card-pin-watchdog.ts +0 -98
- package/telegram-plugin/progress-card.ts +0 -1409
- package/telegram-plugin/tests/HARNESS.md +0 -340
- package/telegram-plugin/tests/_progress-card-harness.ts +0 -109
- package/telegram-plugin/tests/active-pins-boot-reaper.test.ts +0 -211
- package/telegram-plugin/tests/active-pins-sweep.test.ts +0 -309
- package/telegram-plugin/tests/active-pins.test.ts +0 -187
- package/telegram-plugin/tests/auth-account-identity-surface.test.ts +0 -118
- package/telegram-plugin/tests/auth-dashboard-edge-cases.test.ts +0 -260
- package/telegram-plugin/tests/auth-dashboard-restart-flow.test.ts +0 -140
- package/telegram-plugin/tests/auth-dashboard-v3b.test.ts +0 -559
- package/telegram-plugin/tests/auth-dashboard.test.ts +0 -1045
- package/telegram-plugin/tests/auth-slot-commands.test.ts +0 -640
- package/telegram-plugin/tests/bg-agent-progress-card-757.test.ts +0 -201
- package/telegram-plugin/tests/boot-card-account-quota.test.ts +0 -137
- package/telegram-plugin/tests/card-event-log.test.ts +0 -145
- package/telegram-plugin/tests/first-paint.test.ts +0 -257
- package/telegram-plugin/tests/foreman-create-flow.test.ts +0 -359
- package/telegram-plugin/tests/foreman-handlers.test.ts +0 -347
- package/telegram-plugin/tests/foreman-state.test.ts +0 -164
- package/telegram-plugin/tests/foreman-write-ops.test.ts +0 -214
- package/telegram-plugin/tests/harness-ordering-invariants.test.ts +0 -243
- package/telegram-plugin/tests/pin-event-log.test.ts +0 -124
- package/telegram-plugin/tests/progress-card-api-failure-during-deferred.test.ts +0 -73
- package/telegram-plugin/tests/progress-card-close-paths-converge.test.ts +0 -272
- package/telegram-plugin/tests/progress-card-cross-turn.test.ts +0 -258
- package/telegram-plugin/tests/progress-card-delay-842.test.ts +0 -160
- package/telegram-plugin/tests/progress-card-dispose-preservepending.test.ts +0 -81
- package/telegram-plugin/tests/progress-card-draft-flag.test.ts +0 -80
- package/telegram-plugin/tests/progress-card-driver-eviction.test.ts +0 -215
- package/telegram-plugin/tests/progress-card-driver-fleet-shadow.test.ts +0 -123
- package/telegram-plugin/tests/progress-card-driver-force-complete-parent-done.test.ts +0 -76
- package/telegram-plugin/tests/progress-card-edit-timestamps-budget.test.ts +0 -62
- package/telegram-plugin/tests/progress-card-memory-bounds.test.ts +0 -84
- package/telegram-plugin/tests/progress-card-pin-failure-paths.test.ts +0 -139
- package/telegram-plugin/tests/progress-card-pin-manager.test.ts +0 -773
- package/telegram-plugin/tests/progress-card-pin-race-fast-turn.test.ts +0 -66
- package/telegram-plugin/tests/progress-card-pin-sidecar-partial-write.test.ts +0 -64
- package/telegram-plugin/tests/progress-card-pin-watchdog.test.ts +0 -190
- package/telegram-plugin/tests/progress-card-sigterm-pin-flush.test.ts +0 -146
- package/telegram-plugin/tests/real-gateway-f1-ladder-integrity.test.ts +0 -123
- package/telegram-plugin/tests/real-gateway-f2-instant-draft.test.ts +0 -82
- package/telegram-plugin/tests/real-gateway-f3-late-card.test.ts +0 -114
- package/telegram-plugin/tests/real-gateway-harness.ts +0 -699
- package/telegram-plugin/tests/real-gateway-i6-turn-flush-replay-dedup.test.ts +0 -313
- package/telegram-plugin/tests/real-gateway-ipc-lifecycle.test.ts +0 -299
- package/telegram-plugin/tests/real-gateway-spec.test.ts +0 -487
- package/telegram-plugin/tests/real-gateway.smoke.test.ts +0 -101
- package/telegram-plugin/tests/setup-flow.test.ts +0 -510
- package/telegram-plugin/tests/setup-state.test.ts +0 -146
- package/telegram-plugin/tests/sync-chat-running-subagents.test.ts +0 -116
- package/telegram-plugin/tests/turn-end-regressions.test.ts +0 -489
- package/telegram-plugin/tests/turn-flush-card-takeover.test.ts +0 -218
- package/telegram-plugin/tests/turn-flush-prose-recovery.test.ts +0 -78
- package/telegram-plugin/tests/two-zone-bg-carry-full-lifecycle.test.ts +0 -131
- package/telegram-plugin/tests/two-zone-bg-detection.test.ts +0 -120
- package/telegram-plugin/tests/two-zone-bg-done-when-all-terminal.test.ts +0 -116
- package/telegram-plugin/tests/two-zone-bg-early-turn-end.test.ts +0 -87
- package/telegram-plugin/tests/two-zone-bg-survives-next-turn.test.ts +0 -211
- package/telegram-plugin/tests/two-zone-card-cap.test.ts +0 -62
- package/telegram-plugin/tests/two-zone-card-fleet-row.test.ts +0 -101
- package/telegram-plugin/tests/two-zone-card-header-phases.test.ts +0 -78
- package/telegram-plugin/tests/two-zone-card-html-balance.test.ts +0 -110
- package/telegram-plugin/tests/two-zone-card-lifecycle.test.ts +0 -128
- package/telegram-plugin/tests/two-zone-card-sanitise.test.ts +0 -58
- package/telegram-plugin/tests/two-zone-card-snapshot.test.ts +0 -133
- package/telegram-plugin/tests/two-zone-concurrent-turns-isolation.test.ts +0 -155
- package/telegram-plugin/tests/two-zone-phasefor-precedence.test.ts +0 -117
- package/telegram-plugin/tests/two-zone-snapshot-extras.test.ts +0 -187
- package/telegram-plugin/tests/two-zone-stuck-edit-throttle.test.ts +0 -149
- package/telegram-plugin/tests/two-zone-stuck-header-escalation.test.ts +0 -101
- package/telegram-plugin/tests/two-zone-stuck-per-member.test.ts +0 -114
- package/telegram-plugin/tests/two-zone-stuck-recovery.test.ts +0 -105
- package/telegram-plugin/tests/waiting-ux-harness.ts +0 -381
- package/telegram-plugin/tests/waiting-ux.e2e.test.ts +0 -233
- package/telegram-plugin/turn-flush-prose-recovery.ts +0 -40
- package/telegram-plugin/two-zone-card.ts +0 -269
- package/telegram-plugin/uat/scenarios/smoke-clerk-reply.test.ts +0 -61
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PR-C2 — end-to-end memory bounds: drive 100 turn cycles and assert
|
|
3
|
-
* every internal Map remains bounded.
|
|
4
|
-
*
|
|
5
|
-
* Companion to PR-B's targeted eviction test, which drove only 20
|
|
6
|
-
* cycles and asserted on `seenEnqueueMsgIds` / `pendingSyncEchoes`.
|
|
7
|
-
* This larger run is a regression net for "everything else" — if a
|
|
8
|
-
* future refactor forgets to evict any new map keyed by chat/turn,
|
|
9
|
-
* the size invariant blows up here even when the PR-B test still
|
|
10
|
-
* passes.
|
|
11
|
-
*
|
|
12
|
-
* fails when: any of the per-chat/per-turn Maps in `_debugGetMaps`
|
|
13
|
-
* grows linearly with turn count (e.g. cleanup is removed from
|
|
14
|
-
* completeTurnFully, or a new Map is added without an eviction hook).
|
|
15
|
-
*/
|
|
16
|
-
import { describe, it, expect } from 'vitest'
|
|
17
|
-
import { makeHarness, enqueue } from './_progress-card-harness.js'
|
|
18
|
-
|
|
19
|
-
describe('PR-C2: end-to-end memory bounds across 100 turn cycles', () => {
|
|
20
|
-
it('all _debugGetMaps Maps stay bounded', () => {
|
|
21
|
-
const { driver, advance } = makeHarness({
|
|
22
|
-
heartbeatMs: 5_000,
|
|
23
|
-
promoteAfterMs: 999_999,
|
|
24
|
-
})
|
|
25
|
-
const maps = driver._debugGetMaps!()
|
|
26
|
-
|
|
27
|
-
for (let i = 0; i < 100; i++) {
|
|
28
|
-
driver.ingest(enqueue('chatA'), null)
|
|
29
|
-
driver.ingest({ kind: 'tool_use', toolName: 'mcp__switchroom-telegram__reply' }, 'chatA')
|
|
30
|
-
driver.recordOutboundDelivered('chatA')
|
|
31
|
-
driver.ingest({ kind: 'turn_end', durationMs: 50 }, 'chatA')
|
|
32
|
-
// Advance well past TTLs (60s) and the eviction throttle (~30s).
|
|
33
|
-
advance(65_000)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
expect(maps.chats.size).toBe(0)
|
|
37
|
-
expect(maps.chatRunningSubagents.size).toBe(0)
|
|
38
|
-
expect(maps.baseTurnSeqs.size).toBe(0)
|
|
39
|
-
// The dedup maps may keep at most one straggler from the final turn.
|
|
40
|
-
expect(maps.seenEnqueueMsgIds.size).toBeLessThanOrEqual(1)
|
|
41
|
-
expect(maps.pendingSyncEchoes.size).toBeLessThanOrEqual(1)
|
|
42
|
-
// editTimestamps is per-turnKey; cleared on completeTurnFully.
|
|
43
|
-
expect(maps.editTimestamps.size).toBeLessThanOrEqual(1)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('with a long-lived bg sub-agent across cycles, only the originating turnKey persists', () => {
|
|
47
|
-
const { driver, advance } = makeHarness({
|
|
48
|
-
heartbeatMs: 5_000,
|
|
49
|
-
promoteAfterMs: 999_999,
|
|
50
|
-
})
|
|
51
|
-
const maps = driver._debugGetMaps!()
|
|
52
|
-
|
|
53
|
-
// One bg sub-agent that NEVER finishes; 50 surrounding turns close cleanly.
|
|
54
|
-
driver.ingest(enqueue('chatA'), null)
|
|
55
|
-
driver.ingest(
|
|
56
|
-
{
|
|
57
|
-
kind: 'tool_use', toolName: 'Agent', toolUseId: 'tu1',
|
|
58
|
-
input: { prompt: 'forever-bg', run_in_background: true },
|
|
59
|
-
},
|
|
60
|
-
'chatA',
|
|
61
|
-
)
|
|
62
|
-
driver.ingest({ kind: 'sub_agent_started', agentId: 'saBG', firstPromptText: 'forever-bg' }, 'chatA')
|
|
63
|
-
driver.ingest({ kind: 'tool_use', toolName: 'mcp__switchroom-telegram__reply' }, 'chatA')
|
|
64
|
-
driver.recordOutboundDelivered('chatA')
|
|
65
|
-
driver.ingest({ kind: 'turn_end', durationMs: 50 }, 'chatA')
|
|
66
|
-
|
|
67
|
-
for (let i = 0; i < 50; i++) {
|
|
68
|
-
driver.ingest(enqueue('chatA'), null)
|
|
69
|
-
driver.ingest({ kind: 'tool_use', toolName: 'mcp__switchroom-telegram__reply' }, 'chatA')
|
|
70
|
-
driver.recordOutboundDelivered('chatA')
|
|
71
|
-
driver.ingest({ kind: 'turn_end', durationMs: 50 }, 'chatA')
|
|
72
|
-
advance(65_000)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// After 50 clean surrounding turns each followed by `advance(65_000)`
|
|
76
|
-
// (well past TTL + eviction throttle), every chatState — including
|
|
77
|
-
// the originating one whose bg sub-agent never finished — has been
|
|
78
|
-
// rolled forward and evicted. Empty is the correct steady state, not
|
|
79
|
-
// the "≤ 2" the original PR shipped. What this test really proves
|
|
80
|
-
// is that `chats` doesn't grow with cycle count.
|
|
81
|
-
expect(maps.chats.size).toBe(0)
|
|
82
|
-
expect(maps.baseTurnSeqs.size).toBeLessThanOrEqual(1)
|
|
83
|
-
})
|
|
84
|
-
})
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PR-C2 — pin/unpin failure paths beyond what PR-A covered.
|
|
3
|
-
*
|
|
4
|
-
* PR-A added: pin reject + sidecar still cleared (`firePin API rejection
|
|
5
|
-
* deletes from pinned map and clears sidecar`), unpin reject + sidecar
|
|
6
|
-
* still cleared.
|
|
7
|
-
*
|
|
8
|
-
* This file extends with the consistency-of-internal-state angle:
|
|
9
|
-
*
|
|
10
|
-
* 1. After a pin REJECTION, the manager's `pinned` map must NOT
|
|
11
|
-
* retain the failed message id — otherwise a later completeTurn
|
|
12
|
-
* would issue an unpin for a message that was never actually
|
|
13
|
-
* pinned, and pinnedTurnKeys() would lie.
|
|
14
|
-
*
|
|
15
|
-
* 2. After an unpin REJECTION, the (turnKey, agentId) must still be
|
|
16
|
-
* considered "unpinned" so a duplicate completeTurn doesn't
|
|
17
|
-
* double-fire deps.unpin (the .finally branch only clears the
|
|
18
|
-
* sidecar; the in-memory `pinned`/`unpinned` bookkeeping is what
|
|
19
|
-
* guards against duplicate API calls).
|
|
20
|
-
*
|
|
21
|
-
* fails when: firePin's catch branch forgets to delete the composite
|
|
22
|
-
* from the `pinned` map (so pinnedTurnKeys grows ghost entries) OR
|
|
23
|
-
* doUnpin's `unpinned.add(key)` is moved to inside the success branch
|
|
24
|
-
* of the unpin promise (so a reject leaves unpinned set un-flipped and
|
|
25
|
-
* a second completeTurn double-unpins).
|
|
26
|
-
*/
|
|
27
|
-
import { describe, it, expect } from 'vitest'
|
|
28
|
-
import { createPinManager, type TimerHandle } from '../progress-card-pin-manager.js'
|
|
29
|
-
import { errors } from './fake-bot-api.js'
|
|
30
|
-
|
|
31
|
-
interface T { fn: () => void; cancelled: boolean; fired: boolean }
|
|
32
|
-
function makeHarness() {
|
|
33
|
-
const timers: T[] = []
|
|
34
|
-
const sidecar: Array<{ chatId: string; messageId: number }> = []
|
|
35
|
-
let pinCalls = 0
|
|
36
|
-
let unpinCalls = 0
|
|
37
|
-
|
|
38
|
-
let pinReject: Error | null = null
|
|
39
|
-
let unpinReject: Error | null = null
|
|
40
|
-
|
|
41
|
-
const mgr = createPinManager({
|
|
42
|
-
pin: async (_chatId, _messageId) => {
|
|
43
|
-
pinCalls++
|
|
44
|
-
if (pinReject) {
|
|
45
|
-
const e = pinReject
|
|
46
|
-
pinReject = null
|
|
47
|
-
throw e
|
|
48
|
-
}
|
|
49
|
-
return true
|
|
50
|
-
},
|
|
51
|
-
unpin: async (_chatId, _messageId) => {
|
|
52
|
-
unpinCalls++
|
|
53
|
-
if (unpinReject) {
|
|
54
|
-
const e = unpinReject
|
|
55
|
-
unpinReject = null
|
|
56
|
-
throw e
|
|
57
|
-
}
|
|
58
|
-
return true
|
|
59
|
-
},
|
|
60
|
-
addPin: (e) => { sidecar.push({ chatId: e.chatId, messageId: e.messageId }) },
|
|
61
|
-
removePin: (chatId, messageId) => {
|
|
62
|
-
const i = sidecar.findIndex((s) => s.chatId === chatId && s.messageId === messageId)
|
|
63
|
-
if (i >= 0) sidecar.splice(i, 1)
|
|
64
|
-
},
|
|
65
|
-
log: () => {},
|
|
66
|
-
now: () => 1000,
|
|
67
|
-
scheduleTimer: (fn): TimerHandle => {
|
|
68
|
-
const t: T = { fn, cancelled: false, fired: false }
|
|
69
|
-
timers.push(t)
|
|
70
|
-
return { cancel: () => { t.cancelled = true } }
|
|
71
|
-
},
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
mgr,
|
|
76
|
-
sidecar,
|
|
77
|
-
fireTimers: () => {
|
|
78
|
-
for (const t of [...timers]) {
|
|
79
|
-
if (t.cancelled || t.fired) continue
|
|
80
|
-
t.fired = true
|
|
81
|
-
t.fn()
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
setPinReject: (e: Error) => { pinReject = e },
|
|
85
|
-
setUnpinReject: (e: Error) => { unpinReject = e },
|
|
86
|
-
counts: () => ({ pin: pinCalls, unpin: unpinCalls }),
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
describe('PR-C2: pin/unpin failure → internal map consistency', () => {
|
|
91
|
-
it('pin REJECT: pinned map drops the composite so pinnedTurnKeys() does not lie', async () => {
|
|
92
|
-
const h = makeHarness()
|
|
93
|
-
h.setPinReject(errors.forbidden())
|
|
94
|
-
h.mgr.considerPin({
|
|
95
|
-
chatId: 'c', threadId: '0', turnKey: 'c:0:1', messageId: 500, isFirstEmit: true,
|
|
96
|
-
})
|
|
97
|
-
h.fireTimers()
|
|
98
|
-
await h.mgr.drainInFlight()
|
|
99
|
-
|
|
100
|
-
// Sidecar cleared by firePin's catch branch (already covered in PR-A).
|
|
101
|
-
expect(h.sidecar).toEqual([])
|
|
102
|
-
// CRITICAL extension: the in-memory pinned map must not still claim
|
|
103
|
-
// turnKey c:0:1 was successfully pinned.
|
|
104
|
-
expect(h.mgr.pinnedTurnKeys()).toEqual([])
|
|
105
|
-
expect(h.mgr.pinnedMessageId('c:0:1')).toBeUndefined()
|
|
106
|
-
|
|
107
|
-
// And a follow-up completeTurn must NOT issue any unpin call —
|
|
108
|
-
// there's nothing to unpin.
|
|
109
|
-
h.mgr.completeTurn({ chatId: 'c', turnKey: 'c:0:1' })
|
|
110
|
-
await h.mgr.drainInFlight()
|
|
111
|
-
expect(h.counts().unpin).toBe(0)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
it('unpin REJECT: duplicate completeTurn does NOT double-fire deps.unpin', async () => {
|
|
115
|
-
const h = makeHarness()
|
|
116
|
-
h.setUnpinReject(errors.badRequest('chat not found', 'unpinChatMessage'))
|
|
117
|
-
|
|
118
|
-
h.mgr.considerPin({
|
|
119
|
-
chatId: 'c', threadId: '0', turnKey: 'c:0:1', messageId: 500, isFirstEmit: true,
|
|
120
|
-
})
|
|
121
|
-
h.fireTimers()
|
|
122
|
-
await h.mgr.drainInFlight()
|
|
123
|
-
expect(h.counts().pin).toBe(1)
|
|
124
|
-
expect(h.mgr.pinnedTurnKeys()).toEqual(['c:0:1'])
|
|
125
|
-
|
|
126
|
-
// First completeTurn — unpin attempted, rejects.
|
|
127
|
-
h.mgr.completeTurn({ chatId: 'c', turnKey: 'c:0:1' })
|
|
128
|
-
await h.mgr.drainInFlight()
|
|
129
|
-
expect(h.counts().unpin).toBe(1)
|
|
130
|
-
|
|
131
|
-
// Second completeTurn (e.g. forceCompleteTurn racing with turn_end).
|
|
132
|
-
// The in-memory bookkeeping must guard against re-firing unpin.
|
|
133
|
-
h.mgr.completeTurn({ chatId: 'c', turnKey: 'c:0:1' })
|
|
134
|
-
await h.mgr.drainInFlight()
|
|
135
|
-
expect(h.counts().unpin).toBe(1)
|
|
136
|
-
// pinned map empty (doUnpin deletes regardless of unpin promise outcome)
|
|
137
|
-
expect(h.mgr.pinnedTurnKeys()).toEqual([])
|
|
138
|
-
})
|
|
139
|
-
})
|