Commit Graph

11392 Commits

Author SHA1 Message Date
Peter Steinberger 02c08bba71 fix(codex): unblock Computer Use after plugin install (#126699)
* fix(codex): release config fence before readiness probe

* chore(codex): upgrade managed app-server to 0.148.0
2026-08-20 08:26:41 -07:00
Marvinthebored afc2a1ebb4 fix(agents): fail closed on code-mode alias invalidation (#126660)
Reconcile code and command aliases after trusted-policy and hook rewrites so explicit blank or non-string mutations fail closed, including simultaneous valid rewrites. Add owner-boundary regression coverage and document the contract.
2026-08-20 20:39:19 +05:30
Ayaan Zaidi 8458777e6a feat(qa): trigger Mantis proof from pull requests (#126658)
Add trusted ClawSweeper-label and maintainer-comment dispatch for Mantis Telegram proof. Short-circuit non-visible PRs before desktop setup while preserving exact-head, fork, credential, and comment-ownership boundaries.
2026-08-20 20:05:51 +05:30
Vito Cappello 1b9d3ac57d fix(claude-cli): apply thinking and keep live sessions warm (#125528)
* fix(models): preserve CLI runtime thinking capabilities

* fix(models): preserve configured thinking overrides

* fix: keep Claude live CLI process warm across captured turns

MCP delivery capture no longer kills the warm Claude process after every
turn. Capture-key admission is fenced by grant activate/deactivate so
prompt-cache continuity can survive across messages.

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

* fix(claude-cli): apply thinking levels

* fix(claude-cli): materialize thinking capabilities

* test(claude-cli): cover warm thinking budget reuse

* test(models): restore prepared catalog contracts

* fix(agents): restore catalog test boundaries

* fix(agents): break prepared catalog import cycle

* refactor(gateway): extract model-choice runtime resolution into public-projection module

Keeps models-list-result.ts under the max-lines cap after the origin/main
merge by moving resolveModelChoiceAgentRuntime next to the projection
helpers it feeds.

Claude-Session: https://claude.ai/code/session_01QXUQuDVataA5o16kxNnmoX

* test(claude-cli): cover thinking cache reuse

* test(claude-cli): cover captured live reuse

* fix(claude-cli): rotate MCP grants across live turns

* fix(anthropic): respect mandatory adaptive thinking

* fix(claude-cli): restore warm MCP bearer

* fix(anthropic): keep Mythos adaptive thinking

* test(claude-cli): prove live MCP cache reuse

* test(claude-cli): align live cache coverage

* fix(claude-cli): reuse live sessions across MCP grant rotation

* test(claude-cli): satisfy cache lane static gates

* fix(claude-cli): preserve runtime thinking policy

* fix(thinking): honor concrete runtime policy

* fix(gateway): honor mandatory thinking in model list

* refactor(auto-reply): extract prepared catalog merge

* docs(cli-backend): document thinking execution input

* refactor(auto-reply): extract catalog lookup helper

* style(auto-reply): format catalog helper import

* fix(claude-cli): stabilize live context budget

* fix(auto-reply): type prepared context metadata

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-20 06:44:49 -07:00
Peter Steinberger 584e750c16 fix(tui): route usage cost correctly (#126668) 2026-08-20 05:55:11 -07:00
Peter Steinberger bb96493ebe fix(logging): make clawlog JSON parseable (#126651) 2026-08-20 05:02:28 -07:00
Vincent Koc c28c279afa fix(release): keep frozen validation independent of main (#126622)
* fix(release): freeze validation tooling identity

* fix(release): enforce frozen validation contract

* fix(release): validate candidate identity in parent

* fix(ci): close release isolation gate findings
2026-08-20 04:32:38 -07:00
Ayaan Zaidi b7b7eec5ee feat(qa): run Mantis Telegram proof on local desktop (#126220)
Move Mantis Telegram Desktop proof from the remote AWS/Crabbox lane to a recorder-driven local Docker desktop. Keep proof scenarios agent-authored, cache trusted build outputs, and publish exact visible Telegram evidence without writing the QA bot token to artifacts.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-20 11:12:51 +00:00
Pavan Kumar Gondhi dff0f41e4a fix(imessage): reject ambiguous outbound recipients (#126564)
* fix(imessage): reject ambiguous outbound targets

* fix(imessage): preserve tel URI identities

* fix(imessage): explain target qualification

* test(imessage): keep target proof plugin-local

* docs(imessage): explain qualified contact targets
2026-08-20 16:16:18 +05:30
Marvinthebored bbee5467bc fix(agents): run code-mode exec when a model sends a blank code alias (#126599)
Treat blank code and command aliases as absent while preserving mismatch rejection when both aliases contain different instructions. Keep trusted hook and policy rewrites normalized at the Code Mode owner boundary.

Co-authored-by: Marvinthebored <marvin.assistant@lindsey.jp>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-20 15:57:46 +05:30
Peter Steinberger 6932897bf9 docs(plugins): show root CLI commands (#126621) 2026-08-20 02:42:05 -07:00
Koduri Mahesh Bhushan Chowdary bb134fef12 fix(cli): clarify cron channel plugin ids (#124655)
Keep cron delivery help and automation docs explicit that --channel selects a channel plugin, not a per-conversation channel identifier.

Fixes #124646

Punchcard-Session: clear-timber-orchard-n1
2026-08-20 01:45:01 -07:00
Peter Steinberger 1d2986b06f fix: prevent incompatible cloud runtime dispatches (#126585)
* fix(ui): gate cloud profiles by runtime mode

* test(gateway): expect cloud placement mode

* test(gateway): keep route suite within lint budget
2026-08-20 01:31:27 -07:00
Vyctor H. Brzezowski 68ae235318 improve(ui): refine chat widget host and image actions (#125250)
* improve(ui): refine chat widget host actions

* fix(ui): keep widget pin presentation unchanged

* fix(ui): compact widget actions and restore rounded host

* style(ui): format widget action menu

* test(canvas): refresh widget host document contract

* test(ui): model the widget host wrapper

* fix(ui): preserve retained widget downloads

* fix(ci): register Codex tool coverage

* fix(protocol): keep version exports compact

* fix(ui): preserve widget action outcomes

---------

Co-authored-by: RoboClaw <309084314+roboclaw-bot@users.noreply.github.com>
2026-08-20 05:27:56 -03:00
Peter Steinberger 10e707435a fix(mcp): repair channel lifecycle ownership (#126592)
Restore persisted channel media, cancellation cleanup, retryable permission delivery, bounded-event gap recovery, complete shutdown, and actionable Gateway startup diagnostics.
2026-08-20 01:14:43 -07:00
Peter Steinberger 147edf47f3 fix(auth): keep a retired auth JSON from stranding a migrated store (#126562)
* fix(auth): keep a retired auth JSON from stranding a migrated store

Runtime failed closed with AUTH_PROFILE_MIGRATION_REQUIRED whenever a retired
credential file was present, even when the canonical SQLite store already held
the agent's profiles. One leftover auth.json therefore made a fully migrated
install unusable, and the gateway lifecycle preflight refused start/restart on
top of it, so every channel and provider stayed offline until Doctor ran.

A legacy file is now only fatal when the canonical store cannot serve
credentials. Doctor's importer never overwrites a usable stored credential, so
a file sitting beside a populated store is unarchived bytes, not pending
migration: runtime logs a one-time warning and keeps serving. An empty store
with a credential file still fails closed and never falls through to
environment auth. Startup degrades that owner to configured-unavailable
instead of refusing to boot, which lets the lifecycle preflight go away.

* refactor(secrets): retire the auth-profiles.json vocabulary

Auth profiles moved to SQLite, but operator-facing surfaces still named the
retired JSON file. The duplicate-agentDir error told operators to copy
auth-profiles.json to share credentials, which does nothing and lands the
second agent in a migration-required state; `openclaw migrate plan codex`
reported a target file that is never created; and the secrets picker labelled
candidates with a filename that no longer exists.

Renames the SecretTargetConfigFile discriminator to "auth-profile-store" and
corrects the operator-facing text, the migrate plan target, and the docs that
described the file as a live target. Genuine legacy-filename uses in doctor,
the security fixer, and migration fixtures are unchanged.

Also deletes resolveSecretPlanTargetByPath and ResolvedSecretPlanTarget from
the plugin SDK. They have no callers in core, plugins, or tests, and the
symbols are absent from the latest stable tag, so they carry no compatibility
obligation and are removed rather than deprecated. Their inline parameter type
was the only thing putting the retired filename on the public SDK surface.

* improve(wizard): warn about device-code phishing

The device-code prompt only warned against sharing the code, and only when an
expiry was known. Device-code phishing works the other way around: the attacker
starts the login and gets the victim to enter the attacker's code. Codes
delivered over a chat channel are the risky case and carry no expiry hint, so
the warning is now unconditional and covers received codes, matching the Codex
CLI prompt.

Also documents the Codex auth handoff: a subscription profile is installed as
in-memory external auth rather than persisted, and token refresh is inverted
so the refresh token stays in OpenClaw's store.

* fix(test): make transcript read-failure injection order-independent

server.sessions.compaction-read-errors.test.ts injected its failures with
mockRejectedValueOnce, which fails the NEXT call to loadTranscriptEvents
globally. Under --isolate=false a shard shares one worker, so any sibling
transcript read could consume the one-shot rejection before the compaction RPC
issued its own; compaction then ran against the real reader and returned ok,
failing three assertions. This shard was already red on main; a prior repair
fixed the mock's initialization order but left the call-order dependency.

Key the injection on the seeded sessionId instead, so unrelated readers cannot
consume it and the re-read case counts only its own session's reads.

Also updates two expectations invalidated by this branch: the duplicate-agentDir
remediation text, and the plugin SDK export ratchet, shrunk by the two retired
secret-plan exports.
2026-08-20 00:42:41 -07:00
Peter Steinberger 29f86119e0 docs(gateway): recommend Access service tokens over route exemption (#126536)
* docs(gateway): recommend Access service tokens over route exemption

* docs(gateway): fix Nodes heading link
2026-08-19 21:40:44 -07:00
Omar Shahine 641ccba793 fix(cli): allow agent selection for direct inference (#125143)
* fix(cli): inherit inference agent options

* fix(cli): route inference model auth agents

* fix(cli): route video describe agent

* fix(cli): route audio transcription agent

* fix(cli): preserve inherited agent selectors

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
2026-08-19 21:27:09 -07:00
Shakker 441f0a3388 fix: allow backing out of agent imports (#126515) 2026-08-20 04:10:44 +01:00
Shakker 32223ac536 fix: group agent imports in onboarding 2026-08-20 04:10:44 +01:00
Peter Steinberger 35e0bc22ea fix(memory): distinguish missing file reads (#125979)
* fix(memory): distinguish missing file reads

* test(memory): keep adapter identity assertion bound

* fix(memory): preserve statusless manager reads
2026-08-19 20:08:50 -07:00
Josh Avant 29cfd195d1 fix(memory): honor turn tool policy during automatic recall (#126482)
* fix(memory): bind prompt recall to turn tool policy

* test(plugins): update hook contract inventory

* fix(memory): bind recall to active run lifecycle

* docs(plugins): define prompt authority contract

* test(plugins): track prompt authority type guard

* fix(plugins): revalidate prompt authority per handler
2026-08-19 19:21:51 -07:00
Peter Steinberger e001542388 fix(skills): keep workshop revisions atomic (#126485)
* fix(skills): keep workshop revisions atomic

* fix(skills): keep proposal artifact paths stable

* fix(gateway): preserve proposal inspect schema

* fix(gateway): hide proposal generation paths

* fix(skills): sync proposal generation files
2026-08-19 19:03:10 -07:00
Peter Steinberger 19316660e4 fix(agents): consolidate ambient owner resolution (#126504) 2026-08-19 18:54:32 -07:00
Peter Steinberger 4118f31d89 fix(llama-cpp): make endpoint auth transitions reproducible (#126498) 2026-08-19 18:37:28 -07:00
Peter Steinberger 8b15dc9447 refactor: share media and process runtime helpers (#126490)
* refactor(media): share video description requests

* refactor(process): expand buffered runtime options
2026-08-19 17:48:49 -07:00
Peter Steinberger 0a86702241 feat(github): authorize agent identities from Settings (#126474)
* feat(github): add device authorization lifecycle

* fix(github): harden device authorization lifecycle

* fix(github): refresh native tool display snapshot

* fix(github): refresh config and UI baselines

* refactor(github): break OAuth identity import cycle

* test: make gateway retry deadline assertion scheduler-safe
2026-08-19 17:41:58 -07:00
Peter Steinberger 177828aa75 fix(cron): honor failure alert thresholds (#126483)
* fix(cron): honor failure alert thresholds

Per-run Gateway announcements bypassed threshold, cooldown, and opt-out policy. Make the scheduler the sole owner of failure notification decisions.

* fix(cron): preserve safe failure details

Keep trusted failure detail proof on the scheduler-authorized transport and remove the obsolete Gateway event-context handoff after the ownership consolidation.

* test(cron): assert alternate failure route isolation
2026-08-19 17:25:14 -07:00
Peter Steinberger 6ca7b43263 fix: preserve worker lease during cleanup recovery (#126465) 2026-08-19 16:17:54 -07:00
Markus Hartung 4970ed2357 fix(matrix): accept Room v12 IDs without server suffix (#123931)
* fix(matrix): recognize room version 12 room IDs (no :server suffix)

Room version 12 (MSC4291) dropped the trailing ":server" from room
IDs -- they are now a hash of the create event. Every place in the
Matrix plugin that treated "!" + ":" as the signature of an
already-resolved room ID silently discarded valid v12 room IDs as
unresolved instead of using them directly:

- channels.matrix.rooms config resolution (config.ts) dropped the
  entry entirely, so group rooms could never pass the groupPolicy
  "allowlist" gate on a v12 homeserver -- messages were dropped with
  no reply and no default-level log line, since the only trace is a
  verbose-only debug log.
- The invite auto-join allowlist validator and the interactive
  group-room setup resolver in onboarding.ts had the same check
  duplicated, so a user typing a v12 room ID during setup would be
  told it was invalid.
- session-route.ts's per-room DM recipientSessionExact check had the
  same gap for room-kind sends.

Runtime auto-join (auto-join.ts) already only checked for the "!"
sigil, which is why joining a v12 room worked while responding in it
did not -- this made the bug hard to spot from the join path alone.

Fix: add a single canonical isMatrixRoomId predicate next to the
existing isMatrixQualifiedUserId in target-ids.ts (user IDs and
aliases still require ":server" per spec; only room IDs changed) and
reuse it at all four sites instead of repeating the stale check.

Confirmed live against a real Room v12 homeserver (Conduit): the
server's own /joined_rooms response returns bare "!<hash>" room IDs
with no colon.

* docs(matrix): document suffixless room version 12 room IDs

Room version 12 (MSC4291) dropped the ":server" suffix from room
IDs. Document that the suffixless "!room" form is accepted anywhere
the docs previously only showed "!room:server", matching the
target-ids.ts fix landed in this same PR.

* fix(matrix): update stale Room v12 guidance text

* docs(matrix): accept suffixless Room v12 IDs in the group-policy guide

docs/channels/matrix.md already documents that channels.matrix.groups
accepts the suffixless !room form on room version 12+, but the
group-policy guide (docs/channels/groups.md) still only listed
!room:server, contradicting the channel doc an operator on a v12
homeserver would actually be following.

Addresses the ClawSweeper P2 finding on PR #123931.

* fix(matrix): advertise suffixless Room v12 IDs in onboarding placeholders

The invite auto-join and group-room setup prompts' placeholder text
still showed only `!roomId:server`, even though the retry note,
validation, and unresolved-room diagnostic already accept and describe
the suffixless `!roomId` form on room version 12+. An operator on a
v12 homeserver would see their homeserver's own room IDs contradicted
by the very placeholder guiding them through setup.

Updated both placeholders to list the suffixless form alongside the
existing examples, matching the phrasing already used in
docs/channels/matrix.md and the invite retry note. Added
configureRoomsAccess/roomsAllowlist options to the shared
createMatrixUpdateKeepCredentialsPrompter test harness (mirroring the
existing inviteAutoJoin option) so the group-room setup flow can be
exercised without duplicating the base prompter setup, then added
focused tests asserting the exact placeholder text for both prompts.
Verified both new tests fail against the pre-fix placeholders and pass
after.

Addresses the two ClawSweeper P2 findings on PR #123931.

* test(matrix): restore only allowlisted environment keys

* fix(matrix): reject empty room identifiers

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-19 16:12:05 -07:00
Ben Badejo 20af8688dd fix(codex): refresh stale isolated Computer Use bundles (#126080)
* fix(codex): refresh stale isolated Computer Use bundles

* fix(codex): satisfy Computer Use CI contracts

* fix(codex): constrain Computer Use bundle refresh

* test(codex): guard Computer Use cache fixture

* fix(codex): contain native Computer Use refresh paths

* fix(codex): keep service path type private

---------

Co-authored-by: Benjamin Badejo <ben@benbadejo.com>
Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
2026-08-19 16:02:23 -07:00
Josh Lehman 841f25eae6 fix(codex): accept newer desktop app-server versions (#126450) 2026-08-19 15:36:54 -07:00
Peter Steinberger 7e0b599ca4 fix: surface Codex input prompts across runtimes (#126387)
* fix: surface Codex input prompts across runtimes

Codex structured input now reaches bounded Gateway questions in native and ACP runs, with exact turn ownership, explicit unsupported outcomes, and cancellation fencing. Consume the published ACPX elicitation support.

* chore: align elicitation helpers with current guards

Use protocol-specific helper names required by current main and update the reservation regression to the generalized input owner.

* fix: formalize structured input SDK surface

Expose one documented, frozen agent-harness structured-input contract with runtime and subpath coverage, replacing the accidental function-property API.

* fix: satisfy elicitation architecture gates

Register the real-process ACPX fixture as an executable test root and move shared structured-input types into the boundary leaf to keep Knip and Madge clean.

* fix: remove structured input lint suppression

Preserve the rejected control and invisible-character ranges with an explicit code-point check so the production suppression inventory stays closed.
2026-08-19 15:25:33 -07:00
Steven ff37627804 fix(discord): resolve realtime voice API key references (#125443)
* fix(discord): resolve realtime voice SecretRefs

* fix(discord): isolate realtime voice secret owners

* fix(discord): contain realtime secret owner gate

* fix(build): align plugin SDK boundary paths

* fix(discord): normalize realtime secret owner accounts

* fix(discord): gate canonical realtime secret owners

* style(discord): format realtime voice tests

* test(codex): assign run-attempt tools shard

* fix(discord): skip unavailable realtime providers

* fix(discord): preserve realtime provider availability errors

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-19 15:23:14 -07:00
Jason (Json) 45b8750d8b fix(compaction): default maintenance reasoning to low (#126421)
* fix(compaction): default maintenance reasoning to low

* test(compaction): cover explicit inherit fallback

* test(compaction): preserve inherit literal type
2026-08-19 16:18:06 -06:00
Peter Steinberger 7769cb6466 fix(cli): accept daemon --json before subcommands (#126447)
* fix(cli): accept daemon json before subcommands

* test(cli): update doctor public-surface fixture

* test(cli): classify daemon parent JSON output
2026-08-19 15:17:21 -07:00
Vitor Cepeda Lopes e00f860198 fix(codex): Computer Use fails when Desktop bundles a newer app-server (#125883)
* fix(codex): allow newer app-server runtimes

* fix(codex): bound external app-server compatibility

---------

Co-authored-by: TheAngryPit <16145902+TheAngryPit@users.noreply.github.com>
Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
2026-08-19 14:42:33 -07:00
Peter Steinberger 513ec6218c fix(crabbox): harden worker desktop setup (#126417)
* fix(crabbox): harden desktop provisioning

* docs(gateway): clarify worker desktop routes
2026-08-19 14:13:06 -07:00
Peter Steinberger 0135046830 refactor(llama-cpp): use one provider for managed and existing servers (#126434)
* refactor(llama-cpp): unify server ownership modes

* test(llama-cpp): preserve shared discovery limits

* fix(plugin-sdk): retain provider auth removal export
2026-08-19 13:57:33 -07:00
Peter Steinberger a1db88b2c5 fix: show useful automation failure details (#126384)
* fix(cron): show useful automation failure details

* test(cron): align failure detail expectations

* fix(cron): use trusted failure details

* fix(cron): preserve event callback shape
2026-08-19 13:34:30 -07:00
Peter Steinberger fd2fccbc8e docs(agents): restore the non-default scope for systemAgent ownership (#126431)
Live-testing #126377 in a real explicit fleet surfaced an inaccuracy that PR
introduced. It dropped 'Other agent-scoped methods do not use this setting as a
general default', which is still true: only models.list, models.authStatus,
skills.status, and doctor.memory.status opt in, while the generic Gateway
resolver in agent-id-shared.ts deliberately does not.

Verified against a live gateway and CLI on a three-agent explicit fleet with
systemAgent.agentId set: 'openclaw models list', 'openclaw sessions', stored
session lookup, and TUI startup all still require an explicit agent. Name those
surfaces so operators know where the owner does and does not apply.
2026-08-19 13:08:34 -07:00
Peter Steinberger 2d13e16705 fix: harden node desktop carrier (#126425) 2026-08-19 12:57:26 -07:00
Peter Steinberger 615ff6ac94 fix: queued deliveries never recover at startup in multi-agent fleets (#126377)
* fix(outbound): resolve ambient delivery owner through the system-agent chain

Agent-less outbound channel bootstrap resolved its owner via the deprecated
throwing resolver, so multi-agent explicit-ownership configs with only
agents.defaults.systemAgent.agentId set threw AgentSelectionRequiredError from
inside gateway delivery recovery, aborting the whole drain ("Delivery recovery
failed") for every queued entry.

Bootstrap now follows the same ambient owner chain heartbeats and cron use
(legacy default, then systemAgent, then sole agent), consolidated into one
canonical tryResolveAmbientOwnerAgentId in agent-scope-config; the duplicated
chain in cron/agent-id.ts is deleted and heartbeat resolution reuses the
helper. Truly ownerless fleets no longer throw either: bootstrap proceeds with
global-scope plugin discovery only, never selecting an agent workspace, so
per-entry delivery outcomes stay recorded instead of one entry starving the
recovery loop.

Regression tests fail pre-fix: agent-less bootstrap routes through the
configured system-agent owner, and ownerless fleets bootstrap without
throwing.

* refactor(agents): route ambient owner resolution through one canonical chain

The idiom `tryResolveLegacyCompatibilityAgentId(cfg) ?? resolveDefaultAgentId(cfg)`
was copied across nine ambient surfaces. It reads like a fallback but is not: when
the first call returns undefined, resolveDefaultAgentId reduces to resolveSoleAgentId
and throws, so the second leg only ever throws — and neither leg consults
agents.defaults.systemAgent.agentId. Every one of those surfaces raised
AgentSelectionRequiredError in explicit fleets that own ambient work through a
system agent.

Promote the chain to one owner in agent-scope-config: tryResolveAmbientOwnerAgentId
(undefined when ownerless) and resolveAmbientOwnerAgentId (throws with the caller's
existing selection context). The throwing variant is a drop-in for every former
composite: identical message when a fleet has no owner, but the system-agent leg
now resolves.

Converted: resolveDefaultAgentDir (the shared producer behind auth, model catalog,
doctor, wizard, and Plugin SDK helpers), config identity-avatar validation, prepared
model catalog and registry, session reset, Talk target, main-session routing and its
routing-contract fingerprint, session store targets, hooks CLI, plugin LLM
completion, and first-run onboarding.

resolveDefaultAgentId keeps backing explicit-selection surfaces where 'pass --agent'
is the right answer; its deprecation note now sends ambient callers to the new
helper.

* fix(sessions,hooks): keep agent-narrowing surfaces on explicit selection

CI caught the over-reach: session-store listing and hooks status reporting are
deliberately explicit-selection surfaces, not ambient system work. Both narrow
output to one agent, so adopting agents.defaults.systemAgent.agentId would hide
the other agents' sessions/hooks instead of failing with the escape hatches the
operator needs. sessions.default-agent-store.test.ts pins that contract by
configuring a system agent and still expecting the --agent/--all-agents error.

Restore the prior behavior at both sites, spelled honestly as
tryResolveLegacyCompatibilityAgentId ?? resolveSoleAgentId — provably identical
to the old composite, since the composite's second leg could only ever throw —
with a comment recording why these two resist the ambient chain.

* test: declare the ambient owner binding in agent-scope mock factories

Explicit vi.mock factories enumerate exports, so production calling
resolveAmbientOwnerAgentId broke prepared-model-catalog, prepared-model-registry,
and channel-resolution with 'No "resolveAmbientOwnerAgentId" export is defined on
the ... mock'. Declare it in the four factories; channel-resolution now drives the
non-throwing variant the bootstrap actually calls.

Also restore session-store targets and hooks status to their exact previous code.
Both stay out of the ambient chain by design, so the smallest correct diff at an
out-of-scope site is none: they now differ from main only by the comment recording
why they resist it.

* fix(models): resolve the model-config workspace through the ambient owner

ClawSweeper P1: prepareModelsConfigContext resolved agentDir through
resolveDefaultAgentDir (ambient chain) but its workspace through
resolveDefaultAgentId (deprecated throwing chain), so explicit fleets owned by a
system agent still failed model preparation on the workspace lookup — a one-sided
fix inside a single function.

Both halves now resolve the same ambient owner.

* docs(agents): describe the widened ambient system-agent ownership

config-agents.md claimed 'Other agent-scoped methods do not use this setting as
a general default', which this branch makes false: systemAgent.agentId is now
the ambient owner for agent dir/workspace resolution, outbound bootstrap and
delivery recovery, main-session routing, Talk, and onboarding.

Record the widened set, the two surfaces that deliberately still demand explicit
selection (sessions, hooks), and delivery recovery's per-entry degradation.
2026-08-19 12:24:25 -07:00
Peter Steinberger 84c2111b30 fix: restore cloud worker Desktop on node-backed Crabbox workers (#126393)
* fix(gateway): carry cloud worker desktops over nodes

* fix(crabbox): restore node-backed worker desktops

* refactor(crabbox): split worker provider owners
2026-08-19 11:50:48 -07:00
Peter Steinberger 61d217fd2a fix: stop routing IDs from masquerading as delivery receipts (#126385)
* fix(channels): separate routing from receipt identity

Routing identifiers no longer fabricate message delivery evidence; provider-canonical thread placement is preserved.

* fix(channels): preserve conflicting receipt threads

Keep aggregate thread placement absent when provider receipt parts disagree, even when a requested route thread is available.
2026-08-19 11:33:16 -07:00
Peter Steinberger 0606e31d0e feat(gateway): broker GitHub publication (#126306)
* feat(gateway): broker GitHub publication

* refactor(gateway): split publication owners

* fix(gateway): enforce publication branch authority

* fix(gateway): bind publication to remote identity

* fix(gateway): bind publication recovery to remote state

* fix(gateway): preserve publication git state

* fix(gateway): retain publication recovery authority

* fix(gateway): commit publication index atomically

* fix(gateway): narrow publication index errors

* refactor(gateway): keep publication CAS errors private

* fix(gateway): recover publication index transactions

* fix(agents): describe GitHub publication tool

* fix(gateway): harden publication base fetch

* fix(gateway): reject publication filter semantics

* fix(gateway): verify publication creation base

* refactor(agents): align publication tool options

* fix(gateway): isolate publication object lineage

* refactor(gateway): use shared table probe

* test(gateway): keep publication helpers in routed suite

* perf(ui): lazy-load GitHub publication request

* fix(gateway): preserve publication support contracts

* fix(gateway): recover publication before authority checks

* fix(gateway): fence local publication snapshots

* fix(android): format generated protocol models

* fix(gateway): harden publication recovery

* fix(gateway): fence publication recovery

* fix(ui): reset completed publication cycles
2026-08-19 11:05:12 -07:00
Peter Steinberger 51599041bc fix: explain preserved session worktrees accurately (#126347)
* fix(sessions): report worktree preservation reasons

* fix(sessions): align preservation checks with current main

* perf(ui): keep preservation copy within startup budget

* perf(ui): reuse localized preservation copy

* test(ui): match preserved worktree confirmation copy

* test(ui): await committed raw config state
2026-08-19 10:59:42 -07:00
Peter Steinberger 6267703b30 refactor(canvas): share eligible node selection (#126374) 2026-08-19 10:51:02 -07:00
Peter Steinberger 4994f7bacf fix(cli): resolve infer command owners via --agent and systemAgent fallback (#126234)
* fix(cli): resolve infer command owners via --agent and systemAgent fallback

Multi-agent rosters (agents.ownership=explicit) dead-ended every infer
runner command: resolveDefaultAgentId threw AgentSelectionRequiredError
telling callers to pass --agent, a flag none of the commands registered,
and agents.defaults.systemAgent.agentId was ignored.

Route model run, image generate/edit/describe/describe-many, video
generate, embedding create, and model auth logout through the existing
resolveCapabilityProviderAgentId chain (explicit --agent, then
agents.defaults.systemAgent.agentId, then the sole agent) with
per-command error surfaces, and register --agent on each command.

* docs(config): scope systemAgent infer fallback help to agent-owned commands
2026-08-19 08:44:52 -07:00
Peter Steinberger ae55a4090c refactor(canvas): make the panel a widget presenter (#126030)
* refactor(canvas): retire legacy host and commands

* refactor(apple): narrow shared Canvas contracts

* refactor(macos): keep Canvas as widget presenter

* refactor(ios): remove Canvas client

* refactor(android): remove Canvas client

* refactor(linux): remove Canvas client

* fix(ci): isolate native locale artifacts

* fix(linux): regenerate companion lockfile

* fix(canvas): refresh native tool display metadata

* test(canvas): align coverage with presenter surface

* test(canvas): remove obsolete asset root seam

* test(canvas): stabilize retirement CI coverage

* refactor(swift): remove orphaned resource wrapper

* test(ios): remove retired canvas layout assertion

* fix(macos): reserve retired canvas command namespace

* refactor(macos): isolate canvas command policy

* fix(canvas): select only eligible macOS panels

* fix(canvas): keep panel selection plugin-owned
2026-08-19 08:21:07 -07:00