Commit Graph

401 Commits

Author SHA1 Message Date
Peter Steinberger 12165769c7 refactor(agents): move OpenRouter failover ownership to its plugin and derive reason schemas from one tuple (#121898)
* refactor(agents): centralize failover ownership and reasons

* test(agents): move OpenRouter failover cases to plugin owner

* fix(agents): preserve prepared provider failover ownership

* test(agents): avoid failover mock shadowing

* fix(agents): preserve provider owner in error copy

* fix(agents): complete provider owner propagation

* chore(plugins): refresh failover type closure hashes
2026-08-11 04:30:18 -07:00
Peter Steinberger e71d56d557 feat(cloud): let cloud sessions spawn and message cloud children (#121846)
* feat(cloud): add nested worker session capabilities

Amp-Thread-ID: https://ampcode.com/threads/T-019feaaa-c7ed-769e-9f29-a3612bec72e7

* fix(cloud): harden nested worker sessions

Amp-Thread-ID: https://ampcode.com/threads/T-019feaaa-c7ed-769e-9f29-a3612bec72e7

* fix(cloud): repair exact-head integration

Amp-Thread-ID: https://ampcode.com/threads/T-019feaaa-c7ed-769e-9f29-a3612bec72e7

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-11 02:07:49 -07:00
Ayaan Zaidi ba9e72c17f fix(heartbeat): deliver to the last conversation by default (#121892)
Unset heartbeat.target silently collapsed into the explicit "none" opt-out: heartbeats ran every 30m by default, elected notifications were dropped with only an in-memory event, and health read fine. Unset now resolves to "last" (the most recent conversation); explicit target: "none" keeps its internal-only contract. Polls skip pre-model with reason no-route while no route exists yet, and status/doctor surface the waiting-for-route state. Deliberate maintainer-owned default cutover: existing installs without a configured target start receiving heartbeat alerts in their last conversation after upgrade.

Fixes #121880

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 08:45:30 +00:00
Peter Steinberger ea06d72e85 feat(secrets): manage team secrets in Control UI (#121724)
* feat(secrets): add gateway store settings

* perf(control-ui): trim secrets startup copy

* perf(control-ui): reduce secrets startup payload

* fix(secrets): harden store mutation refresh

* perf(control-ui): meet secrets startup budget

* test(control-ui): update secrets navigation copy

* fix(ui): pluralize secret-detection count and drop duplicated dialog hint

* chore(protocol): regenerate gateway clients and SDK baseline after rebase

* fix(gateway): merge secrets store methods after project RPCs in advertised order

* chore: leave changelog to release generation

* test(gateway): retain desktop launch train coverage
2026-08-11 07:20:38 +00:00
Josh Avant 73a9eed95b refactor(audit): add canonical admitted-run context (#120534)
* feat(audit): carry canonical admitted execution context

* fix(agents): preserve admitted context across retries

* fix(worker): fence legacy launch dialect

* test(gateway): track approval temp dirs

* fix(plugin-sdk): preserve harness attempt compatibility

* fix: close delegated run authority at owner boundaries

* fix: internalize delegated authority validators

* refactor: split delegated authority proof surfaces

* refactor: centralize command admission identity

* test: claim runtime tool authority

* fix(gateway): keep lifecycle cleanup within static budgets

* fix(agents): revalidate harness policy authority

* fix(agents): fence awaited approval capability results

* test(copilot): supply required harness capability fixtures

* fix(agent): preserve scoped embedded run admission

* fix(agent): preserve keyless and worker authority

* test(agent): bind incomplete-turn authority

* docs: preserve execution authority invariants

* chore(plugin-sdk): regenerate API baseline

* fix(gateway): notify pending claim closure

* fix(gateway): revalidate delegated tool authority

* fix(plugin-sdk): keep source guard internal

* fix: close delegated authority races

* fix: revalidate delegated side effects

* fix: close harness authority projection gaps

* fix: align authority integration types

* fix: isolate settled harness finalization

* fix: fence recovery identity finalization

* fix: preserve committed session worktrees

* fix: preserve worker placement agent identity

* fix: fence active harness tool work

* fix(plugins): restore embedded run admission owner

* chore(plugin-sdk): compose integrated surface budgets

* fix(copilot): keep finalization attempt type internal

* fix(plugins): complete admission owner type imports

* test(harness): use settled finalization attempt shape

* fix(security): retain exact side-run and approval authority

* fix(security): preserve protected authority through terminal sweep

* fix(agents): follow moved recovery store owner

* fix(ci): align integrated authority owners with gates

* fix(plugins): distinguish embedded agent adapter export

* chore(plugin-sdk): regenerate API baseline after rolling integration

* refactor(gateway): keep session authority within owner budgets

* fix(gateway): keep session helpers private

* docs(plugin-sdk): name the V2 parameter subpath

* chore(integration): reconcile worker and SDK surfaces

* docs(plugin-sdk): require the V2 host API floor

* chore(plugin-sdk): regenerate after proxy-auth integration
2026-08-10 23:15:20 -05:00
Peter Steinberger 7dbc2916a3 fix: cloud workers work with trusted-proxy browser auth (#121671)
* fix(ui): make cloud recovery scope gateway-owned

Allow trusted-proxy and other authorized browser sessions to use cloud workers without deriving recovery ownership from client-visible credentials or Web Crypto. The Gateway now emits an opaque principal-bound recovery scope.

* test(gateway): type recovery scope fixture

* fix(ui): preserve cloud recovery across upgrades

Keep the shipped credential-derived scope for older v4 Gateways and migrate credential-proven pending recovery rows to the Gateway-owned namespace before publishing readiness.

* perf(ui): lazy-load recovery migration

* fix(ui): preserve canonical recovery promotion

* test(ui): use deterministic provider navigation

* fix(ui): authorize recovery scope migration

* build(plugin-sdk): refresh recovery compatibility baseline

* test(gateway): expect recovery migration authorization
2026-08-10 20:52:55 -07:00
Peter Steinberger b5d5ec340f feat(cloud-workers): add desktop apps and browser autonomy (#121475)
* feat(cloud-workers): add desktop apps and browser autonomy

provider-attested Browser/Terminal launchers, shared visible loopback CDP Browser tool, no MCP/cookies/generic command.

* feat(ui): add cloud desktop app launcher

* docs(gateway): document cloud desktop apps and browser autonomy

* perf(ui): trim desktop launcher startup copy

* refactor(ui): simplify desktop launch feedback

* perf(ui): reuse desktop app labels

* fix(ui): keep desktop launch failures actionable

* fix(crabbox): allow browser bootstrap to finish

* fix(cloud-workers): honor provider provision budgets

* fix(cloud-workers): persist browser screenshot receipts

* fix(cloud-workers): bound browser screenshot lifecycle

* fix(cloud-workers): avoid replaying desktop launches

* test(cloud-workers): isolate browser runtime integration

* refactor(cloud-workers): tighten desktop runtime boundaries

* test(cloud-workers): keep browser runtime mock synchronous

* fix(cloud-workers): break gateway type import cycle

* fix(ci): settle admitted setup sessions in tests

* build(plugin-sdk): refresh desktop app contract

* ci: refresh merge-tree validation

* build(plugin-sdk): regenerate desktop app baseline

* style(gateway): format merged method order test
2026-08-10 20:31:07 -07:00
Peter Steinberger b985d5a1ed feat: stream live subagent progress in task events (#121549)
* feat(tasks): stream live subagent activity

* fix(tasks): correlate edit activity from start events

* fix(gateway): sanitize live task activity

* test(reply): align custody harnesses with lifecycle

* fix(outbound): preserve post-send recovery evidence

* fix(types): align reply harnesses with current contracts

* fix(tasks): preserve activity liveness and SDK parity

* test(sdk): avoid unsafe task summary assertion

* chore(contracts): refresh Plugin SDK API baseline
2026-08-10 18:37:58 -07:00
Peter Steinberger 32894a3ba5 feat: start sessions from registered projects (#121465)
* feat(gateway): add project registry sessions

* fix(gateway): authorize project branch discovery

* test(gateway): reuse worktree test imports

* fix(protocol): register projects schema owner

* fix(gateway): gate project paths by write scope

* feat(control-ui): register projects from folder browser

* refactor(gateway): extract session diff baseline preparation

* fix(gateway): honor admin scope in project listings
2026-08-10 17:56:12 -07:00
Ayaan Zaidi 9935ca3b30 fix(approvals): bind native requests to channel accounts (#121673)
Native approval delivery and resolution now stay bound to the originating or explicitly targeted channel account. Unbound requests fail closed across multiple eligible accounts; trusted reviewer-less SDK callers remain compatible.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-11 01:42:41 +05:30
Peter Steinberger f4bac99a81 feat(secrets): add SQLite-backed secret store (#121559) 2026-08-10 07:08:40 -07:00
Peter Steinberger 3b3c540896 refactor: remove dead branches and test-only helpers (#121345)
* refactor: remove dead branches and test-only helpers

* fix: preserve codex cleanup error causes

* fix: preserve gateway error code compatibility

* chore: update plugin sdk api baseline

* docs: fix live cache runner path
2026-08-10 06:47:43 -07:00
Peter Steinberger 8e1c238c1c fix(cron): prevent invalid timestamps from stranding jobs (#121394)
* fix(cron): harden scheduling timestamp boundaries

Amp-Thread-ID: https://ampcode.com/threads/T-019fe949-92e4-76bd-8cfa-aea44fcfaebe

* test(prompts): refresh cron tool snapshots

Amp-Thread-ID: https://ampcode.com/threads/T-019fe949-92e4-76bd-8cfa-aea44fcfaebe

* test(cron): keep config revision fixture Date-valid

Amp-Thread-ID: https://ampcode.com/threads/T-019fe949-92e4-76bd-8cfa-aea44fcfaebe

* refactor(cron): consolidate scheduling lifecycle

Amp-Thread-ID: https://ampcode.com/threads/T-019fe949-92e4-76bd-8cfa-aea44fcfaebe

* refactor(cron): keep task history dependencies acyclic

Amp-Thread-ID: https://ampcode.com/threads/T-019fe949-92e4-76bd-8cfa-aea44fcfaebe

* fix(cron): canonicalize timestamp auto-disable

Amp-Thread-ID: https://ampcode.com/threads/T-019fe949-92e4-76bd-8cfa-aea44fcfaebe

* test(cron): verify startup overflow notifications

Amp-Thread-ID: https://ampcode.com/threads/T-019fe949-92e4-76bd-8cfa-aea44fcfaebe

* chore(ci): repair main baseline gates

Amp-Thread-ID: https://ampcode.com/threads/T-019fe949-92e4-76bd-8cfa-aea44fcfaebe

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-10 03:20:23 -07:00
jesse-merhi 2300de7162 Gateway: negotiate Custodian wizard cancellation 2026-08-10 20:01:24 +10:00
Jesse Merhi d31c20c416 docs: preserve protocol changelog spacing 2026-08-10 20:01:24 +10:00
Jesse Merhi e863839577 docs: remove release-owned cancel notes 2026-08-10 20:01:24 +10:00
Jesse Merhi d9d0b30ce3 System agent: keep wizard cancel local 2026-08-10 20:01:24 +10:00
Jesse Merhi 890a4b0089 Control UI: add direct Custodian wizard cancel 2026-08-10 20:01:24 +10:00
Peter Steinberger bab4546b41 refactor(gateway): remove dead rpc surfaces (#121387) 2026-08-10 02:41:57 -07:00
Ayaan Zaidi 4b0151682e refactor(commitments): remove inferred follow-up subsystem
Remove hidden follow-up extraction, heartbeat delivery, CLI, docs, and supporting tests/tooling. Existing commitment records remain inert pending separately approved cleanup.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-10 13:48:32 +05:30
Peter Steinberger f6298bf84d fix(workers): preserve disappeared-worker failures across restarts (#121122)
* fix(workers): persist placement terminal failures

* fix(workers): refresh placement protocol clients

* refactor(workers): isolate error formatting

* fix: integrate cloud terminal state with current main

* chore(plugin-sdk): refresh API baseline

* refactor(ui): inline one-use cloud terminal-reason banner helper

Keeps the Control UI startup JS bundle inside its 317 KiB gzip budget
(the helper + type-only import tipped it by 16 bytes).

* refactor(ui): trim terminal-reason lookup to type-erased optional access

Recovers the last gzip byte of the Control UI startup budget
(324609 B vs the 324608 B limit).
2026-08-10 00:36:52 -07:00
Peter Steinberger 3621c4b511 feat: browse and start sessions inside agent workspaces (#121417)
* feat(gateway): allow workspace-contained browsing

* fix(ui): preserve canonical workspace selections
2026-08-09 23:57:46 -07:00
Patrick Erichsen d4c3b9e783 refactor(sessions): remove custom icon feature (#121263)
* refactor(sessions): remove custom icon feature

* test(sessions): expect legacy icons to be stripped

* fix(gateway): preserve retired icon request compatibility

* chore(plugin-sdk): refresh API baseline

* fix(plugins): reserve retired session icon slot
2026-08-10 04:51:56 +00:00
Peter Steinberger 1367e9a79f refactor(packages): collapse duplicate type surfaces (#121340)
* refactor(packages): collapse duplicate type surfaces

* chore(generated): refresh package contract artifacts
2026-08-09 20:45:15 -07:00
Peter Steinberger 3d5f916523 fix(protocol): align fallback reason schemas (#121334)
Worker live events rejected tls_certificate fallback payloads because duplicated closed reason lists had drifted. Establish one canonical dependency-light fallback vocabulary and share its explicit TypeBox schema across worker and cron protocol boundaries.
2026-08-09 19:02:23 -07:00
Peter Steinberger 9066ba948a fix(gateway): accept tls_certificate in worker-live fallback reason schema (#121285)
* fix(gateway): accept tls_certificate in worker-live fallback reason schema

* chore(gateway): refresh plugin SDK API baseline

* test(gateway): move worker-live failover conformance guard
2026-08-09 18:21:29 -07:00
Peter Steinberger d3c84674e8 feat(gateway): task-suggestion acceptance modes with compact split-button card (#121173)
* feat(gateway): task-suggestion acceptance modes with compact split-button card

- taskSuggestions.accept gains additive mode (worktree default | local | cloud | session) + cloudProfileId; operator.admin unchanged; worktree requests stay {taskId}-only for older gateways
- local reuses the plain-cwd create; cloud mirrors the Control UI create-empty -> sessions.dispatch -> send sequence with pre-claim profile validation and full rollback; session delivers the prompt into the source session (steer single active run, plain turn when idle, ambiguous refused) and can only cancel the chip on failure, never touch the source session
- Control UI card redesigned per owner reference: repo-basename eyebrow, clamped summary, instructions expander, split button with per-profile cloud items or a disabled "No cloud environment configured" hint
- TUI gains the same modes as selector rows with capability gating and double-Enter arming

Release-note context: operators now choose where an accepted follow-up runs — isolated worktree (default), the project checkout, a configured cloud worker, or as the next instruction in the current session — from a compact suggestion card.

* fix(gateway): negotiate task-suggestion acceptance modes and enforce steerable-run invariant

- Gate non-worktree task-suggestion actions on the negotiated Gateway capability.
- Require exactly one steerable run ID before delivering into an active source session.
2026-08-09 12:21:21 -07:00
Peter Steinberger 8fdf7570a1 feat(gateway): live Desktop observer for cloud workers (Labs) (#120727)
* feat(gateway): live desktop observer for cloud workers

Adds live observation for cloud worker desktops through the gateway and Crabbox plugin, including desktop provisioning, persisted desktop metadata, tunneled WebSocket proxying, and the worker.desktop.observe protocol method.

The gateway, Crabbox plugin, and gateway protocol surfaces remain off by default behind the cloudWorkers.desktop Labs flag.

* feat(ui): Desktop panel for cloud worker observation

* docs(gateway): document cloud worker desktop lab

* fix(ci): regenerate contract baselines after rebase

* fix(protocol): regenerate Android gateway methods

* fix(ci): align rebased SDK and lint baselines

* fix(gateway): enforce view-only RFB boundary and fence desktop teardown

* fix(gateway): tighten RFB filter surface

* fix(state): keep pre-desktop databases readable and harden view-only RFB

* fix(gateway): fence desktop observer upgrades behind work admission

* fix(gateway): bind desktop observer tokens to their owner epoch

* fix(ci): regenerate config and SDK baselines after rebase

* fix(ci): regenerate native protocol and SDK baselines

* fix(ci): regenerate contracts after main rebase

* fix(state): register desktop metadata as lazy additive

* fix(ci): regenerate SDK baseline after final direct-merge rebase
2026-08-09 09:37:01 -07:00
Peter Steinberger 9a96375e60 feat(gateway): session-catalog terminal start plans behind cliAgents gate (#121020)
* feat(gateway): add session-catalog terminal start plans

* refactor(gateway): split catalog terminal start handler

* fix(gateway): enforce catalog terminal start eligibility

* test(gateway): split session catalog snapshot coverage
2026-08-09 08:13:39 -07:00
Peter Steinberger 7dcb4fb760 feat(talk): broker realtime sideband control (#121054)
* feat(talk): broker OpenAI realtime sideband

* test(openai): prove audio-only sideband offer

* fix(talk): harden realtime sideband control

* fix(talk): restore sideband session update fence

* fix(talk): recognize GA function output events

* refactor(talk): unify realtime broker session leases

* fix(talk): use PCM audio for WebRTC sideband

* chore(plugin-sdk): refresh API baseline
2026-08-09 05:14:20 -07:00
Colin Johnson c44b01614d fix: profile saves leave stale sidebar identity (#120791)
Profile identity changes now refresh immediately across connected browsers, including revisioned avatar URLs that avoid stale cached images.

Fixes #120784
Prepared head SHA: 20fb9ea42d
Co-authored-by: Colin Johnson <211764741+Solvely-Colin@users.noreply.github.com>
Co-authored-by: Shakker <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-08-09 11:58:19 +01:00
Peter Steinberger 411777dc1f fix(gateway): recover cloud worker placement state (#120976)
* fix(gateway): recover cloud worker placement state

Related: #120953

* test(gateway): type failed placement fixture

Related: #120953
2026-08-09 01:01:31 -07:00
Dallin Romney dcdbd7aab6 fix(update): prevent stable upgrade notices on extended-stable (#118518)
* fix(update): keep extended-stable update notices on channel

* fix(update): repair extended-stable CI checks

* fix(update): retain verified extended-stable channel

* fix(update): normalize gateway install surface

* test(update): split effective channel coverage

* fix(update): resolve verified extended-stable status paths

* fix(update): preserve Sparkle fallback on missing channel

* fix(update): restore effective channel after rebase

* fix(update): repair rebased CI coverage
2026-08-09 16:01:14 +08:00
Peter Steinberger 5297429b3e fix(gateway): keep task suggestions recoverable (#120940)
Abandon unexpected acceptance failures instead of leaking accepting slots. Reject non-Git or blank suggestions before side effects, and protect unseen pending suggestions ahead of accepted replay state.
2026-08-08 23:38:50 -07:00
Vincent Koc 587def9c9d fix(gateway): keep new nodes compatible with older gateways (#119981)
* fix(gateway): keep new nodes compatible with older gateways

Punchcard-Session: golden-brook-lantern-zp

* fix(gateway): clear protocol compatibility check failures

Punchcard-Session: cobalt-timber-orchard-d1

* fix(node-host): retire manifest before inventory refresh

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): keep new nodes compatible with older gateways

Punchcard-Session: golden-brook-lantern-zp

* fix(gateway): clear protocol compatibility check failures

Punchcard-Session: cobalt-timber-orchard-d1

* fix(node-host): retire manifest before inventory refresh

Punchcard-Session: cobalt-timber-orchard-d1

* docs(gateway-client): describe compatible admission

Punchcard-Session: cobalt-timber-orchard-d1

* fix(node-host): ignore retired publication failures

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): keep new nodes compatible with older gateways

Punchcard-Session: golden-brook-lantern-zp

* fix(gateway): clear protocol compatibility check failures

Punchcard-Session: cobalt-timber-orchard-d1

* fix(node-host): retire manifest before inventory refresh

Punchcard-Session: cobalt-timber-orchard-d1

* docs(gateway-client): describe compatible admission

Punchcard-Session: cobalt-timber-orchard-d1

* fix(node-host): ignore retired publication failures

Punchcard-Session: cobalt-timber-orchard-d1

* test(node-host): split optional publication coverage

Punchcard-Session: cobalt-timber-orchard-d1

* fix(node-host): retain latest rejected inventory

Punchcard-Session: cobalt-timber-orchard-d1

* chore(gateway-protocol): remove release-only changelog edits

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): normalize blank node host families

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): normalize node metadata before pairing

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): negotiate legacy node metadata

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): complete rolling node convergence

Punchcard-Session: cobalt-timber-orchard-d1

* fix(node-host): honor publication retry backoff

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): close rolling compatibility gaps

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): migrate node pairing rollback metadata

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): scope legacy support to wire admission

Punchcard-Session: cobalt-timber-orchard-d1

* test(gateway): type legacy hello protocol fixture

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): converge node protocol after upgrade

Punchcard-Session: cobalt-timber-orchard-d1

* fix(node-host): preserve publication retry backoff

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): honor latest node compatibility state

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): recover protocol negotiation after rollback

Punchcard-Session: cobalt-timber-orchard-d1

* fix(gateway): guard legacy metadata lookup

Punchcard-Session: cobalt-timber-orchard-d1
2026-08-09 13:16:37 +08:00
Peter Steinberger 73bdb4b924 feat(agents): record run-end worktree cleanup outcome; prove Workboard dirty retention (#120434)
* feat(agents): record run-end worktree cleanup outcome

Persist removed, retained, and failed run-end cleanup outcomes on managed worktree records. Operators and QA can inspect the durable fact through worktrees.list and openclaw worktrees list --json.

Release note: Managed worktree run-end cleanup now records why a checkout was removed or retained in worktree list JSON.

* test(qa): prove dirty worktree retention outcome

* chore(protocol): regenerate swift gateway models

* fix(agents): harden worktree cleanup recovery

Register run_end_cleanup_json as a lazy compatible column so same-version v6 index repair and read-only doctor migration can recover databases created before the column existed.

Type removal contention at the registry boundary; unexpected claim failures now best-effort record a bounded failed outcome and rethrow the original error.

* fix(ci): clear repo-wide lint debt blocking merge gates

The red-main landing rule requires this PR to repair repository-wide merge-gate debt instead of bypassing it. Apply the current lint contracts mechanically and split turn-transition coverage into a concept-named sibling with per-file-safe test state.

Exact line delta: +676/-574 (net +102) across 44 test/support files.

* fix(ci): preserve cached health refresh proof

Require the public refresh call to exist before accepting that sensitive fields were omitted, so the boundary proof cannot pass on a missing call.

* fix(ci): correct test typing left by the lint sweep

Literal-widened totalTokensVersion fixtures, a WebSocket RawData overload
mismatch, and the protocol schema document cast broke check-test-types
after the repo-wide lint repair. Aligns the fixtures with SessionEntry,
narrows Buffer handling per RawData, and keeps the JSON-shaped undefined
omission under structuredClone.

* test(agents): reuse upstream resource-loader test support

The session-loop split and #120463's helper extraction landed the same
createResourceLoader/createCompactionHandlers twice; the rebase kept both,
orphaning main's agent-session-loop-resource-loader.test-support.ts and
failing the dead-code gate. Import the upstream helpers and delete the
duplicates.

* fix(agents): reject finalized rows at the worktree removal claim

Address the accepted ClawSweeper late-claim finding by rereading and rejecting missing or finalized worktree rows inside the synchronous removal-claim transaction.

Preserve the authoritative cleanup invariant: finalized contenders record nothing, while retained-busy is written only while the row remains live.

* refactor(agents): reuse registry update for busy outcomes

Keep the live-row conditional write in the canonical registry update path so the finalized-claim repair stays below the registry max-lines ratchet without weakening the authoritative-outcome invariant.

* test(agents): drop session test duplicates after rebase

Keep current main as the canonical owner of next-turn lifecycle coverage and correctness test support after replaying the older lint-debt split.

* fix(agents): guard post-abort cleanup outcomes against finalization

After abortWorktreeRemoval releases a stale remover's claim, its retained or
failed write raced a finalizing remover and could overwrite the authoritative
removed-lossless fact. Route every retained/failed write through the live-row
condition; only the finalizing remover's own removed-lossless write stays
unconditional.

* fix(agents): persist the removal outcome atomically with finalization

A delayed removed-lossless write after remove() finalized could race a
restore plus newer cleanup and overwrite the newer operator-visible fact.
The run-end outcome now rides remove()'s finalization update; every other
cleanup write stays live-row conditional, so no post-finalize write path
remains.

* test(qa): restore strict cached-health contract assertions

The lint sweep's Boolean() coercions let truthy non-booleans satisfy the
wire-typed cached-meta contract. Assert the literal boolean for unknown-typed
fields and use nullish-coalesced strict equivalents for boolean chains.

* fix(agents): clear the stale cleanup outcome when restoring a worktree

A restored checkout begins a new lifecycle; leaving the removed-lossless
fact on the live row showed operators a stale result until the next
cleanup. Restore clears the recorded outcome and the regression asserts
the cleared state before the next cleanup records fresh truth.

* fix(agents): scope stale cleanup outcomes to their observed lifecycle

A stale remover's retained/failed write raced a concurrent remove-plus-
restore: the revived row is live again, so the live-row condition alone
could stamp a prior-lifecycle outcome. Condition those writes on the
activity stamp the remover observed; restore bumps lastActiveAt, making
any prior-lifecycle write a no-op.

* fix(agents): advance the restore activity stamp within one millisecond

Stale cleanup writes fence on the activity stamp they observed; a restore
completing in the same millisecond could revive the row with an identical
stamp and let the fence match. Restore now always advances past the
stored value, and the ABA regression pins the clock to prove the
same-millisecond case.
2026-08-08 20:32:11 -07:00
Peter Steinberger 121ce7faed fix(worker): preserve long Responses sessions across cloud handoff (#120803)
* fix(worker): preserve Responses replay across handoff

Long OpenAI Responses cloud-worker sessions retain authoritative compaction replay through windowing and fail visibly when it cannot be preserved.

* test(worker): align replay fixture with frame limit
2026-08-08 19:11:29 -07:00
Peter Steinberger c8cd98cf52 refactor(gateway): centralize connect failure classification (#120505)
* refactor(gateway): centralize connect failure classification

* fix(gateway): project connect failure into status JSON

* fix(protocol): restore remote-auth context in pairing remediation

* fix(gateway): classify generic probe failures by close reason

* fix(gateway): keep transport closes unreachable

* fix(gateway): preserve rate-limit diagnostics

* fix(gateway): preserve typed rate-limit failures
2026-08-08 18:34:01 -07:00
Peter Steinberger b4cedfd40e fix(ui): show dev checkout commit lag in Updates (#120769)
* fix(ui): report dev checkout update status

Show tracked-upstream commit lag and verified install/commit timestamps in Settings > Updates. Verify the post-restart Git revision before reporting success, and surface same-revision updates as an explicit no-op unless plugin convergence changed the install.

* test(ui): expect authoritative update reconciliation
2026-08-08 17:21:42 -07:00
Peter Steinberger 51944498eb refactor(gateway): generalize bulk session patches (#120629)
* refactor(gateway): generalize bulk session patches

* fix(gateway): normalize bulk session fences

* refactor(gateway): simplify normalized target fence

* test(ui): align disconnected session wording
2026-08-08 15:00:09 -07:00
Peter Steinberger 0b85f9c174 feat: resolve short session references in the gateway (#120512)
* feat(gateway): resolve short session references

* refactor(ui): delegate short session resolution to gateway

* fix: complete short session resolver integration

* fix(gateway): filter deleted-agent short sessions

* fix(ui): support older gateway short links

* docs(web): qualify short-link candidate limits for older gateways

* refactor(protocol): split session resolve schema

* fix(gateway): filter session resolver visibility
2026-08-08 12:52:06 -07:00
Peter Steinberger 47f78a32eb fix(ai): preserve long Responses sessions after server compaction (#120457)
* fix(ai): preserve Responses server compaction state

Persist opaque Responses compaction items as fenced provider replay state so long stateless sessions can resume authoritative compressed history without exposing it in display or diagnostics. Carry state through worker transcripts and prune replay prefixes without splitting tool pairs.

Release note: Preserve long OpenAI Responses sessions across server-side compaction and worker restarts.

Related: #95788

* test(ai): align long-context fixtures with CI contracts

Make tool-result fixtures type-complete, use the canonical model selector helper, remove unused test-helper exports, and route the paid long-context live probe through the dedicated Gateway profile shard.

* test(ai): type mocked Responses terminal events

Give the mock SSE event collection an explicit open event shape so terminal response events coexist with output-item events under the root test typecheck.

* fix(ai): suppress rejected compaction replay

Persist a route-fenced suppression tombstone when encrypted-content recovery rejects a compaction item, so later turns do not retry the same opaque state. Preserve the tombstone through transcript redaction and cover successful fallback followed by the next turn.

* fix(ai): keep compaction suppression transport-private

Keep the suppression contract local to its sole Responses transport owner and make the regression fixture satisfy root type and lint checks without widening the Plugin SDK surface.

* refactor(ai): remove compaction suppression re-export

* fix(ai): scope compaction suppression to replay route

Keep foreign-route rejection tombstones from hiding the newest compatible Responses compaction while preserving same-route suppression.

* fix(ai): harden Responses replay recovery

Stage encrypted replay recovery so compaction is only suppressed after an attributable rejection. Preserve terminal ordering and keep provider replay within worker frame budgets without truncating opaque state.

* refactor(ai): centralize Responses output indexes

Keep normalized output identity tracking in the stream-slot owner, move response failure state to its diagnostic owner, and remove the obsolete replay clone export so exact-head static gates remain shrink-only.

* fix(ai): retain idless terminal tool identity

Use the canonical empty identity only when a provider supplies neither call nor item id, preventing terminal recovery from duplicating a done-only tool call while preserving stronger identities when available.

* fix(sessions): hide provider replay from public events

* fix(ai): stage encrypted replay recovery

* fix(ai): keep replay attempt kind internal

* fix(ai): route Azure through replay recovery

Use the shared encrypted-content retry owner for Azure Responses so compaction suppression and prompt-observer variants stay coherent across transports.

* fix(ai): harden replay persistence boundaries

Fence Azure replay by the resolved request endpoint, drop invalid replay during transcript sanitization, and surface worker-launch replay omissions through the existing redacted diagnostic path.
2026-08-08 11:55:26 -07:00
Peter Steinberger e3de98a451 feat(update): scheduled update campaigns with countdown, dev-channel auto-update, and Updates settings page (#120506)
* feat(update): scheduled update campaigns with countdown, dev-channel auto-update, and Updates settings page

* fix(ui): satisfy update campaign deadcode checks

* feat(update): extend scheduled update campaigns

* test(ui): include Updates page in settings sidebar search expectations

* fix(update): end campaigns when apply fails

* fix(update): pin dev campaign applies to the announced commit

* test(ui): align update e2e fixtures

* fix(update): pin adopted dev updates to the announced commit

* docs(update): document automatic dev update campaigns

* fix(ui): gate automatic dev updates on git installs

* fix(gateway): scope detailed update metadata to read-capable clients

* fix(gateway): break post-attach madge cycle with a leaf client-lookup type

* chore(protocol): regenerate clients after rebase

* test(gateway): update method tail after rebase

* fix(update): preserve campaign target and hold state

* test(update): align adoption mocks and split handoff suite

* test(update): route split handoff suites on Windows
2026-08-08 11:19:53 -07:00
Peter Steinberger 876a3f0d8f fix(ui): bulk session archive no longer stalls per thread (#120493)
* perf(ui): batch session archive requests

* fix(ci): sync bulk archive protocol surfaces

* fix(plugins): validate bulk archive ownership

* fix(ci): restore current main quality gates

* fix(ui): bound bulk archive dispatch

* fix(ui): bound bulk archive dispatch

* fix(ui): preserve bulk archive compatibility

* fix(ui): recover metadata-less archive fallback
2026-08-08 07:53:43 -07:00
Peter Steinberger fa0fcef9f6 fix(sessions): require provenance for fresh context-size facts (#120497) 2026-08-07 23:06:30 -07:00
Peter Steinberger 48639663b0 chore(release): prepare 2026.8.1 (#120375) 2026-08-07 18:44:12 -07:00
Peter Steinberger fa9626c4e1 refactor(steering): make active-run admission exact and atomic (#120285)
* refactor(steering): make admission exact and atomic

* fix(steering): bind targets by run identity

* fix(steering): inject before reply dispatch

* fix(steering): preserve backend injection modes

* fix(steering): target session suggestions

* fix(steering): preserve sibling delivery contracts

* style(steering): satisfy exact-head lint

* fix(steering): preserve targetless protocol compatibility

* fix(steering): preserve exact targets through replies
2026-08-07 16:58:04 -07:00
joshavant 026f4045b7 Revert "fix(protocol): preserve gateway session attribution across node runs"
This reverts commit 735f176b01.
2026-08-07 18:40:17 -05:00
joshavant 75eeacd445 Revert "docs(protocol): record node attribution envelope"
This reverts commit ec023a4336.
2026-08-07 18:40:17 -05:00
joshavant d4c9a4d8f1 Revert "feat(audit): preserve exact agent execution provenance"
This reverts commit 79b8775bc9.
2026-08-07 18:40:17 -05:00