Commit Graph

121 Commits

Author SHA1 Message Date
Shakker fcf2e7aadc test: type session request parameters (#116713) 2026-07-31 09:21:05 +01:00
Shakker 75d10f8e4f fix: retain event invalidation for pagination 2026-07-31 09:21:05 +01:00
Shakker fe5d591cc3 fix: preserve queued session refresh options 2026-07-31 09:21:04 +01:00
Peter Steinberger b44890bf2d fix(sessions): recover deleted chats without endless retries (#115974)
* fix(sessions): recover deleted chats without lifecycle races

* fix(sessions): narrow deleted route commit keys

* test(sessions): isolate deleted-chat recovery regressions

* fix(sessions): recover chats after agent removal

* fix(sessions): fence recreated session deletion races

* fix(sessions): preserve filtered active conversations

* test(sessions): preserve canonical main during chat recovery

* test(ui): follow canonical agent channels route
2026-07-29 13:22:29 -04:00
Peter Steinberger af717db39c feat(ui): add per-connector tool access to composer (#115907)
* feat(ui): per-connector tool access in composer menu

* fix(ui): harden tool access loading and dynamic keys

* fix(ui): harden tool access reads and catalog freshness

* fix(ui): invalidate tool catalog on connector edits

* test(ui): fix composer capability checks
2026-07-29 11:39:53 -04:00
Peter Steinberger f27899181e feat(ui): add composer capability menu (#115800)
* feat(ui): composer capability menu with per-session overrides

* refactor(ui): keep chat render within lint ceiling

* fix(ui): preserve loaded capability overrides

* fix(ui): remove stale capability menu field

* fix(ui): gate capability menu on runtime-config readiness
2026-07-29 06:48:08 -04:00
Peter Steinberger ad3f74f296 fix(chat): make web and terminal share one session state (#115429)
* fix(chat): consolidate web and terminal session state

* fix(chat): preserve live history across stale snapshots
2026-07-28 18:53:21 -04:00
Peter Steinberger 18ecde3d9f refactor(chat): keep web and terminal sessions synchronized (#115377)
* refactor(chat): unify web and TUI session synchronization

* refactor(chat): extract canonical projection and transcript owners

* test(gateway): verify private transcript store identity

* test(agents): protect public transcript storage boundary

* fix(chat): harden cross-client identity and subscription lifecycles

* fix(gateway-client): preserve type-safe release callback rejection

* test(ui): complete shared sidebar gateway fixture
2026-07-28 16:08:10 -04:00
Peter Steinberger c536b0731e perf(ui): debounce event-driven session list refreshes and right-size child paging (#115374) 2026-07-28 15:16:28 -04:00
Peter Steinberger 13f20055f0 refactor(ui): split Profile (identity) from Usage (statistics) (#115245)
* refactor(ui): profile owns identity; usage owns statistics

* fix(ui): rerender profile on connection transitions

* chore(ui): drop usage exports orphaned by the profile split

* chore(ui): localize usage TTL constant in gateway source replacement test
2026-07-28 12:09:50 -04:00
scotthuang 35f035806b fix(ui): avoid duplicate session refreshes during startup (#114764)
* fix(ui): avoid duplicate startup session refreshes

* fix(ui): remove redundant hydration return

* test(ui): prove session hydration reconnect ownership

* test(ui): align reconnect proof with single hydration

* test(ui): wait explicitly for catalog startup

* test(ui): isolate tool anchor navigation state

---------

Co-authored-by: scotthuang <scotthuang@tencent.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-28 23:15:07 +08:00
Peter Steinberger 7f37900bca perf(ui): flip sessions instantly and drop redundant switch RPCs (#115129)
* perf(ui): flip sessions instantly and drop redundant switch RPCs

* chore: revert changelog edit (release generation owns CHANGELOG.md)

* test(ui): adapt ported switch e2e tests to split-suite helpers

* chore(ui): un-export internal CachedShortSession type (knip)
2026-07-28 06:25:25 -04:00
Peter Steinberger 0771486cc1 fix(ui): mirror optimistic session-settings patches into the sessions capability snapshot (#115009)
Chat kept optimistic thinking-level and fast-mode row patches only in the
host copy of the session list. Any mid-flight capability publish (for
example the loading flip at the start of the post-patch list refresh)
replaced that copy wholesale and reverted the patched row until the
refreshed canonical list landed. The reasoning slider visibly snapped
back to the inherited default during that window and keyboard commits
landing inside it were swallowed, which is the race behind the flaky
chat-composer-redesign thinking-slider e2e assertion on CI.

patchSessionRow now mirrors the optimistic fields into the published
capability snapshot via a new SessionCapability.patchRowLocal, matching
how model overrides already live capability-side, so intermediate
publishes carry the patch and the revert window is gone.
2026-07-28 03:27:51 -04:00
Peter Steinberger f0a963a2cb fix(ui): isolate case-sensitive channel sessions (#114638) 2026-07-27 12:55:36 -04:00
Peter Steinberger c56689416e fix(ui): scope global route resolution by agent 2026-07-27 05:43:19 -04:00
Peter Steinberger 2e9621018a fix(ui): keep derived session titles after sidebar mutations (#114474) 2026-07-27 05:36:56 -04:00
Peter Steinberger af552d4bc6 feat(ui): resolve session URLs through the gateway with best-effort slug matching (#114422)
* feat(ui): resolve session URLs through the gateway with best-effort slug matching

Session URLs now resolve a stored board face and a display-name slug through
the gateway instead of guessing from the browser's cached session page.

- An uncached open marks only the in-app navigation, never the shareable href,
  so the chat loader can re-derive the face and replace the URL.
- A cached row settles the lookup locally, keeping navigation off the wire.
- A one-segment reference resolves short id, then literal key, then display-name
  slug; ties reuse the existing disambiguation view.

* refactor(ui): keep slug ties on short disambiguation prefixes

Slug candidates reused the full uuid, which produced 32-character links in the
disambiguation view. uniqueShortIdPrefix already falls back to the full id when
the bounded search was truncated, so reuse it and drop the flag.

* fix(ui): navigate worktree owner links in-app so the face marker survives

The Worktrees owner link was a bare anchor consuming only the shareable href,
so preferenceDerivedFace was a no-op there and an uncached owner always opened
on chat. Match the other session surfaces: keep the clean href and navigate
with the options on plain clicks.

* fix(ui): search the first uuid block so long session references resolve

The gateway matches sessions.list search as a plain substring and stored keys
hold a hyphenated uuid, so any hyphen-stripped reference past the first block
matched nothing and 404'd. This hit disambiguation links, which offer prefixes
longer than eight characters. Send the first block and keep applying the full
prefix per row.

A resolved slug now canonicalizes to that same short reference instead of a
full uuid, so /chat/main/deploy-monitor settles on -6db92d48.

* docs(ui): record why the face marker stays out of shareable hrefs
2026-07-27 04:31:33 -04:00
Peter Steinberger 8b66fc103d feat(ui): durable session board face and dashboards index (#114262)
* feat(ui): durable session board face and dashboards index

Board face lived only in client-side boardSessionViews, capped at 50 entries,
so the preference never followed the user to another device, evicted as
sessions accumulated, and could not be seen as a set.

Persist it as SessionEntry.boardFace, which rides the existing entry_json blob
and so needs no SQLite schema change or version bump. Expose it on the session
list row and add it to the sessions.patch write-scope allowlist alongside label,
pinned, and archived: setting your own view preference is user-level chat
organization, not policy. Unknown patch fields still fail closed to
operator.admin.

Generic navigation now reads the stored face, so the sidebar and session list
open a thread on the face you left it on. boardSessionViews keeps only
activeTabId and reopenDockByTab, which are genuinely per-device.

Add /dashboards listing threads whose preferred face is dashboard. Filtering
runs server-side in filterSessionEntries before pagination, because the client
holds only a capped page and a client-side filter would silently omit
dashboards.

* test(protocol): assert the pre-rename face param is rejected

The gateway-protocol validator test still passed the pre-rename 'face' key,
which the closed schema rejects. Use boardFace, and pin the old name as a
negative case so it cannot silently return.

* chore(protocol): regenerate Swift bindings and docs map for boardFace

Adding boardFace to the sessions schema changes two committed generated
artifacts: the Swift gateway models (pnpm protocol:gen:swift) and the docs map
(pnpm docs:map:gen), which now lists the dashboards index section.
2026-07-27 00:35:34 -04:00
ClawSweeper ca11ee6db1 fix(ui): new worktree sessions stay in Coding during creation (#113834)
* fix(ui): preserve new coding session selection

* test(ui): cover prepared sidebar sessions

* fix(ui): retire prepared work sessions on delete

* test(ui): refresh prepared sidebar mock for the configured main key

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-26 22:18:07 -04:00
Peter Steinberger cca5b14785 feat(ui): path-based session and dashboard URLs (#113883)
* 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
2026-07-26 12:46:04 -04:00
Peter Steinberger cd5a5ecb4c fix(ui,gateway): make catalog sidebar sections drag-reorderable (#114074)
* fix(ui,gateway): make catalog sidebar sections drag-reorderable

* test(ui): split sidebar section-reordering cases under max-lines

* perf(ui): keep catalog section rendering out of startup bundle
2026-07-26 05:31:33 -04:00
Peter Steinberger 2de58d408a Control UI: gateway-owned sidebar section order (#113930)
* feat(ui): gateway-owned sidebar section order with hover-only drag grips

* fix(ui): repair sidebar section order CI gates

* fix(protocol): keep sectionOrder optional for older gateways

Native Swift clients ship separately from gateways, so new clients must decode older gateway responses that omit sectionOrder.

* fix(ui): reconcile gateway section ordering with main

* fix(state): allow lazy tables in v5 maintenance

* refactor(ui): retire prefs session section order in favor of gateway-owned order

Supersedes #113948 by deleting the unreleased ui.prefs.sessionSectionOrder key and its browser plumbing. Gateway SQLite sidebar_sections remains the single canonical store.
2026-07-26 01:15:19 -04:00
Peter Steinberger 852a686a1b feat(chat): restore prompt image attachments on rewind/fork (#113945)
* feat(chat): restore prompt image attachments on rewind/fork

* chore(i18n): refresh native source inventory anchors

* fix(gateway): restore media-store images on rewind/fork

* fix(gateway): bound and dedupe rewind media reads

* fix(sessions): bound inline editor attachments in message cut

* fix(ui): align restored attachment cap with gateway 5 MiB limit

* fix(gateway): dedupe rewind media refs by resolved id

* fix(sessions): lint-safe __openclaw access in message cut
2026-07-25 20:32:16 -07:00
Peter Steinberger 71cb266c1f fix(ui): keep Coding sessions visible after reconnect (#113981)
* fix(ui): preserve scoped session hydration

* chore: leave changelog to release automation

* build(ui): refresh startup budget baseline
2026-07-25 19:56:50 -07:00
Peter Steinberger f90cef67c8 feat(ui): drag custom sidebar groups between built-in session zones (#113948)
* feat(ui): drag custom sidebar groups between built-in session zones

* test(ui): remove stale split ratio fixture

* perf(ui): raise startup budget baseline for session-section ordering pref
2026-07-25 19:11:25 -07:00
Peter Steinberger a328e900fd fix(ui): keep sidebar selection on archived sessions and replace the composer with an archived notice (#113882)
* fix(ui): keep sidebar selection on archived sessions and replace composer with archived notice

* fix(ui): narrow lineage-row lookup and restructure fallback projection scan

* fix(ui): publish routed lineage row so cold-loaded archived sessions replace the composer

* chore(ui): drop unused mergeChildSessionRows export
2026-07-25 19:07:25 -07:00
Peter Steinberger 360fe2317c feat(ui): person grouping and people filter in the sidebar catalog view menu (#113943) 2026-07-25 18:17:12 -07:00
Peter Steinberger fb26903d6c feat: add flexible multi-sidebar chat layout (#113712)
* feat(ui): add persisted sidebar layout model

* feat(ui): render flexible chat sidebar columns

* test(ui): align board sidebar fixture type

* fix(ui): preserve sidebar panels across responsive layout

* fix(ui): satisfy sidebar CI ownership and performance

* test(ui): derive discussion helpers from panel config

* test(ui): mount session rail through its registry

* fix(ui): preserve sidebar state across projections

* style(ui): format sidebar state fixes

* fix(ui): satisfy sidebar lint constraints

* refactor(ui): break sidebar layout import cycle

* fix(ui): stabilize sidebar panel rendering

* fix(ui): keep the narrow sidebar grid off for an empty layout

The two-row narrow grid reserved a panel row even with no sidebar panel open, halving the primary surface height on every default mobile chat pane.

* fix(ui): lazy-load chat sidebar region

* style(ui): format rebased chat state page

* chore(ui): raise sidebar startup baseline

* fix(ui): preserve sidebar move and resize state

* chore(ui): align sidebar startup baseline

* chore(ui): refresh sidebar startup baseline

* test(ui): register discussion element in isolated test

* fix(ui): persist the dragged panel as the collapsed active panel

Drag moves activated the panel in its destination column but left the separate persisted collapsed-mode selection stale, so the narrow layout foregrounded the wrong panel after a move and the stale choice survived reload.

* fix(ui): preserve resolved canvas URL in detail panel
2026-07-25 17:45:29 -07:00
Peter Steinberger fde3cdf27b perf: multi-select archiving no longer stalls a second per row (#113623)
* perf(ui): refresh the session list once per batch action

Batch sidebar actions patched each row and then forced a full sessions.list
replacement per row, so archiving a nine-row multi-select paid nine list
rebuilds on top of nine patches. Measured against the gateway handlers on a
60-session store, sessions.list costs ~2.9s versus ~176ms for sessions.patch.

Batch rows now pass deferListRefresh and each batch helper issues one refresh
per owning agent after its last row; pushed sessions.changed events keep rows
reconciled while the batch runs. Single-row actions are unchanged.

* test(ui): prove batch archive costs one list refresh in the browser

Adds a Control UI e2e case that cmd-clicks three sidebar rows, archives the
selection from the batch menu, and asserts the Gateway saw three sessions.patch
calls in row order plus exactly one sessions.list. It holds past the batch so a
late per-row refresh would still be caught.

Before the batch-refresh change this flow issued one full sessions.list per
archived row.
2026-07-25 05:06:07 -07:00
Peter Steinberger 421e287c45 fix(ui): show Swarm progress in Chat (#113619)
* fix(ui): show Swarm progress in chat

* style(ui): format rebased Swarm integration

* fix(ui): bound inline Swarm progress height
2026-07-25 04:36:50 -07:00
Peter Steinberger 013b24dd6d feat(sessions): archive attribution (archivedBy) (#113116)
* feat(sessions): attribute archive transitions

* docs: add archive attribution report

* fix(sessions): restore alias layout after archive audit failure

* docs: update archive attribution report

* fix(sessions): isolate archive audit rollback

* docs: record final archive rollback design

* fix(sessions): make archive audit note best-effort

* docs: record best-effort archive audit policy

* chore: refresh native i18n baseline
2026-07-23 11:23:30 -07:00
Jason (Json) 2f5e7cfc5d fix(ui): prevent duplicate image prompt and flicker (#113113)
* fix(ui): stabilize initial image prompt handoff

* chore(protocol): refresh sessions create model

* chore(i18n): refresh native source inventory
2026-07-23 12:11:52 -06:00
Peter Steinberger 09672312c4 feat(gateway): incognito sessions for the web Control UI (#113006)
* feat(gateway): add web-only incognito sessions held in process memory

* feat(ui): add incognito toggle and badges to the web new-session flow

* fix(sessions): classify incognito by key shape, fail closed on stale keys, and gate memory writes

* fix(codex): start harness threads ephemeral for incognito sessions

* fix(sessions): reshape internal-effects incognito keys and add doctor repair for reserved key collisions

* refactor(plugin-sdk): export canonical incognito key classifier and guard the sentinel path

* fix(state): classify incognito DB handles from the recorded open-time set

* fix(gateway): isolate incognito sessions from durable lineage and allocation on read-only misses

* docs(sessions): pin the reserved incognito namespace ownership decision

* feat(gateway): admin-scope incognito visibility and incognito-blind cross-session surfaces

* fix(ci): repair kysely guardrails, dead export, docs map, protocol bindings, and ACP reset rotation

* fix(gateway): remove non-admin observability side channels for incognito sessions

* fix(gateway): enforce admin-scope incognito access and cover all parent-reference creation paths
2026-07-23 09:04:36 -07:00
Peter Steinberger 1e3192c0b4 refactor(ui): model gateway connection state as one closed phase union (#112909)
* refactor(ui): model gateway connection state as one closed phase union

ApplicationGatewaySnapshot carried connected + reconnecting as parallel
booleans whose illegal combination (both true) was representable, and
every consumer re-derived the same flag logic. The snapshot now carries
phase: "stopped" | "connecting" | "connected" | "reconnecting" |
"offline"; offlineStable stays as the store-owned 2s debounced
presentation boolean, and lastError/lastErrorCode are unchanged.

Mapping preserves shipped behavior exactly: never-connected terminal
closes return to "stopped" (login gate), established-connection drops
with retry are "reconnecting" (shell stays mounted), without retry
"offline". Component props stay boolean, derived once at the app-host
boundary; no compat aliases remain on the snapshot.

Closes #112741.

* fix(ui): migrate rebased-in test fixtures to the gateway phase union

* fix(ui): migrate post-rebase gateway snapshot readers to the phase union

* fix(ui): migrate document-title test harness snapshot to the phase union
2026-07-23 07:00:26 -07:00
Peter Steinberger ad505a7b55 fix(swarm): keep collector results reliable through races and restarts (#112989)
* fix(swarm): harden collector lifecycle and dashboards

* fix(swarm): initialize collector completion state

* test(swarm): satisfy cross-environment type checks

* test(codex): allow direct request handler calls

* style(ui): avoid Swarm widget shadowing

* test(swarm): keep internal helpers private

* refactor(ui): own Swarm roster helpers in runtime
2026-07-23 06:26:31 -07:00
Peter Steinberger 099d6351b3 refactor(sessions): canonical lineage model — creation provenance, fork ancestry, generation chain, typed row contract (#111861)
* fix(sessions): preserve spawn/fork lineage across implicit daily/idle rollover

* refactor(sessions): canonical creation model with forkSource ancestry and generation chain

* feat(sessions): stamp creation provenance across all creation paths and emit created events

* refactor(gateway): lock lineage patching, split control from navigation, add typed session-row contract

* docs(gateway): document creation provenance stamping and lineage patch tightening

* fix(sessions): keep provenance proof-only on wire fallbacks and strip node-local lineage from cron continuations

* fix(gateway): never journal a created event for session adoption

* fix(gateway): keep post-create work on adoption while gating the created event

* fix(sessions): restore trusted ensure-main provenance and stamp navigation parent at spawn

* fix(sessions): allow parentSessionKey through the direct child spawn patch

* fix(ci): break type cycles, satisfy export scan, regenerate Swift protocol models

* refactor(sessions): replace createdBy with createdActor

* fix(protocol): export session row type

* fix(sessions): preserve proven creation provenance

* fix(sessions): close lineage creation gaps

* test(sessions): align atomic spawn lineage coverage

* test(sessions): widen transcript search reconcile wait

* fix(sessions): stamp reset-created rows

* test(sessions): keep reset provenance coverage focused

* fix(sessions): journal chat-created rows

* test(ci): anchor release skill reads to repo

* test(ci): avoid cached module paths
2026-07-22 22:54:31 -04:00
Peter Steinberger cf2f591161 feat(sessions): permanent creator attribution, owner avatars, person filter, multi-user docs (#112658)
* feat(sessions): persist creator attribution

* feat(ui): add session creator filtering

* chore(sessions): refresh sqlite schema baseline

* docs(security): explain shared-agent trust

* fix(sessions): project catalog creator ownership

* fix(ui): restore startup JS budget headroom for creator attribution
2026-07-22 05:47:21 -07:00
Peter Steinberger d4f19bfd79 feat(sessions): first-class archived-session handling (tri-state filter, pruning exemption, inline archived UI) (#112554)
* feat(sessions): first-class archived-session handling

Archived sessions are now exempt from every automatic maintenance path
(age prune, entry cap, model-run prune, disk budget, cleanup repairs);
only explicit sessions.delete removes them. sessions.list gains an
additive tri-state archived filter (true | false | "all"). The sidebar
gets a persisted Active/Archived/All status filter with inline dimmed
archived rows, replacing the nav-away View-archived button; the Sessions
page toggle becomes the same tri-state with dimmed+badged rows in All
mode; the chat composer's archived notice becomes a full-width banner
with an Unarchive action.

* chore(protocol): regenerate Swift gateway models for tri-state archived filter
2026-07-22 01:28:53 -07:00
Peter Steinberger 70fd8d23c8 fix(ui): keep session narration live across chat switches (#112526)
* fix(ui): refcount session message subscriptions

* chore(release): keep changelog generation release-owned
2026-07-21 22:32:06 -07:00
Peter Steinberger b83af8157b test(ui): reuse shared non-isolated workers (#112493)
* test: isolate OpenClaw home in shared setup

* test(ui): reuse shared workers for pure suites

* test(ui): align scoped runner contract
2026-07-21 21:08:12 -07:00
Peter Steinberger b2aa21612d feat(ui): show PR status on Claude threads (#112180)
* feat(ui): show PR status on catalog threads

* fix(ui): complete PR summary protocol artifacts

* perf(anthropic): bound PR metadata deduplication
2026-07-21 05:01:04 -07:00
Jason (Json) 21bfc75648 fix(ui): show new task prompts immediately without duplicates (#111953)
* fix(ui): stabilize new task prompt rendering

* test(ui): cover prompt handoff integration

* test(ui): initialize prompt handoff fixtures
2026-07-20 14:47:32 -06:00
Peter Steinberger c715d89de8 fix(ui): show newly created PRs in session sidebar (#111783)
* fix(ui): surface newly created session PRs

* test(ui): split sidebar PR state coverage
2026-07-20 10:04:41 -07:00
Peter Steinberger 248726fafd feat(anthropic): import Claude Desktop custom groups (#111644)
* feat(anthropic): import Claude Desktop custom groups

* fix(anthropic): resolve Claude Desktop groups from LevelDB entries

Group discovery regexed whole decompressed blocks, so matches were not
attributable to a Local Storage value and byte order decided the winner.
On a real 5.4MB store that mislabelled 59 of 159 sessions, surfacing a
mojibake label spliced out of Snappy copy-record bytes.

Parse SSTable entries properly instead: prefix-delta keys bounded by the
restart array, newest internal sequence per user key (honoring deletions),
and record scanning confined to a single value. Values are normalized so
Chromium's UTF-16 form scans like Latin-1, and unflushed WAL writes keep
precedence over SSTables.

Prod LOC grows ~77; it buys structural correctness in place of ordering
luck, and folds the old index-only walk into one shared entry decoder.

Verified against the live store: 159 assignments, 0 mislabelled versus an
independent entry-level ground truth, 0 control-character labels.

* fix(ui): sort custom session groups ahead of project groups

Custom groups were pushed into the section list as encountered, so their
position depended on roster order rather than the documented behavior;
the existing test only passed because its fixture happened to be ordered
that way. Collect custom and project groups separately and concatenate,
and assert the guarantee with a reversed-input case.

* fix(anthropic): widen LevelDB fixture key type for test typecheck

The prefix-delta helper assigned a Buffer into a Buffer-typed accumulator
whose generic argument differed, which tsgo rejects in the test lane.

* chore(anthropic): drop release-owned changelog edit from the PR

CHANGELOG.md is generated at release time, so a normal PR must not carry
an entry. The release-note context lives in the feature commit message and
the PR body instead.
2026-07-20 00:30:37 -07:00
Peter Steinberger bc76bb8933 feat(agents): agent-controlled session status, attention, and TTL in the sessions tool (#111583)
* feat(agents): agent-controlled session status, attention, and TTL in the sessions tool

* feat(protocol): sessions.patch agent status fields and curated attention icon ids

* chore(protocol): regenerate bindings for agent-status patch fields, unexport internal cap

* chore(sessions): unexport internal agent-status TTL default
2026-07-19 21:01:09 -07:00
Peter Steinberger 7d4dccf959 improve(swarm): close out wait, phase, and worker follow-ups (#111605)
* fix(codex): support full swarm wait budgets

* feat(ui): bucket swarm dots by phase

* docs(swarm): document flat worker patterns

* fix(codex): configured per-tool timeout still wins over swarm wait default

* fix(codex): outer swarm-wait watchdog outlives the 600s budget (cap + grace)

* fix(ui): order swarm phase buckets by observation rank

* fix(ui): repair rank-order widget test — proper lit render container, untangle sibling assertions

* fix(ui): implicit swarm phase assignment only on child creation events

* test(ui): split swarm activity integration coverage
2026-07-19 20:11:54 -07:00
Peter Steinberger 6a408983d0 fix(onboard): make first-run hatch reliable (#111465)
* fix(onboard): harden first-run handoff

* style(ui): avoid onboarding comparator shadowing

* fix(agents): preserve mixed refresh failures
2026-07-19 14:38:58 -07:00
Peter Steinberger 6c2973dee4 feat(ui): automatic session attention states in the sidebar (#111035)
* feat(ui): automatic session attention states in the sidebar (question, approval, failed run)

* test(ui): split attention presentation and read-marker cases under line budgets

* fix(ui): restore precise chat-pane test-support signatures
2026-07-18 17:43:59 -07:00
Alex Knight 66aa22e4e8 fix(ui): keep session rosters consistent (#108249)
Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
2026-07-19 09:06:32 +10:00
Peter Steinberger bb7b2bca68 feat(ui): finish the chat session → thread rename across the Control UI (#110973)
* feat(ui): finish the chat session → thread rename across the Control UI

Completes the #110933 creation-surface rename mechanically: Threads page
(title, filters, archive/delete/rename/pin menus, transcript search),
sidebar labels and menus, welcome suggestion, palette category, tools
availability copy, workboard lifecycle/card strings, dreaming history,
board/diff/workspace-rail chrome, and the untitled main/channel fallback
names. Technical identifiers stay: Session ID, session keys, terminal
sessions, protocol wording. Living docs updated (control-ui.md);
historical release notes left as shipped.

* style(ui): format session-management e2e

* fix(ui): finish thread rename in navigation labels and stale test literals

Codex review caught the palette Threads entry and the Worktrees owner
column still saying Session; CI caught test literals asserting the old
copy (Threads page overview tile, filter tooltips, group counts, catalog
terminal notice, create-rejection error, workboard lifecycle hint). Also
completes the usage-stat cluster (Threads + hints) and the tool-catalog
group label. Native app strings (iOS/Android/macOS) keep session wording
and reconcile through their own i18n pipelines as a follow-up.
2026-07-18 23:15:13 +01:00