Commit Graph

1568 Commits

Author SHA1 Message Date
Peter Steinberger 9b17b93414 refactor(ui): derive cron types from gateway protocol (#124827)
* refactor(ui): derive cron types from gateway protocol

* fix(protocol): preserve cron session target type
2026-08-16 14:34:26 -07:00
Peter Steinberger 0c6040eb14 fix(runners): align reclaim results with runtime (#124791)
* refactor(runners): prepare placement move targets

* fix(runners): preserve normalized dispatch targets

* style(protocol): format reclaim result type
2026-08-16 13:46:00 -07:00
Peter Steinberger 32f056f011 refactor(agents): persist directive facts at the assistant write boundary (#124793)
* refactor(agents): persist directive facts at the assistant write boundary

Assistant final text is now stripped of inline delivery directives once, at
the SessionManager append boundary, with the parsed facts persisted as a
typed openclawDelivery field on the assistant message (openclawDeliveryMirror
precedent, inside event_json — no schema change). Live session state is
replaced with the persisted canonical bytes so same-run continuations and
next-turn store rebuilds never diverge (prompt-cache invariant).

Delivery and restart recovery consume the stored facts instead of re-parsing
persisted text; pre-upgrade in-flight messages without facts intentionally get
no text-parse fallback (commented tradeoff at the read site). Directive
parsing is now code-region aware, so markers quoted in inline code or fences
neither parse nor strip — fixes the empty-code-pill display bug.

The undocumented reaction marker DSL ([[react:]], [[react_to_current:]]) is
deleted; structured message-tool reactions remain the canonical path. Stale
assertion-safety baseline entry removed with the parser.

Production net -10, tests net +38. Focused suites: 9,068 passed; pre-fix
regressions fail for the intended reasons. Codex autoreview clean.

* fix(agents): satisfy directive persistence gates

* fix(config): drop unused directive export

* fix(agents): preserve indented directive examples
2026-08-16 13:44:11 -07:00
Peter Steinberger 486b272e8c fix(ui): stop stale clients from acting connected (#124772)
* fix(ui): stop stale clients from acting connected

Carry reload metadata on terminal Control UI build rejections, render an explicit refresh-required recovery state, fence reconnect-only actions, and surface disconnected approval failures with accessible modal controls.

* fix(ui): preserve reconnecting session drafts

* fix(ui): preserve offline preference intent

* fix(ui): return owned fallback digest bytes

* test(ui): follow passive approval presentation

* fix(ui): distinguish stale builds from protocol mismatches

* style(ui): format gateway recovery phase
2026-08-16 13:38:09 -07:00
Peter Steinberger 568b920b21 feat(lint): enforce import ordering and deduplication (#124730)
* refactor(imports): dedupe and hoist imports

* feat(lint): enforce import/no-duplicates and import/first
2026-08-16 11:44:52 -07:00
Peter Steinberger aeff737da9 fix(agents): prevent invalid names from targeting the default agent (#124670)
* fix(agents): reject unrepresentable agent ids

* refactor(system-agent): split model selection setup

* chore: shrink assertion safety baseline

* docs: record strict agent id validation proof

* style: format strict agent id report

* chore: drop stray unrelated report artifact

* chore: restore REPORT.md to main state
2026-08-16 10:37:06 -07:00
Peter Steinberger 715c379fd9 refactor(config): consolidate context budget to one per-model knob (#124665)
* refactor(config): consolidate context budget settings

* test(config): type legacy context fixtures

* test(config): align context budget fixtures

* fix(status): honor runtime context discovery

* docs(config): clarify context budget fallbacks

* fix(ci): resolve context budget lint failures

* test(ci): align context budget shard fixtures

* fix(models): preserve catalog context metadata

* fix(config): surface context migration diagnostics

* test(plugin-sdk): keep live catalog coverage focused
2026-08-16 10:05:01 -07:00
Peter Steinberger 4d872fbfbc feat(nodes): expose installed worker bundle status (#124640)
* feat(nodes): expose installed worker bundle status

* perf(nodes): defer bundle status validation

* fix(nodes): tighten bundle status type contracts

* docs(gateway): document node worker bundle status

* refactor(gateway): split runner inventory runtime

* test(ui): keep healthy device status quiet

* fix(ui): preserve steer target ordering

* test(ui): isolate catalog handoff lifecycle
2026-08-16 10:04:46 -07:00
Peter Steinberger bdcc6836e0 refactor(gateway): retire the Control UI device-auth migration window (#124667)
* refactor(gateway): delete the retired Control UI device-auth migration window

The one-time remediation window for the retired
gateway.controlUi.dangerouslyDisableDeviceAuth break-glass threaded a pending
state machine through the connect pipeline, startup bootstrap, lifecycle,
request context, device management, security audit, the hello frame, and a
Control UI banner flow — steady-state runtime carrying a retired-shape shim
the architecture reserves for doctor. The window is closed: the retired key
is now fully inert, doctor still detects and removes it, and a browser that
never completed the migration pairs through the normal device flow (one
approval, no data loss).

Deleted with it: the config-machine-state import of the legacy flag, the
hello deviceAuthMigration field (optional; clients validate envelopes only,
so older gateways emitting it stay compatible), the migration-bound device
management authz states, the requireNoPairingCapableOperator approval mode,
the effective-operator pairing event emitter whose only subscriber was the
migration completion, and the Control UI banner, loader, overlay wiring,
i18n strings, and e2e scenario support. Swift and Kotlin protocol models
regenerated.

Live-verified on an isolated gateway with the retired key present in config:
clean boot with no migration warning, silent CLI pairing and silent local
scope widening unaffected, and doctor reporting the key as retired-and-inert.

Net -1111 production LOC.

* fix(ci): finish migration-window cleanup surfaced by the gates

The doctor migration for the retired key kept its "Preserved for remediation"
change text and describe; both now state plain removal, with the retired
tests updated. peekStoredDeviceIdentityId lost its only production consumer
with the deleted banner loader and is removed with its test mock. Also fixes
the unrelated no-unnecessary-boolean-literal-compare lint break that #124636
landed on main in scripts/check-changed.mts (truthiness is equivalent for the
boolean-or-undefined TTY probe).

* fix(ui): drop the retired-key device-auth reader from the security summary

Review findings on the migration-window removal: the Control UI security
summary still derived its "Device auth" row from the retired
dangerouslyDisableDeviceAuth key, rendering device auth as disabled on
configurations that merely retain the inert key. Device auth is now
unconditionally enforced, so the row and its derivation are removed rather
than pinned to a constant. The build-admission test also tracks and removes
its temporary device-identity databases after each run.
2026-08-16 09:39:15 -07:00
Peter Steinberger fa29984096 fix(cron): missing automations show recovery guidance (#124663)
* fix(cron): report missing automations as not found

* refactor(protocol): group gateway error exports
2026-08-16 09:25:03 -07:00
Peter Steinberger 9873b0f6ad feat(ui): named glyphs and custom emoji entry for session icons (#124629)
* feat(protocol): add named session icon glyphs

* feat(ui): add session glyph and custom emoji picker

* docs: describe named and custom session icons

* fix(ui): give the custom emoji input an accessible name

ClawSweeper P2: the input had no label relationship; assistive tech announced an unnamed edit control.

* fix(protocol): guard the v-flag icon regex for browser module loads

ClawSweeper P1: the picker's static import evaluates this module in the browser; pre-Unicode-Sets engines threw at module scope and took down the session menu. Lazy capability-guarded construction; such engines fall back to the grapheme heuristic as client pre-validation while the Gateway keeps exact RGI validation.
2026-08-16 07:55:31 -07:00
Peter Steinberger 99bda3d8cd refactor: make transport stream writer types honest (#124587)
* refactor(ai): give transport streams an honest writer type

* test(ai): use canonical transport stream fixtures

* fix(ai): preserve partial-less stream deltas
2026-08-16 07:03:36 -07:00
Peter Steinberger 9a555b6a9d fix(ai): preserve WebSocket response failure semantics (#124591) 2026-08-16 06:32:05 -07:00
Peter Steinberger 18d130fc1b fix(workers): bound node bundle retention (#124590)
* fix(workers): bound node bundle retention

* docs(runners): track bundle retention
2026-08-16 06:25:05 -07:00
Peter Steinberger 761203b7fe fix(compaction): bound the ratcheting file-operations summary lists (#124577)
formatFileOperations in agent-core joined every accumulated read/
modified path unbounded — and the lists ratchet: each compaction merges
the prior summary's file operations into the next accumulation, so a
long default-mode session (or branch summarization, which runs in every
mode) re-emitted an ever-growing path dump into each model-visible
summary with no cap, violating the context-budget invariant.

The safeguard extension already solved this with a bounded formatter
(900 chars/list, 2000 chars/section, '...and N more' overflow). Move
that implementation into the agent-core owner so compact(),
generateBranchSummary, and the safeguard all share one bounded
formatter, and delete the safeguard-local duplicate plus its constant
copies.
2026-08-16 06:11:39 -07:00
Peter Steinberger dbad5e385d refactor(workers): separate runner consent from capacity (#124356)
* refactor(workers): separate runner inventory state

* docs(runners): track inventory cleanup

* test(workers): use bundle-only launch wire

* test(workers): update optional inventory fixture

* test(workers): validate prewarm inventory capability

* fix(workers): version runner inventory cutover
2026-08-16 04:46:38 -07:00
Peter Steinberger 46f5951d53 fix(audit): reject filter combinations that cannot match (#124513) 2026-08-16 02:09:23 -07:00
Peter Steinberger f19f62cb77 perf(node-host): prewarm worker bundles (#124427)
* perf(node-host): prewarm worker bundles

* test(gateway): gate worker finalization responsiveness

* fix(node-host): negotiate bundle prewarming

* fix(protocol): refresh worker prewarm models

* fix(node-host): preserve prewarm upgrade compatibility
2026-08-16 00:41:42 -07:00
Peter Steinberger 6aa27d6ecd refactor: retire August compat windows (embedding API, pi aliases, target parser, spawning hook, setup exports, WhatsApp inbound aliases) (#124416)
* refactor(plugin-sdk): retire embedded Pi aliases

* refactor(channels): retire explicit target compatibility

* refactor(plugins): retire subagent spawning hook

* refactor(plugin-sdk): retire shipped channel setup exports

* refactor(whatsapp): retire inbound callback aliases

Proof: focused build and WhatsApp E2E green; broad WhatsApp suite 188/189 files green. extensions/whatsapp/src/monitor-inbox.policy.test.ts flakes only in the parallel batch and passes isolated (10/10).

* refactor(plugin-sdk): retire memory embedding registrar

Migrate every bundled provider and manifest to registerEmbeddingProvider and contracts.embeddingProviders. Preserve memory-specific batching, local-service acquisition, index identity, and auto-selection through the canonical generic registry adapter, then remove the parallel registrar, registry, diagnostics, contracts, tests, and docs.

* chore(plugin-sdk): tighten retired surface budgets

Pin the post-retirement public SDK surface to 144 entrypoints, 4,312 exports, 2,564 callable exports, and 1,133 deprecated exports; agent-harness-runtime now permits exactly nine deprecated exports.
2026-08-15 22:43:47 -07:00
Peter Steinberger 1384e277af refactor(types): enforce chained-assertion guard in AI and UI (#124361)
* refactor(types): drain chained-assertion ledger — ai and ui

* refactor(ui): extract chat state contract

* fix(ai): preserve strict Claude request cleanup

* test(ui): synchronize terminal timeout clock

* fix(ui): validate observer digest before run mutation
2026-08-15 22:25:42 -07:00
Vyctor H. Brzezowski f61ec66249 Preserve ClawHub external source identity and expose only supported actions (#124250)
* fix(skills): keep ClawHub search results on the source the operator picked

ClawHub search returns each result's origin under `install.reference`, but the
response model expected a flat `installRef`. That field is never present, so
every row fell through to a synthesized `@owner/slug` reference. External
skills.sh results were rewritten onto a ClawHub-native identity, dropping both
the commit-pinned source and the "not scanned by ClawHub" trust record.

Map the search wire shape explicitly and make the search contract
action-specific: `installRef` always names the result's own source, `detailRef`
appears only while ClawHub can serve a detail card for that identity, and
`trustState` travels with unscanned sources. Clients render install directly
when detail is absent instead of offering a review the Gateway must refuse.

Covers the Control UI, macOS, iOS Settings, iOS AgentPro, and Android, which
previously routed every row through review and could not install an external
skill at all.

* fix(skills): make install-only sources explicit and keep legacy review intact

Address review findings on the search identity contract:

- Replace the detail-reference capability with an explicit `installOnly` flag.
  A Gateway released before this field omits it, and reading omission as
  install-only made ordinary registry results skip the reviewed-version flow on
  every client. Absence now means the existing review-then-install path.
- Parse closed source variants in the producer. A row whose source is unknown,
  whose external reference is missing, or whose registry publisher is absent is
  dropped instead of falling through to `@owner/slug`, which was the original
  source swap in a different disguise.
- Carry the exact install reference alongside the canonical slug. The Gateway
  already records `requestedReference`; the clients dropped it and matched
  installs by slug, so a completed external install read back as unknown.
- Gate the direct-install action on admin rights. The row previously stayed
  enabled for read-only operators and reached a guard that silently returned.
- Route the unscanned-source warning through the native and Control UI string
  catalogs instead of a hardcoded literal.

* chore(i18n): leave generated native locale artifacts to the refresh workflow

Preflight isolates generated locale output from source changes: only the native
sources and apps/.i18n/native-source.json belong in a feature commit.

* fix(skills): satisfy Android ktlint wrapping and Swift test link construction

Extract the ClawHub result action guard into a named value so the multiline
condition follows ktlint wrapping, and pass the new requestedReference field in
the OpenClawKit installed-link fixtures.

* fix(skills): preserve external install identity across clients

* test(skills): add exact refs to recommendation fixtures

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-15 21:38:46 -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 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
Peter Steinberger e9d70a1169 perf(test): run hidden reasoning watchdog cases concurrently (#124330) 2026-08-15 18:29:02 -07:00
Peter Steinberger 78502eda6d feat(workers): run device sessions from Gateway bundles (#124037)
* feat(workers): run device sessions from Gateway bundles

Install the current Gateway bundle before a device environment becomes ready, verify it at attach and tunnel boundaries, launch only from the immutable namespaced bundle directory, and retire stale environments for idempotent reprovisioning. Remove the local execution mode and preserve the node-local build claim only as temporary inventory metadata for the final projection/cleanup slice.

* docs(runners): record Gateway bundle cutover

* test(ci): repair runner validation fixtures

# Conflicts:
#	src/scripts/test-projects.test.ts

* fix(workers): surface outdated node recovery

Keep legacy runner inventory diagnostic-only while exposing the update-and-reconnect action through node, environment, provider, placement, and Control UI surfaces.

* fix(workers): reject legacy inventory with recovery

* fix(workers): bundle worker deploy closure

* test(workers): close bundle cutover gates

* fix(workers): compose browser runtime at build

* fix(workers): satisfy bundle cutover gates

* fix(workers): route temp runtime through infra

* docs(workers): align bundle host guidance

* fix(ui): fence outdated session destinations
2026-08-15 17:46:44 -07:00
Josh Lehman de23bf1893 test: repair worker environment E2E fixtures (#124202) 2026-08-15 09:57:02 -07:00
Peter Steinberger f4a047b87c test: trim residual subset assertions (#124203) 2026-08-15 09:11:36 -07:00
Peter Steinberger aad64693ba test: remove redundant subset assertions (#124198) 2026-08-15 08:57:45 -07:00
WhatsSkiLL 632581477f fix(session-catalog): preserve explicit agent ownership across UI and CLI (#123899)
* fix(session-catalog): preserve explicit agent ownership across UI and CLI

* fix(session-catalog): repair owner routing regressions

* Fix-session-catalog-CI-checks

* test(ui): split chat catalog pane coverage

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>

* refactor(session-catalog): bind Codex homes per request

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>

* refactor(session-catalog): centralize owner resolution

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>

* fix(codex): resolve session fork against the adopted home

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>

* refactor(ui): extract chat session discussion

* test(sessions): stabilize archive worker responsiveness check

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-15 04:47:28 -07:00
Peter Steinberger 447393dc32 test(core): remove residual duplicate assertions (#124116) 2026-08-15 02:06:44 -07:00
Peter Steinberger aaa509b26e refactor(types): remove chained type assertions in core and ui (#124073)
* refactor(types): remove chained assertions in core and ui

* fix(types): preserve legacy cron migration identity

* fix(types): preserve settings patch key types
2026-08-15 01:32:04 -07:00
Peter Steinberger 52adbf4c60 fix(acp): cancel pending prompts when the bridge shuts down (AI-assisted) (#124068)
* fix(acp): cancel pending prompts on shutdown

ACP shutdown now aborts accepted Gateway runs and releases bridge session state rather than leaving prompts pending.

* fix(acp): preserve injected store ownership

Keep caller-provided ACP session stores generic while disposing only the concrete store created by the agent.
2026-08-15 00:45:42 -07:00
Peter Steinberger d2be00e171 feat(ui): persistent emoji session icons in the sidebar (#124034)
* feat(gateway): persist emoji session icons

* feat(ui): add persistent session icon menu

* docs: explain persistent session icons

* docs: list Set icon in the session context menu enumeration

* test(gateway): canonicalize group defaults workspace path

* fix(ci): sync session icon protocol coverage

* fix(sessions): enforce RGI emoji sequences for session icons

ClawSweeper P2: single non-emoji graphemes like 漢 passed the segmenter-based predicate. Anchored \p{RGI_Emoji} admits exactly one interchange emoji sequence and deletes the length cap and ASCII carve-out.

* fix(sessions): compile RGI emoji validation
2026-08-15 00:15:55 -07:00
Patrick Erichsen f6359140f1 fix(ui): show skill titles in chat reference picker (#124017)
* fix(ui): use skill names for chat references

* fix(ui): show skill titles in reference picker
2026-08-14 23:39:02 -07:00
Peter Steinberger 9050ff0e9e test(acp): remove cleanup-only session seam (#124043)
* test(acp): remove cleanup-only session seam

* test(infra): stabilize routing and PID readiness

* test(gateway): synchronize post-rejection frame proof
2026-08-14 23:26:33 -07:00
Jesse Merhi edb5adfbf5 Start new sessions with folder group defaults (#123276)
* feat(ui): add folder group session defaults

* fix(ci): align folder group contracts

* fix(protocol): refresh Android gateway methods

* fix(ui): reuse folder picker for group defaults

* fix(ui): harden session group defaults

* test(ui): align group defaults with current main

* test(ui): keep group catalog defaults path-free

* fix(ui): close folder group CI gaps

* fix(ui): satisfy folder group CI contracts

* fix(session-groups): enforce defaults safety

* test(gateway): keep group defaults in workspace

* fix(session-groups): enforce defaults participation

* fix(session-groups): close review authorization races

* fix(session-groups): canonicalize defaults authorization

---------

Co-authored-by: Jesse Merhi <jesse-merhi@users.noreply.github.com>
Co-authored-by: Jesse Merhi <openclaw@users.noreply.github.com>
2026-08-15 15:24:13 +10:00
Jesse Merhi 47442197a1 feat(ui): review install policy warnings (#120900)
* feat(ui): review install policy warnings

* fix(ui): keep install feedback on runtime plugin
2026-08-15 13:07:02 +10:00
Peter Steinberger 86f38f7c8f fix(terminal): shrink widest flex table columns first (#123934) 2026-08-14 19:32:08 -07:00
Peter Steinberger d8cd661517 fix(gateway): keep supervised restarts from migrating live state (#123920)
* fix(gateway): fence supervised restart schema ownership

* fix(gateway): target supervised safe restarts

* chore: leave changelog to release automation

* fix(gateway): satisfy restart control checks
2026-08-14 19:31:15 -07:00
Peter Steinberger 0982ee5729 perf(ui): reduce startup connect error overhead (#123910) 2026-08-14 18:07:20 -07:00
Peter Steinberger 7f891f4a78 fix(ui): stale tabs keep dispatching after gateway updates (#123882)
* fix(ui): reject stale bundled clients at connect

* chore: keep release notes out of runtime fix

* fix(ui): preserve stale-build admission invariants
2026-08-14 17:05:10 -07:00
Peter Steinberger 0a6b95a3df feat: cloud workers for the codex runtime (remote-exec placements) (#123743)
* feat(gateway): add remote-exec cloud placements

* feat(codex): run cloud turns through remote exec

* fix(sandbox): quote ssh_config path directives containing whitespace

Crabbox lease keys default to ~/Library/Application Support/... on macOS;
unquoted IdentityFile/UserKnownHostsFile/CertificateFile arguments tokenize
on the space and fail as 'extra arguments'. Found via live remote-exec
cloud-worker proof.

* test: consolidate gateway maintenance schedule coverage

* fix(ci): invalidate plugin sdk declarations on state changes
2026-08-14 16:46:56 -07:00
Peter Steinberger 1cf932295c refactor(ui): trim pairing uncertainty state (#123856)
* refactor(ui): trim pairing uncertainty state

* test(ui): stabilize navigation and worker readiness

* test(ui): drop popover flip geometry replay
2026-08-14 16:16:57 -07:00
ClawSweeper c12745429a fix(ui): fork active sessions from stable history (#123718)
* fix(ui): fork active sessions from stable history

* fix(protocol): align active fork types

* test(ui): match main-session fork routing

* fix(sessions): unify stable fork admission

* fix(native): fork active sessions from stable history

* fix(android): fork active sessions from stable history

* style(android): simplify active fork result handling

* fix(native): preserve legacy fork transport API

* test(native): complete legacy fork transport stub

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-14 14:13:25 -07:00
Peter Steinberger bf70d5ddb6 refactor(ai): remove Responses replay test seams (#123825) 2026-08-14 14:05:36 -07:00
Peter Steinberger 58ab589da5 fix(ui): stale tabs restore terminals without owners (#123660)
* fix(ui): fence stale same-version clients by build

* test(ui): satisfy build identity lint guards

* fix(ui): complete build identity fencing

* chore: leave release notes to release prep

* test(ui): align build identity fixtures

* fix(ui): fence reconnects on pending worker

* test(ui): stabilize cross-platform update proof

* test(ui): satisfy service worker lint

* test(ui): preserve offline socket cohorts
2026-08-14 13:19:02 -07:00
Peter Steinberger 17eb646bb3 refactor(ai): consolidate Responses replay paths (#123762)
* refactor(ai): consolidate Responses replay ownership

* refactor(codex): consolidate completion plumbing

* refactor(agents): centralize replay pairing repair

* refactor: preserve replay static contracts
2026-08-14 11:20:57 -07:00
Vyctor H. Brzezowski 3f006ba0fc fix(ui): complete mobile pairing after code redemption (#120933)
* fix(ui): complete pairing setup lifecycle

Redeemed and expired mobile setup codes stayed on screen as usable QR
codes, so a successful pairing had no visible outcome and expired bearer
material still looked live.

The Gateway now mints an opaque, non-authorizing setupId beside each
setup credential, returns its authoritative expiresAtMs, records the
terminal outcome of the exact redemption, and broadcasts
device.pair.setup.completed. Because that broadcast is dropped for
buffered operator sockets, the completion is persisted first and can be
reconciled through the new device.pair.setupStatus method: the Control UI
asks for the recorded outcome before it may present a credential as
expired, so a pairing that succeeds is never shown as a failure.

The Control UI models one closed lifecycle (selection, loading, waiting,
success, expired, error) correlated only by the active setupId, and
Pairing help now carries the external-link affordance.

* fix(ui): preserve unknown pairing outcomes

* test(ui): target pairing terminal headings

* test(ui): align pairing completion fixture

* fix(gateway-protocol): decode setup-code results from older gateways

Older protocol-v4 gateways omit the new setupId and expiresAtMs
lifecycle fields, so requiring them in the generated native model broke
decoding an existing device.pair.setupCode response. Keep both optional
at the wire boundary, require lifecycle metadata before the Control UI
enters its waiting state so a missing outcome stays visible, and cover
the legacy payload with Swift and schema regressions.

* fix(ui): surface rejected pairing dialog loads

The lazy pairing chunk could reject while its overlay was already open,
leaving the shell rendering nothing at all. Record the rejection on the
shell and render a recoverable modal with a reason and a retry so the
open action always ends in a visible outcome.

* fix(state): preserve pairing setup schema compatibility

* test(gateway): cover pairing setup release train

* fix(gateway): commit pairing setup completion atomically

* refactor(state): distinguish setup transaction helpers

* refactor(state): remove obsolete bootstrap restore path

* fix(gateway): preserve setup handoff type safety

* fix(gateway): keep pairing completion terminal after consume

* fix(gateway): validate Watch binding during setup commit

* fix(gateway): revalidate setup credential expiry at commit

* chore: refresh Plugin SDK API contracts after rebase

* fix(pairing): prune expired setup completions

* chore: retrigger CI

* fix(protocol): deduplicate setup expiry field

* fix(protocol): refresh pairing setup clients

* fix(gateway): make pairing setup completion durable

* fix(ui): retire expired pairing credentials immediately

* fix(ui): keep pairing dialog visible while loading

* fix(macos): align setup result initializer order

* fix(gateway): restore generic bootstrap retries

* chore(ui): record pairing startup budget

* chore(ui): refresh pairing startup budget

* style(gateway): format maintenance imports

* test(gateway): cover session-sharing mock

* fix(state): defer setup correlation schema

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-14 11:10:30 -07:00
Peter Steinberger c3887db7c1 feat: compact xAI sessions server-side (AI-assisted) (#123622)
* feat: add xAI Responses compact endpoint

* docs: explain xAI server-side compaction

* refactor: persist server compaction via session manager

* refactor: simplify server compaction results

* fix: preserve server compaction result kind

* test: satisfy server compaction CI contracts

* fix(xai): prepare server compaction requests

* refactor(ai): extract prepared compaction request

* fix(xai): preserve compaction fallback semantics

* test(xai): use the stream function type owner

* fix(xai): enable compact endpoint for provider alias
2026-08-14 07:02:47 -07:00
Peter Steinberger 7c579abf06 fix(cli): approval listings no longer execute stored terminal escapes (#123671)
* fix(cli): sanitize approval table values

* test(cli): avoid control regex in approval safety check
2026-08-14 06:46:45 -07:00