Commit Graph

38896 Commits

Author SHA1 Message Date
Peter Steinberger 067635cb51 fix(ui): prevent generated locale rebase conflicts (#109393)
* ci(ui): make locale refresh bot-owned

* test(ui): keep locale gate coverage scoped

* fix(ci): preserve generated PR merge policy

* fix(ci): wait for generated PR head convergence

* fix(ci): retry transient guard API failures

* fix(ci): enforce locale isolation across CI events

* fix(ci): harden generated PR publication

* fix(ci): validate release gate merge tree

* fix(ci): allow trusted main locale output
2026-07-16 18:48:20 -07:00
Peter Steinberger 172c63dc23 test: synchronize transcript completion queue (#109507) 2026-07-16 18:45:40 -07:00
ooiuuii a82c72904a fix: block no-auth managed gateway LAN installs (#98022)
* fix: block no-auth managed gateway LAN installs

* test(gateway): cover managed install bind resolution

Co-authored-by: luyifan <al3060388206@gmail.com>

* test(gateway): drop unrelated env cleanup

* test(gateway): use synthetic token fixture

* fix(gateway): reject dynamic tailnet no-auth installs

Co-authored-by: luyifan <al3060388206@gmail.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 18:45:05 -07:00
qingminlong fb0346fe45 fix(read): normalize displayed line ranges for limits (#105105)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 18:38:27 -07:00
mushuiyu886 9ff25ca65f fix(fleet): reject hexadecimal CPU limits (#105158)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 18:30:43 -07:00
Peter Steinberger 510cf46330 test: compact large transcript fixture (#109489) 2026-07-16 18:29:00 -07:00
qingminlong d6a561e92b fix(gateway): clarify malformed call params errors (#105217)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 18:24:08 -07:00
Peter Steinberger 784ede0af1 feat(system-agent): local-model viability — context cap, thinking off, route-aware timeout (#109445)
* feat: improve system agent local model viability

* fix: forward Ollama effective context cap

* fix(system-agent): keep flat 120s agent-turn budget

* fix(system-agent): keep manifests timeout helper module-local
2026-07-16 18:11:22 -07:00
Peter Steinberger 92146f9f80 refactor(talk): share audio-energy stats and speech-threshold gate across voice surfaces (#109466) 2026-07-16 18:10:26 -07:00
Peter Steinberger 0f1b0e6679 test: defer migration fixture cleanup (#109475) 2026-07-16 18:01:18 -07:00
Peter Steinberger 0136bb4dca test: shorten cron process-group timeout probe (#109457) 2026-07-16 17:37:55 -07:00
smthfoxy eb4f3d792f fix(agents): wake top-level requester when its last parallel child settles (#99396)
* fix(agents): wake top-level requester when its last parallel child settles [AI]

A top-level session (normal chat/dashboard, not itself a subagent) that
spawns parallel subagents and waits via sessions_yield never receives the
"all descendants settled -> synthesize" wake: wakeSubagentRunAfterDescendants
only targets orchestrators with a subagent-registry run record. The parent
only sees passive per-child announces, commonly mis-tracks the outstanding
set on the final completion turn (or never hears results whose announce gave
up), and then parks until a human sends a message.

Fix: when a child reaches a terminal settle (announce delivered, give-up, or
delivery suspended) and its requester has no more descendants awaiting
settle, deliver a one-shot "all spawned subagents settled - synthesize and
deliver now" wake to the parked top-level requester through the existing
announce delivery pipeline (active requesters get it steered into the live
turn; parked ones get a new origin-routed turn).

- hasDescendantRunAwaitingSettle: early-exit drain check where a suspended final
  delivery counts as settled (suspension is terminal for automatic retries).
- maybeWakeRequesterAfterAllChildrenSettled (subagent-announce.ts): scopes
  the batch to the settling child's parallel wave (the connected component of overlapping run
  lifetimes), skips nested/cron requesters (owned by the descendant-settle
  wake), skips single delivered completions and fire-and-forget children,
  and dedupes concurrent last-sibling settles via a batch-stable
  announce idempotency key (requester-settle:<requester>:<sorted runIds>).
- Trigger fires from completeCleanupBookkeeping (all cleanup-terminal paths)
  and suspendPendingFinalDelivery, and is skipped by the suspended-delivery
  discard sweep, so the wake is outcome-independent: a child whose announce
  gave up with NO_REPLY still counts toward - and can trigger - the drain.

Companion to the nested-orchestrator wake; covers the top-level case it
left open.

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

* fix(agents): retry the requester settle wake on transient turn failures [AI]

The settle wake is the only event that ever fires after a fan-out drains, so
a wake turn lost to a transient infra failure re-parked the requester
permanently. Observed live: the wake turn survived dispatch, reconciled all
investigators, and then died to a provider stream stall (LLM idle timeout)
mid-synthesis — with nothing left to retry it.

Bounded recovery: up to 3 attempts with 30s/120s backoff. Each retry uses a
fresh `:retry-N` idempotency suffix because the gateway dedupe caches
terminal run outcomes per key, so re-dispatching the same key would no-op. A
legitimately silent wake reply already classifies as delivered and never
retries; terminal failures and an abandoned requester stop immediately.

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

* fix(agents): ledger retired delete-cleanup rows for the requester settle wake [AI]

cleanup="delete" retires a child's registry row in the same funnel pass
that schedules the settle wake, so a pure delete-mode fan-out could never
rebuild its drained wave from live rows: empty batch, no wake, requester
parked — the exact incident class this wake exists to close.

Retiring cleanup paths (delete branch, reconciled-killed tombstone) now
pass settledRowRetired, and the wake ledgers the in-hand record before
its first await: concurrent last-sibling settles all see the same
ledgered rows by the time any batch computation runs, keeping batch
membership and the idempotency key stable — the guarantee keep-mode gets
from rows persisting in the registry. Ledgered rows merge into the batch
candidates (a live registry row wins by runId); entries clear on
delivered/terminal wakes and the nested/requester-gone exits, with a 24h
TTL prune as the memory backstop. In-memory only: a restart degrades a
mid-wave delete fan-out to waking with the surviving rows.

* fix(agents): snapshot delete-mode child results before cleanup clears them [AI]

The delivered-finalize path clears completion.resultText (delete mode) and
the frozen delivery payload before cleanup bookkeeping runs, so the
requester-settle wake ledgered a row whose findings had already been
emptied: a cleanup="delete" fan-out woke its requester with "(no output)"
for successfully delivered children.

Capture an immutable snapshot of the entry (completion + delivery payload)
at the top of finalizeSubagentCleanup and in the resumed-announce give-up
path — before any clearing — and pass it through completeCleanupBookkeeping
to the settle wake for the retired-row branches. Keep-mode is unchanged:
its registry rows keep their result text and win over ledgered copies.

Regression: a lifecycle-driven test drives the real delivered delete-mode
cleanup (completeSubagentRun -> announce -> finalize -> funnel) and asserts
the wake's settledEntry still carries the child's result text after the
live entry was cleared and the row retired.

* fix(agents): release drained no-wake batches from the settle ledger [AI]

The zero-required and single-delivered guard exits decline to wake a wave
that has already fully drained. Ledgered delete-mode rows in such a batch
can never join a later wake (a child spawned after the drain cannot
lifetime-overlap rows that already ended, and any still-running overlap
would have failed the drain gate before these exits), so holding their
child-result snapshots for the 24h TTL was pure retention: high-volume
delete-mode fan-outs could pin large result texts in process memory.

Release the batch at both exits. No behavior change: waves with pending
overlapping children return earlier at the drain gate, which still keeps
their rows.

* test(agents): route e2e session fixture through the sqlite accessor [AI]

Upstream flipped session reads to the sqlite-backed session accessor
(#98236), which bypasses the loadSessionStore mock this e2e used for its
in-memory session fixture — requester entry lookups came back empty and
the settle wake exited at the usable-session guard. Serve loadSessionEntry
from the same fixture; everything else in the accessor stays real.

* refactor(agents): move the requester settle wake into its own module [AI]

Two pieces of fallout from rebasing across upstream tooling changes:

- The max-lines lint budget (#107315) has no grandfathered suppression for
  subagent-announce.ts, and the settle wake + retired-row ledger pushed it
  past the cap. The wake is a coherent unit, so it moves to
  subagent-announce.requester-settle-wake.ts (matching its test file) with
  its own registry-runtime seam; the registry's lazy dep and the lifecycle
  type alias point at the new module. announce.ts drops back well under
  the budget with no suppression needed.

- The announce read-path refactor rewired the runtime barrels onto
  subagent-registry-announce-read.js, orphaning the
  hasDescendantRunAwaitingSettle re-export on subagent-registry.ts, which
  the deadcode-exports gate now flags. Removed; the retry-grace e2e reads
  the announce-read implementation directly.

* fix(agents): admit the requester settle wake as tracked gateway root work [AI]

The settle wake was launched as a detached promise from cleanup
bookkeeping, so registry cleanup or shutdown could reach quiescence
before the wake admitted its gateway turn and the last-child completion
could still be lost during restart or teardown. Route the wake through
runWithGatewayIndependentRootWorkContinuation: a live cleanup parent
reserves the root synchronously, and restart drain now waits for the
in-flight wake. Adds a deterministic quiescence-race regression.

* fix(agents): persist requester settle recovery

Store requester-settle wake obligations on subagent run rows, replay them after restart, and retire cleanup rows only after a durable outcome. Persist admitted attempts and retry deadlines, coalesce live restores, drain disconnected waves, and let the sweeper recover stranded processors.

Co-authored-by: smthfoxy <263563487+smthfoxy@users.noreply.github.com>

* test(agents): allow durable settle persistence

Keep the bulk-cancellation regression focused on recovery after the injected persistence failure instead of assuming an exact write count; requester-settle bookkeeping now adds a legitimate durable write.

Co-authored-by: smthfoxy <263563487+smthfoxy@users.noreply.github.com>

* style(agents): declare settle wake scheduler

Use a hoisted function declaration for the lifecycle scheduler so lint accepts the intentional callback cycle without a mutable binding.

Co-authored-by: smthfoxy <263563487+smthfoxy@users.noreply.github.com>

* fix(agents): harden requester settle recovery

Co-authored-by: smthfoxy <263563487+smthfoxy@users.noreply.github.com>

* fix(agents): release settle wake during retry backoff

Co-authored-by: smthfoxy <263563487+smthfoxy@users.noreply.github.com>

* test(agents): type settle wake fixtures

Co-authored-by: smthfoxy <263563487+smthfoxy@users.noreply.github.com>

* style(agents): bind settle wake transition callbacks

Co-authored-by: smthfoxy <263563487+smthfoxy@users.noreply.github.com>

* test(agents): restore past-due settle wake

Co-authored-by: smthfoxy <263563487+smthfoxy@users.noreply.github.com>

---------

Co-authored-by: smthfoxy <263563487+smthfoxy@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 17:37:18 -07:00
NianJiu 7ba436ac70 fix(cron): enforce max concurrent runs across triggers (#103323)
* fix(cron): enforce max concurrent runs across triggers

* fix(cron): cleanup failed run reservations

* fix(cron): retain queued disabled force runs

* refactor(cron): tighten shared run admission

* fix(cron): stop activation after shutdown

* fix(cron): preserve queued reservation ownership

* fix(cron): harden queued run cleanup

* fix(cron): drain admitted timer runs on failure

* fix(cron): make run reservations durable

* refactor(cron): keep admission state internal

---------

Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 17:31:57 -07:00
Lu Wang 2972db5649 fix: preserve Claude resumed synthetic turns (#90799)
Preserve Claude CLI replies that continue after a resumed-session synthetic placeholder while retaining bounded fallback for terminal no-output cases.

Fixes #99131.
Related #90789.
Prepared head SHA: 08cd27aaeb
Co-authored-by: Lu Wang <7668944+wangwllu@users.noreply.github.com>
Co-authored-by: Shakker <165377636+shakkernerd@users.noreply.github.com>
Reviewed-by: @shakkernerd
2026-07-17 01:30:59 +01:00
Peter Steinberger d71c1fe596 feat(onboarding): prefer strongest local model in guided detection (#109250)
* feat(onboarding): rank detected local models

* docs(sdk): comment local-model rank bucket layout

* feat(sdk): rank gemma4 first for local setup-assistant models
2026-07-16 17:30:49 -07:00
Peter Steinberger 167a8ef20a fix(onboarding): harden fresh local startup and activation (#108764)
* fix(macos): preserve gateway during fresh setup

* fix(macos): validate reusable gateway service

* chore(macos): sync native i18n inventory

* fix(macos): preserve latest gateway service request

* test(macos): isolate gateway port concurrency coverage

* fix(macos): recover gateways after failed readiness

* fix(macos): repair wedged gateway listeners

* fix(macos): bound gateway startup probes

* chore(macos): sync native i18n inventory

* fix(onboarding): activate verified inference immediately

* fix(macos): isolate readiness failure generations

* chore(macos): refresh native i18n inventory

* fix(macos): serialize gateway service lifecycle

* fix(macos): sequence gateway startup persistence

* fix(macos): close gateway readiness races

* fix(macos): publish recovered gateway state

* fix(macos): make gateway readiness generation-safe

* chore(macos): refresh native i18n inventory

* fix(macos): preserve gateway endpoint identity

* fix(macos): refresh gateway ownership after attach

* fix(macos): distinguish transient gateway readiness

* refactor(macos): split gateway readiness lifecycle

* chore(macos): refresh native i18n inventory

* chore(release): keep changelog release-owned
2026-07-16 17:24:53 -07:00
Peter Steinberger 08b071ee50 test: avoid duplicate updater timeout probe (#109438) 2026-07-16 17:20:33 -07:00
iloveleon19 382d570cbf feat(channels): add unified implicit mention policy (#108829)
* feat(mattermost): add thread.requireExplicitMention to opt out of thread auto-follow

Mattermost treats any reply in a thread the bot has participated in as an
implicit mention, so requireMention only gates the first message and the bot
then answers follow-ups addressed to other people for the participation TTL.
Slack exposes channels.slack.thread.requireExplicitMention for exactly this;
Mattermost had no equivalent and its strict schema rejected the key.

Add channels.mattermost.thread.requireExplicitMention (channel + per-account),
mirroring Slack. When set, thread participation no longer counts as a mention.
Default (unset/false) keeps today's auto-follow behavior unchanged.

Related: #108269

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(channels): add implicit mention policy foundation

* feat(channels): unify implicit mention policy

Co-authored-by: leon <dodoma0919@gmail.com>

* refactor(channels): keep implicit policy inside evaluator

* fix(channels): use exported implicit mention type

* chore(channels): satisfy extension lint

* fix(config): break implicit mention type cycle

* fix(plugin-sdk): account for implicit mention config export

* refactor(config): isolate implicit mention schema

* chore(plugin-sdk): align implicit mention surface budget

* fix(config): remove unused schema re-export

---------

Co-authored-by: leon <dodoma0919@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 17:16:01 -07:00
Peter Steinberger dbf3597f9b fix(cli): restore lint after restart health growth (#109359)
* fix(cli): split restart-health over max-lines

* fix(cli): drop dead export from restart-health test helpers
2026-07-16 17:13:58 -07:00
pacoa 14dc557cee fix: use effective daemon port flag (#109294)
* fix: use effective daemon port flag

* fix(daemon): unify effective port parsing

Co-authored-by: pacoa <29181120+pacoa-kdbg@users.noreply.github.com>

* fix(daemon): skip consumed port values

Co-authored-by: pacoa <29181120+pacoa-kdbg@users.noreply.github.com>

* style(daemon): format effective port handling

Co-authored-by: pacoa <29181120+pacoa-kdbg@users.noreply.github.com>

---------

Co-authored-by: Paco Avelar <[email protected]>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 17:11:09 -07:00
Wynne668 ccb251c570 fix(process): report actual elapsed time for early lane timeouts (#109287)
* fix(process): clarify command lane timeout cause

* fix(process): complete timeout cause formatting

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 17:03:43 -07:00
Peter Steinberger 9899121b61 test: reduce redundant state database race stress (#109426) 2026-07-16 16:56:25 -07:00
mushuiyu886 91df2d1812 fix(cli): bound container runtime probes (#109199)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-16 16:54:23 -07:00
Peter Steinberger 349f78776d fix(models): refresh bundled provider catalogs (#109410)
* fix(models): refresh bundled provider catalogs

* docs(models): refresh generated docs map

* fix(xiaomi): keep provider helper private

* chore(release): defer catalog release note
2026-07-16 16:47:25 -07:00
Peter Steinberger 334c182c27 refactor(diffs): move ephemeral artifacts to SQLite (#109328)
* refactor(diffs): move ephemeral artifacts to SQLite

* fix(plugin-state): satisfy SDK validation gates

* test(diffs): satisfy lint contracts

* fix(plugin-state): count expired blobs toward quotas

* fix(plugin-state): harden blob storage boundaries

* fix(plugins): replace stale install provenance
2026-07-16 16:47:19 -07:00
Alix-007 23de5c297d fix(infra): bound macOS metadata probes (#109241) 2026-07-16 16:10:39 -07:00
plexustech2006 a434ee7d30 fix(agents): scope compaction lock reentry to logical writer (#88919)
* fix: allow preflight compaction to reenter session locks

* chore: refresh proof checks

* test(agents): cover compaction lock reentry

Replace the source-text guard with behavior-level coverage through the compaction harness.

Co-authored-by: Plexus Technology <plexusadmin@plxsai.localdomain>

* fix(agents): scope compaction lock reentry

Reuse only the matching logical transcript writer lock and keep unrelated same-process compaction serialized.

Co-authored-by: Plexus Technology <plexusadmin@plxsai.localdomain>

* test(agents): preserve lock runner generics

Co-authored-by: Plexus Technology <plexusadmin@plxsai.localdomain>

* test(agents): preserve generic lock wrapper type

Co-authored-by: Plexus Technology <plexusadmin@plxsai.localdomain>

---------

Co-authored-by: Plexus Technology <plexusadmin@plxsai.localdomain>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 16:08:00 -07:00
Alix-007 f61a3d46a2 fix(doctor): bound GitHub issue creation (#109253) 2026-07-16 16:00:20 -07:00
Alix-007 ad06d83597 fix(windows): prevent encoding probes from blocking commands (#109319) 2026-07-16 15:57:06 -07:00
Shakker b2b6e2d03b test: keep channel setup fixtures review-safe 2026-07-16 23:56:29 +01:00
Shakker e6c8f82f50 feat: expose ClickClack setup codes in channels add 2026-07-16 23:56:29 +01:00
Shakker 4cd07e5e8c feat: configure ClickClack accounts from setup codes 2026-07-16 23:56:29 +01:00
Shakker 13306d66e3 feat: prepare channel setup input before config writes 2026-07-16 23:56:29 +01:00
Peter Steinberger 6d20432a29 improve: reduce agent startup cost from TTS imports (#109344)
* perf(tts): split lightweight settings imports

* fix(tts): drop redundant internal exports

* fix(tts): remove unused settings type import

* docs(sdk): refresh speech settings API baseline

* fix(tts): align SDK surface gates

* fix(tts): ignore non-object preference roots
2026-07-16 15:50:59 -07:00
wahaha1223 a70d583f24 fix(node-host): connect to IPv6 gateway hosts (#109179)
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-16 15:47:21 -07:00
Peter Steinberger 20b1bc02f8 test: avoid redundant heartbeat runtime integration (#109371) 2026-07-16 15:44:54 -07:00
maweibin b8c7f31894 fix(sessions): prevent delivery-mirror prompt contamination with adjacent dedup and identity fallback (#99470) (#99504)
* fix(sessions): prevent delivery-mirror prompt contamination with adjacent dedup and identity fallback (#99470)

Two-layer defence against delivery-mirror entries leaking into provider
prompts after session rebuild / side-branch merge strips metadata:

Layer 1 (identity fallback): isTranscriptOnlyOpenClawAssistantMessage
gains an openclawDeliveryMirror field check to catch stripped-metadata
survivors that lost provider/model during rebuild.

Layer 2 (adjacent dedup): normalizeAssistantReplayContent collapses
adjacent byte-identical no-tool-call assistant messages, catching
fully-bare {role,content,usage} survivors invisible to any metadata
filter.

P1 fix: added 'tool_use' (native Anthropic snake_case) to
TOOL_CALL_TYPES in extractToolCallsFromAssistant so adjacent dedup
never collapses tool-call-bearing turns.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(sessions): narrow delivery mirror replay filtering

* test(sessions): preserve tool-call replay duplicates

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 15:19:49 -07:00
Peter Steinberger 7a45a65827 fix: recover from temporary provider overloads (#109354)
* fix(auto-reply): retry provider overloads

* fix(auto-reply): type notice delivery errors

* fix(auto-reply): guard overload replay safety

* fix(auto-reply): close overload retry races

* test(auto-reply): inject operation abort signals

* docs: leave overload note to release automation

* test(auto-reply): cover capacity retry exhaustion
2026-07-16 15:13:44 -07:00
Peter Steinberger 8680faf83c refactor(discord): retire internal abort signal helper (#109369) 2026-07-16 15:12:50 -07:00
Wynne668 13ca829e2e fix(sessions): preserve lifecycle headers across short reads (#109205) 2026-07-16 15:09:06 -07:00
Wynne668 6c8ab16158 fix(trajectory): clean up runtime files across short reads (#109206) 2026-07-16 15:02:08 -07:00
krissding ff1687e04f fix(cli): filter Commander value placeholders from Fish completion flags (#109324)
* fix(cli): filter Commander value placeholders from Fish completion flags

The Fish completion generator was treating Commander.js value placeholders
(like <path|->, <file>, [optional]) as command-line tokens, causing the
angle-bracket values to be interpreted as shell redirects when the
completion script was sourced.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(cli): use parsed option flags for completions

Co-authored-by: 丁宇婷0668001435 <ding.yuting@xydigit.com>

* fix(cli): support long option aliases in Fish completion

Co-authored-by: 丁宇婷0668001435 <ding.yuting@xydigit.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-16 14:57:23 -07:00
Peter Steinberger 40b10eb3d1 perf: avoid plugin cold loads in request hot paths (#109348)
* perf: avoid cold plugin discovery in hot paths

* chore: remove stale harness policy re-export

* fix: preserve active thinking clamps in status
2026-07-16 14:54:32 -07:00
Peter Steinberger bd9a996b78 refactor(slack): drive progress drafts through the shared compositor (#109336)
* test(slack): drop rotating loading-message fixture expectations

* refactor(slack): drive progress drafts through the shared compositor

Slack's status_final progress path now uses the shared channel compositor
(preamble headline, reasoning, tools, plan checklist, commentary
arbitration) instead of its hand-rolled gate/merge/render pipeline, and
native task cards consume compositor snapshots with stable row identity
(line ids first, fixed reasoning id, occurrence-suffixed content hashes).
Finals in progress mode post as fresh messages that follow the draft's
thread; the working draft then collapses into a compact activity receipt,
while failed or error finals leave the draft as the turn record. The
rotating native loading messages are gone in favor of the plain typing
status. Queued and assistant-boundary turns re-arm with clean delivery
state, and native completion status survives transient append failures.
2026-07-16 14:50:36 -07:00
Peter Steinberger 58f43c703e test(auto-reply): consolidate command suites (#109342) 2026-07-16 14:23:11 -07:00
pick-cat 7cde0ac8c0 fix(proxy-capture): guard body-less arrayBuffer reads against oversized responses (#101268)
* fix(proxy-capture): guard body-less arrayBuffer reads against oversized responses

* fix(proxy-capture): exercise body-less fallback in bounded read tests

New tests use mock clones with body: null plus arrayBuffer spies to
prove the content-length precheck guards the !body path. A real
Response clone exposes body.getReader in Node 24, so the prior test
only exercised the streaming branch and would stay green even if
the precheck were deleted.

* chore: retrigger CI

* fix(proxy-capture): reject non-safe content-length before arrayBuffer (#101268)

ClawSweeper P2: the body-less fallback used Number(content-length), so a
huge digit-only Content-Length value could overflow to Infinity, bypass the
Number.isFinite guard, and still call arrayBuffer() — leaving an OOM path in
the hardening PR.

Add declaredContentLengthExceedsCap, which accepts only plain digit strings,
treats any value longer than Number.MAX_SAFE_INTEGER as oversized, and
compares safe-integer parsed values against the cap. Non-numeric or malformed
values fall through to the post-read length check.

Adds a regression test for a 100-digit Content-Length that would previously
have bypassed the guard.

* fix(proxy-capture): normalize zero-padded Content-Length before digit-count guard

* fix(proxy-capture): fail closed without response streams

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 14:12:43 -07:00
Peter Steinberger 411c09f9be test(infra): skip real recovery pacing waits (#109338) 2026-07-16 14:12:07 -07:00
Peter Steinberger 7d71d7cf6b fix(sessions): large histories no longer load entire transcripts (#108851)
* perf(sessions): bound SQLite history reads

* fix(sessions): keep history pagination gap-free

* test(sessions): use shared temp cleanup

* fix(sessions): reconcile mixed transcript projections

* fix(sessions): preserve strict schema migration

* refactor(sessions): trim internal export surface

* refactor(sessions): keep reader helpers private

* fix(sessions): reconcile transcript projections off requests

* test(sessions): await transcript projection repair

* fix(sessions): normalize projection worker failures

* fix(sessions): satisfy projection release gates
2026-07-16 14:11:33 -07:00
Dallin Romney 5a0fcc2ff9 test(cli): distinguish silent hook relay completion (#109339) 2026-07-16 13:59:34 -07:00
tzy-17 84fb48c3be fix(sandbox): use Buffer.byteLength for env var value size limit (#105017)
* fix(sandbox): use Buffer.byteLength for env var value size limit

validateEnvVarValue checked value.length (UTF-16 code units) against
the 32768-byte limit, so multi-byte CJK values like "值".repeat(11000)
passed the check despite exceeding 33 KB in UTF-8. Switch to
Buffer.byteLength(value, "utf8") so the limit matches the actual byte
count the OS and child processes see.

* test(sandbox): simplify env byte-limit coverage

Co-authored-by: 唐梓夷0668001293 <tang.ziyi@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 13:56:23 -07:00