Commit Graph

81255 Commits

Author SHA1 Message Date
Peter Steinberger 1ca4103fe9 fix(voice-call): expose realtime/streaming stream paths through tailscale serve/funnel (#125468)
* fix(voice-call): expose realtime/streaming stream paths through tailscale serve/funnel

Tailscale serve/funnel now auto-exposes the realtime and streaming WebSocket stream paths when those audio modes are enabled; previously Twilio <Connect><Stream> could not reach wss://<ts-host><streamPath> and realtime calls dropped after ~1s with no log.

Also: CLI voicecall expose mounts/clears stream paths symmetrically, partial tailscale mounts roll back on failure, and a warning now fires when a call's stream WebSocket never arrives within the token TTL. Reported/observed live by Peter Steinberger.

* fix(voice-call): make tailscale stream exposure atomic

Preserve configured public Tailscale prefixes when mapping realtime and streaming routes, and roll back the full route set when any mount fails. The CLI now uses the same transactional setup path and reports failure instead of accepting a partial exposure.

* fix(voice-call): expose Twilio's configured streaming path

Keep realtime routes under the public webhook prefix they advertise, while mounting streaming.streamPath exactly as Twilio emits it. This preserves the canonical public-to-local route list without expanding the provider API outside the scoped repair.
2026-08-17 18:10:45 -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
Josh Avant aea7ee7088 fix(matrix): keep user ID authorization case-sensitive (#125432)
* fix(matrix): preserve case-sensitive user IDs

* docs(matrix): clarify exact user ID casing

* fix(matrix): preserve exact IDs during resolution

* docs(matrix): clarify approval target casing
2026-08-17 18:08:25 -07:00
Josh Avant f0fd1c6e82 fix(agents): keep node agent tools on dedicated surfaces (#125434)
* fix(agents): block generic node tool reentry

* fix(agents): enforce node tool ownership for typed actions

* fix(agents): clarify dedicated node tool policy errors
2026-08-17 18:08:16 -07:00
Peter Steinberger 60920998c0 feat(apps): migrate iOS/macOS plan surface to the durable progress card (#125442)
* feat(apps): migrate iOS/macOS plan surface to the durable progress card

Replace the legacy stream:"plan" agent-event pipeline (runId-scoped state,
run-gated pill) with the sessionKey-scoped progress-card store: the shared
chat surface now renders progressCard.get snapshots, refetches on
progressCard.changed pokes with revision dedupe, clears on null-revision
pokes, and persists the card after the run completes. The card renders
markdown through the shared markdown view plus typed steps. Legacy Apple-side
plan handling (agent-event case, run-snapshot plan reconciliation,
OpenClawChatPlanStep parsing) is deleted; gateway emission stays for Android.
Removes the ios progressCard.changed coverage allowlist entry so the check
enforces the handler.

* chore(i18n): refresh native inventory for the progress-card rename

* fix(apps): keep the last progress card when a refresh fails

A transient progressCard.get failure no longer clears an already-rendered
durable card; only a successful null fetch or a null-revision poke clears it.
2026-08-17 18:07:17 -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 d32c09f843 fix(ai): accept retained messages from Responses compact (#124974)
* fix(ai): accept retained output from Responses compact

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(ai): replay retained compact messages

* fix(ai): scope retained compaction to OpenAI

* refactor(ai): reuse response endpoint contract

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 18:05:52 -07:00
Peter Steinberger b7ec596e38 fix(gateway): persist session cwd in transcript (#125484) 2026-08-17 18:02:33 -07:00
Heming Zeng b1d5e78771 fix(queue): arbitrate shared capacity across grouped lanes (#122764)
* fix(queue): arbitrate shared capacity across lanes

* fix(queue): preserve scoped lane completion ownership

* test(gateway): prove cross-lane capacity fairness

* fix(queue): preserve group helper API closure

* fix(queue): remove unsafe drain callback cast

---------

Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
2026-08-17 17:57:23 -07: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 1c91f1dce5 fix(pr): repeated review checkout recovers partial transitions (#125467)
* fix(pr): recover interrupted review checkouts

* fix(pr): preserve ignored transition collisions
2026-08-17 17:56:13 -07:00
Peter Steinberger 857c8c0864 fix(workboard): avoid false lifecycle warning during gateway startup (#125470)
* fix(workboard): defer lifecycle sweep until gateway ready

* test(workboard): cover lifecycle sweep after plugin reload
2026-08-17 17:56:04 -07:00
Peter Steinberger 850faa0367 fix(ui): guard browser ResizeObserver construction (#125480) 2026-08-17 17:55:09 -07:00
Peter Steinberger 064efce056 fix(agents): report node exec timeouts and process kills truthfully (#125466)
Two model-visible outcome bugs in the exec surface:

- formatNodeRunToolResult read only stdout/stderr/error, so a node-host
  timeout rendered as '(no output)' and a nonzero exit with stdout read
  as success; details carried no timedOut. Render the same timeout
  marker + retry guidance and exit-code note the local/gateway host
  produces, and record timedOut in details (the node detached follow-up
  path already rendered both).

- process kill and remove-running returned details.status 'failed' for
  a successfully performed termination, flagging the tool call as an
  error and inviting the model to retry a kill that worked. The
  finished-session branches already return 'completed'.
2026-08-17 17:54:51 -07:00
Peter Steinberger 720da745d9 fix(voice-call): keep realtime calls alive through brief stream reconnects (#125469)
* fix(voice-call): grace realtime stream disconnects

Share reconnect grace by CallSid and stream ID across classic and realtime streams while cleaning realtime bridge resources immediately.

Log terminal call reasons and document Twilio inbound voice and status callback setup.

* test(voice-call): align reconnect grace after rebase

Preserve the newly landed realtime generation and inactivity coverage while updating its terminal expectations for shared delayed finalization.

Remove the redundant replacement cross-product case so the lifecycle suite remains below the max-lines limit.
2026-08-17 17:51:46 -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
Marvinthebored 3d016975c3 fix(codex): degraded-engine continuity no longer projects the whole context window per turn (#125324)
* fix(codex): bound no-engine continuity projections to half the context window

A degraded or absent context engine sends fresh-thread continuity through
projectContextEngineAssemblyForCodex with the whole-window projection cap
((window - 20k) x 4 chars), so a large uncompacted transcript renders into
a single turn/start input consuming up to 90% of the model context window.
That turn fills its own native thread, the next turn's token fuse rotates
it, and the following fresh thread re-projects the transcript again -
observed as 11 near-window turn inputs on cold threads in one day
(openclaw/openclaw#125254).

Continuity projections now use a dedicated cap that reserves half the
context token budget, so the fresh thread keeps headroom for later turns
and the existing delta-resume path can actually engage. The active-engine
projection path keeps its whole-window cap unchanged.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* fix(codex): size continuity projections from real token cost, not the optimistic estimate

The continuity cap reserved half the context window in tokens but converted
that budget to characters with APPROX_RENDERED_CHARS_PER_TOKEN = 4, so at a
258,400-token window it permitted 516,800 chars. A live projection measured
703,134 chars for 226,146 input tokens, meaning that cap really costs about
166k tokens (~64% of the window), not the intended 129.2k.

Codex reports input tokens only after a turn and bounds turn input by
characters, so the projection cannot be sized in verified tokens before it is
sent. Convert the continuity budget at a conservative 3 chars/token instead,
which holds the reserved half in real tokens at the densest ratio observed.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* fix(codex): scope the continuity sizing claim to the density it was measured at

The half-window claim was stated as a guarantee, but the 3 chars/token
conversion rests on one observed projection. Input that tokenizes more densely
(CJK, base64, minified code) still exceeds the reserved half, so the constant is
renamed to CONTINUITY_EMPIRICAL_CHARS_PER_TOKEN and its comment says plainly
that it is an empirical floor rather than a bound.

The invariant test is narrowed to the measured density, and a companion test
pins the break-even ratio at 3 chars/token so the limitation is visible in the
suite instead of implied. Choosing between a guaranteed worst-case bound and
this empirical cap is a maintainer-owned tradeoff, left open on the PR.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* feat(codex): size continuity projections from the session's observed token density

Each completed Codex turn now records a calibration sample on the thread
binding: prompt chars actually sent vs the provider-reported input token cost
(uncached + cache read + cache write). The no-engine continuity cap converts
its half-window token budget at that observed ratio instead of a fixed
chars-per-token guess, so capChars / ratio stays at the reserved budget for
any content density - CJK, base64, and minified code included. The sample is
captured before startup rotation so a rotated-away thread's density still
sizes the fresh thread's projection; without a sample the empirical 3
chars/token default applies, and degenerate samples clamp to [0.5, 4].

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* fix(codex): make continuity calibration monotone - samples only tighten the cap

Red-team finding: a loose sample (up to 4 chars/token) followed by denser
content could size the cap past the empirical default, and stale or
non-continuity samples persist on the binding. Clamping the calibrated ratio
at the empirical default makes every such failure mode degrade to the
uncalibrated behavior instead of past it, and the invariant test asserts
monotonicity across poisoned samples directly.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* fix(codex): record continuity calibration only from continuity projections

ClawSweeper P2: calibration ran after every successful turn filtered only by
prompt size, so a dense direct or active-engine prompt could persist a sample
whose density later shrinks continuity history it never measured. The
no-engine continuity appliers now mark the prompt state, finalize gates the
sample on that marker, and a cross-mode regression proves a large direct
prompt records nothing.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

---------

Co-authored-by: Marvinthebored <262704729+Marvinthebored@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 17:41:45 -07:00
Peter Steinberger 85336be36d fix(cli): honor automation gateway port options (#125474) 2026-08-17 17:39:39 -07:00
Josh Lehman 02ec1b6166 fix(ui): keep acknowledged sends pending during stale history (#125426) 2026-08-17 17:33:40 -07:00
Peter Steinberger 5028ce87b0 fix(code-mode): show the final tool surface in debug logs (#124934)
* fix(code-mode): isolate and harden diagnostics

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(code-mode): share payload diagnostics across wrappers

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(code-mode): preserve transport debug behavior

* refactor(code-mode): simplify tool observer carrier

* refactor(code-mode): keep spread-safe observer metadata

* test(qa-lab): allow elapsed cron wait budget

* docs(code-mode): preserve transport debug contract

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 17:32:14 -07:00
Peter Steinberger 7e998a367f fix(cli): avoid exposing provider env values in parse errors (#124714)
* fix(cli): omit provider env values from parse errors

Amp-Thread-ID: https://ampcode.com/threads/T-01a00ae0-190d-718b-8a76-b75f3e8d1fae

* fix(config): redact provider env guidance

Amp-Thread-ID: https://ampcode.com/threads/T-01a00ae0-190d-718b-8a76-b75f3e8d1fae

* fix(config): redact provider env audit arguments

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 17:26:09 -07:00
Peter Steinberger 784dba0703 build(macos): pin final Peekaboo 4.2.1 source (#125464) 2026-08-17 17:24:46 -07:00
Peter Steinberger b295ae1625 docs(onboard): match classic setup order (#125454)
* docs(onboard): match classic setup order

* docs(onboard): align first-run setup order
2026-08-17 17:19:31 -07:00
Peter Steinberger e3de722971 refactor(tooling): consolidate baseline ratchets (#125459) 2026-08-17 17:17:49 -07:00
Peter Steinberger 244712f69a fix(voice-call): tear down realtime calls on stream close and media inactivity (#125463)
Realtime call teardown previously depended on an object-identity guard
that silently skipped ending the call record when bridge instances were
replaced, and had no transport-liveness backstop: a WS close that never
propagated left an answered call running forever. Bindings are now
socket-bound with current-generation terminal ownership, predecessor
audio is retired on successor admission (the overlapping-voices bug),
a 30s media-inactivity watchdog with 2s grace ends calls whose
transport dies silently, and every realtime call end is logged with
its cause.
2026-08-17 17:17:47 -07:00
Peter Steinberger e169520fef fix: surface swallowed failures on action paths (#125319)
* fix: surface swallowed failures on action paths

* fix(memory): propagate directory traversal failures
2026-08-17 17:14:05 -07:00
Peter Steinberger 3cc55589e3 fix(agents): stop silent compaction failures (#125302)
* fix(agents): stop silent compaction failures

* fix(agents): preserve aborted compaction outcomes

* fix(agents): preserve manual abort outcomes
2026-08-17 17:07:11 -07:00
Peter Steinberger 04c9924c45 fix(macos): keep elevation host CUA-free (#125408)
* fix(macos): isolate elevation host from CUA

* fix(macos): fail closed on unsafe elevation rollback

* fix(macos): quarantine unsafe elevation state before recovery

* fix(macos): bind elevation recovery ownership
2026-08-17 17:03:04 -07:00
Peter Steinberger a996ea25d9 fix(update): support npm before lifecycle allowlists (#125452) 2026-08-17 17:01:23 -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 b3248bf8f1 fix(release): authenticate performance health probes (#125453) 2026-08-17 16:54:21 -07:00
Jason (Json) 723259273a fix(compaction): anchor pressure to provider usage (#124267)
* fix(compaction): anchor pressure to provider usage

Use the latest transcript assistant with available context usage as the provider boundary, then estimate only later messages. Preserve conservative full-transcript fallback when no boundary is available.

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>

* fix(compaction): estimate post-usage transcript tail

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>

* fix(compaction): honor unavailable usage barriers

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-17 17:53:15 -06:00
Peter Steinberger 1fab280924 refactor(scripts): unify shrink-ratchet mechanics under one owner (#125301)
* refactor(scripts): unify shrink-ratchet mechanics under one owner

* refactor(scripts): tighten shrink-ratchet owner

* fix(scripts): widen ratchet comparator type

* test(scripts): type heterogeneous ratchet fixtures
2026-08-17 16:46:06 -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
Peter Steinberger 741250f5bb test(upgrade): add opt-in live OpenAI survivor (#125448)
Amp-Thread-ID: https://ampcode.com/threads/T-01a00a6a-b64e-74a5-8b15-2d3b966a468d

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 16:35:27 -07:00
Jason (Json) 57c27b114b fix(workboard): stop lifecycle sync errors with multiple agents (#125429)
* fix(workboard): scope lifecycle session discovery

* test(gateway): isolate explicit ownership regression

* test(workboard): satisfy lifecycle lint

* fix(workboard): preserve captured unknown lifecycle
2026-08-17 17:34:42 -06:00
Peter Steinberger f67602a7b4 fix(codex): keep valid tools when one name is unsupported (#124932)
* fix(codex): quarantine invalid dynamic tool names

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(mcp): preserve safe server names across fallbacks

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(codex): report retained tools after quarantine

* fix(codex): preserve shared MCP identifiers

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 16:33:39 -07:00
Peter Steinberger 3a431bc5c0 test(control-ui): pin repeated same-method e2e waits with after-cursor (#125439)
waitForRequest(method) is satisfied by ANY prior request of that method
and returns the latest match, so a second same-method wait in one page
context can return a stale earlier request on slow runners. Add the
opt-in { after: priorCount } cursor (same shape as PR #125107's helper
change) and pin the 11 genuinely stale-prone waits: chat-composer-
capability-menu, claude-sessions (3), desktop-panel, model-providers (3,
replacing expect.poll count workarounds), session-management.group-
defaults (3). Skipped: cloud-workers-settings (owned by PR #125107),
chat-attachment-read-lifecycle (ring asserted empty), login-gate (waits
follow app-initiated stale-build reloads, which restart the ring).
2026-08-17 16:31:24 -07:00
Peter Steinberger aeee426180 feat(control-ui): persistent Ask OpenClaw companion with global toggle (#125107)
* feat(control-ui): persistent Ask OpenClaw companion with global toggle

The custodian surface now behaves like the persistent machine-wide agent it
already is on the Gateway: the session id persists in localStorage so a
reopened surface rebinds to the live engine (wizard and approval state
survive close/reopen), the durable transcript is refetched when a surface
opens or the gateway reconnects (idle-gated so active question/wizard cards
are never clobbered), and the panel toggles from anywhere via the shared
panel-toggle contract, a command-palette action, and an admin-gated lobster
chrome button.

One server-side line: the openclaw.chat owner-mismatch rejection now carries
the existing structured session-invalidated details so persisted clients
re-mint their id from a closed code instead of matching error prose.

No gateway events, no protocol schema changes, no polling. Splits
(session-identity/variant modules, session-lifecycle and panel-toggle test
files) keep the touched files under the max-lines ratchet.

* fix(control-ui): coerce custodian toggle detail without a type assertion

The assertion-safety ratchet holds custodian-panel.ts at zero uncommented
assertions; parse the toggle CustomEvent detail through the canonical
record-coerce guard and literal narrowing instead of casting.

* fix(control-ui): delete unused CustodianPanelToggleDetail export

The record-coerce toggle parsing left the exported type without a
production consumer; the deadcode gate rightly flags it. The palette test
keeps a local shape.

* test(control-ui): select the palette custodian item via keyboard

Async session-search results can reflow the palette list mid-click on slow
CI runners, silently dropping the positional click; keyboard selection of
the asserted-active item is atomic against reflow. Also stage the reopen
wait (panel section, then text) for sharper failure localization.

* fix(control-ui): project live wizard state on rejoin and scope-gate the toggles

Address both ClawSweeper P1 findings. The welcome-only rejoin of an
existing session now routes through engine.decorateRejoinReply (the
existing ChatWizardHost projection), so a reconnecting client re-renders
the live wizard/question controls the session still awaits; the stale
welcome question only fills in when no interaction is live. The chrome
button, palette action, and deferred panel loading now use the
scope-aware canCallGatewayMethod gate (operator.admin) that the session
store already used, so advertised-but-read-scoped clients see nothing.

* test(control-ui): fix the cloud-workers e2e flake at both roots

The mocked config.get stayed frozen at the empty initial config while
patch responses advanced, so a config-store reconciliation refetch could
flap the snapshot to empty and saveProfile silently dropped the next
save; the mock now stays consistent before each patch resolution. Also
give waitForRequest an opt-in after-cursor: it is satisfied by any prior
same-method request and returns the latest match, so a second wait could
assert against the stale earlier request; the cloud-workers waits pin it
(15x green locally, previously failing 1-in-3).

* fix(ci): cover rejoin projection in sibling engine mocks; bump startup baseline

The greeting-welcome and session-ownership suites' engine mocks now
export decorateRejoinReply like the handler requires. The Control UI
startup-JS baseline moves 337511 -> 338920 B via the documented update
command: the shell chrome toggle, palette action, and scope-aware gating
are genuine startup surface (~1.4 KiB gzip, within the committed
ceiling).

* fix(control-ui): settle interrupted structured replies and racing turns on rejoin

Address both ClawSweeper reconnect P1s. A submitted question/wizard reply
with an unknown outcome now triggers a full session rejoin on reconnect
instead of being blocked by its own uncertainty flag: the Gateway projects
whether the answer was consumed and which control is live. A restored
persisted id also arms a one-shot rejoin barrier: the welcome-only request
queues behind any in-flight turn on the Gateway's per-session queue, so a
post-response history refresh deterministically surfaces rows a racing
turn persisted after the initial fetch. The open-agent handoff moved to
custodian-navigation (its owner) to keep the store under the size cap.
Live-Gateway proof (isolated state dir, real gpt-5.6-luna turns): video
and screenshots on the PR.

* test(control-ui): reopen via the chrome toggle in the custodian e2e

The palette click-through composition proved timing-flaky on loaded CI
runners in three different ways while adding no coverage: the palette
action's dispatch is pinned by the palette unit test and the event-opens-
panel path by the chrome-toggle step. Keep the gated palette entry
assertion + screenshot; reopen through the chrome path.

* fix(control-ui): keep the agent-handoff path helper module-local

The store now routes through performCustodianAgentHandoff, leaving the
path builder without external callers; the deadcode gate rightly flags
the export.

* fix(control-ui): run the rejoin barrier even when a live control projects

The racing-history refresh happens before the reply/control message is
appended, so skipping it for projected wizard/question rejoins had no
purpose and lost rows a turn persisted while the page was closed mid-
wizard. Regression covers the live-step rejoin reconciling racing rows.
2026-08-17 16:28:43 -07:00
Peter Steinberger 44e8b6f12b fix(onboarding): stop printing gateway token URLs (#124687)
* fix(onboarding): stop printing gateway token URLs

Amp-Thread-ID: https://ampcode.com/threads/T-01a00ae0-190d-718b-8a76-b75f3e8d1fae

* fix(onboarding): finish token-free handoff cleanup

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 16:23:16 -07:00
Peter Steinberger 39dc653c5e fix(telegram): unify targeted command grammar (#125195)
* fix(telegram): unify command target parsing

* fix(telegram): align supersede target routing
2026-08-17 16:22:46 -07:00
Peter Steinberger 47afdd9665 test: make descendant pid files signal readiness (#125441) 2026-08-17 16:20:01 -07:00
wanyongstar 438c55cc4f fix(ai): skip malformed thinking signatures during replay (#123228)
Responses replay parsed persisted thinking signatures without validating their JSON shape, so corrupt or unrelated values could prevent every later turn in a session.

Parse signatures in the shared replay owner and accept only reasoning records. Cover malformed syntax, null, arrays, and wrong item types through both provider- and transport-style converters.
2026-08-17 16:19:47 -07:00
Vyctor H. Brzezowski d975d9ba4a improve(ui): simplify message chrome and actions (#125241)
* improve(ui): simplify message chrome

* fix(ui): clear loading bubble shadow
2026-08-17 20:19:31 -03:00
Peter Steinberger b49e655a81 fix: archived channel sessions resume on new messages (#125163)
* fix: resume archived channel sessions on new messages

Restore deterministic external channel routes when a newly admitted user message reaches an archived session, while preserving fail-closed lifecycle guards for internal and native-command work.

* fix: restore archived sessions before reply admission

Move deterministic channel restoration to the pre-dispatch lifecycle owner so admitted human messages can resume archived routes before reply-operation guards run. Also make the SQLite retention probe exit after flushing its isolated result.

* fix(reply): preserve plugin-bound archive ownership

* fix(reply): preserve cloud placement archive safety

* fix(gateway): keep archive placement helper internal

* fix(gateway): preserve placement preflight ordering
2026-08-17 16:19:21 -07:00
Peter Steinberger 682b05dcac test(browser): use per-run temp dirs for shared /tmp profile fixtures (#125440)
Remove the fixed /tmp/brave-profile and /tmp/openclaw-brave-profile fixture paths and add cleanup for per-run temporary roots.
2026-08-17 16:15:06 -07:00
Peter Steinberger 9de703e584 fix(plugins): surface invalid metadata manifests (#125117) 2026-08-17 16:14:01 -07:00
Josh Avant beebeac11d fix(gateway): restore external Tailscale Serve and Funnel proxies (#125412)
* fix(gateway): allow trusted external Tailscale routes

* fix(gateway): require auth for external Funnel

* docs(gateway): clarify external Funnel probe behavior
2026-08-17 16:01:35 -07:00
Peter Steinberger daafb2bf5c fix(agents): preserve migrated configured workspaces (#125435)
Amp-Thread-ID: https://ampcode.com/threads/T-01a00a6a-b64e-74a5-8b15-2d3b966a468d

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 15:54:15 -07:00
Peter Steinberger 6e458d84bf feat(agents): configure per-agent GitHub identities (#125199)
* feat(agents): add managed GitHub identities

* fix(agents): use opaque GitHub setup handles

* style(codex): format managed shell environment call

* refactor(agents): own managed GitHub process identity

* chore(config): refresh baseline after rebase

* fix(ci): satisfy managed GitHub identity gates

* fix(ci): repair managed GitHub identity checks

* test(agents): align GitHub identity CI coverage

* fix(codex): scope login shell isolation

* fix(agents): let managed gh profiles authenticate

* fix(agents): harden GitHub identity setup

* test(gateway): align method suffix counts

* fix(ui): serialize GitHub identity mutations

* fix(protocol): generate GitHub configure requests

* test(ui): restore timers after identity tests

* fix(ui): preserve GitHub identity mutation ownership

* fix(agents): preserve native GitHub CLI auth
2026-08-17 15:54:03 -07:00