Without this the file was missing on first run, load_builtin_permissions()
returned {}, and the agent fell through to _DEFAULTS={Bash:'ask'} even
though the Settings UI showed green 'always_allow' checkmarks (because the
UI defaulted missing entries to always_allow for DISPLAY but the agent
defaults to ask for SAFETY). The mismatch meant users got prompted on
every ls/cd/pwd despite having flipped Bash to always_allow in the UI.
Lifespan now seeds the file with Bash=ask and everything else=always_allow,
matching agent_manager._DEFAULTS. Idempotent: only writes if a tool is
missing; never clobbers a policy the user already set.
(1) After MCPActivate, the continuation prompt now enumerates the
activated server's callable tool names so the next turn calls them
directly instead of burning a turn on tool-discovery guesses.
(2) Resume no longer deletes the session file from disk; previously
every click on a past chat permanently removed it from history.
(3) WS replay skips agent:closed events; replaying them on a fresh
client destructively deleted the session being opened.
App Builder launched from canvas chat now seeds the React template and
registers an Output row tied to the session id, so the Apps sidebar
lights up immediately. Adds a post-session-complete sync that reads
meta.json from the workspace folder and updates the Output row's name
and description, ending the 'Untitled App' problem. Also adds a stale-
approval filter to the WS replay: resolved approvals no longer
resurrect as dead cards when the user navigates back to a chat.
Adds an × button to the integration-suggestion banner so it doesn't
linger after the user dismisses it. On successful MCP activate, clears
the banner so the user gets visual confirmation the click did
something. On unknown_server response (not yet connected), navigate to
/actions so the user can finish OAuth there.
claude_code preset auto-attaches the user's claude.ai-connected partner
MCPs (mcp__claude_ai_*). They bypass MCPActivate, don't share OAuth
state with OpenSwarm's Gmail/Drive/Calendar connectors, and confuse
the model into picking the partner shim instead of our vetted server.
Hard-block via disallowed_tools + add a system-prompt rule.
google-workspace-mcp's gauth.py hardcodes token_uri to oauth2.googleapis.com
and uses local CLIENT_ID/SECRET on every refresh. OAuth runs through a
rotation pool on the cloud side, so the refresh_token is bound to the
pool slot that minted it, not the single client baked into the DMG, and
direct refreshes return unauthorized_client. Redirect spawn through a
shim that monkey-patches get_credentials to point token_uri at a local
proxy (/api/tools/google-oauth-token), which forwards the refresh to
api.openswarm.com/api/oauth/google/refresh (pool-aware). Unblocks every
Gmail/Drive/Calendar query for users on the cloud OAuth pool.
Workflow's new-branch fallback fell through to a full repo scan whenever
merge-base with main equaled HEAD (empty range). That re-flagged every
historical secret a prior PR had already cleared. Now: empty range means
nothing new to scan, log + exit clean. Genuine no-shared-history case
still falls through to full scan.