v1.1.2 is a stability release focused on chat continuity. Chats no longer lose their history (or freeze) when you switch projects, close a tab, or come back hours later. It also folds in the iOS polish and App Store review prep that were originally planned for v1.1.1 — privacy page, Tailscale routing cleanup, iOS Work timeline stability, and a large pass on orphan-lane sessions.Documentation Index
Fetch the complete documentation index at: https://ade-app.dev/docs/llms.txt
Use this file to discover all available pages before exploring further.
Chat continuity
The biggest change: the desktop renderer had no snapshot-on-resubscribe path. Switching projects (or tabbing away from Work) would drop IPC events while you were gone, and on return the pane only got the transcript tail — long chats lost earlier history, and a transient read error could leave the pane frozen with no retry.- In-memory per-session event ring buffer.
agentChatServicenow records every emitted envelope into a 2,000-event-per-session buffer alongside the on-disk transcript. A newgetChatEventHistoryIPC method merges the buffer with the disk transcript on first read so a late subscriber always sees the full history. - Freeze recovery on error.
AgentChatPanenow clears its load-gate in the catch path when a history read fails, so a transient miss no longer traps the UI in an empty state. The Work-tab single-session tile also force-reloads on mount, matching the behavior the other chat surfaces already had. - Cross-run-safe dedup. Sequence numbers restart at 0 every time a session rebuilds, so the disk-buffer merge dedupes on timestamp + event type + payload content instead — true duplicates still collapse, but streaming text fragments that land in the same millisecond stay distinct.
- Path validation.
getChatEventHistoryvalidates the session id is a registered chat session before opening any transcript file, since the endpoint is reachable over IPC.
- Resume state survives non-terminal teardowns. When the runtime is torn down for
idle_ttl,budget_eviction,pool_compaction,paused_run,project_close, orshutdown, the V2sdkSessionIdand lane directive are now preserved to disk so the next turn re-attaches to the same SDK session instead of cold-starting. - Terminal teardowns still invalidate.
handle_close,ended_session, andmodel_switchkeep the old behavior even when the runtime is already null — closing a chat invalidates its resume state so a future resume can’t accidentally reattach.
mergeChatEventHistory, deduplicatedChatEventHistory, 2 MB snapshot request, 1,000-event retention); this release brings the desktop to parity and then tightens both sides further:
- Raised iOS chat history window to 2 MB and up to 1,000 envelopes per session.
mergeChatEventHistorymerges truncated snapshots with existing events instead of replacing.- Fallback to
messageIdwhen Claude assistant-text events are missing a non-emptyitemId, so live-path and transcript-replay render the same number of bubbles. deduplicatedChatEventHistorynow parses ISO-8601 timestamps with a fractional-seconds formatter + fallback before comparing, so mixed-precision snapshots sort chronologically instead of lexicographically.recordChatEventEnvelopefalls back to the full sort path when a delayed envelope predates the last-recorded one, healing out-of-order live arrivals after a snapshot merge.
Orphan lanes
Sessions whose lane isn’t in the current UI lane list (archived lanes, lanes hidden by filter) now render as their own collapsible groups instead of disappearing.- Desktop
SessionListPanerenders orphan-lane groups sorted by lateststartedAt, with aNumber.isFiniteguard so malformed timestamps don’t triggerNaNcomparator ordering. - iOS
workSessionGroupsByLanemirrors the same shape: per-lane groups for orphaned sessions, sorted newest-first with alphabetical name tiebreak, trimmed-laneName→laneIdfallback for empty labels, and an ISO-8601 parser that handles both fractional and non-fractional variants. - Orphan labels use the session’s preserved
laneNamewhen present so users still recognize which branch each belongs to.
Sync and discovery
- Unified tailnet discovery.
SyncTailnetDiscoveryhost and port candidates are consolidated. Tailnet-address detection is centralized insyncIsTailscaleRoute, covering MagicDNS hostnames,ts.netsuffixes, and100.64/10IPv4 literals. Port8788is preserved as a fallback since the desktop retries there when8787is busy. - IPv6 route normalization.
syncNormalizedRouteHostonly strips a trailing:portwhen there’s exactly one colon, so unbracketed IPv6 literals (::1,fc00::1) survive normalization instead of being truncated before the allowlist check. - Shared desktop device ID.
deviceRegistryServicenow accepts an optionallocalDeviceIdPathso the device identity can live underuserDatainstead of per-project secrets. The shared file is authoritative across projects: on first use we migrate whichever legacy per-project id we encounter (or mint a fresh UUID), and every project context afterwards returns that same identity.O_EXCLon the seed write prevents two concurrent contexts from racing to mint different ids. - Runtime discovery toggle.
syncHostServiceexposessetDiscoveryEnabled()to gate LAN/Tailnet advertisement at runtime, withunpublishLanDiscoverycalled on dispose so stale entries don’t linger.
iOS polish
- App Store review prep. The placeholder privacy page is replaced with an Apple-grade policy (effective date, data categories, third parties, retention, contact).
vercel.jsongained an SPA catch-all so/privacyand/downloadstop 404’ing — both required for external TestFlight review. - App icon. Full-bleed opaque export of the centered ADE artwork so the mark matches the macOS logo and satisfies App Store upload checks.
- Launch and root polish. Tighter top-of-screen rhythm on the five root tabs (Work, Lanes, PRs, Files, CTO). The connection header chip meets the 44 pt hit-target minimum, and the connection-dot hover around the gear icon is consistent across tabs.
Work transcript stability
- Shared itemId resolution policy.
WorkTranscriptParserandWorkEventMappingnow share a singleworkStableTimelineItemIdhelper (with an optional-itemIdoverload for the raw-dict transcript path). File-change events deliberately keep the rawitemIdrather than collapsing tologicalItemId— OpenCode’s patch emitter produces one event per file with a shared logical ID, and collapsing was dropping all but the last file. - Streaming-aware tool groups. Tool cards that are still streaming inside a group auto-expand (
localExpanded || running), so mid-stream progress doesn’t disappear into the collapsed group hint. - Assistant-text grouping.
buildWorkChatMessagestracks whether the previous envelope was assistant text, so nil-itemIdstreaming fragments merge into it without being pulled across intervening tool calls or user messages.
Other
workSessionGroupsByLaneon iOS: orphan-lane ordering tests now use distinctstartedAttimestamps so the “latest first” sort is actually exercised.SessionListPaneon desktop: blanklaneNamenow trim-falls-back tolaneIdso orphan-group headers never render empty.syncService.test.ts: retry-test host mock stubssetDiscoveryEnabled.browserMock.getEventHistoryechoes the requested session id.registerIpc: the newagentChatGetEventHistoryhandler coercesmaxEventsto finite positive integers.- Internal docs updated for the new chat lifecycle, iOS companion sync story, and terminals UI surfaces.