Commit Graph

19601 Commits

Author SHA1 Message Date
Peter Steinberger bbf7454b17 fix(codex): retain structured tool result details (#125610) 2026-08-17 22:13:33 -07:00
Peter Steinberger 69a0f2d0ff fix(browser): keep screenshot sharing hints capability-neutral (#125597)
Browser screenshot results always named the message tool even when policy had
removed it from the model's effective tool surface. Report the staged sanitized
outbound copy and its path without naming another independently gated tool, so
the result remains actionable without becoming hallucination bait. Update the
vision, fallback, and raw-image result tests to protect that contract.
2026-08-17 22:07:17 -07:00
Peter Steinberger 7fc3371eac fix(codex): enforce hosted search domains for web fetch (#125574)
* fix(codex): apply hosted search domains to web fetch

* fix(net): preserve allowlist error wording

* fix(codex): enforce search domains in side questions
2026-08-17 21:49:35 -07:00
Josh Avant 916aca13f3 feat: record subagent execution lineage (#122015)
* feat(audit): record subagent execution lineage

* fix(audit): type-check spawn lineage validation

* docs: preserve spawned-run lineage invariants

* fix(audit): preserve lineage for worker spawns

* fix(audit): bind worker lineage to live authority

* fix(audit): keep lineage carrier private

* fix(sessions): preserve ACP participant recording

* fix(audit): keep lineage out of runtime bearer

* fix(audit): keep lineage type private

* test(audit): match current worker claim shape

* test(audit): preserve readonly lineage result

* fix(audit): redeem spawn lineage privately

* fix(audit): preserve lineage redemption on copy

* test(audit): prove nested worker spawn lineage

* fix(audit): restore execution identity CI gates
2026-08-17 21:41:30 -07:00
Peter Steinberger 7e7b860bca fix: preserve message delivery after result middleware (#125497)
* fix(agents): carry typed message delivery receipts

* fix(agents): preserve receipts across harness middleware

* fix(agents): preserve plugin broadcast delivery receipts

* fix(agents): preserve partial broadcast delivery receipts
2026-08-17 21:16:14 -07:00
Peter Steinberger b7ccf62fbd fix(voice-call): keep Funnel off occupied HTTPS ports (#125552)
* fix(voice-call): support alternate Tailscale HTTPS ports

* refactor(voice-call): keep Tailscale DNS lookup private

* fix(voice-call): preserve config normalization contract
2026-08-17 21:04:17 -07:00
Peter Steinberger 7242074ecc fix(memory): prevent silent context loss in resets and search (#125534)
* fix(memory): record transcript capture failures

* fix(memory): backfill filtered search results
2026-08-17 20:46:52 -07:00
Peter Steinberger ebac731352 fix(google-meet): classify gateway CLI fallback with typed guards instead of message matching (#125495)
* fix(google-meet): classify gateway CLI fallback with typed guards instead of message matching

Replaces the message-substring classifier in the Meet CLI's
gateway-unavailable local fallback with the structural
isGatewayTransportError/isGatewayClientRequestError guards (seam shared
verbatim with #125458). Decision surface chosen per Meet semantics:
uncoded transport closes (unreachable sockets, now incl. ETIMEDOUT/
ENETUNREACH) fall back; coded closes incl. 1006 deliberately do not,
since a live gateway may still own Meet browser sessions; unknown-method
fallback stays but requires a structural gateway request error. Adds
ECONNRESET to GATEWAY_UNREACHABLE_SOCKET_CODES so connect-time resets
wrap into the typed unreachable error instead of escaping raw.

* test(process): treat Linux zombies as terminated
2026-08-17 20:40:46 -07:00
Peter Steinberger 1acabe40a9 feat(voice-call): let realtime agents end calls (#125525) 2026-08-17 20:39:13 -07:00
Peter Steinberger 41c0818751 fix(openai): prevent realtime barge-in truncation errors (#125502)
* fix(openai): clamp realtime barge-in truncation

Clamp OpenAI Realtime barge-in truncation to the audio duration produced for each assistant item. This prevents interruption failures observed live when 3,700 ms of decoded audio was paired with a 3,760 ms transport-clock timestamp.

* fix(openai): propagate PCM sideband audio format

The browser sideband negotiated PCM16, but its bridge defaulted to G.711 for duration accounting. Propagate the negotiated format so truncation uses the actual PCM duration and closes ClawSweeper's in-scope finding.
2026-08-17 19:29:50 -07:00
Peter Steinberger 75fcaba919 fix(voice-call): survive gateway in-process restart and stop CLI dead-ends (#125458)
* fix(voice-call): survive gateway in-process restart and stop CLI dead-ends

The gateway's in-process restart (SIGUSR1 config reload) reuses the cached
plugin registry, so service stop/start run on the same retained voice-call
registration. Generation fencing from #120289 treated that restart as a stale
actor: stop retired the generation forever, the next start silently bailed,
and every voicecall.* RPC answered UNAVAILABLE "runtime generation is
retired" while the webhook never rebound.

- Registrations now hold a replaceable generation: service start after stop
  mints a fresh generation, takes over a running slot owned by a retired
  predecessor, and reports start failures to service health instead of
  silently returning.
- The voicecall CLI classifies gateway failures with typed guards instead of
  message substrings: standalone/store fallback only when the gateway is
  genuinely absent; reachable-but-failed (request errors, auth, timeout)
  exits with actionable text; a standalone webhook port collision explains
  that a running Gateway probably owns the port instead of raw EADDRINUSE.
- Plugin SDK gateway-runtime exports structural isGatewayTransportError /
  isGatewayClientRequestError guards (+2 documented surface budget).
- Regression coverage: same-registration stop/start restart, retired-owner
  takeover, typed CLI fallback classification, and a real token-auth gateway
  server routing voicecall.status through callGatewayFromCli.

* refactor(voice-call): split CLI modules and dedupe gateway fallbacks

Collapse the four duplicated gateway-or-runtime command blocks (speak, dtmf,
end, continue fallback) into one generic runGatewayManagerCommand helper —
the continue command owns its legacy-method fallback and operation polling
via a gatewayCall closure, so the helper carries no per-command policy.
Smoke reuses the shared initiateVoiceCall path instead of a bespoke
fallback.

Split the 988-line cli.ts into concept modules (cli-gateway-call,
cli-call-log, cli-command-io) and drop its grandfathered max-lines
suppression plus the now-stale max-lines and assertion-safety baseline
entries (shrink-only ratchet maintenance).

Behavior-frozen: stdout/exit semantics unchanged; net -2 production LOC.

* fix(voice-call): redact gateway URLs in CLI operational errors

ClawSweeper P1: the operational-error formatter interpolated the raw
connectionDetails.url, so a configured gateway URL with userinfo or query
tokens would print credentials into terminal output. Redact the composed
message once with the canonical net-policy redactor (also covers
remote-controlled close-reason text), exported through the plugin SDK
gateway-runtime subpath (+1 documented surface budget). Regression test
covers a credential-bearing URL in both the URL and message fields.
2026-08-17 18:59:19 -07:00
Peter Steinberger b82d07f466 feat(doctor): report unusable cloud worker profiles (#124995) 2026-08-17 18:58:52 -07:00
Peter Steinberger 26353983f3 fix(memory): record the omitted memory corpus in corpus=all searches (#125500)
memory_search corpus=all silently swallowed a returned memory-manager
error (missing sqlite, embedding misconfiguration, corrupted index):
the error branch was gated on !shouldQuerySupplements, so the tool
served wiki-only results in a payload with no error/warning field and
recorded no cooldown — a degraded search read as complete, contradicting
the tool description's own disabled-flag contract. The thrown-error path
already surfaced this; only the returned-error path was silent.

Record the cooldown in both cases and, when supplements still serve,
carry a warning naming the unavailable memory corpus in the payload.
2026-08-17 18:50:49 -07:00
Peter Steinberger b5b17c654b fix: keep Workboard visible in the sidebar (#125473)
* fix(ui): keep workboard in sidebar navigation

* test(ui): align workboard navigation ownership

* fix(ui): preserve saved workboard sidebar slots

* test(ui): shrink assertion safety baseline

* fix(plugins): bind native routes to bundled owners

* refactor(plugins): isolate native route policy
2026-08-17 18:44:39 -07:00
pash-openai 31a240c2b7 fix(slack): remove interrupted previews when turns finish silently (#125494) 2026-08-18 01:36:21 +00:00
Peter Steinberger 1ca4103fe9 fix(voice-call): expose realtime/streaming stream paths through tailscale serve/funnel (#125468)
* fix(voice-call): expose realtime/streaming stream paths through tailscale serve/funnel

Tailscale serve/funnel now auto-exposes the realtime and streaming WebSocket stream paths when those audio modes are enabled; previously Twilio <Connect><Stream> could not reach wss://<ts-host><streamPath> and realtime calls dropped after ~1s with no log.

Also: CLI voicecall expose mounts/clears stream paths symmetrically, partial tailscale mounts roll back on failure, and a warning now fires when a call's stream WebSocket never arrives within the token TTL. Reported/observed live by Peter Steinberger.

* fix(voice-call): make tailscale stream exposure atomic

Preserve configured public Tailscale prefixes when mapping realtime and streaming routes, and roll back the full route set when any mount fails. The CLI now uses the same transactional setup path and reports failure instead of accepting a partial exposure.

* fix(voice-call): expose Twilio's configured streaming path

Keep realtime routes under the public webhook prefix they advertise, while mounting streaming.streamPath exactly as Twilio emits it. This preserves the canonical public-to-local route list without expanding the provider API outside the scoped repair.
2026-08-17 18:10:45 -07:00
Josh Avant aea7ee7088 fix(matrix): keep user ID authorization case-sensitive (#125432)
* fix(matrix): preserve case-sensitive user IDs

* docs(matrix): clarify exact user ID casing

* fix(matrix): preserve exact IDs during resolution

* docs(matrix): clarify approval target casing
2026-08-17 18:08:25 -07:00
Peter Steinberger d32c09f843 fix(ai): accept retained messages from Responses compact (#124974)
* fix(ai): accept retained output from Responses compact

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(ai): replay retained compact messages

* fix(ai): scope retained compaction to OpenAI

* refactor(ai): reuse response endpoint contract

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 18:05:52 -07:00
Peter Steinberger 857c8c0864 fix(workboard): avoid false lifecycle warning during gateway startup (#125470)
* fix(workboard): defer lifecycle sweep until gateway ready

* test(workboard): cover lifecycle sweep after plugin reload
2026-08-17 17:56:04 -07:00
Peter Steinberger 720da745d9 fix(voice-call): keep realtime calls alive through brief stream reconnects (#125469)
* fix(voice-call): grace realtime stream disconnects

Share reconnect grace by CallSid and stream ID across classic and realtime streams while cleaning realtime bridge resources immediately.

Log terminal call reasons and document Twilio inbound voice and status callback setup.

* test(voice-call): align reconnect grace after rebase

Preserve the newly landed realtime generation and inactivity coverage while updating its terminal expectations for shared delayed finalization.

Remove the redundant replacement cross-product case so the lifecycle suite remains below the max-lines limit.
2026-08-17 17:51:46 -07:00
Marvinthebored 3d016975c3 fix(codex): degraded-engine continuity no longer projects the whole context window per turn (#125324)
* fix(codex): bound no-engine continuity projections to half the context window

A degraded or absent context engine sends fresh-thread continuity through
projectContextEngineAssemblyForCodex with the whole-window projection cap
((window - 20k) x 4 chars), so a large uncompacted transcript renders into
a single turn/start input consuming up to 90% of the model context window.
That turn fills its own native thread, the next turn's token fuse rotates
it, and the following fresh thread re-projects the transcript again -
observed as 11 near-window turn inputs on cold threads in one day
(openclaw/openclaw#125254).

Continuity projections now use a dedicated cap that reserves half the
context token budget, so the fresh thread keeps headroom for later turns
and the existing delta-resume path can actually engage. The active-engine
projection path keeps its whole-window cap unchanged.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* fix(codex): size continuity projections from real token cost, not the optimistic estimate

The continuity cap reserved half the context window in tokens but converted
that budget to characters with APPROX_RENDERED_CHARS_PER_TOKEN = 4, so at a
258,400-token window it permitted 516,800 chars. A live projection measured
703,134 chars for 226,146 input tokens, meaning that cap really costs about
166k tokens (~64% of the window), not the intended 129.2k.

Codex reports input tokens only after a turn and bounds turn input by
characters, so the projection cannot be sized in verified tokens before it is
sent. Convert the continuity budget at a conservative 3 chars/token instead,
which holds the reserved half in real tokens at the densest ratio observed.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* fix(codex): scope the continuity sizing claim to the density it was measured at

The half-window claim was stated as a guarantee, but the 3 chars/token
conversion rests on one observed projection. Input that tokenizes more densely
(CJK, base64, minified code) still exceeds the reserved half, so the constant is
renamed to CONTINUITY_EMPIRICAL_CHARS_PER_TOKEN and its comment says plainly
that it is an empirical floor rather than a bound.

The invariant test is narrowed to the measured density, and a companion test
pins the break-even ratio at 3 chars/token so the limitation is visible in the
suite instead of implied. Choosing between a guaranteed worst-case bound and
this empirical cap is a maintainer-owned tradeoff, left open on the PR.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* feat(codex): size continuity projections from the session's observed token density

Each completed Codex turn now records a calibration sample on the thread
binding: prompt chars actually sent vs the provider-reported input token cost
(uncached + cache read + cache write). The no-engine continuity cap converts
its half-window token budget at that observed ratio instead of a fixed
chars-per-token guess, so capChars / ratio stays at the reserved budget for
any content density - CJK, base64, and minified code included. The sample is
captured before startup rotation so a rotated-away thread's density still
sizes the fresh thread's projection; without a sample the empirical 3
chars/token default applies, and degenerate samples clamp to [0.5, 4].

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* fix(codex): make continuity calibration monotone - samples only tighten the cap

Red-team finding: a loose sample (up to 4 chars/token) followed by denser
content could size the cap past the empirical default, and stale or
non-continuity samples persist on the binding. Clamping the calibrated ratio
at the empirical default makes every such failure mode degrade to the
uncalibrated behavior instead of past it, and the invariant test asserts
monotonicity across poisoned samples directly.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

* fix(codex): record continuity calibration only from continuity projections

ClawSweeper P2: calibration ran after every successful turn filtered only by
prompt size, so a dense direct or active-engine prompt could persist a sample
whose density later shrinks continuity history it never measured. The
no-engine continuity appliers now mark the prompt state, finalize gates the
sample on that marker, and a cross-mode regression proves a large direct
prompt records nothing.

Related: #125254

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKtoZgXWnaAH8rmLiSydpN

---------

Co-authored-by: Marvinthebored <262704729+Marvinthebored@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 17:41:45 -07:00
Peter Steinberger 5028ce87b0 fix(code-mode): show the final tool surface in debug logs (#124934)
* fix(code-mode): isolate and harden diagnostics

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(code-mode): share payload diagnostics across wrappers

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(code-mode): preserve transport debug behavior

* refactor(code-mode): simplify tool observer carrier

* refactor(code-mode): keep spread-safe observer metadata

* test(qa-lab): allow elapsed cron wait budget

* docs(code-mode): preserve transport debug contract

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 17:32:14 -07:00
Peter Steinberger 244712f69a fix(voice-call): tear down realtime calls on stream close and media inactivity (#125463)
Realtime call teardown previously depended on an object-identity guard
that silently skipped ending the call record when bridge instances were
replaced, and had no transport-liveness backstop: a WS close that never
propagated left an answered call running forever. Bindings are now
socket-bound with current-generation terminal ownership, predecessor
audio is retired on successor admission (the overlapping-voices bug),
a 30s media-inactivity watchdog with 2s grace ends calls whose
transport dies silently, and every realtime call end is logged with
its cause.
2026-08-17 17:17:47 -07:00
Peter Steinberger e169520fef fix: surface swallowed failures on action paths (#125319)
* fix: surface swallowed failures on action paths

* fix(memory): propagate directory traversal failures
2026-08-17 17:14:05 -07:00
Jason (Json) 57c27b114b fix(workboard): stop lifecycle sync errors with multiple agents (#125429)
* fix(workboard): scope lifecycle session discovery

* test(gateway): isolate explicit ownership regression

* test(workboard): satisfy lifecycle lint

* fix(workboard): preserve captured unknown lifecycle
2026-08-17 17:34:42 -06:00
Peter Steinberger f67602a7b4 fix(codex): keep valid tools when one name is unsupported (#124932)
* fix(codex): quarantine invalid dynamic tool names

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(mcp): preserve safe server names across fallbacks

Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

* fix(codex): report retained tools after quarantine

* fix(codex): preserve shared MCP identifiers

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 16:33:39 -07:00
Peter Steinberger 39dc653c5e fix(telegram): unify targeted command grammar (#125195)
* fix(telegram): unify command target parsing

* fix(telegram): align supersede target routing
2026-08-17 16:22:46 -07:00
Peter Steinberger 682b05dcac test(browser): use per-run temp dirs for shared /tmp profile fixtures (#125440)
Remove the fixed /tmp/brave-profile and /tmp/openclaw-brave-profile fixture paths and add cleanup for per-run temporary roots.
2026-08-17 16:15:06 -07:00
Peter Steinberger 6e458d84bf feat(agents): configure per-agent GitHub identities (#125199)
* feat(agents): add managed GitHub identities

* fix(agents): use opaque GitHub setup handles

* style(codex): format managed shell environment call

* refactor(agents): own managed GitHub process identity

* chore(config): refresh baseline after rebase

* fix(ci): satisfy managed GitHub identity gates

* fix(ci): repair managed GitHub identity checks

* test(agents): align GitHub identity CI coverage

* fix(codex): scope login shell isolation

* fix(agents): let managed gh profiles authenticate

* fix(agents): harden GitHub identity setup

* test(gateway): align method suffix counts

* fix(ui): serialize GitHub identity mutations

* fix(protocol): generate GitHub configure requests

* test(ui): restore timers after identity tests

* fix(ui): preserve GitHub identity mutation ownership

* fix(agents): preserve native GitHub CLI auth
2026-08-17 15:54:03 -07:00
Peter Steinberger 2fc85bdc1b refactor(workers): make worker turns node-only (#125384)
* refactor(workers): bind placement modes to transports

* refactor(workers): split provider reconciliation

* Revert "refactor(workers): split provider reconciliation"

This reverts commit 0a1f97399b23eca81e99af45dd9ea616e266de54.

* refactor(workers): split lifecycle options

* test(workers): align SSH fixture with remote exec

* refactor(workers): encode one placement mode

* fix(workers): fence persisted transport mismatches

* style(workers): keep persisted lease note concise

* test(workers): declare node access fixture modes

* test(agents): match exec notifications by receipt
2026-08-17 15:46:59 -07:00
Josh Avant 9e7da04686 fix(memory): enforce live revocation (#125393) 2026-08-17 14:25:07 -07:00
zengLingbiao 37ca2c6900 fix(parallel): redact x-api-key reflected in web search error bodies (#120205)
* fix(parallel): redact x-api-key reflected in web search error bodies

* fix(parallel): use canonical tool-payload redactor for reflected error bodies

* fix(parallel): layer configured redactPatterns over header-shape redaction
2026-08-17 14:19:27 -07:00
Peter Steinberger 9f5776e071 fix(voice-call): status exits after offline lookup (#125354)
* fix(voice-call): keep status fallback read-only

* test(voice-call): assert offline status stays read-only

* chore: keep changelog release-owned

* test(voice-call): share status fallback harness
2026-08-17 12:34:19 -07:00
Peter Steinberger 7f3b65e783 fix(plugins): expose background service failures in health (#125366)
* fix(plugins): surface service runtime failures

* chore: leave changelog to release tooling
2026-08-17 12:18:50 -07:00
Peter Steinberger 0cc4d42f3f fix(discord): accept shipped nested DM access config (#125359)
Amp-Thread-ID: https://ampcode.com/threads/T-01a00a6a-b64e-74a5-8b15-2d3b966a468d

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 11:49:26 -07:00
Peter Steinberger 45e6784338 feat(gateway): run disposable cloud workers through node transport (#125288)
* feat(gateway): converge cloud workers onto nodes

* fix(gateway): honor public URL for cloud enrollment

* fix(crabbox): execute cloud bootstrap package binary

* fix(gateway): bind cloud nodes in pairing transaction

* fix(crabbox): prefer exact installed cloud bootstrap

* fix(gateway): complete cloud node bootstrap

* fix(gateway): enforce cloud worker capability boundaries

* fix(gateway): complete cloud node migration

* fix(gateway): preserve paired node roles on teardown
2026-08-17 11:49:06 -07:00
Peter Steinberger 0c9d1e468c perf(nostr): replace startup drain wait with completion gate (#125355) 2026-08-17 11:44:55 -07:00
Peter Steinberger 976d99995a perf(test): await 1Password descendant cleanup (#125321) 2026-08-17 09:48:00 -07:00
Peter Steinberger 7170a6231a feat(agents): unify agent status into a durable progress_card (#125125)
* feat(agents): unify agent status into a durable progress_card

Replace the write-only update_plan to-do tool and the fragmented plan
rendering with one durable status artifact per session: progress_card
({plan?, markdown?}, replace-on-write, 8 KiB markdown / 50-step caps).
Cards persist in a lazy-additive session_progress_cards table in the
per-agent DB (no schema-version bump), broadcast progressCard.changed,
and render from the store with exactly one live placement per view
(session rail when visible, else the composer-adjacent bar); transcripts
collapse to one-line receipts, and the sidebar hovercard shows other
sessions' cards inline (markdown + <progress>, DOMPurify allowlist, no
iframes). The three stream-derived plan renderers and their dedup
heuristics are deleted.

Codex runs disable the native plan tool per thread
(tools.update_plan.enabled=false) and receive progress_card via the
dynamic-tool bridge; compaction restore now reinjects the card (steps +
bounded markdown). Card writes still emit the legacy plan stream event so
native apps and channels keep working until their per-platform
migrations. Policy names map update_plan -> progress_card; the shipped
tools.updatePlan=false kill switch is honored.

Net -277 production LOC; -480 test LOC.

* test(agents): regenerate Codex prompt snapshots for update_plan thread-config disable

* chore(protocol): allowlist progressCard.changed for native apps pending card migration

* fix(ci): repair progress card integration checks

* fix(codex): canonicalize native progress cards

* test(gateway): reconcile progress card method order

* test(codex): stabilize native approval fixture
2026-08-17 09:44:04 -07:00
Peter Steinberger 793669c8f6 fix: targetless replies retain conversation correlation (#125283)
* fix(agents): preserve contextual reply correlation

Carry prepared reply policy into embedded and CLI message tools so targetless direct replies retain transport correlation and Reef thread identity.\n\nCloses #125279

* fix(reef): preserve unthreaded reply correlation

Keep reply-only inbound messages unthreaded unless the transport supplies a thread, while still anchoring new exchanges to their initiating envelope.\n\nRefs #125279
2026-08-17 06:40:28 -07:00
Peter Steinberger eb38d5e486 fix(reply): report settled delivery outcomes once (#124773)
* refactor(reply): publish settled dispatch receipts

* refactor(reply): isolate dispatch outcome accounting

* refactor(discord): infer settled dispatch result

* test(reply): model settled dispatch receipts

* test(reply): type settled receipt fixtures

* test(telegram): declare settled final receipt

* test(telegram): adapt legacy dispatch fixtures

* fix(reply): complete settled receipt compatibility

* test(channels): keep delivery suite within lint budget

* test(channels): reuse settled count fixture

* test(channels): consolidate receipt assertions

* test(channels): extract delivery receipt fixtures

* fix(qa): recover stopped clients after config restart

* fix(reply): settle deferred delivery receipts

* test(channels): share delivery turn fixtures

* fix(channels): preserve non-visible reconciliation

* fix(reply): preserve settled receipt compatibility

* refactor(reply): make settled receipts canonical

* refactor(reply): absorb settlement at dispatcher boundary

* test(matrix): prove settled receipt precedence

* refactor(sessions): extract prompt snapshot types

* fix(reply): restore queued admission counts
2026-08-17 06:38:16 -07:00
Peter Steinberger bc277fa095 fix(qa): reject inconsistent suite summaries (#125122)
Amp-Thread-ID: https://ampcode.com/threads/T-01a00b7c-b9f0-73d5-8fb7-e619e8e458e1

Co-authored-by: Amp <amp@ampcode.com>
2026-08-17 06:19:25 -07:00
Ayaan Zaidi d90dcc2111 feat(plugin-sdk): export saveMediaSource from media-store (#125278)
Plugins holding a remote URL had no non-deprecated Plugin SDK path to turn it into managed media; saveMediaSource was only reachable through the deprecated media-runtime barrel while docs pointed at media-store. Re-export it from the focused subpath and move the bundled qa-channel plugin off the deprecated barrel. Maintainer decision: full saveMediaSource (local path + HTTP(S)) is the supported media-store contract.

Fixes #125259
2026-08-17 12:54:52 +00:00
Peter Steinberger 4f898a4081 fix(state): migrate legacy state to system agent (#125266) 2026-08-17 05:32:40 -07:00
Peter Steinberger 4b0d573437 feat: session permission modes with worktree-scoped defaults (#124909)
* feat(gateway): add session permission modes

* feat(agents): enforce session permission policies

* test: cover session permission modes

* docs: explain session permission modes

* fix(agents): preserve apply patch default root

* feat(codex): map session permission modes

* feat(ui): add session permission controls

* test: cover session permission surfaces

* fix(agents): enforce session permissions from entry

* fix(codex): pass params object to requirements reader

* fix(codex): honor session permission modes

* fix(codex): preserve exec approval floors

* chore: revert changelog edit (release-owned)

* test: align full-mode promotion with upstream semantics

* chore(protocol): regenerate session permission models

* docs: register session permission modes

* fix(ui): use shared permission dropdown

* fix(sessions): restore permission mode contracts

* fix(ci): record session permission startup JS growth in the budget baseline

* refactor(agents): prepare session exec mode at dispatch

Host dispatch owns permissionMode→exec override preparation; the codex
plugin consumes prepared facts and the SDK barrel export is removed,
keeping the plugin-sdk surface at its recorded budget.

* test: type exec mode fixtures as ExecMode

* fix(codex): require admin scope for yolo permissions

* test: isolate codex permission command state

* ci: refresh PR checks against current main

* ci: refresh checks after gateway test repair

* test: fix main-fallout CI suites

* chore: refresh CI merge ref

* fix(worker): fence permission-mode cloud placements

* fix(sessions): clear worktree policy on detach

* chore(protocol): generate session permission mode enum

* test(gateway): type dispatch fixtures from session entries

* fix(ui): allow clearing session permission mode

* chore: refresh CI merge ref

* fix(ci): record permission picker startup growth in the budget baseline

* fix(gateway): gate session root projections
2026-08-17 04:37:35 -07:00
Ayaan Zaidi 75c5d9e208 fix(agents): show waiting reply when sessions_yield pauses a turn (#125106)
Show an explicit waiting acknowledgment when sessions_yield ends an otherwise-silent interactive turn, while keeping private resume context out of channel delivery and preserving existing visible replies.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-17 17:01:48 +05:30
Peter Steinberger 5e964265fd fix(canvas): omit deleted snapshot paths (#125216)
* fix(canvas): omit deleted snapshot paths

* refactor(canvas): return pathless snapshot details
2026-08-17 04:18:01 -07:00
Peter Steinberger e30b425e18 fix: recovery no longer claims interrupted commands succeeded (#125209)
* fix(agents): report interrupted tool outcomes honestly

Prevent restart recovery from claiming that an interrupted tool call completed when no successful matching result was recorded.

* fix(agents): keep ambiguous recovery restart-safe

Classify failed replay-unsafe tool results at the shared restart-recovery owner so interrupted side effects remain unavailable until their external state is verified.

* fix(agents): distinguish missing tool outcomes

Carry the existing missing_tool_result fact into projected Codex transcripts so restart recovery restricts only genuinely unknown outcomes, while confirmed failures remain retryable.
2026-08-17 04:11:57 -07:00
Peter Steinberger 9329e4d76a refactor(approvals): consolidate channel approval kind (#125215) 2026-08-17 04:08:10 -07:00
Peter Steinberger 6d04fe5305 fix(heartbeat): avoid claiming excluded outcomes were recorded (#125207)
* fix(heartbeat): report accepted outcomes honestly

* test(heartbeat): refresh response tool snapshots

* fix(heartbeat): align tool catalog wording
2026-08-17 03:58:23 -07:00