Commit Graph

8010 Commits

Author SHA1 Message Date
Peter Steinberger 9924e2d7a7 feat(cli): prepare session-host onboarding (#125879)
* feat(cli): prepare session-host onboarding

* fix(cli): gate session-host installer capability
2026-08-18 16:08:48 -07:00
Peter Steinberger e8312171c1 fix: direct Gateway stops wait for active work (#126024)
* fix(gateway): drain active work on direct stop

* test(ui): isolate widget fetch retry mock
2026-08-18 15:29:52 -07:00
Peter Steinberger b34eb16071 fix(copilot): restore OpenClaw guidance to agent turns (#125997)
* fix(copilot): add OpenClaw prompt guidance

Copilot append-mode system messages included credential safety, workspace bootstrap, and extra context but omitted OpenClaw delegation and reply-delivery policy.

Build guidance from the final policy-filtered tool surface so visible delegated work, Skill Workshop, and source replies follow the same behavior as Codex.

* fix(copilot): break prompt guidance import cycle

The CI architecture gate detected a cycle through attempt-config and prompt-guidance. Isolate raw-run mode detection in a leaf module.
2026-08-18 15:01:15 -07:00
Onur Solmaz 5cabd2b72e Revert "fix(providers): report request acceptance consistently (#125807)" (#126021)
This reverts commit f5e9622fc9.
2026-08-19 00:16:09 +03:00
Onur Solmaz f5e9622fc9 fix(providers): report request acceptance consistently (#125807)
* fix(providers): report request acceptance consistently

* fix(providers): retain response hook compatibility

* fix(providers): keep legacy response hook path

* fix(providers): distinguish rejected response attempts

* fix(providers): keep acceptance evidence truthful

* fix(google): preserve provider acceptance errors

* test(google): satisfy acceptance callback lint

* fix(google): exclude acceptance hooks from retry deadline

* fix(openai): report Codex websocket acceptance

* fix(openai): commit websocket state before acceptance hook

* fix(google): abort pending acceptance callbacks

* fix(providers): abort pending acceptance callbacks

* fix(mistral): report observed HTTP response

* fix(mistral): report rejected HTTP responses

* fix(providers): derive acceptance from HTTP status

* fix(providers): preserve acceptance lifecycle cleanup

* fix(anthropic): report observed HTTP response

* fix(anthropic): report rejected HTTP responses

* fix(plugin-sdk): expose provider lifecycle

* fix(providers): stop after lifecycle abort

* fix(mistral): cancel unread acceptance failures
2026-08-18 23:50:57 +03:00
Peter Steinberger 347a0eaf8c feat(ui): activity feed automation grouping, live status, deep-link inspector (#125981)
* feat(ui): collapse automation sessions in activity feed

* feat(ui): show live run status on activity feed rows

* feat(ui): make run inspector deep-link only

* fix(ui): only link inspect run to a current active run

Addresses ClawSweeper P1: a stale observer digest could deep-link a live
row to an ended run's audit record; trust digest runId only when it is
still in activeRunIds.
2026-08-18 13:49:25 -07:00
Peter Steinberger d1a194b52f fix(gateway): refresh edited skills in agent RPC sessions (#125962)
* fix(gateway): watch skills for agent RPC turns

* ci: rebalance hosted agent chat shard
2026-08-18 13:06:48 -07:00
Peter Steinberger ab2bd4faa8 feat(ui): consolidate activity filters into toolbar with people popover (#125917)
* test(ui): seed mock activity sessions across owners

* feat(ui): consolidate activity filters into toolbar

Also restores the shared .input styling contract for standalone form controls.

* test(ui): update activity feed e2e for toolbar people popover
2026-08-18 11:41:06 -07:00
Peter Steinberger fead7fee27 refactor: consolidate small shared helpers (#125805)
* refactor: consolidate small shared helpers

* fix: reject inherited Parallels smoke arguments

* fix: preserve day-prefixed CPU probe times
2026-08-18 10:23:40 -07:00
Peter Steinberger f8ba65636c feat(control-ui): simplified settings experience for non-admin operators (#125492)
* test(control-ui): add --operator-scopes flag to the mock dev server

* feat(control-ui): simplified settings experience for non-admin operators

Non-admin browsers previously saw every settings page, many of which
dead-ended or rendered enabled controls whose RPCs fail with
'missing scope: operator.admin'.

- config.schema drops from operator.admin to operator.read: the schema is a
  static document describing options whose values are already readable via
  read-scoped config.get; admin-only schema only broke read-only settings
  rendering (Automation/Infrastructure/AI Agents/Communications showed
  'Schema unavailable. Use Raw.').
- Settings sidebar and settings search hide admin-only routes (custodian,
  labs, updates, automation, infrastructure, mcp, security, secrets,
  cloud-workers, communications, ai-agents, model-setup) for non-admin
  viewers; legacy gateways without advertised scopes keep the full UI.
- Channels, Devices, Worktrees, Memory Import, Profile gate their mutation
  controls on actual scopes with 'Browsing only…' notices instead of
  enabled-but-failing buttons; Devices no longer fires device.pair.list /
  exec.approvals.get without the scopes to call them (kills the two red
  error callouts on page load).
- Scope-upgrade banner: dismissing it in the guidance phase (no in-app
  upgrade path) now hides it fully instead of leaving a permanent chip.
- Config write coordinator surfaces scope refusals as a visible
  admin-required error instead of silently resolving false.

* test(control-ui): advertise config.schema in the mock dev gateway

ensureSchemaLoaded now checks method advertisement + scope before loading
the schema; the mock harness must advertise config.schema like a real
gateway does or schema-driven settings pages render empty in the mock.

* fix(control-ui): close the worktree create draft on scope downgrade

* perf(doctor): isolate memory health artifact

Doctor lint loaded the broad Memory Core API barrel only to register health checks and read isolated check IDs. That synchronously pulled the full memory public graph into the first lint run, consuming most of the 120-second test budget.

Load a dedicated doctor-health public artifact instead and verify it is packaged. The bisect boundary was 9de3ca5fc9 (#125571); because that commit only adds upgrade-test assets, it exposed a pre-existing runner-sensitive cost rather than introducing the expensive import path.

* test(control-ui): restore device lifecycle test boundary

* perf(control-ui): lazy-load settings sidebar

* fix(ui): recheck access after confirmations

* fix(control-ui): gate presence-driven device reloads on pairing access

The presence connectivity-change path still called device.pair.list without
operator.pairing, the same invariant the pair-event and poller paths already
guard; a limited browser got a doomed RPC on every connectivity change.

* fix(control-ui): fail open on schema loads for legacy scope-less gateways

canCallGatewayMethod hardened to strict advertisement+scope checks (#125478),
which made the new ensureSchemaLoaded gate silently skip config.schema for
legacy hellos without advertised scopes or a method list. Schema loads now
skip only on a definitive denial (method advertised absent, or advertised
scopes without operator.read), reusing the fail-open hasOperatorReadAccess
semantics the rest of the non-admin UI uses; regression test pins the
legacy snapshot path.

* test(control-ui): split schema-access coverage into its own file

runtime-config-capability.test.ts crossed the max-lines cap; the legacy
fail-open regression and its denial counterpart move to a colocated
schema-access test file.

* fix(scripts): keep mapped Vitest lanes at their measured no-output floor

The codex extension shard legitimately works in silence beyond 300s under
the default reporter (measured 61s import + 293s testing at ~95% CPU); the
CI-wide OPENCLAW_VITEST_NO_OUTPUT_TIMEOUT_MS=300000 env override shrank the
lane below that and the watchdog killed healthy runs, flipping with
incidental flake output (#125825). Per-config entries in
VITEST_CONFIG_NO_OUTPUT_TIMEOUT_MS now act as measured silence floors: a
global env value may widen a mapped lane's window but no longer shrinks it;
unmapped configs and the explicit '0' disable keep env verbatim. Adds the
codex extension lane to the map at the extra-long tier (same class as the
discord entry from #123025).
2026-08-18 10:15:10 -07:00
Peter Steinberger b9d0120ee2 fix(cli): protect immutable deployment artifacts (#125902) 2026-08-18 10:11:43 -07:00
Peter Steinberger b9d0e13b5d fix(agents): share one delegation policy across agent runtimes (#125892)
The `## Delegation` guidance added in #125691 lived only in
buildAgentSystemPrompt, so Codex-runtime agents never received it: the
Codex harness builds its own developer instructions in
extensions/codex/src/app-server/thread-prompt.ts and imports nothing
from the system-prompt builders. Live A/B on gpt-5.6-luna had the native
runtime answer "spawn a visible session" while the Codex runtime
answered "spawn a hidden subagent".

Move the policy into src/agents/delegation-guidance.ts, owning both the
main-session mode resolver and the section text, and export it through
the agent-harness plugin SDK barrel that the Codex harness already uses.
The hidden-delegation vocabulary is injected by each runtime, so core
never names a plugin-owned tool: native passes `sessions_spawn`, Codex
passes native `spawn_agent`. Visible sessions stay `sessions_spawn`
with visible=true on both runtimes because Codex-native children are
never OpenClaw sessions.

Also narrows the Codex line that told the model to use `sessions_spawn`
only for OpenClaw/ACP delegation; it now scopes that to internal
legwork, so user-facing deliverables still route to a visible session.
2026-08-18 09:57:52 -07:00
Peter Steinberger 9e24399e82 fix(ci): stop the codex lane hanging on a cold real-tool graph (#125864)
* fix(ci): stop codex lane cold-graph hangs

The side-question domain-policy test loaded the complete agent-harness tool graph inside a one-second readiness race, making the serial non-isolated Codex shard fail or stay silent under cold imports. Build the test's web_search marker and real web_fetch tool from the narrow implementation, then synchronize on turn startup before issuing the tool call. Cap each Codex test process at 12 files so CI gets bounded time-to-first-output as defense in depth.\n\nRefs #125839

* fix(test): keep codex web fetch fixture on sdk boundary

Load the real web_fetch factory on demand through the existing local-only plugin test runtime. This preserves the narrow cold-graph fix without letting a bundled plugin test reach into core internals.
2026-08-18 09:15:38 -07:00
Peter Steinberger 5f65ef8138 feat: add A2UI widgets to session boards (#125803)
* feat: add A2UI board widgets

* fix: harden A2UI board widget integration

* fix: repair A2UI CI contracts

* fix(canvas): keep native A2UI pushes on v0.8

* fix(canvas): support board-only widgets without file host
2026-08-18 09:08:45 -07:00
Dallin Romney 8de2679a5e test(release): preserve Codex follow-through finality (#125619)
* fix(ci): mark Codex follow-through progress non-final

* test(ci): assert Codex progress finality

* test(ci): align Codex follow-through assertion

* test(codex): accept explicit progress finality

* test(release): preserve frozen Codex finality
2026-08-18 08:53:48 -07:00
Dallin Romney f25f7429df test(release): redact shared failure diagnostics (#125697)
* test(release): use shared channel diagnostics

* fix(release): redact shared E2E failure logs

* test(release): configure redaction timeout fixture
2026-08-18 08:52:17 -07:00
Peter Steinberger 13e3d4535b fix(agents): finalize guided creation safely (#125768)
* fix(agents): finalize guided creation safely

Run channel post-write hooks only after config publication, defer portable auth copying until agent creation succeeds without overwriting newer credentials, and provision existing workspaces before publishing updates.

Keep JSON-only guided creation interactive while routing wizard output to stderr so stdout remains one machine-readable summary.

* fix(terminal): preserve note call signature

* fix(agents): pass committed config to setup hooks

* ci: split heavy codex changed-test shards

Cap non-isolated Codex extension processes at 20 files so 4-vCPU changed-target jobs do not starve real-time watches or hit the no-output watchdog.

* test(ci): align codex shard cap fixture

* docs(cli): clarify agents add JSON mode
2026-08-18 08:50:01 -07:00
Peter Steinberger 005a63f252 test: remove prompt snapshot facades (#124333) 2026-08-18 08:45:44 -07:00
Peter Steinberger c77feb00f3 feat(ui): move session filter to a global sidebar toolbar (#125690)
* feat(ui): promote session controls to toolbar

* test(ui): add session toolbar proof capture script

* chore: register session toolbar proof script

* test(ui): target ungrouped session drop zone

* fix(ui): trim session toolbar startup cost

* docs(ui): point new-session guide at the Sessions toolbar

Also name the accepted tradeoff for the inert ungrouped-collapse preference at the partition site (ClawSweeper P1/P3 response).

* test(ui): deflake new-session workspace-memory e2e

Menu-geometry assertions now measure relative to the picker anchor in one atomic evaluate (immune to unrelated page settles, still catches focus-induced moves). The post-reload refill raced the composer's async draft restore, which appended the stored draft to the typed text; waiting for the restored draft asserts the documented persistence instead. Failed CI shard checks-ui-e2e 5/12 on runs 32122284238 attempts 1-2.

* fix(ui): use canonical session owner filter state

* chore(ui): keep session toolbar proof artifacts ignored
2026-08-18 08:09:57 -07:00
Peter Steinberger 4048ae26e0 feat: credit linked session participants as Git co-authors (#125827)
* feat: credit linked session participants as co-authors

Authenticated profiles can link GitHub and receive automatic co-author credit in shared coding sessions.

* style: format rebased co-author registries

* fix: mark profile schema DDL boundary
2026-08-18 07:15:01 -07:00
Peter Steinberger 1ecd53fe27 fix(qa): handle zombie proc stats in upgrade survivor (#125829) 2026-08-18 06:58:16 -07:00
Peter Steinberger f886ab181e fix(ui): align session owner filtering terminology (#125645)
* fix(ui): align session owner filtering terminology

Owner filters now use owner terminology consistently across the Gateway, Control UI, and generated native protocol clients. The old terms were prerelease-only, so no migration or compatibility aliases are needed.

* fix(gateway): preserve creator provenance filtering

Keep creatorId scoped to immutable createdActor provenance while ownerId queries the current projected assignable owner. This preserves independent creator and responsibility filtering after reassignment.

* test(ui): wait for remembered draft before reload

CI exposed an IndexedDB draft-persistence race: the test reloaded before the write completed and then re-filled the message while restoration arrived. Wait on the canonical durable-draft helper before reload so the reload cannot race the write.

* fix(ui): keep session menus clear of hovercards

Horizontal sidebar previews were positioned from the inner link rect instead of the complete session row, allowing the hovercard to overlap trailing actions.

Anchor preview placement to the full row while preserving the link trigger and ownership flow so the session menu remains clickable.

* perf(ui): keep hovercard fix within startup budget

Use the sidebar direct-row invariant to anchor the hovercard outside trailing actions without a selector lookup. This preserves the fix without increasing the startup budget.

* fix(qa): preserve Matrix CLI timeout precedence

Keep the primary timeout operator-visible when descendant settlement also reports secondary cleanup trouble. Preserve the complete AggregateError as the public wrapper cause so settlement evidence remains inspectable.

* test(ui): isolate Markdown table clipboard boundary

With isolate:false, the shared module registry can retain clipboard imports before this test installs its module mock, leaving the spy disconnected from the production call.

Stub navigator.clipboard.writeText instead so the test exercises the real copyToClipboard boundary regardless of module load order, then restore the original descriptor.
2026-08-18 03:07:21 -07:00
Peter Steinberger 8a0d28d6ba refactor(qa): simplify scenario runner infrastructure (#125738) 2026-08-18 02:03:37 -07:00
Peter Steinberger 6ed136b22d fix(ui): restore mock chat startup (#125729) 2026-08-18 02:02:31 -07:00
Peter Steinberger ad475ce33a feat(gateway/ui): command-lane diagnostics with debug page table and global busyness overlay (#125591)
* feat(gateway): expose command lane diagnostics

* feat(ui): add live debug busyness overlay

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

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

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

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

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

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

* test(gateway/ui): register diagnostics.lanes in the 2026.8 train and mock it in the debug e2e
2026-08-18 01:10:32 -07:00
Peter Steinberger 475d20a034 fix(ui): stop the model picker from nagging about refresh failures (#125661)
* fix(ui): stop the model picker from nagging about refresh failures

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

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

Two adjacent simplifications in the same surface:

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

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

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

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

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

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

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

It adds a pinned-SHA git worktree and cold-compiles the audit and state
modules under tsx, which takes minutes on a contended runner. The 120s
default made it fail by construction; it timed out on an unrelated PR shard
while passing locally at ~55s.
2026-08-18 00:58:19 -07:00
Hannes Rudolph 34c3d15a6b fix(macos): complete Codex onboarding and model picker (#124829)
* fix(setup): refresh Codex registry with staged install

* fix(macos): verify inference before onboarding handoff

* fix(setup): use native Codex home for subscription auth

* fix(codex): honor attempt-scoped setup config

* fix(macos): align onboarding handoff with reopen

* fix(setup): await prepared model convergence

* fix(ui): avoid false auth state for empty catalog

* fix(setup): scope catalog convergence to Codex gateway

* fix(setup): publish the committed runtime catalog

* fix(models): project configured static runtime models

* fix(codex): expose app-server model catalog

* fix(models): preserve Codex auth across reloads

* fix(ci): align Codex onboarding checks

* test(ui): stabilize dock suppression environment

* fix(codex): honor discovery config in app-server model catalog

The manifest documents discovery.enabled (bundled fallback list) and
discovery.timeoutMs (default 2500ms) for model discovery; the new catalog
path used the generic 60s request timeout and ignored the enable gate.
Also drop the test-only listModels injection seam in favor of vi.mock.

* fix(setup): refuse prepared Codex auth over an explicit remote transport

configureCodexCliPreparedAuth silently rewrote an explicitly configured
websocket/unix app-server to local stdio (keeping a dangling url), moving
the credential boundary onto this host. Fail setup with actionable
guidance instead; also surface the root cause when the prepared model
catalog refresh fails after activation.

* refactor(agents): one canonical model-catalog identity key

Three near-identical key helpers existed (models-list-result,
models-list-configured-static, harness/model-catalog). Export
resolveModelCatalogIdentityKey from the route-policy owner, collapse the
duplicate dedupe loops into dedupeByKey, make donor enrichment Map-based,
and inline the one-off harness-augment wrapper.

* fix(macos): restore custodian handoff for fresh activations

Landing every finish on the plain dashboard stranded the custodian
first-run flow (memory import, channels, permissions, hatch). Fresh
activations now hand off to custodian onboarding; live-verified
pre-existing setups reopen the normal dashboard, matching the removed
already-configured shortcut. Tests pin the destination per path.

Also isolate the post-startup Codex login test from developer machines:
ambient OPENAI_API_KEY and a real Codex login made it assert-fail.

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-17 23:31:12 -07:00
Peter Steinberger b934625d80 fix(test): name Vitest unhandled errors instead of burying them (#125615)
* fix(test): surface Vitest unhandled errors

* fix(test): keep Vitest error helpers private
2026-08-17 22:49:19 -07:00
AmAzing- fc2529e229 fix(docker): preserve importer-resolved runtime dependencies (#125580)
Resolve retained dependency closures from each physical importer so Docker pruning preserves concurrent nested package versions required at runtime.

Add importer-bound regressions and a post-prune grammY import gate.

Co-authored-by: AmAzing129 <115673583+AmAzing129@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-18 11:14:48 +05:30
Peter Steinberger 603b0ec7f5 fix(macos): avoid elevation codesign metadata SIGPIPE (#125487)
* fix(macos): avoid elevation codesign metadata SIGPIPE

* fix(macos): preserve codesign metadata failures
2026-08-17 21:40:38 -07:00
Peter Steinberger 9de3ca5fc9 test(upgrade): add high-volume SQLite survivor (#125571)
Amp-Thread-ID: https://ampcode.com/threads/T-01a00a6a-b64e-74a5-8b15-2d3b966a468d

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

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

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

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

Missing package.json entry made the deadcode full-tree scan flag the
new capture script as an unused file, same as the existing
ui:proof:workboard sibling.
2026-08-17 21:09:17 -07:00
Peter Steinberger de41c7de8c fix(scripts): release the PR operation lock when review-init metadata fails (#125547)
The lock auto-releases only while the pre-side-effect validation marker is active; review_init marked side effects before the read-only metadata fetch, so a transient GitHub failure retained the lock and forced a lock-recover loop. The read-only fetch now runs before the marker.
2026-08-17 20:26:20 -07:00
Peter Steinberger 44b41d5686 fix(scripts): avoid false PR head changes during GitHub outages (#125517)
gh exit status was treated as proof that stdout held a PR object. The Octopool cache shim reports upstream 5xx responses as exit 0 with empty stdout, so reads now use a bounded-retry validation helper. Convert 9 of 28 gh pr view sites where an empty payload could produce a wrong decision.
2026-08-17 19:26:51 -07:00
Peter Steinberger 448eb41653 refactor(tooling): unify benchmark and process helpers (#125491)
* refactor(tooling): unify benchmark and process helpers

* test(tooling): harden process fixture readiness

* fix(tooling): keep benchmark harness types private
2026-08-17 19:08:22 -07:00
Peter Steinberger 75fcaba919 fix(voice-call): survive gateway in-process restart and stop CLI dead-ends (#125458)
* fix(voice-call): survive gateway in-process restart and stop CLI dead-ends

The gateway's in-process restart (SIGUSR1 config reload) reuses the cached
plugin registry, so service stop/start run on the same retained voice-call
registration. Generation fencing from #120289 treated that restart as a stale
actor: stop retired the generation forever, the next start silently bailed,
and every voicecall.* RPC answered UNAVAILABLE "runtime generation is
retired" while the webhook never rebound.

- Registrations now hold a replaceable generation: service start after stop
  mints a fresh generation, takes over a running slot owned by a retired
  predecessor, and reports start failures to service health instead of
  silently returning.
- The voicecall CLI classifies gateway failures with typed guards instead of
  message substrings: standalone/store fallback only when the gateway is
  genuinely absent; reachable-but-failed (request errors, auth, timeout)
  exits with actionable text; a standalone webhook port collision explains
  that a running Gateway probably owns the port instead of raw EADDRINUSE.
- Plugin SDK gateway-runtime exports structural isGatewayTransportError /
  isGatewayClientRequestError guards (+2 documented surface budget).
- Regression coverage: same-registration stop/start restart, retired-owner
  takeover, typed CLI fallback classification, and a real token-auth gateway
  server routing voicecall.status through callGatewayFromCli.

* refactor(voice-call): split CLI modules and dedupe gateway fallbacks

Collapse the four duplicated gateway-or-runtime command blocks (speak, dtmf,
end, continue fallback) into one generic runGatewayManagerCommand helper —
the continue command owns its legacy-method fallback and operation polling
via a gatewayCall closure, so the helper carries no per-command policy.
Smoke reuses the shared initiateVoiceCall path instead of a bespoke
fallback.

Split the 988-line cli.ts into concept modules (cli-gateway-call,
cli-call-log, cli-command-io) and drop its grandfathered max-lines
suppression plus the now-stale max-lines and assertion-safety baseline
entries (shrink-only ratchet maintenance).

Behavior-frozen: stdout/exit semantics unchanged; net -2 production LOC.

* fix(voice-call): redact gateway URLs in CLI operational errors

ClawSweeper P1: the operational-error formatter interpolated the raw
connectionDetails.url, so a configured gateway URL with userinfo or query
tokens would print credentials into terminal output. Redact the composed
message once with the canonical net-policy redactor (also covers
remote-controlled close-reason text), exported through the plugin SDK
gateway-runtime subpath (+1 documented surface budget). Regression test
covers a credential-bearing URL in both the URL and message fields.
2026-08-17 18:59:19 -07:00
Peter Steinberger b5b17c654b fix: keep Workboard visible in the sidebar (#125473)
* fix(ui): keep workboard in sidebar navigation

* test(ui): align workboard navigation ownership

* fix(ui): preserve saved workboard sidebar slots

* test(ui): shrink assertion safety baseline

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

* refactor(plugins): isolate native route policy
2026-08-17 18:44:39 -07:00
Peter Steinberger af599f2cf7 feat(android): render durable progress card in chat (#125444)
* feat(android): render durable progress card in chat

Remove Android consumption of the legacy stream:"plan" agent events and in-flight plan snapshots.\n\nHandle progressCard.changed through the durable progressCard.get store and remove the Android protocol coverage allowlist entry.

* fix(android): refetch progress card on unattributable poke

The changed event carries the server-derived observer scope key, which the
client only learns from a get response carrying a card. Before that, a
canonical-keyed poke (e.g. global session scope) failed both match checks and
was silently dropped until reconnect. Unknown attribution now triggers an
authoritative refetch instead.

* chore(i18n): refresh native source baseline for progress-card strings

* fix(android): render legacy plan events when the gateway lacks the progress-card store

Released gateways through v2026.7.x emit stream:"plan" events and do not advertise progressCard.get, so retain a negotiated Android fallback.

Remove this branch with the gateway legacy dual-emit after the minimum supported gateway ships the progress-card store.
2026-08-17 18:42:19 -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
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 e3de722971 refactor(tooling): consolidate baseline ratchets (#125459) 2026-08-17 17:17:49 -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 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
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 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
Peter Steinberger de9b367214 fix(ui): generic mock chat sends show a visible outcome (#125347)
* fix(ui): make generic mock chat sends observable

* test(ui): stabilize control UI e2e timing
2026-08-17 11:40:56 -07:00
Peter Steinberger 7170a6231a feat(agents): unify agent status into a durable progress_card (#125125)
* feat(agents): unify agent status into a durable progress_card

Replace the write-only update_plan to-do tool and the fragmented plan
rendering with one durable status artifact per session: progress_card
({plan?, markdown?}, replace-on-write, 8 KiB markdown / 50-step caps).
Cards persist in a lazy-additive session_progress_cards table in the
per-agent DB (no schema-version bump), broadcast progressCard.changed,
and render from the store with exactly one live placement per view
(session rail when visible, else the composer-adjacent bar); transcripts
collapse to one-line receipts, and the sidebar hovercard shows other
sessions' cards inline (markdown + <progress>, DOMPurify allowlist, no
iframes). The three stream-derived plan renderers and their dedup
heuristics are deleted.

Codex runs disable the native plan tool per thread
(tools.update_plan.enabled=false) and receive progress_card via the
dynamic-tool bridge; compaction restore now reinjects the card (steps +
bounded markdown). Card writes still emit the legacy plan stream event so
native apps and channels keep working until their per-platform
migrations. Policy names map update_plan -> progress_card; the shipped
tools.updatePlan=false kill switch is honored.

Net -277 production LOC; -480 test LOC.

* test(agents): regenerate Codex prompt snapshots for update_plan thread-config disable

* chore(protocol): allowlist progressCard.changed for native apps pending card migration

* fix(ci): repair progress card integration checks

* fix(codex): canonicalize native progress cards

* test(gateway): reconcile progress card method order

* test(codex): stabilize native approval fixture
2026-08-17 09:44:04 -07:00
Peter Steinberger 70ce8ea6f7 fix(pr): verify hosted commit membership locally (#125335)
One-time maintainer-authorized bootstrap landing for the exact reviewed head. This direct merge replaces the broken self-hosted verifier so subsequent pull requests can return to the native review, prepare, and merge workflow.
2026-08-17 09:41:13 -07:00
Peter Steinberger 49af98c12b fix(macos): avoid codesign metadata SIGPIPE (#125281) 2026-08-17 09:17:47 -07:00