* fix(gateway): preserve work during recovered Node restarts
Let Unix Node recovery wrappers respect the existing Gateway stop budget.
Share startup-safe command classification and deadline facts, and resolve
managed restart intent against the live serving owner in its write
transaction with current update authority.
Preserve the existing public PID intent API, record format, and Windows
behavior. Keep cold lifecycle test preparation outside timed hooks.
Inspired by @ly85206559's wrapper-grace approach in #147054; this repair
is independently authored from main. Related: #146956. Windows cooperative
shutdown remains a follow-up.
* refactor(gateway): stabilize restart callback and test setup
Declare receiver-independent restart intent callbacks as arrows and retain typed signal spy handles for lint-safe assertions. Move cold lifecycle imports into test collection so worker preparation cannot consume timed setup hooks.
* fix(macos): redesign Quick Chat around one composer
Keep Quick Chat input in one bottom composer, preserve draft and disclosure intent across replies, and share web-style native effort and context controls. Completed work stays in the transcript, and transcript-only surfaces do not expose actions targeting a hidden composer. Verify with signed native light/dark GUI fixtures and Quick Chat behavior tests.
* fix(macos): preserve streaming replies when collapsing Quick Chat
Keep the transcript mounted while collapsed so reopening cannot restart history bootstrap and clear a live reply. Exercise rendered disclosure with a streaming delta and unavailable history. Brighten dark reading text to retain enhanced contrast across session accents.
* test(macos): disambiguate the accessibility value in Quick Chat proof
* test(macos): wait for Quick Chat disclosure animations to settle
* fix(browser): preserve snapshot targets and automation deadlines
Bind scoped role references to native DOM identities and keep capture cleanup
alive through timeout settlement. Preserve shared CDP connections when one
reader cancels and reject captures spanning replaced child documents.
Use native Chrome MCP coordinate input, preserve actual action errors, and
align extension and node request budgets. Repair aborted pairing, tab adoption,
and lifecycle cleanup; remove the retired plain-ARIA reference builder.
* test(browser): preserve endpoint redaction coverage and fix snapshot lint
* fix(onboarding): avoid blocking recommendation storage
Keep recommendation reads on the independent read-only worker and route all five mutations through the existing shared-state actor. Preserve workspace identity, no-create reads, transaction and CAS behavior, and await persistence in registered CLI actions and both wizard completion paths.
* refactor(onboarding): keep state decoding and dispatch with owners
Publication and confirmation now distinguish held workspace leases from unavailable storage and caller-canceled acquisition. The shared SQLite lease owner records these outcomes, replacing the publication-specific retry inference while preserving caller authority, native settlement, and retired-owner fencing.
Doctor records pre-grant cancellation as a visible inspection warning without changing its signal budget or mutating source state. No new configuration, CLI options, schemas, dependencies, or wait limits are introduced.
Validation: scoped-clean Codex review; native SQLite/worker, registered publication RPC, Doctor, updater-authority, and wrapper-boundary proof; exact-head CI gate success. The current candidate's published-updater through healthy Gateway restart scenario remains an explicitly accepted, bounded validation gap recorded in the PR body.
* fix(ui): navigate image attachments in message galleries
Project raster attachments into their message image gallery before rendering. Preserve image order, repeated uploads, and bounded SVG previews while excluding persisted mirrors.
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: d5224f8b-1a08-4aec-9e36-f9c9d0476e15
* test(ui): make gallery fixture fields explicit
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: dec9cdff-6a66-4fb1-a54e-38f696e04504
* test: observe complete cleanup and scroll handoff
Join the existing terminal cleanup boundary before checking process-group death, and measure footer handoff over the full native gesture sequence so successful early chaining cannot exhaust the comparison range.
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: 60672b30-f369-4bcd-b3b2-be2da9f529a5
* fix(ui): prevent chat crashes after copying a message
Keep hovered virtual rows uncontained through native mouse focus, preserving keyboard focus rings and offscreen layout skipping. The unchanged desktop Copy/right-click E2E fails on main and passes with this repair.
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: cbae2874-a8c7-4c20-9b2d-89810cd95075
* fix(ui): preserve contained metadata alongside copy context menus
Limit mouse uncontainment to hovered message bubbles so metadata retains its top-layer containment contract. Keep focus-within as a separate selector for touch keyboard focus through the existing hover guard. All 25 unchanged related E2E cases, seven end-follow browser tests, and the metadata context test pass.
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test: isolate mocked agent cleanup owner
Route the transport-mocked cleanup fixture through the existing audited isolated lane so it cannot inherit a real shared-state owner from preceding files. Preserve all schema assertions and broker guards.
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: 2b4bb607-7cfd-491b-96e8-350dcbf48992
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: e85c8770-b690-419e-b5ed-d5ef128175a5
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: bb22d663-12e4-46cf-bc8f-a8fa3b01d6b5
* test: reconcile upstream isolation and ACK ownership contracts
Keep the cleanup fixture routing now supplied by main exactly once. Settle the worker ACK fixture through its real claim, then verify explicit null/undefined still differ from omitted ownership on a missing row.
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: a379f540-9ec3-47ac-92f7-fa42c521ec16
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: 656c73f6-d633-465c-86fb-2dc47fbec8e8
* test: align upstreamed cleanup fixture comments
The functional assertion ordering and safety check already match main. Drop only the two conflicting local explanatory comments; no runtime or test behavior changes.
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: 36336d8f-dec6-4d44-a022-f37e89270a40
* fix(ui): navigate image attachments in message galleries
Worked on by:
- @vyctorbrzezowski
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
OpenClaw-Publication: f96b2955-db9a-4106-a45c-69fe98ebe31e
---------
Co-authored-by: vyctorbrzezowski <51521767+vyctorbrzezowski@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
## What Problem This Solves
Fixes broken characters at the end of long GitHub descriptions, comments, and file diffs in the Control UI reader when a truncation limit splits a UTF-16 surrogate pair.
## User Impact
Bounded reader text now ends on a complete character. Existing size limits and incomplete-content notices remain intact. Explicitly empty patches remain complete rather than acquiring false shortened/incomplete warnings; omitted patches remain marked unavailable. No configuration or migration is required.
## Why This Change Was Made
The GitHub detail owner now uses the existing SDK truncation helper for text and patches. An explicit undefined check preserves the distinction between empty and unavailable patches. No second renderer, cache policy, transport setting, or new helper was introduced.
## Evidence
[Inspected before/after screenshots of the actual reader](https://github.com/openclaw/openclaw/pull/153344#issuecomment-5747664285).
- Reproduced the broken body and patch characters through the registered `github.detail` Gateway RPC and real source Control UI. Corrected RPC payloads and rendered DOM contain no split surrogate at those boundaries.
- Exercised descriptions, discussion/review text and context, commit text, exact-fit and ASCII controls, aggregate patch-budget boundaries, and empty versus omitted patches. Public-only rejection and anonymous request headers stayed intact.
- Real-time cache checks preserved the complete empty-patch cache while omitted patches refreshed after the partial-cache deadline.
- 52 focused tests passed. The Unicode regression fails on original main; the explicit-empty regression fails on the original PR proposal. Scoped lint, formatting, and whitespace checks passed.
Proof used main `48bcfda392` plus the exact two-file repair, with changed-file hashes matched to this branch and actual Gateway-loaded plugin bytes captured. Only upstream GitHub was simulated through a loopback HTTP fixture: this is not live GitHub or TLS proof. Screenshot crops remove unrelated host/account UI, not reader content.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* refactor(auth): prepare bounded shared auth scopes asynchronously
Read shared ownership and portable credentials through the existing state
worker before entering bounded CLI and provider-setup auth scopes. Resolve
paths before awaiting and recheck admission and ownership before entry.
Preserve local overrides, OAuth refresh ownership, and personal-account
isolation. Record the cold-worker latency and memory tradeoff in PR evidence.
Related: #149309
* fix(test): await scoped auth while staging live fixtures
Wait for the portable auth view and target persistence before fixture
installation continues. Drain the CLI's existing maintenance owner before
exit and run direct helper tests through the host database-worker lane.
* test(auth): include cacheability in scoped read fixtures
* test(auth): align cancellation fixture with current row metadata
* test(outbound): clean up ACK fixtures with their owner
(cherry picked from commit 4681239a66)
* fix(update): keep a managed update from stranding the gateway after the install swap
A managed package update stages the new version, swaps it over the live
install root, and only then restarts and verifies the gateway. That
restart runs inside the updater process, which is still executing the
build that was just replaced. The bundled dist is split into
content-hashed chunks, so any `import()` reached for the first time after
the swap resolves to a chunk name that only the old tree contained:
Gateway: restart failed: Error: ENOENT: no such file or directory,
open '.../node_modules/openclaw/dist/shared-DFJEouXv.js'
`maybeRestartService` caught that as a restart failure, which became
`recovery.serviceRestartSafe: false`, which made the update helper exit
with the unsafe code and log "keep the gateway stopped until the
installation is repaired". The installation was fine -- npm install, the
swap, and doctor had all exited 0 -- but the gateway stayed down until
someone restarted it by hand. Observed on a 2026.9.1 -> 2026.9.2 npm
update: a 3h outage from a successful upgrade.
Two changes:
- Warm the restart path's lazy modules in `beforeActivate`, the last
point where this process can still read its own install tree. The probe
gained a loader for `gateway/call.js`, which was a bare dynamic import
and so could not be warmed.
- Recognize a missing module inside our own install root and stop
treating it as a verdict on the new install. Restarting the service is
strictly better than parking it: the old process is gone either way,
and a genuinely broken install still surfaces through the service's own
supervision. A missing *data* file in the install root is still a real
failure.
Claude-Session: https://claude.ai/code/session_01WKVaMWLzdHNJCa82nnTfWg
* test(update): use canonical normalization in restart regression
* test(update): register package-swap regression in its CI owner
* test(gateway): join task events before reset fixture cleanup
* test(gateway): join task events before in-test settlement
* test(gateway): prepare auth command runtime before handshake
* fix(ci): bound serial storage-state test stripes
* fix(ci): scope storage file ceiling to hosted jobs
* test(transcripts): wait for routed provider startup
* test: honor delivery and session fixture ownership
* test(transcripts): join configured provider startup
---------
Co-authored-by: baovo15 <duybao.vin@gmail.com>
Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
* perf(tasks): use indexed mutation snapshot lookups
Use exact task/run/child predicates and omit empty optional scopes. Normalize new run and child identifiers at the row writer. Preserve ordering and delivery selection with query-plan regression coverage. Historical padded identifiers are not backfilled.
* fix(tasks): preserve matching in indexed task-ID snapshots
* refactor(outbound): settle pending delivery failures off the host thread
* fix(ci): align status timeout fixture with shared auth
* test(outbound): clean up ACK fixtures with their owner
* fix: avoid blocking Gateway work on queued collector registry writes
* fix(tasks): retain delayed flow repairs through cleanup
Move live flow retries and projection snapshots onto the shared task-domain
worker while retaining transaction-time live selection and lifecycle custody.
Join failed projection reads before releasing Gateway work, and give durable
retry timers their own async cleanup scope when they fire.
Preserve immediate synchronous compatibility, full-row compound writer checks,
and the existing retry schedule. No schema or retention changes.
* fix(tasks): avoid redundant mirrored-flow snapshot reads
Let the canonical write transaction classify dirty mirrored-flow targets
without first refreshing the full projection. Preserve clean missing and
managed no-entry behavior and use the existing getter on failure to retain
current failure metadata. Keep unrelated dirty obligations and query budgets.
* fix(test): remove duplicate Codex attempt inventory entries
* test(ci): distinguish retained job worker caps
* fix(test): preserve under-cap syntax repairs in validation
* refactor(tasks): share creation and transition operations
* fix: publish acknowledged managed task receipts
* fix: await initial task persistence before Gateway activation
* fix(subagents): settle cancelled queued launch metadata
* fix(test): await registration in waiting reply fixtures
* test: await routed transcript provider readiness
* test(outbound): clean up ACK fixtures with their owner
* fix: restore Mac presence context and Canvas media playback
* refactor(gateway): separate the node session type contract
* test(codex): cover active presence in prompt fixtures
* test: include active computer in Codex context ordering
* test: supply snapshot auth-profile store
* test: align presence search and CLI prompt expectations
Replace the duplicate first-request wrapper with mockFirstObjectArg.
Keep all 27 preflight, real transport, and fallback cases and their
existing lifecycle assertions. Production unchanged; test code net-13.
Validated with paired 27-case runs, the full LOCAL changed gate against
the fixed source base, a complete diff cleanup, and managed Codex P2.
Distinguish a complete lint report followed by a process or output-pipe stall from checks that have not produced a report. Capture the same child's completion evidence before cleanup, retain explicit timeout metadata and all real lint findings, and record unavailable automatic repair as skipped only before a turn starts so the original failed check remains the reported cause.
Keep this diagnostic change with the existing candidate-canary and update-command repair owners. Existing stored status values and report readers already support skipped; no migration, schema, dependency, option, or lifecycle change is required. Document the published driver's shared deadline and aggregate log-tail semantics. This does not patch an already-installed updater or claim to resolve an identified leaked handle.
Validation: campaign evidence records 71/71 canary tests, 9/9 repair-worker tests, check-changed exit 0, and a scoped-clean Codex review. The exact-head required CI gate passed. The isolated published 2026.9.4 to 2026.9.5 update succeeded; no post-completion hang was reproduced, and that run is investigation evidence rather than execution of the new timeout branches.
Thanks to @Lendersmark for the detailed Linux timing analysis and elimination of competing causes.
Related: #152759, #151546, #153049.
Preserve short requests in compaction summaries without broadening keyword-bearing request matching through shared numbers. Add regression coverage at the summary audit and registered compaction handler boundaries.
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Closes#152978
Related: #151911
## What Problem This Solves
Slack and Discord lose the automatic recent discussion window when their channel monitor restarts, leaving the next addressed turn without the surrounding conversation.
## User Impact
Slack and Discord recover recent channel/thread discussion after restart while keeping unmentioned messages quiet. Existing history limits remain in effect: Slack defaults to 50 and Discord to 20; zero disables automatic history reads. Explicit `message(action="read")` remains available independently, including after a session reset.
There is no new local message archive, database migration, configuration key, or permission expansion. Retrieval depends on the platform's current access, retention, availability, and rate limits. Existing installations need no configuration migration; this does not replay missed messages as new agent turns.
**Slack limitation:** thread replies arrive oldest-first. Automatic recovery stops after three pages and omits an incomplete prefix rather than calling old messages recent. Explicit reads remain pageable.
## Why This Change Was Made
This follows up Telegram's history work in #151911 using Slack and Discord's native history APIs as the authority. Admitted turns receive a bounded fresh snapshot scoped to the current account and conversation, with session boundaries, sender policy, and current/debounced-message exclusions applied. Failed recovery logs the omission and preserves the addressed turn instead of falling back to stale buffered content.
Slack initial thread history is rendered once. Recovered bots obey the existing context allowlist; Discord's mentions-only bot policy uses the existing active-mention rules. Resumed room-event prompts omit repeated history while preserving current-turn context.
Historical media carries recovery authority through queued downloads, metadata refreshes, retries, and file publication. The existing media owner accepts an optional `saveRemoteMedia.assertCurrent` guard and combines it with any enclosing read scope; callers omitting it keep their existing behavior. Admission cancellation is forwarded separately. Direct and forwarded media branches are observed immediately and all started work settles before an error propagates, preventing an unhandled rejection while another download is pending.
## Evidence
Candidate: `0708cff9bf310c0adc88ece5d2e06a048b69525f`.
- **Real Slack and Discord transport:** isolated Gateways and deterministic model providers exercised native history APIs, registered message-tool reads, and delivered replies at `994bfaf54ec`. Slack passed seven phases: latest 50, reset, new post-reset discussion, replacement Gateway using the same state, zero history, thread warmup, and exact-thread recovery. Discord's full run passed **70 assertions across 10 phases**, including cold/restarted 20-message windows, reset, cold/restarted zero history, and older-message reads. All 417 owned messages were cleaned up and leases released. The final incremental repair changes media authority, not these text-only recovery paths.
- **Mid-download authority RED/GREEN:** through the registered Slack monitor and real media store, four historical images were queued and the first three HTTP responses held. Revoking policy before releasing them previously allowed five file requests, one metadata refresh, and four published files. The repaired path makes only the three requests already started, then performs **zero refreshes, file publications, model dispatches, or sends**. The permitted control still completes all four files, including one stale-URL refresh/retry, reads their bytes back, and reaches reply dispatch. Slack REST/file responses are synthetic for this deterministic race; the store and handler are real.
- **Mixed-attachment rejection RED/GREEN:** after revocation, a direct image settles while a forwarded image remains held. The old run exits with an unhandled policy rejection; the repaired run stays pending until the forwarded branch settles and has no unhandled error, media publication, or dispatch. The complete affected Slack group passes **110 tests across three files**; targeted lint, extension test types, and source-size checks pass.
- **Sender-authority controls:** restricted visibility modes exclude denied bot identities from the actual core-rendered prompt and from media requests. Explicit `all` mode preserves all four fixture messages. Revocation during either room or initial-thread retrieval prevents media work and dispatch.
- **Compatibility and regression checks:** 573 focused history/context tests passed before the media repair. The media repair passed 250 relevant cases; after extracting its private scope adapter to satisfy the existing source-size limit, all 125 core media, scope-lifecycle, and monitor-policy cases passed again. Extension test typechecking, targeted core/plugin lint, documentation checks, and source-size ratchets passed. The private-QA build at `f5b2f6f3998` passed and verified all 156 public SDK subpaths; the subsequent fix changes only internal media-task joining, not the public contract or import boundaries. A source smoke verified unchanged pending-history bytes, legacy 20-entry prompt bounds, configured recent bounds, and compact resumed prompts.
- **CI attribution:** prior run [35484057866](https://github.com/openclaw/openclaw/actions/runs/35484057866) failed only the outbound-ACK shard and aggregate gate. Its two worker-transfer tests were inherited from main: #153083 tightened claimless settlement, while those fixtures still finish with a claimless ACK of a claimed row. The test, ACK wrapper, and kernel are byte-identical between main parent `42dcea5312` and tested merge `35a5adce2a93`; this PR changes none of their infra/state/test-routing owners. A new exact-head run covers the final revision.
The transport proofs use real channel APIs, not a live language model. No UI presentation change.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* fix(ui): keep native titlebar buttons consistently borderless
Remove the floating Inbox border, fill, shadow, and backdrop blur in native web-chrome titlebars while preserving browser floating chrome, hover and keyboard focus.
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(ui): keep native titlebar buttons consistently borderless
Worked on by:
- @steipete
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
OpenClaw-Publication: e02eb098-869b-4b02-824a-fc4458a6991b
* fix(ui): keep native titlebar buttons consistently borderless
Worked on by:
- @steipete
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
OpenClaw-Publication: de1c9117-329e-4f38-8175-8d3bea0d3ba3
* test(ui): wait for responsive shell before measuring setup controls
Wait for the viewport-specific shell state and stable control actionability before recording layout. Preserve every row-count, size, bounds, and non-overlap assertion. The unchanged rail suite and native titlebar suite pass; the corrected responsive suite passes all five cases.
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(ui): keep native titlebar buttons consistently borderless
Worked on by:
- @steipete
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
OpenClaw-Publication: 80b5d233-d82b-43b4-8b79-ab076f10374a
* fix(ui): preserve title clearance beyond the borderless Inbox badge
Reserve the badge's one-pixel overhang in native titlebar clearance. Await the actual badge and settled layout before measuring; preserve the eight-pixel assertion and all behavior checks. Deterministic before proof fails at seven pixels; all 28 native-titlebar, responsive setup, and page-header cases pass after the fix. Scoped autoreview is clean.
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
---------
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* perf(projects): move durable listings to retained workers
* perf(sessions): move placement evidence reads into workers
* refactor(state): remove placement reader type cycles
* refactor(state): query registry schema through Kysely
* fix(ci): align status timeout fixture with shared auth
* test(gateway): adopt timeout persistence synchronization
Carry the exact reviewed test-only fix from #153342. Await the captured
terminal persistence owner before advancing the abandoned producer's grace.
Preserve all original deadlines, clock steps, receipt, removal, and retry
assertions. No production changes or diagnostic delay are included.
The patch and relevant lifecycle owners match the donor's 35-test,
selected-check, and independent review evidence byte-for-byte.
* test(outbound): retain live claim during ACK fixture cleanup
Closes#146447
## What Problem This Solves
Fixes the cron form telling users that timeouts must be greater than zero when zero is already a valid value.
## User Impact
The English validation message now explains that zero is accepted and disables this timeout.
## Why This Change Was Made
Align the error message with the existing validator and timeout behavior. This changes one English string; runtime behavior is unchanged.
## Evidence
- [Fresh inspected before/after and zero-timeout browser proof](https://github.com/openclaw/openclaw/pull/152814#issuecomment-5747471672), also delivered in the originating chat. Matched current-main UI inputs show negative values rejected and numeric zero submitted on both versions; only the English guidance changes. Gateway responses were mocked, so this does not claim real persistence or unlimited agent execution.
- Canonical English baseline/verification passed. The complete one-line introduced patch matches the tested current-main overlay; the contributor head remains unchanged.
### Contributor-reported verification
- All 214 existing cron form tests passed, including zero-timeout validation and create/update payload coverage.
- The i18n baseline and verification commands, scoped formatting and lint checks, and `git diff --check` passed.
- Checked the form against the isolated mock Gateway: `-1` shows the corrected error; `0` clears the error and permits submission. These screenshots use synthetic fixture data and are also attached in the originating work discussion.
**Before: timeout `-1` shows misleading guidance**

**After: timeout `-1` shows the corrected guidance**

**After: timeout `0` is accepted**

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Closes#152921
## What Problem This Solves
Fixes: compact tool-metadata inference throws `RangeError` when an argument contains a deeply nested array.
## User Impact
Tool and plugin callers receive a bounded preview instead of a stack overflow from this formatter. Values beyond 64 array levels are intentionally omitted, including some values that previously rendered successfully. Shallower siblings still contribute; executable arguments and stored transcripts are unchanged. No configuration or migration is required.
## Why This Change Was Made
The existing formatter already limits visible array entries and string length, but its recursive array descent had no depth bound. A private depth counter keeps the same formatter, redaction, per-array width rules, and ordinary fallback behavior. No new API or renderer is introduced.
## Evidence
- Verified the named `openclaw/plugin-sdk/agent-harness-runtime` export in published `openclaw@2026.9.5`. A separate Node consumer resolved that real package export from built current-main and candidate packages, without importing private source or a hashed chunk.
- Same JSON-derived 20,000-level input: current main throws `RangeError` from `coerceDisplayValue`; candidate returns `undefined`. A deep branch followed by a shallow sibling retains the sibling. Original argument depth and leaf remain unchanged, and a subsequent ordinary SDK call succeeds.
- The SDK comparison explicitly records the tradeoff: 64 levels still render, while 65 levels now omit the value. Per-array ellipsis, ordering, empty values, the unread fifth child, and ordinary output match the baseline.
- 119 focused tests passed. Three depth/mixed-sibling regressions fail with the original production file; at 5,000 levels this host returned the old preview rather than overflowing, so that test is not presented as the stack-overflow witness. Scoped lint, formatting, and both source-size checks passed.
- The complete production file is byte-identical between the prepared PR and the tested current-main overlay. Tests replace a redundant shallow case with depth-boundary and mixed-sibling coverage; SDK documentation states the lossy preview contract.
This is public SDK metadata proof, not a full agent, CLI, TUI, or Control UI run. Serialization and argument sanitization have independent limits. The change does not establish a total-work bound or comprehensive cycle/getter safety, and does not guarantee that every deeply nested model response completes an agent run.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>