* feat(sessions): teach session tools the Control UI link rule
Gate guidance on publicOrigin plus enabled Control UI, with exact literal-URL fallback after short-link misses.
* feat(ui): linkify session keys in chat markdown
Match agent session keys structurally in plain text and inline code, then delegate canonical chat navigation.
Allowlist data-session-key through markdown sanitization.
Pathfinder: keep internal Control UI route anchors in-app by removing target="_blank" and external-link rel attributes while preserving external link behavior.
* feat(ui): session hovercard + titled session chips backed by controlUi.sessionPreview
* fix(gateway): scope controlUi.sessionPreview to caller-visible sessions
Hover previews now apply the same createSessionListEntryFilter predicate as
sessions.list, so identity-bearing non-admin callers cannot preview-by-key
incognito rows or non-owner drafts the sidebar hides. Regression test proves
the viewer/admin split; pre-fix run leaked ok-status metadata.
* feat(sessions): carry the session-link rule in tool result envelopes
Deferred-description mode hides prose tool descriptions at decision time. Carry the shared Control UI session-link sentence in successful session lookup result envelopes so every tool mode sees the rule.
* fix(ui): upgrade session chips on appearance, not first pointer event
* fix(android): regenerate gateway protocol methods
* test(gateway): track session preview release train
* perf(ui): lazy-load session hovercard registration
* fix(ui): keep session hovercards off sidebar navigation
* fix(ui): cancel routed session-link navigation
* fix(sessions): advertise forced-literal ~key URLs so short-ID collisions cannot misroute
* test(sessions): update forced-literal guidance expectation
* fix(ui): collision-proof raw-key navigation and SPA-route internal session URLs
* perf(ui): preserve session route lazy boundary
* fix(ui): defer unseeded session-preview fetches to hover intent
* fix(sessions): hard-cap the model-visible session-link base
* feat(ui): path-based session and dashboard URLs
* docs(ui): document control UI URLs
* fix(ui): finalize session path routing
* feat(ui): anchor session URLs on stable keys
* docs(ui): clarify stable session URL identity
* fix(ui): resolve session prefixes with full prefix and pagination
Query sessions.list with the full supplied prefix instead of an eight-char
truncation, and paginate up to a bounded page count so longer disambiguation
links resolve instead of being reported ambiguous. Zero strict-prefix matches
now fall through to literal-key resolution rather than rendering an empty
ambiguity view.
Also document the ~dot/~dotdot segment escape: peer ids reach session keys
trimmed and lowercased only (src/routing/session-key.ts), so a literal '.' or
'..' segment is reachable and browsers would normalize it away.
* fix(ui): synchronize committed session routes
* test(ui): split native shell host coverage
* fix(ui): thread configured mainKey through session URL builders
Reserved-set disambiguation needs the operator-configured mainKey at runtime, so
thread it from agentsList through every session path builder and the ClickClack
control URL. Unambiguous non-hex single-segment rests now resolve literally while
short-id-shaped rests still fail closed, which restores ClickClack channel
compatibility detection and control-link reconciliation.
Also bound prefix-resolution retries, preserve catalog thread identity, and keep
draft state on ambiguous candidate links.
* fix(ui): repair session URL CI integration
* perf(ui): lazy-load session route resolution
* perf(ui): isolate session prefix resolution
* perf(ui): defer session path parsing
* perf(ui): defer session navigation startup
* fix(ui): preserve first-run and literal session navigation
* fix(ui): satisfy session routing type and export gates
* fix(clickclack): preserve unscoped control link agent
* style(ui): satisfy chat page line limit
* refactor(ui): move chat page helpers to owning modules
* fix(ui): preserve destination session route identity
* fix(ui): preserve agent identity in session routes
* fix(ui): escape dots in literal session path segments
encodeURIComponent leaves periods intact, so a literal key segment like
channel:release.js produced /chat/main/channel/release.js. In-app navigation is
intercepted by the SPA, but a refresh, an external link, or a ClickClack link
would be served as a static asset request and never reach the app.
pathForWorkboardBoard already escapes dots for this reason; mirror it in both the
session URL contract and the ClickClack encoder, route the agent id through the
same segment encoder, and pin the case in both shared vector tables.
* fix(ui): stop bootstrap after teardown race
* refactor(ui): centralize session navigation targets
* fix(ui): consume bootstrap teardown abort
* fix(ui): canonicalize configured main session routes
* fix(ui): preserve distinct session references
* fix(ui): redirect released session query links
* fix(ui): make bootstrap teardown abort-safe