Commit Graph

5450 Commits

Author SHA1 Message Date
Peter Steinberger afa3e18dea fix(ui): suppress tooltips that repeat visible labels (#125684)
* fix(ui): suppress redundant native tooltips

* fix(ui): collect visible tooltip text safely
2026-08-18 01:32:14 -07:00
Vyctor H. Brzezowski e349d520a2 feat(ui): add typed update recovery actions (#125098)
* feat(ui): add typed update recovery actions

* fix(ui): surface update status refresh failures

* fix(ui): keep update failure type internal

* fix(ui): publish update failure facts atomically

* fix(ui): validate update recovery startup budget

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-18 01:31:21 -07:00
Peter Steinberger ad475ce33a feat(gateway/ui): command-lane diagnostics with debug page table and global busyness overlay (#125591)
* feat(gateway): expose command lane diagnostics

* feat(ui): add live debug busyness overlay

* fix(ui): show newest events in debug overlay and update diagnostics call-list tests

* test(ui): add lane and status fixtures to the mocked dashboard

* feat(ui): add System busyness entry to the account menu

* fix(gateway/ui): bound lane diagnostics, append-only descriptor, fail-visible lanes load

Addresses ClawSweeper review findings on #125591: diagnostics.lanes moves to
the append-only tail of the descriptor table, the Control UI lanes request
fails visibly instead of masking errors, and the RPC exports only static
lane snapshots plus a bounded dynamic-session aggregate composed in the new
command-lane-diagnostics module.

* chore(protocol): regenerate Kotlin gateway methods for diagnostics.lanes

* test(gateway/ui): register diagnostics.lanes in the 2026.8 train and mock it in the debug e2e
2026-08-18 01:10:32 -07:00
Peter Steinberger d9dfc5b3d9 feat(ui): show online people and session activity (#125695)
* feat(ui): add sidebar Online presence section and Activity session feed

Adds a sidebar "Online" section (visible only when at least one other
identity is connected, idle users dimmed) that links into a new
session-feed default view on the existing Activity page: search, time
window, and per-person facets over day-grouped sessions, with a
per-person identity header (devices, viewing-now) when one person is
selected. Removes the dead footer viewer-facepile roster that the
sidebar-zone refactor (#112936) left unmounted.

Client-only; no gateway/protocol changes.

* test(ui): make activity capture date-boundary safe
2026-08-18 01:03:22 -07:00
Peter Steinberger 475d20a034 fix(ui): stop the model picker from nagging about refresh failures (#125661)
* fix(ui): stop the model picker from nagging about refresh failures

A failed background catalog refresh rendered a "Couldn't refresh models"
banner plus a Retry button on top of a complete, working model list, and
replaced the composer trigger's model name with that error text. The
picker already keeps the last-known catalog and re-requests it on every
open, so the operator was being asked to press a button for something the
UI does by itself.

The error stays recorded on the host — it is what drops the stale
availability gate so the composer remains usable — but it is no longer
surfaced while there are models to show. Only a genuinely empty catalog
still says "Models unavailable". The new-session picker gains the chat
picker's open-triggers-revalidate behavior so re-opening it is the retry
there too, instead of dead-ending until a page reload.

Two adjacent simplifications in the same surface:

- Model rows reserve their provider-icon slot as an invisible stem, so
  names line up with the provider heading label (same 34px stem grouped
  and filtered, nothing shifts while typing).
- The "Using agent default" footer is gone: the default row already
  carries a DEFAULT badge and the checkmark. Typing "default" in the
  picker search now matches the default model instead.

Proof: scripts/capture-model-picker-proof.mts captures the open picker
against a mocked gateway; alignment delta 0px (was -24px), search
"default" matches the default row (was nothing), and a failed models.list
leaves no catalog-state element with all rows intact.

* fix(ci): register the model-picker proof script and await its picker revalidation

The unused-file scan needs every scripts/ entry point referenced, like the
sibling ui:proof:* recipes. The catalog-reconnect assertion also has to wait
for the picker's own metadata request instead of reading the log the moment
the rows render.

* test(ui): split model-catalog scenarios out of the new-session e2e file

The catalog-reconnect file hit the 1000-line cap. Its model-catalog metadata
failure/recovery pair is a separate surface from CLI-agent targets, terminal
start, and draft reconnect, so it moves to its own file rather than earning a
max-lines suppression.

* test(audit): give the pinned-reader contract test a realistic timeout

It adds a pinned-SHA git worktree and cold-compiles the audit and state
modules under tsx, which takes minutes on a contended runner. The 120s
default made it fail by construction; it timed out on an unrelated PR shard
while passing locally at ~55s.
2026-08-18 00:58:19 -07:00
Peter Steinberger 079a874159 feat: revalidate cached chat history with cursor deltas (#125606)
* feat(gateway): add cursor catch-up to chat history

* feat(ui): revalidate cached transcripts via history cursor

* fix(ui): stop append-miss stubs clobbering persisted snapshots

* fix(gateway): fence history delta cursor to projected events

* fix: repair cursor delta landing gates
2026-08-18 00:54:58 -07:00
Vyctor H. Brzezowski cb5e1d2a2b improve(ui): refine transcript status markers (#125237)
* improve(ui): refine transcript status markers

* fix(ui): attach duplicate marker to message content

* fix(ui): keep duplicate markers outside rich content

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-18 00:50:33 -07:00
Vyctor H. Brzezowski 9fb1b7a1a5 fix(ui): replace user bubble Show more button (#125553)
* fix(ui): replace user bubble show-more button

* fix(ui): remove user bubble chevron surface

* fix(ui): round user bubble chevron hover

* fix(ui): preserve wrapped prompt disclosure

* fix(ui): measure wrapped prompt overflow

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-18 00:34:30 -07:00
Peter Steinberger ebe9d38a5f fix(ui): keep unsent draft indicators visible (#125649)
* fix(ui): keep unsent draft indicators visible

* test(ui): make markdown table copy assertion deterministic

* test(ui): await restored draft attachments
2026-08-18 00:19:14 -07:00
Josh Lehman 5b8dcf9d28 fix(ui): send parent messages while only subagents run (#125428) 2026-08-18 00:10:05 -07:00
Vyctor H. Brzezowski 50f28b3109 fix(gateway): stop chat.startup from blocking on workspace icon discovery (#124269)
* fix(gateway): stop chat.startup from blocking on workspace icon discovery

chat.startup awaited workspace icon preparation before responding, so a
cold icon cache (up to the full favicon candidate list) delayed the first
chat-open response for every session. It now starts discovery eagerly and
returns without waiting for it.

That leaves the icon route's readiness 503. The route already awaits an
in-flight preparation, so the only way to reach 503 is having no cache
entry at all: an icon GET that beat its chat.startup across transports, or
a session whose snapshot aged out of the bounded cache. Neither is fixed by
the client asking again for the same missing snapshot, so the producer
answers instead. prepareSessionWorkspaceIcon() publishes cache entry and
waiting requests through one publication point, and a request that misses
waits up to two seconds for that publish before falling back to 503. The
race resolves into a 200 on the original request, and 503 now means only
what it says: nothing is preparing this session.

* fix(gateway): keep icon absence out of 503 and bound the publish wait

The publish waiter resolved with the snapshot promise itself, so `resolve`
adopted it and a workspace that publishes `null` reached the route as a falsy
value indistinguishable from an expired wait: the common no-icon race answered
503 instead of the stable 404. Waiters now carry a discriminated publication,
so timeout and published absence stay separate outcomes.

Admission is also bounded. Every authenticated unknown key used to create a
bucket, callback, timer, and held response for the full wait with no cap and no
disconnect cleanup, which accumulates once sidebar project groups render icons
for sessions that may never get a chat.startup. Waits are now capped per
session and per process, a saturated pool answers 503 immediately, and every
exit path releases the timer, the disconnect listener, and the slot together.

* fix(gateway): bound cached workspace icon waits

* fix(gateway): recover delayed workspace icons

* test(ui): assert workspace icon retry fallback

* fix(gateway): bound workspace icon recovery

* fix(gateway): satisfy workspace icon lint

* fix(ui): scope workspace icon recovery

---------

Co-authored-by: ClawSweeper <steipete+clawsweeper@gmail.com>
Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-18 00:02:47 -07:00
Peter Steinberger a910d6c80d fix(ui): separate stop action from microphone picker (#125669) 2026-08-18 00:02:40 -07:00
Vyctor H. Brzezowski 540ea124e0 improve(ui): redesign tool calls as lightweight transcript activity (#125240)
* improve(ui): flatten transcript tool activity

* improve(ui): complete tool activity redesign

* improve(ui): normalize activity row typography

* improve(ui): unify activity typography contract

* improve(ui): standardize all activity row text

* improve(ui): increase activity text size

* improve(ui): underline activity filenames

* improve(ui): tighten activity row spacing

* improve(ui): standardize activity chevrons

* improve(ui): reveal child chevrons on interaction

* improve(ui): retain active child chevrons

* improve(ui): space expanded child tools

* improve(ui): remove idle activity fade and gap

* fix(ui): preserve tool activity contracts

* fix(ui): simplify activity basename lookup

* fix(ui): preserve canonical tool row actions

* fix(ui): record tool outcomes and repair transcript row regressions

Neutral collapsed rows are the design, but this branch left failures with
nowhere to land and shipped chrome whose styles it had already deleted.

- Expanded standalone tool messages close with the outcome line, so an inline
  rows shape still reports the failure instead of dropping it.
- Progress-card receipts drop the badge and the spinner: this branch removed
  both styles, leaving a 0x0 invisible running indicator, and the receipt
  label already names the state.
- Single delete patches are non-navigable; their workspace target is gone, so
  the file action could only ever fail to load.
- Flush command padding derives from the action-button size instead of a stale
  42px constant, and the running text wave covers command rows again.
- Activity lane returns to the tool-shell column width the rule claims.
- Drop CSS nothing references: tool-card tabs, empty, plain-output, activity
  scroll masks, secondary command text.
- renderToolDataBlock takes an optional label instead of comparing copy.
- Split the oversized tool-card test file and refresh stale row assertions.

* fix(ui): fold the tool action size into the card header rule

Stylelint no-duplicate-selectors rejects the separate .chat-tool-card__header
block; the custom property belongs in the existing rule.

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-18 03:36:43 -03:00
Peter Steinberger 20199d7e72 fix(ui): coalesce device refreshes during active loads (#125627)
* fix(ui): coalesce device refreshes during active loads

Nodes and device list loaders dropped every refresh request received while a
previous list RPC was in flight. A successful approve, reject, removal, token
mutation, or Gateway resolved event could therefore be overwritten by the old
pre-mutation response and remain stale until the next poll.

Record one closed pending refresh mode per list owner. When the current request
settles, immediately run the coalesced refresh, preserving whether any queued
caller requested visible error handling. Add order-faithful node and device
regressions that fail when the follow-up list request is dropped.

* test(ui): initialize queued device refresh state
2026-08-17 23:25:22 -07:00
Vyctor H. Brzezowski 52eb013330 feat(ui): unify fenced code block visual styling (#125249)
* feat(ui): unify fenced code block styling

* fix(ui): preserve fenced code copy icon

* fix(ui): refine unified fenced code visuals

* fix(ui): increase code fence squircle radius

* fix(ui): inset fence scrolling and add edge fade

* fix(ui): fade overflowing code without surface color

* fix(ui): update code overflow fades by scroll position

* fix(ui): preserve transcript scroll handler with fence fades

* fix(ui): initialize code overflow fades after render

* fix(ui): align JSON tree hierarchy with reference

* fix(ui): remove transcript bullets from JSON tree

* fix(ui): preserve fenced code contracts

* test(ui): align fenced code feedback contracts

* fix(ui): remove fenced code overflow lifecycle

* fix(ui): preserve compact JSON disclosure

* fix(ui): preserve shared fence variants

* fix(ui): address fenced code review findings

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-18 02:57:48 -03:00
Peter Steinberger 0d74bc21b0 fix: keep non-person principals out of session owners (#125579)
* fix: keep non-person principals out of session owners

* fix(sessions): preserve creator filter semantics
2026-08-17 22:55:01 -07:00
Peter Steinberger ac7dbe4f83 improve(ui): show starter automations only for empty inventories (#125631) 2026-08-17 22:52:41 -07:00
Peter Steinberger e5ffbe6800 fix(ui): stop session tooltips covering progress cards (#125594)
* fix(ui): stop session tooltips covering progress cards

* test(ui): align sidebar tooltip expectations

* fix(ui): remove restricted session row tooltip
2026-08-17 22:49:12 -07:00
Peter Steinberger 3daf60adda test(ui): restore synthetic window globals (#125616) 2026-08-17 22:21:02 -07:00
Vyctor H. Brzezowski cbe3116e14 feat(ui): add Markdown table interactions (#125245)
* feat(ui): add Markdown table interactions

* fix(ui): scope table interactions to transcripts

* fix(ui): complete table interaction contracts

* chore: refresh PR head

* fix(ui): satisfy table interaction gates

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-17 22:20:32 -07:00
Vyctor H. Brzezowski e97b42a43a fix(ui): show users typing in the transcript (#125244)
* fix(ui): move typing status into transcript

* fix(ui): complete transcript typing lifecycle

* fix(ui): finish transcript typing presentation

* fix(ui): refine typing bubble tail

* fix(ui): complete transcript typing invariants

* fix(ui): satisfy transcript typing gates

* fix(ui): keep typing presence ownership bounded

* fix(ui): keep typing presence dependencies private

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-17 22:19:37 -07:00
Peter Steinberger e6a427c493 perf(ui): defer offscreen plugin row rendering (#125585)
Amp-Thread-ID: https://ampcode.com/threads/T-01a01277-59ee-703a-b04d-927a3ba733a1

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 21:50:54 -07:00
Peter Steinberger f007b0f7a8 perf(ui): paginate grouped sessions (#125572)
Amp-Thread-ID: https://ampcode.com/threads/T-01a01277-59ee-703a-b04d-927a3ba733a1

Co-authored-by: Amp <amp@ampcode.com>
2026-08-18 04:38:57 +00:00
Peter Steinberger 0776c4680a fix(ui): stop restart errors from masquerading as model auth (#125513)
* fix(ui): distinguish model catalog freshness errors

* test(ui): cover refreshed configured model load

* fix(ui): wait for fresh model catalogs before auth gating

* fix(ui): import pane ids from composer owner
2026-08-17 21:35:49 -07:00
Peter Steinberger ca8bd59df5 improve(ui): reduce startup stylesheet size (#125539)
* perf(ui): lazy-load settings workspace styles

Amp-Thread-ID: https://ampcode.com/threads/T-01a01277-59ee-703a-b04d-927a3ba733a1

* fix(ui): keep picker styles route scoped

Amp-Thread-ID: https://ampcode.com/threads/T-01a01277-59ee-703a-b04d-927a3ba733a1

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 21:32:46 -07:00
Peter Steinberger 90526f3a9c fix(ui): stop composer mic hover shift and stray red hover (#125565)
* fix(ui): stop composer mic hover shift and stray red hover

The device-picker chevron collapsed to width 0 while idle and grew to
20px on hover, shoving the right-aligned mic button 20px left under
the cursor on every mouse-over. Detach the picker into its own
fixed-width ghost button beside the mic instead of morphing the mic's
shape into a split pill; hover only fades the picker's opacity, so the
reserved layout never shifts.

Also fixes the mic showing the send button's loud accent-red hover in
dark/openknot themes: those themes overrode .chat-send-btn:hover
directly, which outranked every variant's own hover rule (including
the intentional neutral mic hover and the stop button's danger hover).
Theme overrides now set a --chat-send-hover-background variable that
each variant's hover rule can still take precedence over.

* chore(scripts): register composer mic hover proof script

Missing package.json entry made the deadcode full-tree scan flag the
new capture script as an unused file, same as the existing
ui:proof:workboard sibling.
2026-08-17 21:09:17 -07:00
Peter Steinberger 6611e409d0 test(ui): cover discussion cold-open without URL (#125498) 2026-08-17 21:08:39 -07:00
Peter Steinberger 33e2e6b0f9 fix(ui): show session hovercards for every sidebar row beside the rail (#125563)
* fix(ui): show session hovercards for every sidebar row beside the rail

Sidebar session rows were excluded from session-link hovercards, so only
the Home (main) row showed a card, and it overlaid the sidebar itself.
Hovercards now open for all sidebar session rows and position to the
right of the sidebar so navigation stays visible.

* fix(ui): yield sidebar previews to active progress hovercards

Sidebar rows already open a progress hovercard when the session has an
active progress card; the new preview card stacked on top of it. The
preview now probes the shared progress-card store (deduped with the
progress provider's own load) and opens only when the row has none.
2026-08-17 21:06:41 -07:00
Vyctor H. Brzezowski c75d4dc911 improve(ui): align chat branch and PR rows (#125232)
* improve(ui): align chat branch and PR rows

* improve(ui): collapse absent PR number slot

* improve(ui): give Create PR a neutral chip surface

* improve(ui): rebalance merged PR row contrast

* improve(ui): use standard squircle for PR rows

* fix(ui): consolidate static PR link styling
2026-08-17 20:52:00 -07:00
Peter Steinberger aa2d3df8e6 test(ui): wait for persisted new-session drafts (#125548) 2026-08-17 20:49:32 -07:00
Ayaan Zaidi 8575ead129 fix(ui): show skill mentions in the new-session composer (#125554)
The /new page renders its own composer, which never wired the `$skill` mention menu owned by the chat composer, so typing `$` there did nothing while /chat offered completions. Narrow the skill-menu module to a small host contract shared by both composers, drive it from the new-session textarea, and refresh commands.list on the first `$`. Also moves `paneDomId` to the composer DOM helpers to break a types→skill-menu→slash-menu→state import cycle.
2026-08-18 03:48:37 +00:00
Peter Steinberger a0c5937fd1 fix(ui): restore full chat history after cached layout changes (#125536)
Cached Control UI transcripts no longer show a large blank region or hide earlier loaded messages after layout/transcript-shape changes.

Closes #125533
2026-08-17 20:33:05 -07:00
Peter Steinberger 974a52f64f refactor(ui): deduplicate session menus and hovercards (#125478)
* refactor(ui): share session menu and hovercard mechanics

* test(ui): align fixtures with gateway hello contract

* fix(ui): close session access and focus gaps

* test(ui): advertise sidebar custodian method

* refactor(ui): split chat pane layout rendering

* fix(ui): align rebased chat render checks
2026-08-17 20:15:04 -07:00
Peter Steinberger e859f2bab3 fix(ui): restore task suggestion checks (#125538) 2026-08-17 20:10:01 -07:00
Jesse Merhi a928da457f Show worktree option only for Git group folders (#125280)
* feat(ui): show worktrees only for Git group folders

* feat(ui): enrich group environment picker

* fix(ui): preserve worktree defaults on probe errors

* fix(ui): reject stale group repository probes

* test(ui): type repository inspection helper
2026-08-17 19:50:15 -07:00
Peter Steinberger 93f7492570 fix(ui): keep side panel tab labels visible (#125511)
Restore the block-axis padding reset lost in #125368 so Web Awesome tab labels remain vertically legible while retaining logical inline spacing. Add LTR and RTL browser geometry coverage for the visible label boundary.
2026-08-17 19:29:18 -07:00
Vyctor H. Brzezowski 47399310a0 improve(ui): redesign suggested task cards (#125231)
* improve(ui): redesign suggested task cards

* fix(ui): preserve suggested task navigation

* fix(ui): refine suggested task card surfaces

* fix(ui): clarify suggested task instruction layers

* fix(ui): normalize task instruction disclosure

* fix(ui): keep split divider stable on hover

* fix(ui): refine suggested task split shape

* fix(ui): tighten task instruction underlap

* fix(ui): smooth suggested task swaps

* fix(ui): wrap suggested task project label

* fix(ui): signal overflowing task paths

* fix(ui): stabilize suggested task stack height

* fix(ui): separate suggested task surface contrast

* fix(ui): narrow suggested task cards

* fix(ui): allow suggested task text selection

* fix(ui): use restrained brand task action

* fix(ui): align dark task action branding

* fix(ui): deepen dark task action color
2026-08-17 23:25:28 -03:00
Vyctor H. Brzezowski 71eab1118d fix(ui): contain session suggestions to composer width (#125225)
* fix(ui): align session suggestions with composer

* fix(ui): match suggestion phone gutters
2026-08-17 23:15:36 -03:00
Vyctor H. Brzezowski 127931c13d fix(ui): keep side panel tab labels legible (#125505) 2026-08-17 23:04:19 -03:00
Peter Steinberger b5b17c654b fix: keep Workboard visible in the sidebar (#125473)
* fix(ui): keep workboard in sidebar navigation

* test(ui): align workboard navigation ownership

* fix(ui): preserve saved workboard sidebar slots

* test(ui): shrink assertion safety baseline

* fix(plugins): bind native routes to bundled owners

* refactor(plugins): isolate native route policy
2026-08-17 18:44:39 -07:00
Peter Steinberger 49cdd54259 feat(control-ui): move the Ask OpenClaw toggle to the sidebar footer (#125486)
* feat(control-ui): move the Ask OpenClaw toggle to the sidebar footer

The sidebar bottom now mirrors its top: big agent selector with inline
chevron + small new-session square above, big account identity card with
inline chevron + small lobster toggle below. The account chevron moves
from the row's far right to directly after the name, matching the top
header treatment; the freed edge hosts the toggle. The old top-left
shell-chrome placement is removed along with its four-button width
reservation (which read-scoped clients paid for without seeing the
button). Scope gating, palette entry, and panel wiring are unchanged;
gating regressions moved to the sidebar cases.

* fix(control-ui): keep Ask OpenClaw reachable while the nav is collapsed

Address the ClawSweeper P1: desktop collapse hides the sidebar entirely
(display:none, no rail), which would have removed the toggle's only
persistent surface. The lobster now joins the chrome strip exactly while
the nav is collapsed — the footer stays its home — and the strip's
collapsed width reserves four controls for that state. Regression covers
collapsed-present/expanded-absent/read-scope-absent.
2026-08-17 18:26:53 -07:00
Peter Steinberger 05b9b39a9e test(ui): synchronize cloud worker settings saves (#125456) 2026-08-17 18:19:49 -07:00
Peter Steinberger fab7fa9910 improve(ui): rebuild agent GitHub identity panel on settings primitives (#125472)
The panel from #125199 rendered raw wire enums in code tags, used
form-grid/field markup whose styles the agents page never loads (bare
unstyled inputs outside the card), referenced non-existent avatar
classes, and put callouts inside the settings group. Rebuild it on the
canonical settings primitives: status rows with dot status and friendly
source/evidence labels, a System/This Agent segmented scope control,
the settings secret input (gains a disabled prop), a danger status row
for errors, and a quiet-inherit + primary-save action row. Retitle to
"GitHub Identity" and move it below Tool Access and Available Right
Now. Add a .settings-account primitive for the 20px round avatar.

Live-tested on an isolated dev gateway: native-credential verify via
the GitHub API, segmented scope switching, and the empty-token error
row. Controller behavior unchanged.
2026-08-17 18:09:22 -07:00
Vyctor H. Brzezowski 86fb87c602 improve(ui): simplify Markdown table styling (#125219)
* improve(ui): simplify Markdown table styling

* fix(ui): scope table styling to transcripts

* fix(ui): keep transcript tables full width

* fix(ui): size transcript tables to content

* fix(ui): gate table fades on overflow

* fix(ui): make table fades theme neutral

* fix(ui): correct table overflow edges

* fix(ui): keep wide table cells readable

* fix(ui): stretch transcript tables full width

* fix(ui): balance transcript table columns

* fix(ui): enforce full-width table layout

* fix(ui): preserve wide table column sizing

* fix(ui): prevent cramped table columns

* fix(ui): align table first column with prose

* fix(ui): use natural table column sizing

* fix(ui): increase transcript table row spacing

* fix(ui): increase table row padding

* fix(ui): keep table restyle CSS-only

* fix(ui): drop table overflow behavior
2026-08-17 22:07:06 -03:00
Peter Steinberger 6b72d65ffe feat(ui): preserve composer drafts across restarts (#125332)
* feat(ui): preserve composer drafts across restarts

Persist draft text and attachment Blobs in browser-local IndexedDB, scoped to Gateway credentials and session or New Session targets. Clean up durable data after successful send or creation, attachment removal, and session deletion.

* fix(ui): preserve text when draft attachments exceed cap

preserve text-only durable fallback for oversized attachments; serialize visible Incognito transition with its storage fence; document retention and disposal.

* test(ui): make draft retirement proof isolate-safe

The shared isolate:false UI suite exposed an order-dependent module mock; exercise and settle the real IndexedDB boundary instead.

* style(ui): format session mutation imports

* fix(ui): keep incognito drafts memory-only

* perf(ui): lazy-load durable draft storage

* fix(ui): sequence durable draft transitions

* fix(ui): restore text-only new session drafts

Programmatic draft restoration must not advance the user-mutation generation; real user input continues through setMessage.

Move navigation transition ownership into the existing handoff module as a behavior-neutral extraction that keeps the submission owner within max-lines.

* fix(ui): restore text-only drafts without import cycles

Complete the text-only restore fix by moving started-session route transitions into a leaf module. This keeps max-lines ownership clean without reintroducing the Madge cycle.

* fix(ui): reconcile attachment handoffs with durable drafts

Restore programmatic attachment handoffs without recording a user mutation. Cover stale navigation state losing to newer durable drafts across two pages and a fresh page.

* fix(ui): start durable attachment writes before teardown

Start each CAS IndexedDB write and retirement immediately so text and attachment transactions register before page teardown. IndexedDB readwrite ordering and draft revisions keep snapshots serialized.

* fix(ui): persist New Session drafts before teardown

Accept the committed predecessor or a known in-flight local write ID atomically so New Session writes can start before teardown without spurious local-lineage conflicts.

Reset cached lineage when authoritative storage is missing and re-snapshot the still-current edit.
2026-08-17 17:56:20 -07:00
Peter Steinberger 850faa0367 fix(ui): guard browser ResizeObserver construction (#125480) 2026-08-17 17:55:09 -07:00
Vyctor H. Brzezowski 3dd95d7bf7 improve(ui): refine Markdown prose presentation (#125242)
* improve(ui): refine Markdown prose styling

* improve(ui): polish Markdown prose spacing

* improve(ui): normalize nested list rhythm

* fix(ui): fill Markdown image fallback width

* improve(ui): mute checked task styling

* fix(ui): align Markdown list markers

* fix(ui): preserve Markdown list rhythm with tasks

* improve(ui): clarify Markdown block rhythm

* test(ui): update Markdown disclosure geometry

* test(ui): match compact Markdown indent

* fix(ui): consolidate task list styling

* style(ui): format Markdown presentation

* test(ui): match Markdown block rhythm

* test(ui): enforce uniform Markdown rhythm
2026-08-17 21:49:21 -03:00
Josh Lehman 02ec1b6166 fix(ui): keep acknowledged sends pending during stale history (#125426) 2026-08-17 17:33:40 -07:00
Peter Steinberger b228c83bfc feat(dashboard): add session:progress board tile rendering the live progress card (#125438)
* feat(dashboard): add session:progress board tile rendering the live progress card

Advertise the core-owned widget kind via hello controlUiWidgetKinds at operator.read.
Render it inline without an iframe from the session-progress-cards store.
Pin it with dashboard tool widget_put using pluginKind session:progress and optional props.sessionKey.
Follow up the progress-card unification from #125125.

* fix(dashboard): surface session progress load failures

Record protected progress-card read failures in the shared per-session store.
Render an actionable board-tile error with retry instead of indefinite loading.
Cover the rejected-read and successful-retry flow at the widget boundary.

* fix(dashboard): honor progress tile access and activity

Avoid progress-card reads while a retained board is inactive.
Distinguish sharing denial from transient load failures and show the correct remedy.
Qualify cross-session pinning docs and cover activation plus denial behavior.
2026-08-17 16:56:23 -07:00
Peter Steinberger 389fed29cf fix(ui): keep composer footer controls readable (#125445)
* fix(ui): move permission picker to footer left

* chore: drop changelog edit (release-owned)
2026-08-17 16:43:04 -07:00