Commit Graph

5410 Commits

Author SHA1 Message Date
Peter Steinberger fa75cdd01c fix(ui): validate automation condition triggers (#126718) 2026-08-20 09:02:48 -07:00
Hiroshi Tanaka 55f1738d50 fix(control-ui): config form save corrupts 64-bit id strings in string|number fields (#126402)
* fix(control-ui): stop config form save from corrupting 64-bit id strings

Saving the schema-driven config form coerced every numeric-looking string
to a JS number before submission. For union-typed fields such as
tools.elevated.allowFrom.* (anyOf: string | number), string entries
holding 64-bit ids (Discord/Telegram snowflakes) were rewritten through
Number(), which rounds past 2^53:
"1048113311314608148" -> 1048113311314608100. The corruption also hit
untouched fields, because serialization coerces the whole form, so merely
saving an unrelated setting silently broke elevated-approval allowlists
(fail-closed: the real user id no longer matched).

Two guards fix this:
- coerceFormValues keeps a string that already satisfies a string variant
  of an anyOf/oneOf union instead of parsing it into another variant's
  number.
- coerceConfigFormNumberString refuses lossy integer parses: plain
  integer text beyond Number.MAX_SAFE_INTEGER that does not round-trip
  through BigInt stays a string, so pure number/integer fields fail
  validation loudly instead of storing a corrupted id.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(control-ui): harden 64-bit config id preservation

* fix(control-ui): validate mixed-union scalar branches

* test(control-ui): prove real gateway id preservation

* test(control-ui): use communications route for config proof

* test(control-ui): grant config proof admin scope

* test(control-ui): reopen raw config for proof

* fix(control-ui): preserve explicit union input types

* test(control-ui): exercise union collection draft

* ci: retry flaky control ui e2e

* fix(control-ui): preserve mixed scalar branch types

* ci: retry service worker e2e

* fix(control-ui): preserve typeless string union branches

* fix(control-ui): reject lossy decimal coercion

* fix(control-ui): reject lossy pure numeric input

* fix(control-ui): preserve exact numeric branch semantics

* ci: retry checkout rate limit

* ci(control-ui): capture real gateway proof

* test(control-ui): frame config proof values

* ci: retry checkout download

* test(control-ui): prove Gateway-served production bundle

* fix(control-ui): preserve exact incremental union edits

* refactor(control-ui): isolate scalar edit session state

* fix(control-ui): keep scalar edit branch type internal

* fix(control-ui): avoid detached focus selector

* fix(control-ui): round-trip exact numeric branches

* refactor(control-ui): share exact scalar formatting

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 08:50:24 -07:00
ClawSweeper 8c6c7a30cf improve(ui): make mobile image previews zoomable (#126528)
* improve(ui): make mobile image previews zoomable

* fix: harden mobile image viewer

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Shakker <shakkerdroid@gmail.com>
2026-08-20 16:39:49 +01:00
SunnyShu 9bba88dbba fix(tasks): rank terminal tasks by completion and keep Recent terminal-only (#123219)
* fix(tasks): rank terminal tasks by completion and keep Recent terminal-only

- updateTaskStateByRunId backfills lastEventAt from endedAt for terminal
  finalizers (mirrors markTaskTerminalById), keeping activity monotonic
- both taskUpdatedAt projections rank terminal tasks by the maximum
  available activity timestamp, healing stale rows while preserving later
  delivery/terminal-outcome events recorded after completion
- Tasks page Recent fetch filters to terminal statuses so queued/running
  rows cannot starve the Recent section

Related to #100911

* refactor(tasks): normalize completion at registry owner

Absorb terminal timestamp ordering into the canonical registry lifecycle boundary, remove duplicated projection and writer policy, and prove Recent remains visible behind 200 active tasks in Chromium.

Co-authored-by: SunnyShu0925 <shu.zongyu@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-20 08:38:57 -07:00
Peter Steinberger 36ca7df091 fix(test): use activated service worker build signal (#126584) 2026-08-20 08:29:50 -07:00
Peter Steinberger 974917f520 fix(ui): keep pending approvals visible throughout Settings (#126698) 2026-08-20 08:10:06 -07:00
Peter Steinberger 855599d7e9 fix(ui): keep sidebar icon endcap intact in single-line session rows (#126567)
With message preview off, rows collapse to one line and the second-row icon
logic (spinner, unread dot, badges, facepile, trail) rides beside the title.
Two defects broke that:

- Long titles crushed the icon endcap: the single-line title used flex-basis
  auto, so overflow shrink was distributed onto the endcap (24px -> ~7px),
  clipping the status icons. Basis 0 now mirrors the two-line subtitle
  contract: text absorbs all shrink before icons do.
- Native catalog session rows always rendered the two-line skeleton with an
  empty details line (46px vs 30px) and never collapsed, in both preview
  modes. Catalog rows never carry preview text, so they are now always
  single-line.

Regression coverage: long-title endcap geometry in
chat-flow.sidebar-presentation.e2e.test.ts (fails pre-fix), and
codex-sessions.e2e.test.ts density assertions updated to the new
all-single-line contract.
2026-08-20 07:37:21 -07:00
ClawSweeper 267ffc4754 feat(ui): manage automation condition triggers (#126534)
* feat(ui): manage cron condition triggers

* test(models): isolate ambient CLI availability

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-08-20 07:20:01 -07:00
Peter Steinberger fae9bd6baf fix(ui): refresh mixed-role node status (#126677) 2026-08-20 06:49:58 -07:00
Vyctor H. Brzezowski 5e6b29d23a fix(ui): keep peer identity stable when actions appear (#126287)
* fix(ui): keep peer identity stable when actions appear

* fix(ui): keep mobile peer actions trailing
2026-08-20 10:30:14 -03:00
Peter Steinberger c8f88a8b38 fix(ui): recover newer builds after stale probes (#126628)
* fix(ui): recover newer builds after stale probes

* fix(ui): elect newest stale-build recovery target
2026-08-20 04:21:57 -07:00
Peter Steinberger 2ebe24e9b2 fix(ui): keep sidebar chat rows separated during resize (#126610) 2026-08-20 02:18:34 -07:00
Peter Steinberger 1d2986b06f fix: prevent incompatible cloud runtime dispatches (#126585)
* fix(ui): gate cloud profiles by runtime mode

* test(gateway): expect cloud placement mode

* test(gateway): keep route suite within lint budget
2026-08-20 01:31:27 -07:00
Vyctor H. Brzezowski 68ae235318 improve(ui): refine chat widget host and image actions (#125250)
* improve(ui): refine chat widget host actions

* fix(ui): keep widget pin presentation unchanged

* fix(ui): compact widget actions and restore rounded host

* style(ui): format widget action menu

* test(canvas): refresh widget host document contract

* test(ui): model the widget host wrapper

* fix(ui): preserve retained widget downloads

* fix(ci): register Codex tool coverage

* fix(protocol): keep version exports compact

* fix(ui): preserve widget action outcomes

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-20 05:27:56 -03:00
Peter Steinberger 83978aec63 fix(ui): refresh approval history when decisions resolve (#126579) 2026-08-20 01:13:42 -07:00
Peter Steinberger 764622342c fix(ui): keep empty session groups compact (#126565) 2026-08-20 00:58:54 -07:00
Peter Steinberger 531fc9b365 fix(ui): read-only Agents identity editor stays stuck on Saving (#126568)
* fix(ui): show accurate save state for read-only agents

* test(ui): use canonical text content in agent save assertion
2026-08-20 00:48:17 -07:00
Peter Steinberger 828f1fa851 perf(test): gate lazy recovery proof capture (#126583) 2026-08-20 00:43:50 -07:00
Alix-007 2a79f74701 fix(ui): prioritize active session quota provider (#120557) (#122053) 2026-08-20 00:22:30 -07:00
Vyctor H. Brzezowski 689ab6ec82 fix(ui): contain narrated tool details (#126348)
* fix(ui): contain narrated tool details

* fix(ui): repair narrated tool details
2026-08-20 04:04:53 -03:00
Vito Cappello f612675284 fix(models): keep Claude CLI OAuth available in Control UI (#125471)
* fix(models): honor Claude CLI OAuth ownership in Control UI

Co-authored-by: XX441 <169966250+XX441@users.noreply.github.com>

* test(models): preserve OAuth fixture literal type

* fix(models): preserve persisted CLI runtime ownership

* fix(auth): discover Claude CLI credentials for Anthropic scope

* fix(models): honor CLI-owned OAuth over legacy metadata

* fix(models): migrate CLI OAuth profile ownership

* fix(models): centralize CLI metadata normalization

* fix(doctor): keep CLI migration result internal

* test(models): type CLI OAuth fixtures

* refactor(models): isolate auth status projection

* refactor(models): split auth status API key projection

* fix(auth): preserve legacy CLI metadata on failed migration

* fix(auth): retain healthy CLI OAuth migration state

* fix(doctor): type CLI migration store fallback

* test(doctor): type CLI migration store mock

* fix(models): retain non-CLI credential expiry status

* fix(models): preserve independent auth route status

* fix(models): retain independently configured alias auth

* test(ui): stabilize activity feed fixture clock

* fix(auth): preserve legacy CLI recovery metadata

* fix(auth): scope legacy CLI migration to Claude

* fix(auth): preserve MiniMax CLI expiry ownership

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: XX441 <169966250+XX441@users.noreply.github.com>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-19 23:05:32 -07:00
Peter Steinberger 0a8226c3db fix(ui): give embedded settings sections the shared section rhythm (#126541)
* fix(ui): give embedded settings sections the shared section rhythm

The agents tab panel hosted settings sections in a bare div, so sections
stacked with zero separation; the bespoke .agents-main margin rule in
agents.css missed the nested tabpanel entirely. Descriptions also pulled
up to 4px under control-height header actions (squeezed Verify/Save rows).

Add a .settings-stack primitive to settings.css for embedded surfaces,
use it on the agent tab panel, delete the page-local margin fork, and let
section descriptions clear action-bearing headers.

* test(agents): export getRuntimeConfigSourceSnapshot from runtime-snapshot mock

Main's checks-node-compact-large shard is red: #126531 routed
provider-model-routes through projectConfigOntoRuntimeSourceSnapshot,
which reads getRuntimeConfigSourceSnapshot, and this suite's explicit
vi.mock factory did not export it (24 failures). Return null so the
projection no-ops and resolvers keep reading the provided config.
2026-08-19 22:31:35 -07:00
Peter Steinberger f289685bf3 fix(ui): stabilize settings and update recovery E2E (#126538)
* test(ui): await settings takeover in app chrome E2E

* test(ui): assert current build after update recovery
2026-08-19 21:39:26 -07:00
Peter Steinberger 70b6f44f13 improve: one alert surface, explained by Ask OpenClaw (#126155)
* refactor(ui): unify sidebar alerts with custodian

* refactor(ui): move custodian alert state

* fix(ui): use the defined mono token in the custodian alert card

* fix(ui): break the update-watcher import cycle

Type the watcher against a structural leaf contract instead of
Pick<ApplicationContext,...>; context.ts reaches this module through
overlays-types.ts, so naming the context type closed a madge cycle.

* fix(ui): re-arm the alert explanation when an incident recurs

Failed-automation and model-auth alerts keep one incident id across
recover-then-fail-again, so an id-keyed dedupe showed the renewed alert
and never explained it. Scope ask-once to the presentation instead.
2026-08-19 21:33:31 -07:00
Vyctor H. Brzezowski 916eef4e99 fix(ui): balance completed-work spacing (#126303)
* fix(ui): balance completed-work spacing

* fix(ui): preserve touch work spacing

* fix(ui): balance touch work spacing

* fix(ui): open completed-work spacing
2026-08-20 00:17:32 -03:00
Patrick Erichsen 6eb9344e7d fix(ui): preserve dashboard side-panel selection (#126511) 2026-08-19 19:11:13 -07:00
Peter Steinberger 0a86702241 feat(github): authorize agent identities from Settings (#126474)
* feat(github): add device authorization lifecycle

* fix(github): harden device authorization lifecycle

* fix(github): refresh native tool display snapshot

* fix(github): refresh config and UI baselines

* refactor(github): break OAuth identity import cycle

* test: make gateway retry deadline assertion scheduler-safe
2026-08-19 17:41:58 -07:00
Vyctor H. Brzezowski 3aff572d74 fix(ui): dismiss session hovercard before its menu opens (#126345)
* fix(ui): dismiss session hovercard before menu

* test(ui): keep hovercard regression focused

* fix(ui): dismiss catalog session hovercards

* test(ui): use typed catalog session key
2026-08-19 21:41:25 -03:00
Vyctor H. Brzezowski 02be7fea97 improve(ui): unify resize handles (#125066)
* improve(ui): unify resize handles

* perf(ui): trim resize handle startup cost

* fix(ui): stop resize drags on blur

* perf(ui): absorb resize blur cleanup

* perf(ui): unify resize drag listener target

* refactor(ui): unify resize drag state

* perf(ui): remove duplicate resize styles

* refactor(ui): let layouts own resize edges

* fix(ui): preserve resize interaction contracts

* test(ui): satisfy resize event lint
2026-08-19 21:11:39 -03:00
Vyctor H. Brzezowski e741649856 fix(ui): keep prose fences fully visible (#126346) 2026-08-19 21:05:51 -03:00
Vyctor H. Brzezowski 16b09ad307 fix(ui): sync Terminal with live theme changes (#126297)
* fix(ui): sync terminal with live theme changes

* test(ui): cover terminal theme lifecycle

* test(ui): supply resolved theme in gateway fixture
2026-08-19 20:21:26 -03:00
Erick Kinnee ee70dbcb14 test(ui): split dynamic catalog convergence e2e test into its own file
Keeps chat-flow.models-reasoning.e2e.test.ts under the 1000-line max-lines
budget; the ratchet forbids new suppressions. The moved test is unchanged.
2026-08-20 00:11:29 +01:00
Erick Kinnee 09d419683e test(ui): cover dynamic catalog projection convergence 2026-08-20 00:11:29 +01:00
Erick Kinnee cc445a32bb fix: refresh dynamic model metadata in session controls 2026-08-20 00:11:29 +01:00
Josh Avant a4f17833ad fix(gateway): make config revision tokens opaque (#126464)
* fix(gateway): make config revision tokens opaque

* test(gateway): cover config revision key startup phase
2026-08-19 16:10:27 -07:00
Peter Steinberger 33e6daa3bd fix(ui): show mixed-role node connectivity (#126428)
Devices keeps machine-wide liveness while showing node-role offline/manual-wake state accurately.
2026-08-19 15:24:31 -07:00
ClawSweeper fa407417f0 fix(ui): honor categories for child sessions (#126388)
* fix(ui): honor categories for child sessions

* fix(ui): admit categorized child sessions as roots

* fix(ui): keep sidebar files within line budget

* fix(ui): include cached categorized children

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-19 15:39:24 -06:00
Peter Steinberger a3ca8466ee fix(ui): refresh device labels after rename (#126432)
* fix(ui): refresh device labels after rename

* fix(ci): classify device label refresh event for mobile

* chore(protocol): regenerate Android gateway events
2026-08-19 14:18:50 -07:00
Peter Steinberger 513ec6218c fix(crabbox): harden worker desktop setup (#126417)
* fix(crabbox): harden desktop provisioning

* docs(gateway): clarify worker desktop routes
2026-08-19 14:13:06 -07:00
ClawSweeper d8fd2937aa fix(ui): keep mobile sidebar session menus reachable (#126355)
* fix(ui): keep mobile sidebar menus in viewport

* fix(ui): bound compact sidebar menu height

* fix(ui): restore Open PR cursor marker

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-08-19 14:00:39 -07:00
Peter Steinberger 108a737552 test(ui): await anchored model picker geometry (#126438) 2026-08-19 13:47:20 -07:00
Peter Steinberger 5eda48ed99 fix(ui): recover failed lazy surfaces (#126409) 2026-08-19 12:27:35 -07:00
Peter Steinberger 0b715e3f5b refactor(ui): share Control UI resource route contract (#126386)
* refactor(ui): share Control UI resource route contract

Gateway and Control UI now share browser-safe resource route grammar, while authorization and domain validation remain handler-owned.

* perf(ui): keep resource routes out of startup

Narrow browser-safe contract modules and the lazy authenticated avatar loader keep route/cache code out of the startup chunk while the stable Gateway barrel remains compatible.
2026-08-19 12:20:22 -07:00
Peter Steinberger 84c2111b30 fix: restore cloud worker Desktop on node-backed Crabbox workers (#126393)
* fix(gateway): carry cloud worker desktops over nodes

* fix(crabbox): restore node-backed worker desktops

* refactor(crabbox): split worker provider owners
2026-08-19 11:50:48 -07:00
Peter Steinberger 5976e74d1c fix(ui): close dashboard side panel in split view (#126397) 2026-08-19 11:36:46 -07:00
Peter Steinberger e47637809c fix(ui): render one assistant reply when history and the terminal event race (#126382)
* fix(ui): render one assistant reply when history and the terminal event race

A finished run's reply reached the Control UI twice: the durable transcript
row and the pane's own terminal projection shared no identity, so the
projection reducer kept both and the transcript collapsed them behind the
"x2" duplicate badge. The gateway's chat final event carries no message id,
and a durable assistant row carries no run id, so the reducer's same-run
promotion could never match them. A WeakMap side channel hid the duplicate
only when history happened to be applied before the terminal event arrived,
which made the badge look intermittent.

The pane now admits the durable assistant row of the run it is finishing
through the reducer, attributed to that run, so the durable row adopts the
terminal projection in place; the reducer refuses to downgrade a row that
already carries a transcript id back to an id-less projection.

Splits the run-terminal bookkeeping tests into a sibling file to stay under
the max-lines ratchet.

* fix(ui): bind a late reply row to its run only when it carries that reply

The terminal tombstone outlives its run by design, so attributing every
unowned assistant row to it could stamp a delayed older row with a newer
run's id; the reducer then matched that row to the newer run's terminal
projection and replaced the answer the user should see. The tombstone now
claims only the row carrying the reply already projected for that run.
2026-08-19 11:33:22 -07:00
ClawSweeper 76fc15c515 fix(ui): dedupe streamed final assistant messages (#126367)
Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-19 12:26:01 -06:00
Peter Steinberger 0606e31d0e feat(gateway): broker GitHub publication (#126306)
* feat(gateway): broker GitHub publication

* refactor(gateway): split publication owners

* fix(gateway): enforce publication branch authority

* fix(gateway): bind publication to remote identity

* fix(gateway): bind publication recovery to remote state

* fix(gateway): preserve publication git state

* fix(gateway): retain publication recovery authority

* fix(gateway): commit publication index atomically

* fix(gateway): narrow publication index errors

* refactor(gateway): keep publication CAS errors private

* fix(gateway): recover publication index transactions

* fix(agents): describe GitHub publication tool

* fix(gateway): harden publication base fetch

* fix(gateway): reject publication filter semantics

* fix(gateway): verify publication creation base

* refactor(agents): align publication tool options

* fix(gateway): isolate publication object lineage

* refactor(gateway): use shared table probe

* test(gateway): keep publication helpers in routed suite

* perf(ui): lazy-load GitHub publication request

* fix(gateway): preserve publication support contracts

* fix(gateway): recover publication before authority checks

* fix(gateway): fence local publication snapshots

* fix(android): format generated protocol models

* fix(gateway): harden publication recovery

* fix(gateway): fence publication recovery

* fix(ui): reset completed publication cycles
2026-08-19 11:05:12 -07:00
Peter Steinberger 51599041bc fix: explain preserved session worktrees accurately (#126347)
* fix(sessions): report worktree preservation reasons

* fix(sessions): align preservation checks with current main

* perf(ui): keep preservation copy within startup budget

* perf(ui): reuse localized preservation copy

* test(ui): match preserved worktree confirmation copy

* test(ui): await committed raw config state
2026-08-19 10:59:42 -07:00
Peter Steinberger 1410ffcd23 fix(ui): show real avatars in session hovercards (#126372)
* fix(ui): show channel avatars in session hovercards

* fix(ui): preserve hovercard avatar fallback
2026-08-19 10:54:56 -07:00