Commit Graph

2143 Commits

Author SHA1 Message Date
Peter Steinberger 99bf0b1f3b fix: preserve cloud workspace results across tunnel reconnects (#124406)
* fix: preserve workspace reconcile across tunnel reconnect

* fix: preserve reconcile before stateful tunnel dispatch

* fix: close reconnect pre-dispatch races

* style: satisfy reconnect gate lint

* test: align workspace action fixture
2026-08-15 23:11:11 -07:00
Peter Steinberger 717f77678a refactor(heartbeat): delete unreachable prompt-null skip and dead lanes-busy surface (#124385)
resolveHeartbeatRunPrompt can no longer return prompt: null — the only
null producer (inferred commitments follow-ups) was deleted in
4b0151682e — so the two not-due short-circuits in
heartbeat-runner-execution.ts were dead branches. Narrow the resolution
type to string and delete both consumers.

HEARTBEAT_SKIP_LANES_BUSY had no remaining producer and
HeartbeatDeps.getCommandLaneSnapshots no prod reader (the per-lane busy
check was consolidated into requests-in-flight admission). Delete the
constant, the dep, and the tests that only exercised the dead seam;
retarget the retry-simulation tests at live retryable reasons and drop
the stale lanes-busy mention from the troubleshooting doc.
2026-08-15 20:48:00 -07:00
Vito Cappello 7f93011562 fix: preserve Claude CLI prompt cache reuse across turns (#124300)
* fix: keep claude-cli prompt-cache prefix stable across turns

Claude CLI has no cache_control breakpoint, so mashed per-turn system
prompts rewrote the native prefix and burned cache hits on follow-ups.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(cli): scope Claude prompt cache suffix

* docs: scope Claude CLI cache guidance

* test(cli): cover Claude cache prompt modes

* fix: gate Claude CLI prompt cache flag

* docs: clarify Claude CLI cache flag gate

* fix: preserve Claude CLI system prompt roles

* fix(claude-cli): close cache flag compatibility gaps

* fix(claude-cli): reject prerelease cache flag versions

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-15 18:17:17 -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
ClawSweeper 4c55629238 feat(sessions): preserve recent session history (#123987)
Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-15 16:25:31 -06:00
Peter Steinberger 3109bc3b5d fix(gateway): restart after prepared maintenance suspension (#124157)
* fix(gateway): hand off prepared suspension to restart

* chore: keep release changelog owner-managed
2026-08-15 04:53:38 -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
Peter Steinberger 6e5bf3ec55 fix(doctor): stop false failures on multi-agent profiles (#124010)
* fix(doctor): resolve multi-agent health owners

* fix(doctor): keep bare json exit advisory
2026-08-14 21:45:55 -07: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
Dallin Romney a01d40bfb9 fix(sessions): honor total entry cap with protected history (#123081)
* fix(sessions): count protected rows toward entry cap

* perf(sessions): defer maintenance snapshot loading

* test(sessions): assert total maintenance cap

* fix(sessions): align warning preservation

* fix(sessions): guard malformed maintenance rows
2026-08-15 08:03:57 +08: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
Colin Johnson 722e1ff48e fix(sessions): honor explicit legacy owner (#123887) 2026-08-14 19:44:34 -04: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
Jesse Merhi bf40269cb7 feat(security): require acknowledgement for policy warnings (#116489) 2026-08-15 03:58:45 +10:00
ClawSweeper e03d1a42f8 improve(ui): collapse limited access notice (#123735)
* improve(ui): collapse limited access notice

* test(ui): follow limited access banner host

* test(ui): await limited access guidance host

* test(compaction): split context budget coverage

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-14 10:25:28 -07:00
Vito Cappello f5c46de8ac fix(compaction): allow Claude CLI sessions to compact without API keys (#120496)
* fix(compaction): route manual CLI compaction natively

* fix(compaction): harden native CLI control operations

* fix(compaction): honor Claude native completion signals

* chore(plugin-sdk): refresh API baseline

* test(compaction): assert native session binding

* fix(compaction): preserve control session reuse

* fix(plugin-sdk): preserve boolean compaction ownership

* fix(agents): preserve native compaction ownership

* fix(compaction): bypass model auth for native control

* test(compaction): isolate authless control fixture

* test(compaction): isolate auth bypass regression

* fix(compaction): bypass generic auth for native CLI control

* fix(compaction): preserve native rejection failover

* test(compaction): isolate native queue regressions

* test(compaction): prevent native auth mock leakage

* fix(cli): isolate control operations from skill env

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-14 09:30:15 -07:00
Josh Avant 97a53a9b35 feat: audit admitted channel participant identity (#122863)
* feat: audit admitted channel participant identity

* fix: preserve Telegram identity through thread recovery

* fix: signal held gateway process groups

* fix: keep audit evidence passive in collect routing

* fix: validate copied channel participant evidence

* fix: bind channel participant evidence to host ingress

* fix: honor Telegram proof credential roles

* fix: restart held Telegram proof through gateway

* fix: repair channel identity CI regressions

* test(matrix): bind thread routing owner

* fix: preserve direct DM SDK compatibility

* fix: bind channel provenance at host runtime

* test(feishu): provide channel context builder

* fix: defer record-bound channel runtime resolution

* fix: keep channel admission evidence core-private

* fix(audit): bind channel admission to plugin lifecycle

* fix(audit): bind ingress provenance to final context

* refactor(audit): split admission scope keys

* test(queue): cover combined metadata carriers

* refactor(audit): keep lifecycle helpers private

* fix(queue): preserve combined turn authority

* test(channels): provide ingress context builders

* test(channels): align integrated CI fixtures

* test(clickclack): resolve model-loop ingress

* docs: preserve channel participant evidence invariant
2026-08-14 08:57:01 -05:00
Peter Steinberger ad6bc6d3ae fix(delivery): keep failed queue rows payload-free (#123642)
* refactor(delivery): collapse failed-row lifecycle

Replace the unshipped failure-operations platform with payload-free terminal receipts owned by existing queue boundaries. Keep bounded/permanent idempotency only for reusable or crash-ambiguous producers, move physical expiry to queue maintenance, and preserve migration and media-cleanup safety.\n\nTogether with #123410, production code is net negative by 11 lines; tests, docs, and generated protocol mirrors are accounted separately.

* fix(delivery): break state DB import cycle

* fix(delivery): classify SQLite boundary uses

* test(gateway): mark retained health fixture
2026-08-14 06:22:51 -07:00
Peter Steinberger e6eebc5ad8 feat(agents): un-reserve literal main (#123609)
* feat(agents): un-reserve literal main

* fix(agents): scan legacy sessions before reusing main
2026-08-14 04:23:19 -07:00
Peter Steinberger 2a77e6e5a0 feat(onboard): named first agent (#123521)
* feat(onboard): named first agent

* fix(onboard): harden named-agent handoff

* test(onboard): preserve authored roster provenance

* test(gateway): restore authorized steering coverage

* fix(onboard): report imported roster name conflicts
2026-08-14 02:54:55 -07:00
Peter Steinberger c0930de5de fix(secrets): scope egress sentinels to Gateway and survive client tunnel resets (#123527)
* fix(secrets): scope exec egress proxy to gateway

* fix(secrets): keep a client reset from crashing the egress proxy host
2026-08-14 01:56:29 -07:00
Peter Steinberger 7cadfb0bd6 fix: speed up local node launches and isolate scratch state (#123503)
* perf(node-host): reuse advertised worker build identity

* fix(agents): keep default workspaces inside state dir

* fix(plugins): package llama.cpp private SSRF runtime

* fix(node-host): silence missing skills directory
2026-08-13 23:24:54 -07:00
Peter Steinberger 7026cf2f21 fix(delivery): bound failed-row retention lifecycle (#123410) 2026-08-13 22:03:33 -07:00
Peter Steinberger 928942d48d feat(sessions): legacy-main session migration engine (#123424)
* feat(sessions): add legacy main migration engine

* fix(sessions): keep migration types internal

* fix(sessions): harden legacy main migration convergence

* fix(sessions): prefer stale migration claims over lock errors

* fix(sessions): keep unresolved owner notices nonblocking
2026-08-13 21:33:37 -07:00
Peter Steinberger 25d4807b38 feat(anthropic): opt-in server-side compaction (compact-2026-01-12) (#123402)
* feat(anthropic): add server-side compaction replay

* docs(anthropic): document server compaction

* test(anthropic): harden compaction live probe

Fix the live fixture baseUrl (the SDK appends /v1 itself), fail fast on
errored turns instead of silently looping, assert request-side injection
before capture, and log per-turn stream outcomes for live debugging.

* test(anthropic): keep live settings type module-local

* refactor(agents): split transcript replay sanitizers

* test(anthropic): move compaction live probe into plugin tree

* refactor(anthropic): consolidate compaction replay duplication

* test(anthropic): align compaction threshold host coverage

* test(anthropic): fabricate checkpoints via capture tracker

Keeps captureAnthropicCompaction module-local; knip flags exports whose
only consumers are tests.
2026-08-13 21:28:19 -07:00
Peter Steinberger b9c6789560 feat(secrets): authenticated egress substitution proxy with destination binding (#123216)
* feat(secrets): add authenticated egress substitution proxy

* feat(secrets): bind egress substitution to hosts

* ci(codeql): classify egress proxy bypass tunnel in network boundary query

* refactor(proxy-capture): use the canonical IP parser instead of node:net

* fix(secrets): compare proxy tokens with a process-keyed MAC
2026-08-13 20:49:31 -07:00
Peter Steinberger 575467aa58 fix(openai): unify server-side compaction gates and harden compaction recovery (#123397)
* fix(openai): unify server compaction policy

* fix(openai): preserve managed responses aliases

* fix(compaction): harden bounded recovery

* refactor(compaction): simplify orphan output classifier

* fix(compaction): unanchor overflow classifiers and route image constant through runtime facade

* test(openai): use provider input config in compaction parity

* test(openai): model default compaction route accurately

* fix(openai): isolate responses payload policy imports

* fix(ai): remove unused responses api re-export

* fix(plugins): resolve responses policy source alias
2026-08-13 20:45:07 -07:00
Peter Steinberger 1348387076 refactor(plugins): replace node-llama-cpp with managed llama-server (#123105)
Move llama.cpp chat and local embeddings onto a verified externally managed llama-server runtime. Remove the in-process native runtime, forked embedding workers, and node-llama-cpp dependency while preserving guided setup, local GGUF models, tool-capable agent runs, diagnostics, and operator docs.
2026-08-13 16:58:20 -07:00
joshavant 639e7718f3 fix(models): preserve refresh generation and fallback 2026-08-13 18:57:50 -05:00
joshavant d83f7b815d fix(models): defer live catalog discovery 2026-08-13 18:57:50 -05:00
Peter Steinberger 927a97c1ea fix: keep automation delivery owned in multi-agent fleets (#123283)
* fix: preserve automation owner during channel bootstrap

* fix: retain scoped runtime during cron delivery

* style: format cron delivery regression

* chore: defer release changelog entry
2026-08-13 12:52:34 -07:00
Peter Steinberger 21d59e16e2 feat(gateway): monitor cloud session disk space (#123177)
* feat(gateway): monitor cloud session disk space

* fix(gateway): keep disk monitor contract acyclic
2026-08-13 12:47:53 -07:00
Peter Steinberger b233ea7957 fix(health): surface blocked ingress lanes (#123234) 2026-08-13 12:44:59 -07:00
Peter Steinberger 2278ca6952 feat(ui): click the desktop to take control (#123096)
* feat(ui): click the desktop to take control

View-only desktop connections now escalate to control by clicking
anywhere on the desktop stage (transparent overlay button, keyboard
accessible, same 'Take control' accessible name). The toolbar button is
removed; the connecting status overlay becomes click-through so control
can still be requested mid-connect.

* fix(ui): use cursor-action token for desktop take-control overlay

* test(ui): prove take-control click above a real noVNC surface

In-page RFB 3.8 fake server (security None) lets the production
DesktopClient drive the real noVNC client; the overlay click must
hit-test above the mounted canvas and reconnect with control.

* fix(ui): narrow fake RFB socket payload to ArrayBuffer-backed bytes
2026-08-13 03:07:11 -07:00
Peter Steinberger 93ebdfa8e0 docs(gateway): document portal tool gating and tighten its description (#123091)
* docs(gateway): document portal tool gating and tighten its description

Portals need no dedicated config key, but nothing said so: add an
availability section covering the coding-profile/group:ui default,
sandbox and owner-only gating, tools.deny recipes, and the fact that
portal listeners inherit the Gateway bind interfaces. The group:ui
roster in config-tools was also missing portal and dashboard.

The tool description named the exec tool, which repo policy forbids
because gating can remove it and leave a dangling reference; it now
states the capability instead, and is ~18% shorter.

* docs(gateway): use the global tools policy for the fleet-wide portal deny

The canonical fleet-wide knob is top-level tools.deny, not the agent
defaults layer; match the json5 style the tools docs already use.
2026-08-13 02:38:24 -07:00
Peter Steinberger cc2fc55f9b feat: portals — expose agent-run dev servers to the operator (#122536)
* feat(protocol): add portal methods and event

Bump the reviewed protocol owner-module count from 55 to 56.

* feat(gateway): add portal service and reverse proxy

* feat(agents): add portal tool

* fix(gateway): refine portal URL and proxy auth

* refactor(gateway): keep portal helper types private

* fix(gateway): declare portal transport service

* test(gateway): satisfy portal proxy lint

* test(gateway): narrow websocket payload types

* refactor(protocol): compact portal schema exports

* fix(gateway): export portal protocol types

* feat(ui): add portals page

* docs(gateway): add portals guide

* fix(gateway): dial portal targets via localhost dual-stack

Vite and other Node >=17 dev servers bind ::1 only for localhost, so a
fixed 127.0.0.1 dial 502s on the default path. Use hostname localhost
with family autoselection and rewrite Host to match.

* fix(gateway): type portal dual-stack connection

* fix: satisfy portal integration gates

* fix(gateway): isolate portal cookie jars per target

Cookies are hostname-scoped, not port-scoped, so the per-port origin
split alone let Gateway plugin-auth cookies reach agent-run targets.
Forward only cookies carrying this portal's own name prefix (stripped),
rewrite target Set-Cookie names to the prefixed form incl. the WS 101
handshake, and drop Domain attributes.

* fix(ui): detect unreachable portals behind proxied gateways

Probe the portal origin from the browser (no-cors, 4s timeout) and show
a recovery notice with the gateway-host URL instead of a dead iframe
when only the gateway port is exposed (Serve/Funnel/reverse proxy).
Docs: cookie isolation + reachability; zh-CN glossary entry.

* test(ui): satisfy portal reachability lint

* test(gateway): provide control UI request hosts

* chore(protocol): regenerate after rebase

* fix(gateway): namespace portal auth cookies by listener

* fix(gateway): scope portal token URLs to write-capable clients

The portal bearer token rides in the summary url/tokenQuery; portal.list
is operator.read and portal.changed fans out to read subscribers, so a
read-only client could harvest an openable URL. Make those fields
optional, redact them from read-scope list responses, and drop them from
every portal.changed broadcast; write/admin clients still receive them
and the UI refetches the list on change.

* docs(web): list the portals route

* fix(gateway): type portal open credentials

* docs(gateway): clarify portals PORT/PUBLIC_URL are agent-set

Opening a portal creates only the proxy listener; the agent sets PORT
and PUBLIC_URL in its own exec command, matching the portal tool
contract. Removes the implication of an automatic env handoff.

* chore(protocol): regenerate portal models

* style(gateway): format portal method-order assertions

Rebase union-merge left the portal.list assertion wrapped; oxfmt fits it
on one line.

* chore(plugin-sdk): refresh API baseline after rebase

* chore(plugin-sdk): refresh API baseline after rebase

* chore(protocol): refresh portal event order after rebase

* chore(plugin-sdk): refresh API baseline after rebase

* fix(gateway): pin portal referrer policy to no-referrer

The portal URL carries its bearer token in the query, and upstream
response headers are copied verbatim, so a target answering with
Referrer-Policy: unsafe-url could leak that URL to every third-party
origin it references. Force no-referrer after the copy and drop any
inbound Referer that still carries the token before forwarding.
2026-08-13 00:46:11 -07:00
Dallin Romney 4afccbdaa4 fix(sessions): exclude protected sessions from entry cap (#123014) 2026-08-13 15:42:55 +08:00
Sarah Fortune 3f731db90c fix(slack): accept org-wide user IDs in Enterprise Grid policies (#122934)
* test(slack): accept org-wide enterprise users

* fix(slack): allow org-wide enterprise users

* style(slack): format enterprise user policy

* test(slack): preserve enterprise user identity scope

* fix(slack): preserve enterprise user identity scope

* fix(slack): import workspace identity normalizer

* fix(slack): normalize enterprise owner ids

---------

Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
2026-08-12 21:01:05 -07:00
Peter Steinberger e45a9460ce docs: repair spellcheck and anchor drift (#122960)
* docs: repair spellcheck and anchor drift

* docs: satisfy markdown anchor lint
2026-08-12 20:50:56 -07:00
Masato Hoshino 4c12c973ed fix(sessions): highWaterBytes 0 no longer deletes all session history (#119909)
* fix(sessions): zero highWaterBytes no longer clears all session history

resolveHighWaterBytes passed an explicit non-positive highWaterBytes through
verbatim. The resolved value is the disk-budget cleanup loop's stop condition,
so a zero target made enforce mode evict every unprotected session and prune
its extracted archives instead of trimming to the documented 80% default.

Route the non-positive case to the function's existing unusable-value branch
(computeDefault). Not null: that disables the budget and permits unbounded
growth, which is right for a cap but wrong for a target.

Sibling of #119422, which fixed the same harm for maxDiskBytes and guarded
only resolveMaxDiskBytes.

* test(infra): isolate worktree migration discovery

Keep worktree migration coverage focused on its real filesystem, Git, and SQLite owner while avoiding unrelated channel and plugin doctor cold starts on fork CI.

Co-authored-by: masatohoshino <g515hoshino@gmail.com>

* test(ci): carry owner-approved SDK and doctor gate repairs

Carry the already-approved plugin SDK contract manifest and focused doctor-flow test isolation from the maintainer-owned CI repair. Preserve real config migration, persistence, snapshot, and SQLite cleanup coverage; no production behavior changes.

Co-authored-by: masatohoshino <g515hoshino@gmail.com>

* fix(sessions): use the renamed withTestDir helper in the new budget test

* fix(sessions): align high-water zero contract

* style(sessions): format high-water changes

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: FullerStackDev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-12 20:05:46 -07:00
Peter Steinberger 6076efc968 docs(gateway): clarify dynamic operator scopes (#122931) 2026-08-12 19:23:54 -07:00
joshavant 8eb9739724 fix: isolate compaction structure audit 2026-08-12 20:46:55 -05:00
joshavant 4cb21b22c0 fix: preserve compaction history when final audit fails 2026-08-12 20:46:55 -05:00
Peter Steinberger cef071582e feat: let limited browsers request admin access (#121459)
* feat(gateway): add live device scope upgrades

* feat(ui): add limited-access upgrade flow

* fix(protocol): refresh Swift scope upgrade models

* perf(ui): lazy-load device scope upgrades

* fix(ci): complete scope upgrade generated surfaces

* perf(ui): lazy-load GitHub link hovercards

* fix(ui): keep admin repair guidance focusable

* fix(ui): gate and refresh scope upgrade banner

* refactor(ui): keep gateway client within line budget

* fix(ci): align rebased scope upgrade checks

* fix(ui): resolve scope upgrade in browser tests

* fix(gateway): honor refreshed scope upgrade deadline

* fix(gateway): honor refreshed scope upgrade deadline

* fix(gateway): coalesce scope upgrade waiters

* fix(ui): gate scope upgrade actions

* chore(plugin-sdk): refresh rebased API baseline

* fix(scope-upgrade): return canonical request ids

* fix(ui): preserve gateway event type binding

* fix(protocol): generate scope upgrade result models

* fix(ui): preserve scope upgrade recovery guidance

* chore(plugin-sdk): refresh rebased API baseline

* test(ui): avoid scope upgrade navigation race

* docs(control-ui): clarify scope upgrade approver

* test(gateway): align appended method counts

* chore(plugin-sdk): refresh rebased API baseline

* refactor(ui): keep place picker within line budget

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): refresh rebased API baseline

* fix(gateway): preserve scope-upgrade browser origin
2026-08-12 18:32:00 -07:00
Peter Steinberger 1ca60fbc3a refactor(agents): make multi-agent ownership explicit (H2-1 core) (#114388)
* refactor(agents): make roster ownership explicit

* feat(config): materialize legacy agent roles

* fix(cron): migrate legacy owners at startup

* feat(gateway): expose agent selection contracts

* fix(gateway): enforce agent-scoped authorization

* docs(config): document explicit agent ownership

* fix(config): pin retained owner workspace

* fix(gateway): target hook wakes at effective agent

* fix(sessions): preserve fixed-store ownership

* fix: preserve retained agent ownership

* fix: preserve legacy agent ownership across runtime surfaces

* fix: fail closed on ambiguous session ownership

* fix: preserve compatibility owners across dispatch and writes

* fix: preserve retained agent projections

* fix: preserve agent ownership compatibility

* fix: preserve per-agent heartbeat guidance

* fix: preserve compatibility owners in generic paths

* fix: enforce configured ownership in session paths

* fix: defer remote roster selection

* fix: preserve ownership across session and config writes

* fix: fail closed on ambiguous restored ownership

* fix: preserve explicit ACP and legacy ownership

* fix: honor durable fixed-store ownership

* fix: enforce fixed-store owner authority

* fix: preserve ownership evidence boundaries

* fix: honor resolved session ownership

* fix: align compatibility ownership paths

* fix: persist legacy main store ownership

* fix: close ownership fallback gaps

* fix(agents): close retained owner compatibility gaps

* fix(agents): enforce session owner resolution

* fix(agents): complete session owner resolution sweep

* fix(agents): preserve durable session ownership

* fix: complete persisted session owner routing

* fix: thread prepared session owners

* fix: preserve stable session ownership

* fix: enforce session ownership boundaries

* fix: close session ownership delta gaps

* fix: reconcile session ownership after rebase

* fix: reconcile ownership with current main

* fix: align session store path imports

* fix: align session store config path import

* fix: reconcile explicit ownership CI

* fix: reconcile ownership rebase checks

* fix: align ownership ci contracts

* fix: align ownership rebase checks

* fix: preserve compatibility owner during setup

* fix(doctor): migrate ownerless heartbeat monitors

* fix(gateway): preserve explicit session ownership

* test: align ownership fixtures after rebase

* test: complete plugin manifest fixture

* test: align runtime context mocks

* fix(gateway): preserve alias routing for existing sessions

* style: format agent routing update

* fix(gateway): preserve selected owner during alias routing

* style: normalize rebased ownership files

* fix(gateway): preserve owner through global alias routing

* fix(gateway): preserve explicit ownership at HTTP boundaries

* fix(gateway): validate compatibility model ownership

* fix(agents): reconcile strict session ownership

* fix(agents): contain media yield callback failures

* fix(agents): avoid eager bare-key owner resolution

* chore: refresh rebased ownership baselines

* chore: align hosted plugin SDK baseline

* chore: refresh ownership baselines after main sync

* chore: refresh ownership baselines after main sync

* test: align routed event owner fixtures

* chore: retrigger CI after runner startup failure

* chore: refresh ownership SDK budgets after main sync

* fix(tasks): require agent identity for bare owners

* chore: align Linux plugin SDK baseline

* chore: remove release-owned changelog entry
2026-08-12 15:55:16 -07:00
Kimi Yu e1b8150a06 fix(codex): let owners install plugins from discovered marketplaces (#122389)
* fix(codex): allow owner-approved marketplace plugins

* fix(codex): preserve marketplace validation and remove unused exports

* docs(codex): clarify already-installed plugin authorization
2026-08-12 20:29:40 +00:00
Peter Steinberger 0c824f09d5 feat(gateway): observe paired node desktops (#122724)
* feat(gateway): stream paired node desktops

* chore(protocol): refresh desktop observe model

* fix(gateway): preserve desktop stream boundaries

* fix(gateway): keep desktop streams lifetime-bound

* fix(gateway): harden node desktop stream lifecycle

* fix(gateway): stabilize node desktop lifecycle setup

* chore(plugin-sdk): refresh API baselines
2026-08-12 13:17:45 -07:00
Peter Steinberger a1615cdfcf feat(linux): suspend the local gateway across host sleep via logind (#122719)
* feat(linux): suspend the local gateway across host sleep via logind

Mirror the macOS sleep cycle in the Tauri companion: a logind
PrepareForSleep listener with a delay inhibitor best-effort prepares a
local gateway suspension before sleep and resumes it on wake with a
reconnect nudge and bounded retries; leases are route-bound, always
cleared on wake, and late prepare responses resume immediately.

* fix(linux): keep the sleep listener alive when inhibitor re-acquire fails

* fix(linux): activate the driver for sleep cycles and bound driver-side sleep RPCs

Sleep cycles temporarily unpark the gateway driver so prepare/resume work
without the Quick Chat window; suspend RPCs carry a 3s driver-side budget
that recycles a hung socket instead of starving wake retries; a mock-logind
integration test exercises the Linux listener end to end.

* fix(linux): count overlapping sleep cycles instead of a boolean flag

An older wake task ending late cleared the shared activation flag and
parked the driver mid-cycle; a saturating depth counter keeps the driver
active until the last cycle ends.

* fix(linux): gate sleep-cycle activation on loopback routes and never block wake on logind

Remote or unconfigured routes no longer activate the driver during
sleep, the paired end hook runs only for cycles that began, and wake
recovery is spawned before the inhibitor re-acquire so a slow logind
cannot delay reconnect/resume.
2026-08-12 11:53:51 -07:00
Peter Steinberger 508dd471b0 feat(slack): live session cards as the default progress mode (#122552)
* feat(slack): render live session cards as the default Slack progress mode

Slack streaming.mode default flips partial->progress.
Progress mode renders one live Block Kit session card with a status header, narration, plan, activity, diff stat, and elapsed time; it is edited in place and finalized to success or error with an Open in OpenClaw button when gateway.publicOrigin is set.
Final assistant text always delivers separately.
The shared progress compositor gains a success-only additive per-turn diffStat mirroring the task ledger fold.
resolveGatewayPublicOrigin is exported through the plugin SDK.
The diffs viewer URL falls back to publicOrigin.
The old rich/text progress render fork is deleted.
Native task cards remain unchanged and opt-in.

* chore(config): regenerate bundled channel config metadata

* refactor(slack): keep session card state type internal

* refactor(slack): split session-card and diff-stat owners under lint ceilings

* refactor(channels): reuse diff-stat type from its owner module

Import ChannelProgressDraftDiffStat from progress-draft-diffstat instead of
redeclaring it in the compositor, resolving the all-exports deadcode scan.

* chore(plugin-sdk): regenerate api baselines for channel barrels

Baselines drifted after the rebase reconciled them against main; regenerate to
match the branch's actual channel-message/channel-outbound surface.

* fix(slack): drop a session card that cannot terminalize after final delivery

If the final reply is delivered but the terminal card edit fails, the caller
now clears the stale card instead of leaving it stuck in its Working state
(mirrors the pre-card preview cleanup). Adds a transport-failure regression and
corrects three tests that asserted the prior ignore-the-result behavior.

Documents resolveGatewayPublicOrigin as a dependency-light runtime helper on the
config-contracts SDK subpath, which previously described a type-only surface.

Addresses ClawSweeper P2 (unfinalized card) and P1 (runtime SDK contract).

* fix(slack): suppress default tool messages under the default progress card

resolveChannelStreamingSuppressDefaultToolProgressMessages re-derived the stream
mode from config with an "off" default, unlike its sibling resolvers which take
a caller-resolved mode override. After this branch made progress the Slack
default, a default-config channel turn saw mode "off" and left a stray
"Using tool: X" plain message posting alongside the session card. Thread the
caller-resolved mode through (compositor passes params.mode; Slack dispatch passes
slackStreaming.mode), matching resolveChannelStreamingPreviewToolProgress.

Retarget the progress-session-card delivery-trace golden at an EMPTY Slack config
so it proves the real default path; the regenerated golden is byte-identical,
confirming defaults now yield the clean card sequence (one card post, separate
final text, one terminal update with the Open in OpenClaw button, no stray tool
message). Switch the dispatch delivery-mode mock to the real resolver so the card
tests exercise the true channel default (automatic), not a hand-rolled one.

* chore(plugin-sdk): regenerate api baselines for the streaming mode param

resolveChannelStreamingSuppressDefaultToolProgressMessages gained an optional
mode override; the changed signature reflows the surface hash of every barrel
that re-exports it, so regenerate the affected baselines.

* chore(config): regenerate config baselines
2026-08-12 10:38:31 -07:00
Peter Steinberger 28a5889e9b feat: supervise headless Linux host desktop (#122677)
* feat(gateway): manage headless Linux host desktop

* chore(plugin-sdk): refresh API baselines

* fix(gateway): tighten managed desktop status proof

* style(gateway): satisfy managed desktop lint

* fix(gateway): preserve explicit port probe result

* fix(doctor): avoid inferring managed desktop runtime state
2026-08-12 08:56:34 -07:00