archived-thread-guard.tsfix(threads): a thread marked done stays gone, whatever writes the list Round 1 treated the optimistic removal as an edit and repaired the one window it could name -- a listThreads response issued inside the archive round-trip -- by re-applying the removal once, the instant the mutation settled. That assumed a 227-380ms round-trip. Staging measures mail.markDone at up to 7381ms, and all three resurrections prod ever recorded landed 15.7-18.2s after the click, every one a fetch-response: seconds after the one-shot repair had already run, with nothing left to oppose them. So the removal becomes an invariant instead of an edit. While a thread is guarded, any write to a mail.listThreads query that reintroduces it is repaired immediately -- late fetch response, IndexedDB restore, side-inbox prefetch and fetchNextPage alike -- so we no longer have to name the guilty write. The guard is time-boxed at 60s; markActive, undo and mutation rollback all release first, so a legitimate return still lands. Suppressions now report to the server, not PostHog. The previous round's diagnostic was PostHog-only and the browser reporting the bug sends PostHog nothing -- 66 archives on staging produced zero client events -- so the fix could never be verified. mail.reportListSuppression writes a structured log readable in CloudWatch. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 24, 2026, 3:51 PMuse-optimistic-actions.tsMerge origin/staging into fix/dm-container-kind Both branches built org-shared MCP connections independently, so the merge picks ONE mechanism and layers the other work on top of it. KEPT (staging) `metadata.scope` / `organizationId` + callability.ts as the single visibility rule for every MCP surface. It resolves name collisions deterministically, narrows in SQL and enforces in JS, and it is what the discovery-based OAuth callback and the credential vault already write. DROPPED (ours) `metadata.orgShared` and the peer-scan in visible-connections.ts. That module survives as the agent-facing ADAPTER over findMcpConnections — `ownedByMe` and the explicit-grant name set — so nothing re-implements a cross-tenant WHERE. KEPT (ours) `toolPolicy` (the per-tool ceiling) and `requiresAgentGrant` (which of a person's agents reach a connection). Staging has no equivalent; they are a different axis from scope, and the types now say so. Settings loses mcp-integration-card.tsx to staging's Systems and credentials section, and the tool-permissions checklist is ported onto system-row.tsx so the ceiling is still editable. The agent's own picker keeps its shape and now reads staging's KNOWN_MCP_PROVIDERS, resolving a provider id through discovery at click time instead of from a second hard-coded catalogue. `probeMcpServer` became discovery, so the pre-save tools/list probe is `probeMcpServerTools`. Also reconciled outside MCP: the Slack Connect webhook scoping (staging's, which handles externally shared channels) keeping this branch's stronger workspace resolver; the agent-archive and subagent-write metadata stamps, chained rather than chosen between; buildAgentDocs' generic folder model with this branch's `listed` on top; and the conferencing-aware event popover with the extracted RSVP hook. Fixes carried by the merge: coach-meeting and coach-weekly had no folder and would have landed in Active; a duplicate source_workspace_id column; a duplicate import; the dead org-admin catalogue bypass. Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 30, 2026, 4:15 PM1 defect