- Replaced time-based sleeps and polling loops with event-driven promise resolvers and fake timers across agent and tool tests.
- Migrated test suites to share in-memory auth storage and fixtures using lifecycle hooks.
- Updated catalog model definitions, metadata, and configurations.
AgentSession.#sessionMessageAlreadyPersisted previously called SessionManager.getBranch() on every message_end event, rebuilding the root-to-leaf path and JSON-comparing each entry; for long sessions this is O(n) per message and O(n²) over a growing transcript. Add #persistedMessageKeys, a memoized Set<string> of persistence keys for the current branch, so the common missing-key check uses Set.has and only falls back to a branch walk on rare key collisions. Invalidate the cache whenever the leaf path changes (newSession, createBranchedSession, resetLeaf, branch, and branchWithSummary) and incrementally warm it after each real append. Verified with git diff --check, a scoped bun build of agent-session.ts, and bun test packages/coding-agent/test/agent-session-persisted-keys-cache.test.ts (2/2 passing).
Closes#4243