Commit graph

79676 commits

Author SHA1 Message Date
Peter Steinberger
a54caf0a66
fix(setup): preserve configured channel when status refresh fails (#124383)
Some checks are pending
Native App Locale Refresh / Refresh native hi (push) Blocked by required conditions
Native App Locale Refresh / Refresh native id (push) Blocked by required conditions
Native App Locale Refresh / Refresh native it (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ja-JP (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ko (push) Blocked by required conditions
Native App Locale Refresh / Refresh native nl (push) Blocked by required conditions
Native App Locale Refresh / Refresh native pl (push) Blocked by required conditions
Native App Locale Refresh / Refresh native pt-BR (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ru (push) Blocked by required conditions
Native App Locale Refresh / Refresh native sv (push) Blocked by required conditions
Native App Locale Refresh / Refresh native th (push) Blocked by required conditions
Native App Locale Refresh / Refresh native tr (push) Blocked by required conditions
Native App Locale Refresh / Refresh native uk (push) Blocked by required conditions
Native App Locale Refresh / Refresh native vi (push) Blocked by required conditions
Native App Locale Refresh / Refresh native zh-CN (push) Blocked by required conditions
Native App Locale Refresh / Refresh native zh-TW (push) Blocked by required conditions
Native App Locale Refresh / Commit native locale refresh (push) Blocked by required conditions
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Waiting to run
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Blocked by required conditions
Plugin Init Scaffold Validation / Validate provider scaffold (push) Waiting to run
Plugin NPM Release / preview_plugins_npm (push) Waiting to run
Plugin NPM Release / Validate release publish approval (push) Blocked by required conditions
Plugin NPM Release / preview_plugin_pack (push) Blocked by required conditions
Plugin NPM Release / Preflight plugin npm package () (push) Blocked by required conditions
Plugin NPM Release / Trusted publisher OIDC exchange (push) Blocked by required conditions
Plugin NPM Release / publish_plugins_npm (push) Blocked by required conditions
Plugin NPM Release / verify_plugins_npm (push) Blocked by required conditions
Workflow Sanity / no-tabs (push) Waiting to run
Workflow Sanity / actionlint (push) Waiting to run
Workflow Sanity / generated-doc-baselines (push) Waiting to run
* fix(setup): preserve channel config on status failure

* fix(setup): limit status recovery to configure results
2026-08-15 21:09:06 -07:00
Peter Steinberger
62deb87ee4
fix(computer-use): converge provider ref lifecycles on the contract (#124374)
* fix(computer-use): converge provider ref lifecycles

* test(computer-use): expect stale lifecycle code

* fix(computer-use): key native window refs on stable window identity

Peekaboo matched an existing window ref on the whole WindowMutationIdentity,
which embeds capturedBounds and isMinimized. Any move, resize, or minimize
therefore minted a new ref for the same live window, never evicted the old
one, and let the old ref keep resolving to a stale ServiceWindowInfo whose
identity and bounds were then used as the per-action expectations, so the
operator saw a downstream mismatch instead of COMPUTER_STALE_OBSERVATION.

Window refs now key on stable identity only (WindowServer id plus the owner
process generation that guards pid reuse) and refresh the stored target in
place on every discovery, so one live window keeps one ref for the whole
lifecycle generation and later checks compare against current data. The
one-instantiation generic reference store is folded back into the service as
plain state plus small concrete helpers.

The shared case table gains window_moved, which both providers must satisfy,
and the Swift side now drives the real ComputerActionServiceV2 with real
Peekaboo values instead of a toy store with an equality matcher. Its
in-flight generation case runs a real perform() whose lifecycle is revoked
mid-action rather than throwing the error it asserted.

* test(cua-computer): drive the real in-flight generation-rotation path
2026-08-15 21:08:41 -07:00
Peter Steinberger
acbbff19ba
refactor(types): drain chained-assertion ledger — extensions (#124378)
* refactor(types): drain chained-assertion ledger — extensions

* fix(types): parse Matrix summary events at the boundary

* style(types): satisfy extension map lint

* style(types): name the Tlon image marker cleanly

* fix(browser): preserve deep MCP snapshots iteratively
2026-08-15 20:55:01 -07:00
Peter Steinberger
9a3f3b7bf1
fix(ui): release losing fallback payloads on composer adoption (#124391)
Global-scope composer fallback adoption coalesces sibling candidates
(bare-global, default-main, qualified-main) into one winner and deletes
the losers from chatComposerFallbackByScope — but never released their
attachment payload-store entries, unlike every clearChatComposerMemory-
Fallback caller. The dropped data URLs and object URLs leaked for the
pane's lifetime.

Release dropped candidates' payloads at the adoption site, retaining ids
still referenced by the live composer or any surviving fallback (the
same retention rule the pane-handoff owner uses).
2026-08-15 20:54:45 -07:00
Peter Steinberger
c6ae99bb96
fix(gateway): stop reporting failed OpenAI HTTP runs as successful (#124039)
* fix(gateway): reject resolved OpenAI HTTP failures

* fix(gateway): reject error stop reasons in OpenAI HTTP
2026-08-15 20:49:19 -07:00
Vito Cappello
9474e55076
fix: consume prepared images once in CLI-backed turns (#120721)
* fix(agents): preserve images across CLI dispatch

* test(agents): format CLI dispatch coverage

* fix(reply): consume prepared images once

* test: cover CLI inbound image reply path

* fix(auto-reply): preserve prepared image state

* fix(auto-reply): preserve queued image fallback

* fix(agents): keep CLI image marker internal

* fix(agents): keep image admission marker private

* fix(agents): preserve internal image admission state

* fix(auto-reply): keep image admission marker internal

* test: keep image preparation marker internal

* fix(cli): preserve queued image metadata

* test(cli): cover filtered media image indexes

* test: restore media fixture cleanup

* test: align filtered media fixture with resolver mock

* style: format CLI image forwarding changes

* fix(auto-reply): preserve queued media slot type

* fix(auto-reply): avoid spread in media slot mapping

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-15 20:49:08 -07:00
Peter Steinberger
717f77678a
refactor(heartbeat): delete unreachable prompt-null skip and dead lanes-busy surface (#124385)
resolveHeartbeatRunPrompt can no longer return prompt: null — the only
null producer (inferred commitments follow-ups) was deleted in
4b0151682e — so the two not-due short-circuits in
heartbeat-runner-execution.ts were dead branches. Narrow the resolution
type to string and delete both consumers.

HEARTBEAT_SKIP_LANES_BUSY had no remaining producer and
HeartbeatDeps.getCommandLaneSnapshots no prod reader (the per-lane busy
check was consolidated into requests-in-flight admission). Delete the
constant, the dep, and the tests that only exercised the dead seam;
retarget the retry-simulation tests at live retryable reasons and drop
the stale lanes-busy mention from the troubleshooting doc.
2026-08-15 20:48:00 -07:00
Peter Steinberger
057f98359e
perf(test): synchronize MCP lifecycle tests (#124389) 2026-08-15 20:45:06 -07:00
Peter Steinberger
4823b236a7
fix(browser): stop cancelled downloads from capturing later files (#124382)
* fix(browser): cancel abandoned download waits

* fix(browser): cancel in-flight download clicks
2026-08-15 20:44:31 -07:00
Peter Steinberger
148229b6dd
fix(ui): keep Logs tails bound to their source file (#124369)
* fix(ui): reset logs when source changes

Reload the active tail without a cursor when logs.tail switches files so the Control UI never mixes sources or skips a new file prefix.

* fix(ui): reset log source after reconnect

* test(ui): harden logs lifecycle proof

* test(ui): route Logs lifecycle through real Gateway lane
2026-08-15 20:42:58 -07:00
Peter Steinberger
a6cb2fbc9f
fix(agents): preserve context engine session ownership (#124376)
* fix(agents): preserve context engine session ownership

Unbound legacy context-engine hooks no longer execute LLM calls under the default agent. Explicit, agent-scoped, main-alias, and persisted session ownership remain supported.

* test(ci): avoid scheduler pid file race
2026-08-15 20:42:26 -07:00
Peter Steinberger
e8e7598c5b
fix(gateway): close ask-fallback replay to cancelled approvals (#124381)
consumeAskFallback gated only on decision-less resolved records, so
run-aborted cancellations and dispatch-fencing revocations — which also
end decision-less — satisfied the timed-out predicate and could be
replayed as ask-fallback. Require the expired/no-route terminal so only
genuinely unanswered approvals re-admit.

Dispatch fencing now records its closure honestly: worker-dispatch
revocation routes through forceDenyDetailed(run-aborted, cancelled)
instead of expire(), which persisted a false 'timeout' terminal.

Rider cleanup: delete the write-only PendingEntry.reject/rejectPromise
plumbing and the lookupPendingId alias (single test caller moved to
lookupApprovalId).
2026-08-15 20:42:08 -07:00
Peter Steinberger
5943cd0362
test(qa): make target-none heartbeat explicit (#124380) 2026-08-15 20:41:14 -07:00
Peter Steinberger
e6d2b1bbac
fix(gateway): bound cloud workspace hash memo (#124373) 2026-08-15 20:39:36 -07:00
Vyctor H. Brzezowski
f38a2f51b3
fix(ui): keep chat file links whole when a line wraps (#123310)
* fix(ui): keep chat file links whole when a line wraps

A file reference in chat prose could end a line on its file-type glyph and strand its label on the next line, splitting one reference into two fragments. The chip is now an atomic inline, so it moves to the next line whole, and it is capped at the column width so an unshortened label wraps inside the chip instead of overflowing the bubble.

Closes #123309

* fix(ui): keep the file-link glyph attached to its label on wrap

The prior fix (display: inline-block + max-width: 100% on the anchor)
stopped the whole chip from splitting across the parent's lines, but
left the glyph itself splittable from its label: the ::before glyph
was display: inline-block, an atomic inline with its own contingent
line-break opportunity, so when a long/unbreakable label couldn't fit
next to it, the UA pushed the whole label onto the next line instead
of letting overflow-wrap continue the run — stranding the glyph alone
above it. Switching the glyph to display: inline (sized via
padding-inline-start + an explicit mask size instead of width/height +
contain) removes that break opportunity; the glyph and the label's
first character now share one unbreakable run, while the rest of a
long label still wraps normally via the inherited
overflow-wrap: anywhere.

The existing wrap test couldn't have caught this: a.markdown-file-link
is inline-block, so its own getClientRects() always reports exactly
one rect regardless of how the content wraps inside it. Added a
table-driven probe (short basename, an unbroken long basename with no
natural break points, and a path with a :line suffix) that compares
the chip's own top against its first character's top via a Range,
which does see the internal split. It fails on the pre-fix CSS and
passes after.

* fix(ui): let the wrap probe infer its page.evaluate types

A single explicit type argument on page.evaluate binds Arg to void, so the
sweep's case ids arrived untyped and the shard failed to compile. Inference
reads both the argument and the result from the call.

Also condenses the layout-invariant comments on the file-link rules and the
probe to three lines each.

* test(ui): sweep the glyph probe over enormous and non-ASCII labels

A 240-character basename with no separator and a CJK label reached through a
host-local href both wrap several times inside the chip, so the first cut is
where a glyph would strand. Both fail on the pre-fix rule.

* fix(ui): give the file-link chip its own wrap policy

The atomic chip capped its box with max-width but relied on .chat-text for
overflow-wrap: anywhere. .sidebar-markdown declares no wrapping policy, so in
the Chat Detail Panel an unbreakable label painted past the capped box and the
panel's hidden horizontal overflow clipped it.

Declare the wrap policy on the shared file-link owner and sweep both renderers
in the browser probe: the separation cases now assert the painted label never
runs past the column's content edge.
2026-08-16 00:37:47 -03:00
wuqxuan
276e5579a4
fix(heartbeat): require explicit message targets (#103711)
Reject targetless proactive message-tool calls during heartbeat runs before mutation tracking, while preserving automatic owner/last heartbeat delivery and explicit plugin-alias recipients.

Co-authored-by: wuqxuan <wuqxuan@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-16 09:06:43 +05:30
Peter Steinberger
10443aacb9
fix(gateway): release remote-exec claims after reconcile failure (#124368) 2026-08-15 20:36:37 -07:00
Peter Steinberger
e87fc87782
fix(gateway): avoid silent unserializable WebSocket responses (#124375)
* fix(gateway): surface response serialization failures

* refactor(gateway): serialize websocket frames once

* refactor(gateway): bound response serialization fallback
2026-08-15 20:35:10 -07:00
Josh Lehman
a0498f7a9c
fix: restore native OpenAI web search in packaged runs (#124215)
* oc-e13.2: preserve web search failure evidence

* oc-e13.2: include provider owners in runtime plans

* oc-e13.2: prepare provider owners before harnesses

* oc-e13.2: retain provider selections in runtime owners

* oc-e13.2: keep harness selection helper internal

* test(agents): cover prepared runtime registry loads

Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-15 20:30:41 -07:00
Peter Steinberger
bb68ad057c
refactor(types): drain chained-assertion ledger — agents (#124354)
* refactor(types): drain chained-assertion ledger — agents

* fix(agents): preserve non-configurable stream iterators

* refactor(agents): call provider failover hook directly
2026-08-15 20:28:31 -07:00
Peter Steinberger
527d155055
docs(plan): mark wave-5 computer-use rows landed (#124155)
* docs(plan): mark wave-5 rows landed and record Linux as partial

* docs(plan): record trust-model, tool-split, ref-convergence, and rig root cause

* docs(plan): carry wave-4 rows forward, define partial status, order rows by wave
2026-08-15 20:24:52 -07:00
Peter Steinberger
6279636985
perf(test): remove duplicate UI place cases (#124370)
* perf(test): remove duplicate UI place cases

* test(ui): fix latent e2e timing assumptions
2026-08-15 20:21:22 -07:00
Peter Steinberger
92b6c17bb8
fix(usage): keep healthy provider usage after auth failures (#124367)
* fix(usage): isolate provider auth failures

* fix(usage): preserve direct auth failures
2026-08-15 19:59:55 -07:00
Patrick Erichsen
a73249c7cd
fix(ui): clarify active model context in picker (#124207)
* fix(ui): show active model context budget

* fix(ui): simplify compact model label

* fix(ui): preserve provider when matching context budget

* fix(ui): hide stale context during model switches

---------

Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-15 19:57:27 -07:00
Peter Steinberger
e68f3d8ad1
fix(ui): surface rejected terminal actions (#124046)
Mark stale terminal tabs exited when the Gateway rejects input or resize, so operators see an actionable outcome instead of silently losing keystrokes.
2026-08-15 19:53:47 -07:00
Peter Steinberger
4b8ca98a94
fix(gateway): omit internal class names from RPC failures (#124329)
* fix(gateway): drop internal error class names from operator output

* test(cli): drop stale Error: prefixes from capability expectations

* test(cli): align invalid-port output with canonical formatting

* fix(errors): preserve primary structured codes

* style(cli): format invalid-port expectation

* test(cli): align shared error rendering expectations

* fix(gateway): scope error code rendering to agent failures

* test(errors): redact opt-in structured codes

* refactor(errors): keep canonical formatter callback-safe

* test(audit): drop stale Error: prefixes after formatter cleanup

PR #124336 landed audit's gateway-error rendering while this branch was
in flight, so its two new assertions were written against the prefixed
output. The canonical formatter no longer emits the generic Error:
prefix, so the expected strings are updated to match.
2026-08-15 19:47:42 -07:00
Peter Steinberger
44c5abb690
fix(gateway): report device worker capacity distinctly from disconnection (#124340)
* fix(gateway): report device worker capacity distinctly from disconnection

This separates paired, disconnected, and connected-but-saturated device worker failures so capacity exhaustion no longer looks like disconnection. Saturated hosts now tell operators to retry after a running turn completes, and table-driven coverage asserts all three messages. AI-assisted.

* test(gateway): expect unpaired reason in startup availability probe
2026-08-15 19:46:06 -07:00
Peter Steinberger
b170c2c021
feat(ui): grid picker for session icons (#124335)
* feat(ui): add session icon grid picker

* fix(ui): use radio semantics for icon grid

* fix(ui): use pressed-state action-grid semantics for the icon picker

ClawSweeper: menuitemradio/radio semantics promise arrow-key selection, but arrows here only move focus (selection persists server-side, so select-on-focus would patch per keypress). Plain buttons with aria-pressed match the click/Enter-only contract.
2026-08-15 19:44:52 -07:00
Patrick Erichsen
1b954672b1
feat(ui): move incognito to new-session rail (#124352) 2026-08-15 19:44:08 -07:00
Peter Steinberger
6bbc57e526
refactor(types): drain chained-assertion ledger — core (#124351) 2026-08-15 19:41:31 -07:00
Vyctor H. Brzezowski
aed4510bd0
improve(ui): unify chat side rails in a tabbed panel (#123874)
* Control UI: unify chat rails in a tabbed panel

* fix(ui): compact chat side panel navigation

* Polish rail separators around the active tab

* Soften rail tab separators

* Inset the rail tab strip from the resize handle

* Remove the rail tab strip bottom rule

* Add compact close controls to rail tabs

* Redistribute rail tabs after closing a surface

* Restore bottom docking from the rail terminal

* Fade clipped rail tab labels at the edge

* Add drag reordering to rail tabs

* Polish terminal tab chrome

* Polish rail tab close controls

* Regularize rail tab separators

* Space rail tabs evenly

* Add feedback to inactive rail tabs

* Smooth rail tab selection

* Hide unavailable rail menu items

* Preserve browser multi-tab entry

* Support bottom-docked rail tabs

* Polish rail tab sizing

* Refine side panel actions

* Neutralize rail empty-state icons

* Separate dark rail surfaces

* Fade only clipped rail tab labels

* Compact rail header controls

* Refine the surface picker

* Raise and tighten the surface empty state

* Keep Browser and Tasks in the chat topbar

* Unify surface list cards

* Keep embedded rails inside their dock

* Reveal rail tab close actions on demand

* Show full rail labels only when clipped

* Let rail tabs use available space

* Align chat topbar surface controls

* Unify rail surface empty states

* Center rail tab glyphs

* Fade clipped rail labels smoothly

* Keep rail tab labels visible

* Tighten rail tab separator and label fade

* Keep the new-tab control beside the rail tabs

* Keep rail tab separators from reflowing on activation

* Anchor the new-tab control outside the rail tab scroll

* Scroll rail tabs at the floor instead of clipping them

* Tighten spacing between rail tabs

* Report an unusable terminal open response as a readable failure

* Keep the terminal session menu inside the panel

* Share one dock destination cluster across rails, terminal and browser

* Align the terminal mini rail with its management icons

* Tidy panel pickers, browser chrome and task detail retry

* Type the sidebar callbacks object so tsgo:ui passes

* Space out the panel picker rows

* Measure tab strip edges by rect and cancel superseded installs

* Validate every terminal session field and release unusable sessions

* Fold the terminal rail stretch rules into one

* test(ui): match rail tab checks to the tabbed panel header

Anchoring the new-tab control outside the scroll area wrapped the strip in
.side-panel__header-tabs, and every query written as a direct-child chain
started matching nothing. The assertions did not fail loudly: they compared
an empty label list, so three side-panel journeys and the background-tasks
rail went red on a selector detail rather than on behaviour.

Give the label query one named owner scoped to the panel's own header, so
Terminal and Browser strips in the panel body stay excluded while header
layout can keep moving. Freeing that width also means two short tabs now
fit where they used to be squeezed, so the closing step asserts the honest
invariant - a strip that fits again releases the fade - while the overflow
and tooltip regime stays proven earlier in the same journey.

Settle the shared side-panel helper on whichever surface renders: an empty
panel offers its type list and a populated one offers the header menu, and
probing before either existed left it waiting for a control that never
comes. Also drop a shadowed seed binding and an unused locator that oxlint
flagged in the same file.

* fix(ui): adapt session discussion slot to the unified panel layout

* test(ui): capture the bottom dock evidence with a resting divider

* fix(ui): drop the dead previousDock toggle path

* test(ui): align sibling suites with the tabbed panel decisions

* fix(ui): keep narrow-pane hides above the icon-button styling cascade

* fix(ui): create tooltip descriptions via ownerDocument

* fix(lint): merge duplicate terminal header styles and drop dead branches

* refactor(ui): extract embedded panel templates from the pane render

* refactor(ui): delete rail-era dead exports

* test(ui): repair type drift after the rebase

* fix(ui): keep the workspace toggle module-local and settle test caps

* fix(ui): give side-panel tabs their runtime and their own header actions

The tabbed side panel dropped two things the old rails owned. The discussion
tab lost its only runtime registration, so `openclaw-session-discussion` was
never defined and the tab rendered as a permanently blank box; it now loads
through the per-slot lazy runtime map like the other panel types.

Panels also have no header of their own anymore, so any action on the active
panel's content had to reach the shared header. The header now takes panel
contributed actions instead of a discussion-only open-url special case, which
brings back the side-chat "Clear thread" overflow menu — its gateway reset had
no reachable entry point at all in the embedded rail.

* test(ui): anchor the sidebar scroll proof to the panel host

The bounding contract moved from `.sidebar-column__panel` to
`.side-panel__panel`; mounting the detail panel under the removed class let it
grow instead of scroll, so the test failed for its harness rather than for the
behavior it guards.

* refactor(ui): move side-panel wiring out of the chat render monolith

`chat-pane-render.ts` crossed its line budget. The region callbacks are layout
policy, so they resolve in the layout module with the pane injecting only what
it owns, and the two panel-action producers collapse into the single header
contribution the region consumes.

* fix(ui): keep one terminal intent queue per document

A session route mounts the side-panel terminal beside the shell instance kept
for the bottom dock. Each owned a private action array over one sessionStorage
key, so their whole-array writes erased each other's intents and a freshly
mounted panel drained through a reconnect fence it never saw.

The queue, its persisted record, and the fence now belong to the document;
panels bind as executors while connected. The chat pane records a toggle intent
where it observes it, instead of parking the raw event in memory and handing it
to a panel that may not be mounted yet — a service-worker reload in that window
dropped the request, thread id and all, with nothing explaining why. That makes
the deferred-restore handshake dead weight, so it goes.

* fix(ui): let the panel that starts a terminal intent finish it

Opening a catalog terminal from a chat route mounts the side-panel terminal
right after the request, which swapped the queue's executor mid-flight and
stranded the in-flight action; the panel's own mount restore then opened a
plain session instead. The executor that began an action stays responsible for
it as long as it can still run.

* test(ui): cover closed legacy side docks

* refactor(ui): split side panel controllers

* fix(ui): stabilize embedded panel handoffs

* style(ui): format browser panel refresh

* test(ui): settle catalog prepend paint incrementally

* docs(ui): describe the unified chat side panel

* test(ui): settle catalog clock transitions

---------

Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-15 20:40:00 -06:00
Peter Steinberger
8d262b96cc
fix(gateway): discard prepared media when a hook blocks the turn (#124353)
#124100's disarm-at-ACK custody rests on dispatch persisting the
referencing transcript on every post-ACK path. The blocked-turn path breaks
that: a before_agent_run block persists only the redacted block reason —
no media markers, no media facts — so the offloaded inbound refs stay
unreferenced forever (the inbound sweep is off unless attachments.ttlHours
is set). Dispatch settle now discards the prepared refs when the recorder
ended blocked, applying the same custody rule as the pre-ACK owner.

Regression test drives a blocked dispatch with an offloaded attachment and
asserts the inbound dir returns to baseline; fails pre-fix.
2026-08-15 19:39:16 -07:00
Peter Steinberger
c3488150c5
refactor(computer-tool): split by responsibility (#124358) 2026-08-15 19:38:16 -07:00
Peter Steinberger
0dd8d3eafd
perf(test): narrow web fetch imports (#124357) 2026-08-15 19:34:20 -07:00
Peter Steinberger
4919c7030d
fix(ci): use OCM native workspace adapter (#124341)
Pin OCM v0.2.32 so Performance validation uses upstream native .mts discovery and transitive workspace dependency handling instead of the local Bash/tsx trampoline.
2026-08-15 19:34:14 -07:00
Peter Steinberger
289a9cabc8
docs(computer-use): state the authorization chokepoint explicitly (#124355) 2026-08-15 19:30:29 -07:00
Peter Steinberger
e2e070c927
fix(ui): keep session context menus on sessions (#124344) 2026-08-15 19:24:59 -07:00
Peter Steinberger
1ab85edb0e
fix(workers): bundle workspace rsync receiver (#124339) 2026-08-15 19:23:05 -07:00
Peter Steinberger
ca849506f3
fix(cli): read node liveness from the recorded node.list fact and drop dead nodes-CLI guards (#124348)
Four nodes-CLI repairs at their owners:

- nodes status --last-connected joined a second pairing-scoped RPC
  (node.pair.list) to reconstruct last-connection times the gateway already
  records on every node.list row (lastConnectedAtMs, max of stored pairing
  history and live connection, since 2dcd47d4f4). The client-side join also
  preferred stored history over a live connection instead of taking the max,
  and made the command fail for callers whose auth grants operator.read but
  not operator.pairing. The filter now reads the recorded fact;
  connectedAtMs covers gateways predating it.
- nodes list --connected blanked pending rows and then printed "Pending: 0"
  while requests waited — asserting a fact it never checked. Pending rows
  carry no connection state to filter on; they now always show.
- nodes remove/rename carried unreachable !nodeId guards (resolveCliNodeId
  throws "node required" on blank input and every parse layer drops id-less
  rows) whose dead text pointed at the wrong command (nodes pending targets
  pairing requests, not paired nodes). Guards deleted; the reachable empty
  --name branch now hints at nodes list.
- status.node-mode derived node-service liveness from the formatted
  runtimeShort display string — parsing a fact back out of its own
  projection, dead in all first-party call paths (both callers pass the
  runtime object it is derived from). Field and branch deleted.

e2e test updated to pin the single-RPC shape (asserts node.pair.list is NOT
called); node-mode fixtures now use the production shape.
2026-08-15 19:19:13 -07:00
Peter Steinberger
df2b83f7ae
refactor(anthropic): split session catalog into concept modules (#124342)
* refactor(anthropic): split session-catalog into concept modules

Follow the #124178 sibling seam pattern while preserving behavior. Remove the max-lines suppression and baseline entry after the split.

* refactor(anthropic): own record caches in session-catalog-discovery

The record-shaped caches (catalogDiscoveryCache, claudeSessionScanCache,
their entry types, bounds, and TTLs) are consumed only by discovery; moving
them out of scan removes the scan->discovery type-import edge flagged by the
madge topology gate and leaves scan as record-agnostic fs primitives.
2026-08-15 19:18:03 -07:00
Peter Steinberger
6432ac3310
fix: agents delete leaves no stale database registry row (#124347)
* fix(agents): deregister agent databases on delete

* refactor(claws): finalize agent registry cleanup with removal state
2026-08-15 19:15:57 -07:00
Jason (Json)
5f1bbed42d
fix(doctor): report missing managed local embedding setup (#123575)
* fix(gateway): expose startup blockers before cutover

* fix(gateway): include session blockers in preflight

* fix(gateway): keep preflight finding type private

* fix(gateway): preflight startup auth blockers

* fix(gateway): complete startup preflight readiness

* fix(llama-cpp): keep preflight remediation private

* fix(gateway): keep preflight passive and activation-aware

* fix(gateway): apply startup guard in preflight

* fix(gateway): align auth mode preflight

* fix(gateway): keep preflight state reads isolated

Share the read-only inspection snapshot scope across duplicated runtime chunks so blocked gateway preflight remains non-mutating when bundled provider artifacts read canonical state.

* fix(gateway): keep startup preflight passive

* fix(gateway): ignore inactive embedding owner shadows

* fix(gateway): preserve startup preflight parity

* fix(llama-cpp): keep cache inspection types private

* fix(gateway): close startup preflight parity gaps

* fix(gateway): handle uninitialized memory databases

* test(gateway): observe shell fallback portably

* fix(llama-cpp): normalize embedding model paths

* refactor(gateway): drop broad startup preflight surface

* fix(doctor): report missing managed local embedding setup

* style(memory): simplify setup enablement check

* fix(memory): keep diagnostic result type private

* fix(memory): inspect local setup with remote secret refs

* fix(memory): keep doctor index inspection immutable

* fix(memory): make readiness inspection owner-aware

* fix(doctor): mirror memory slot allowlist policy

* test(doctor): use canonical memory slot id

* fix(doctor): normalize memory provider ids

* fix(doctor): resolve external embedding readiness owner

* fix(plugins): keep embedding inspection result internal

* fix(doctor): isolate plugin state during lint

* fix(doctor): route lint metadata through snapshot

* fix(cli): keep doctor lint startup source-only

* fix(cli): keep doctor lint compile-cache free

* fix(doctor): keep local embedding readiness opt-in

* test(doctor): preserve plugin artifact roots during lint

* fix(doctor): refresh memory readiness registration

* test(doctor): type nullable provider policy mock

* fix(doctor): scope lint state snapshot to provider check

* fix(doctor): isolate selected plugin state checks

* test(doctor): restore only scoped environment

* fix(doctor): defer readiness state inspection

* fix(doctor): keep deferred config reads isolated

* fix(doctor): keep plugin state mode internal

* fix(config): preserve default plugin validation
2026-08-15 20:15:06 -06:00
Peter Steinberger
635255f4e6
perf(test): shorten Vault timeout regression (#124350) 2026-08-15 19:14:43 -07:00
Saju
300043015b
fix(state): doctor --fix loops on "migration required" for older state databases (#124282)
* fix(state): doctor --fix loops on "migration required" for older state databases

Databases at user_version < 3 cannot complete the STRICT table rebuild when
they predate a first-use additive column such as
device_bootstrap_tokens.setup_id. The rebuild validates each table against its
full canonical column set, so it fails with:

  SQLite table device_bootstrap_tokens does not match its canonical columns
  (missing setup_id)

The repair runs in a single transaction, so this rolls back the audit-events-v2
work that already succeeded. The next open re-detects the legacy audit ledger
and reports that migration instead, which names a table unrelated to the real
failure and leaves doctor --fix repeating the same message. It also early
returns out of runLegacyStateMigrations, skipping the config machine-state
migration, so the gateway keeps failing config validation.

STATE_PERSISTENT_SCHEMA_COMPATIBILITY.allowedMissingColumns already treats
these columns as legitimately absent, so the persistent schema contract and the
STRICT rebuild disagreed about the same database.

Ensure the first-use additive columns immediately before the STRICT rebuild in
both paths that run it, gated on previousVersion < the STRICT schema version.
This mirrors repairLegacyGatewayRestartHandoffsForStrictMigration directly
above it. It is not a semantic change: the rebuild recreates each table from
canonical SQL that already declares these columns, so the resulting shape is
identical either way, and scoping it to pre-STRICT databases keeps the
absent-until-first-use behaviour for every normal open.

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

* test(state): cover the cold-open route and session_groups first-use columns

Adds independent regression cases for the two routes the shared helper covers
but the original fixture did not exercise directly:

- session_groups.cwd / .worktree, the other first-use additive columns, so the
  coverage is not specific to device_bootstrap_tokens.setup_id
- the writable cold-open path, which upgrades the same database during gateway
  startup without doctor running first

Both fail on an unpatched tree with the canonical column mismatch and pass with
the fix, alongside the existing doctor-repair case.

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

* test(state): enforce that first-use additive columns stay bare nullable

Materializing these columns before the STRICT rebuild is only safe while every
one of them is bare and nullable: the rebuild adds them to tables that already
hold rows, so a NOT NULL, defaulted, constrained, or key-bearing column would
fail the migration or silently rewrite existing data.

That property was documented as a convention on the definition list. Assert it
against the canonical schema instead, one case per first-use column, so adding
a non-nullable column to the list fails CI rather than pre-STRICT upgrades.

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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-15 19:08:52 -07:00
Jason (Json)
4490eaac9f
feat(ui): open links in Control UI browser (#123912)
* feat(ui): open links in Control UI browser

* fix(ui): centralize Control UI link routing

* fix(ui): carry narrowed native link poster
2026-08-15 20:05:02 -06:00
Peter Steinberger
2585edba2e
fix(audit): show valid values for rejected filters (#124336)
* fix(audit): validate filter flags before gateway call

* refactor(audit): keep filter constants owner-local

* fix(audit): keep cursor errors operator-facing
2026-08-15 18:53:00 -07:00
Jason (Json)
4be10d44d5
fix(ci): avoid false Crabbox auth failures during readiness (#119700)
* fix(ci): trust Crabbox doctor for broker readiness

* fix(crabbox): preserve doctor auth compatibility

* fix(crabbox): retain legacy auth validation

* fix(ci): trust structured Crabbox doctor readiness

Punchcard-Session: calm-meadow-summit-bc

* fix(ci): trust structured Crabbox doctor readiness

* fix(ci): satisfy Crabbox readiness types

* test(ci): use managed temp directory helper

* test(ci): stabilize Crabbox readiness fixtures

* test(ci): preserve temp helper baseline

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-08-15 19:47:19 -06:00
Peter Steinberger
d58e378157
fix(gateway): avoid quadratic session store discovery (#124334)
Configured agents now use their canonical direct store paths while retired and manual owners retain broad discovery. This prevents Gateway startup prewarm from rescanning every agent root once per configured agent.
2026-08-15 18:45:23 -07:00
Peter Steinberger
9c6539c975
refactor(gateway): one owner for the submitted-config validation pipeline (#124331)
config.set and config.patch each hand-rolled the same normalize ->
raw-validate -> plugin-validate -> respond-invalid pipeline (including the
duplicated errorShape/details blocks the round-5 error-text fix touched in
both places). validateSubmittedConfigOrRespond now owns it; both handlers
consume { validationCandidate, config }.

Behavior-neutral: same validators in the same order, same error shapes
(pinned by the existing 26 config tests including the round-5 regressions).
Net -11 production LOC and one place to evolve validation error content.
2026-08-15 18:37:23 -07:00
Peter Steinberger
1fda883530
fix(ui): recover authorized deep links after Control UI updates (#124328)
* fix(ui): refresh stale dashboard documents

* test(ui): count recovery document requests
2026-08-15 18:32:59 -07:00