Commit Graph

11365 Commits

Author SHA1 Message Date
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
Onur Solmaz c2de3206d4 feat(llama-cpp): support external llama-server
* feat(llama-cpp): add external server provider

* feat(llama-cpp): document external server setup

* refactor(llama-cpp): harden external provider boundaries

* fix(llama-cpp): support external structured output

* fix(llama-cpp): isolate replacement endpoint credentials

* test(llama-cpp): register external live shard

* fix(llama-cpp): preserve explicit endpoint authorization

* fix(llama-cpp): clear disabled inline credentials

* fix(llama-cpp): preserve external local service configs

* test(llama-cpp): cover retained external configs

* test(llama-cpp): cover authorization precedence
2026-08-19 17:32:00 +03:00
Michael Appel 62a97ae4f4 fix: decode NAT64 embedded IPv4 prefixes [AI] (#123241)
* fix: decode NAT64 embedded IPv4 prefixes

* test: update NAT64 SSRF fixtures

* fix: check NAT64 local-use candidates

* fix: decode NAT64 local-use prefix directly

* fix: block NAT64 local-use allocation

* fix: block trusted NAT64 local-use rebinding

* docs: note NAT64 exact-origin block

* fix: block trusted local-use NAT64 labels

* docs: clarify NAT64 private-network opt-in

* fix: keep NAT64 block before proxy exemptions

* fix: explain local-use NAT64 provider opt-in

* fix: keep local-use nat64 out of gateway trust

* test: exercise nat64 configured-origin trust
2026-08-19 06:24:31 -07:00
Peter Steinberger 97557ec3f5 fix(widgets): route show_widget through Discord Activities (#126294)
* refactor(widgets): unify Discord presentation

* fix(discord): keep incomplete Activity routes private

* fix(discord): require usable Activity accounts

* docs(discord): clarify hidden Activity routes
2026-08-19 05:41:37 -07:00
Peter Steinberger a7f9a7fdd4 refactor(gateway): interrupt at admission; sessions.steer delegates to chat.send (#126291)
* refactor(gateway): interrupt at admission; sessions.steer delegates to chat.send

chat.send queueMode interrupt now aborts the captured current operation
at the session-work admission owner (exact-instance abort, never a
same-key successor) and dispatches the new turn after the abort
settles; channel-originated interrupts share the same primitive.
sessions.steer keeps its validation, sharing/access checks, and
response shape but becomes a thin deprecated adapter over that path -
its private inflight/retry and hard-abort machine is deleted. The
Control UI /redirect command rides canonical chat.send. Compaction's
use of the old hard-interrupt helper moves unchanged to
session-run-interruption.ts.

* fix(gateway): interrupt non-reply admissions
2026-08-19 04:36:57 -07:00
Peter Steinberger 4af09d4961 feat(ui): unify focused presentation routes (#126143)
* feat(ui): unify focused presentation routes

/focus/<target> replaces unshipped standalone query links across dashboard, terminal, desktop, and native apps.

Gateway-served index assets are anchored so nested documents resolve their bundles from the Control UI base path.

* test(gateway): narrow emitted asset URLs

Fixes check:test-types TS18048/TS2322 by dropping unmatched optional captures before comparing emitted asset URLs.

* test(docs): follow centralized cloud secret guidance

Fixes the stale current-main docs test after #126132 centralized GCP and Hetzner setup in docker-vm-runtime.

* test(ui): retry missing locator reads

The 500ms locator text read can time out while the menu label is still rendering, causing expect.poll to reject instead of using its owning 10s retry window. Treat only Playwright TimeoutError as a missing value so the outer poll retries while page-closure and arbitrary failures still surface.

* test(android): capture TLS probe coroutine

The TLS probe test inferred its coroutine from mutable scope children, racing unrelated child startup and teardown in CI. Capture the exact Job from inside the probe coroutine and join that owner before asserting the stale-attempt guard.

* fix(gateway): preserve plugin focus routes

Keep approval handling ahead of plugin dispatch, but treat focus documents as an unclaimed Control UI fallback after plugin authentication and routing. Exact and prefix plugin routes therefore retain ownership, while unclaimed reads serve the focus document and other methods return 404.

* fix(ui): migrate released terminal links

Preserve stable v2026.7.1 terminal query compatibility by rewriting the root/base ?view=terminal URL once to the canonical /focus/terminal path with history.replace. Keep URL parsing path-only, and leave the removed desktop and dashboard query forms as a hard cut.

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

Cached filtered configs caused duplicate ownership, and the test lacked a canonical full-suite owner.

* test(ui): keep cloud recovery proof state-owned

The recovery test should assert owner state and reload identity, while dedicated tests own transient alert visibility.

* test(qa): wait for outbound bus state

* fix(qa): reserve gateway ports through staging

* refactor(qa): keep socket creation in gateway owner
2026-08-19 03:41:29 -07:00
Peter Steinberger 46ef757a29 feat: add per-project cloud worker profile defaults (#126238)
* feat(config): add cloud worker project profiles

* feat(gateway): resolve project cloud worker profiles

* docs(gateway): document project profile defaults

* fix(gateway): require admin for project profile dispatch
2026-08-19 03:20:39 -07:00
Peter Steinberger e71fc902ee fix(gateway): make activeRunIds presence mean a complete exact run set (#126106)
* fix(gateway): make activeRunIds presence mean a complete exact run set

Session rows no longer emit activeRunIds: [] while hasActiveRun is
true. Presence now means the complete exact set of direct run ids;
omission means identities are unavailable (projected/embedded owners);
[] only ever represents proven idle. Consumers stop guessing:
soleActiveSessionRunId() replaces the arbitrary [0] fallbacks in the
observer digest, transcript cache key, activity inspector, and
stale-terminal reconciliation, each falling back to its owner fact.

Follows the maintainer direction from #125983: the field stays as
Gateway-owned exact facts; producer-side liveness/observer projections
are a named follow-up.

* fix(gateway): clear unavailable active run ids in events

* fix(gateway): preserve idle active run sets

* fix(clients): close active run id cache gaps

* test(android): isolate history run snapshot
2026-08-19 02:08:57 -07:00
Peter Steinberger 67750753a2 fix: capture GitHub identity from authenticated sign-in (#126114)
* fix: capture GitHub identity from authenticated sign-in

Automatically persist verified GitHub identities from Cloudflare Access and Tailscale Serve while keeping public Git co-author credit as a separate opt-in.

* test: stabilize cleanup and activity capture

* fix(security): bind GitHub profiles by account id

* test: scope activity capture to route

* fix(security): gate profile requests on identity sync

* fix(security): close pending profile authorization gaps

* test(ui): stabilize terminal continuation menu

* test: stabilize startup recovery timing

* test: keep one Codex attempt tools owner

* fix(plugins): allow profile-independent gateway reads
2026-08-19 01:35:52 -07:00
Peter Steinberger fef5fc55f4 fix(codex): prevent node process control from targeting gateway sessions (#126253) 2026-08-19 01:31:52 -07:00
Peter Steinberger 80934e5639 feat(ui): dispatch sessions to paired devices (#126187) 2026-08-19 01:11:49 -07:00
Peter Steinberger 3378e07d50 refactor(plugin-sdk): promote shared runtime primitives (#126193)
* refactor(plugin-sdk): promote shared runtime primitives

* test(codex): keep one attempt tools owner
2026-08-19 01:10:18 -07:00
Peter Steinberger cb5c061cb3 fix(gateway): resolve ambient heartbeat owner without crashing startup (#126232)
Ambient heartbeat ownership now follows the cron owner chain: heartbeat.agentId, legacy default, systemAgent.agentId, then sole agent.
Ownerless multi-agent rosters disable heartbeats with gateway and config-validate warnings instead of throwing AgentSelectionRequiredError during gateway startup.
2026-08-19 01:05:28 -07:00
Peter Steinberger 554fc80e2f fix: Full access sessions no longer request exec approval (#126210)
* fix: stop Full access sessions from requesting exec approval

* fix: propagate Full access policy to compaction

* fix: source compaction permissions from session state
2026-08-19 01:04:36 -07:00
Peter Steinberger 44736749eb feat(skills): custodian-only skill library (first wave) (#126186)
* feat(skills): add custodian-only skill library

* docs: document custodian skill library

* refactor(skills): make custodian skills concrete and non-interactive

Replace docs-link-first playbooks with verified openclaw config/message/infer
one-liners; drop interactive onboard references; encode the in-session
config-write policy boundary (models.*/secrets.* via trusted shell).

* fix(skills): corrections from live A/B testing of custodian skills

--agent required for models list/auth list in multi-agent rosters; drop
hanging channels capabilities probe; telegram target is chatId; roster-safe
prove via agent turn (infer model run has no --agent and dead-ends
multi-agent setups); note expected not-found on pre-setup config get.

* fix(skills): front-load harness plugin check in add-model-provider Gather

A/B timing showed the codex plugin dependency surfacing mid-Prove, at the
most expensive point (approval gate + turn boundary). Checking and
remediating during Gather removes the stall.

* fix(skills): keep status inventory unfiltered while scoping custodian source

buildWorkspaceSkillStatus forwarding agentId activated the loader's agent
allowlist filter, dropping excluded skills from the workshop's status view
(collection-review regression on CI). New closed agentSkillFilter mode lets
agentId scope custodian-source discovery without filtering the entry list,
per the documented status invariant.
2026-08-19 00:33:02 -07:00
Peter Steinberger 554dfbe0a2 feat(discord): auto-join occupied voice rooms (#125974)
* feat(discord): auto-join occupied voice rooms

Add opt-in voice.autoJoin[].whenOccupied residency so Discord voice bots join for the first human and leave when the room becomes empty while preserving existing always-on, manual, transcript, and follow-user behavior.\n\nCloses #125973

* test(discord): isolate process runtime mocks

Use stable hoisted runtime-env mocks so isolate=false Discord test ordering cannot turn sleepWithAbort back into an unmocked function.

* fix(discord): defer unknown voice occupancy

Treat memberless voice states as unresolved instead of human so bot-only rooms cannot trigger occupancy-managed auto-join. Add cache-to-listener and manager regressions.\n\nCloses #125973

* test: isolate shared module mocks

Replace ineffective non-isolated module spies with stable hoisted mocks and a child-process SQLite connection-reuse probe so gateway and Discord shards are order-independent.

* test(gateway): inline connection reuse probe

Keep the child-process SQLite ownership probe in its owning Vitest file so Knip sees the full test surface without weakening process isolation or the original order regression.
2026-08-19 00:08:54 -07:00
Peter Steinberger 57a65def4f fix(ui): restore sidebar session hovercards (#126222)
* fix(ui): restore sidebar session hovercards

* test(codex): include run-attempt tools in full suite
2026-08-19 00:07:05 -07:00
Peter Steinberger 49d8cfd393 fix(security): prevent blocked SearXNG refs from using ambient URLs (#126214)
* fix(security): honor blocked SearXNG secret refs

* docs(searxng): clarify blocked SecretRef policy

* test(codex): route attempt tools coverage
2026-08-19 00:02:58 -07:00
Ayaan Zaidi 97e3136b9e feat(qa): add a standalone Telegram Desktop recorder with a prebaked desktop image (#125186)
Records native Telegram Desktop from a digest-pinned prebaked image: a ready desktop in ~12s with no per-lease apt installs or downloads, which also removes the dpkg-lock failures that killed recent runs.

The recorder only records; callers drive the turn and supply the TDLib driver used for QR authorization. Nothing in this repository invokes it yet - routing the Mantis Telegram Desktop Proof workflow through it is a follow-up.
2026-08-19 11:23:48 +05:30
Peter Steinberger 0d14434d0e feat(secrets): add explicit protected and agent-readable access (#126088)
* feat(secrets): add explicit agent access modes

Distinguish protected write-only secrets from agent-readable Gateway environment values, expose policy-bound Gateway exec aliases to Codex, and activate Node environment proxy support for destination-bound egress.\n\nCloses #125975

* fix(gateway): bind lifecycle dispatch to owning instance

* test(ui): preserve mock gateway recovery state

* fix(codex): avoid unavailable gateway process guidance

* fix(harness): keep run correlation host-owned

* fix(gateway): bind restart delivery to instance

* test(codex): construct tools through test host capability
2026-08-18 22:51:15 -07:00
Peter Steinberger 2bcc06cc22 fix(cron): required delivery failures no longer report success (#126164)
* fix(cron): preserve required delivery completion

Record durable completion independently from payload execution so required delivery failure cannot delete one-shots or report successful waits.\n\nCloses #126163

* fix(cron): keep completion contracts acyclic

* fix(cron): keep delivery predicate private
2026-08-18 22:44:33 -07:00
Peter Steinberger 3550b174e9 fix(crabbox): derive machine classes from catalog (#126184) 2026-08-18 22:35:13 -07:00
Peter Steinberger 404eddbc6a fix(plugins): preserve subagent lifecycle results (#126167) 2026-08-18 22:22:20 -07:00
Peter Steinberger e38a06439e refactor: trim locale and QA fixture debt (#126139)
* refactor: trim locale and QA fixture debt

* fix(qa): preserve shared flow portability

* chore(qa): document shared flow branch

* fix(docs): align plugin SDK subpath catalog

* fix(ci): align shared docs and flow contracts
2026-08-18 22:17:19 -07:00
Peter Steinberger 5564671c4f fix(gateway): bound audit and Codex backlogs (#126154)
* fix(gateway): bound audit and Codex backlogs

Live Gateway SQLite lock failures and process heap pressure exposed two
independent queue owners. Route best-effort audit persistence through the
canonical shared-state connection with bounded contention retries, and remove
the per-notification Codex yield so the keyed turn queue can drain directly.

Follow-up to #126033 and #126073.

* fix(gateway): annotate raw SQLite cold-open probe

* test(codex): register notification burst shard
2026-08-18 21:44:09 -07:00
Peter Steinberger 4ffa2a4418 fix(gateway): avoid readiness flaps during Reef reconnects (#126151)
* fix(gateway): avoid readiness flaps during Reef reconnects

* docs: preserve plugin SDK private-local contract wording
2026-08-18 21:29:43 -07:00
Peter Steinberger 00482543ff fix(agents): bound Skill Workshop model projections (#126158) 2026-08-18 21:28:54 -07:00
Peter Steinberger 7bc994aee8 fix(install): avoid success after incomplete lifecycle changes (#125992)
* fix(install): make lifecycle mutations transactional

Standalone installers now apply npm-version-aware lifecycle approval. Updates verify and repair the installation before reporting success and preserve the prior install owner during method switches. Uninstall now exits nonzero when requested cleanup is only partially completed. Plugin update behavior is unchanged.

Closes #125925

* test(uninstall): assert aggregated live-owner failure

* fix(install): satisfy standalone shell checks

* fix(update): scan PATH for prior Git wrapper

* test(hooks): await Gmail watcher descendant exit

* fix(install): verify Windows npm candidate

* fix(ci): normalize package acceptance version

* fix(update): preserve staged local package links

* test(update): fold staged symlink coverage

* fix(update): retire every legacy Git wrapper

* test(docs): align consolidated ownership checks
2026-08-18 20:50:15 -07:00