* feat(sessions): durable session state events with parent invalidation
Parents no longer act on stale child-session state: a durable, typed
signal log (session_state_events + per-agent heads) records direct human
messages to children, child spawn/terminal outcomes, goal changes, and
compaction at the seams where those facts are created. A frozen-watermark
cursor protocol (session_watch_cursors) delivers one coalesced system
notice to the parent through the existing system-event + heartbeat wake
idiom, acknowledged at the shared generic drain, with a deferred startup
sweep for restart recovery. session_status gains stateVersion and
changesSince (with exact pruned-history gap signaling); sessions_list
rows gain stateVersion.
Closes#104565
* chore: regenerate docs map and prompt snapshots for session_status changesSince
* fix(outbound): preserve backticks on <code> tags with attributes
The plain-text sanitizer only matched bare <code> openers, so attributed
variants such as <code class="language-ts"> lost their backtick wrapping
and were stripped to raw text before channel delivery.
Allow optional attributes on the opening <code> tag, consistent with the
existing handling for <h[1-6]> and <li> in the same function.
Fixes#104117
* fix(outbound): preserve attributed inline formatting
Co-authored-by: chengzhichao-xydt <chengzhichao-xydt@users.noreply.github.com>
* test(outbound): compact attributed tag coverage
* fix(outbound): normalize attributed formatting tags
* docs(outbound): clarify attribute normalization invariant
* fix(outbound): preserve native formatting semantics
* docs(plugin-sdk): document sanitizer markup styles
* docs(plugin-sdk): refresh docs map
---------
Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: chengzhichao-xydt <chengzhichao-xydt@users.noreply.github.com>
* feat(tooling): extend strict-ratchet lane to all remaining leaf packages
* fix(packages): burn down indexed-access debt in ai and agent-core
All 196 noUncheckedIndexedAccess errors fixed behavior-identically
(iteration, .at()/slices, DataView byte math, guarded queue peeks) plus
cleanup finds: a sparse-tool diagnostic bug, deduplicated Responses
call/item ID parsing with an honest string|undefined splitter, and a
clearer local failure for redacted-thinking blocks missing signatures.
Removes all 17 remaining non-null assertions across ai, gateway-client,
and llm-core so the assertion ban aligns 1:1 with the ratchet lane.
speech-core joins memory-host-sdk as structurally deferred (imports
src/** via plugin-sdk path mappings).
* feat(fleet): add openclaw fleet cell supervisor for multi-tenant hosting
* test(fleet): cover cell profile, registry, containers, and service flows
* docs(fleet): document multi-tenant hosting and the fleet CLI
* fix(fleet): verify upgrade replacements and release foreign-collision reservations
* fix(fleet): gate upgrade commit on replacement health
* docs(fleet): mark fleet experimental and pin its single-host scope
* test(fleet): make incomplete-profile casts explicit for test-type lane
* fix(state): regenerate kysely schema artifacts after rebase conflict
* fix(gateway): allow macOS app platform version refresh without re-pairing
When macOS updates (e.g. 26.5.0 → 26.5.1), the Mac app detects a
platform mismatch against its paired record and sends a repair request.
The approval dialog enters an infinite loop because the pending request
TTL (5 min) expires before the user clicks Approve, causing "unknown
requestId" errors that trigger a new repair request ad infinitum.
iOS and Android already had silent platform version refresh via
normalizeMobileAppPlatformPin — this extends the same treatment to the
macOS native app by recognizing "macos X.Y.Z" as the same platform
family regardless of version, renaming the helper to
normalizeNativeAppPlatformPin.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(gateway): validate macOS platform version refreshes
* fix(gateway): avoid native platform family marker collisions
* test(gateway): type node client name
---------
Co-authored-by: 骆毅 <luoyifu.lyf@digital-engine.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(file-transfer): audit dir fetch archive size
* test(file-transfer): guard dir fetch audit archive test on Windows
* test(file-transfer): format dir fetch audit guard
* fix(file-transfer): verify directory archive audit metadata
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
The Codex/Claude sidebar sections leaked long titles across the row
timestamps and past the sidebar edge because the row body was never a
flex container, so the title span stayed inline and ellipsis rules did
not apply. The sections also rendered every loaded session (Codex swept
up to 100 catalog pages per host every 30s) with no height cap, growing
past the sidebar shell and painting over the footer.
Rows now reuse the regular session-row __text anatomy so titles
ellipsize, the sidebar renders only the newest 10 sessions per host
with a derived truncation note (the full catalog stays on the sessions
page), each section shrinks and scrolls inside the sidebar body, and
the shell body clips as a final guard. The sidebar full-catalog
hydration loop and the one-off __body class are deleted.
Formatting proof: oxfmt --check clean on changed files via Testbox
tbx_01kx92cwpr1x9ccp2fgn441y8h (local hook skipped: no node_modules).
Fixes#104584
* feat(tooling): add noUncheckedIndexedAccess strict-ratchet lane
* fix(packages): make indexed access explicit across ratchet packages
Burns down all 65 noUncheckedIndexedAccess errors in the seven ratchet
packages with behavior-identical restructuring (iteration, charAt/slice,
regex-group guards, validated hextet tuple). net-policy invariant
violations now throw instead of failing open. Adds
@openclaw/normalization-core/expect (expectDefined/first/last) with
subpath export and tests. memory-host-sdk fixes kept but the package
stays out of the lane: it re-exports core src/** so the flag would apply
transitively to all of core.
* fix(lint): keep .oxlintrc.json strict-JSON parseable for extension lint wrappers
The mobile single-column override for the welcome suggestion grid sat before
the base two-column rules with equal specificity, so it never applied; iPhone
WebKit views also inflate text via font boosting because text-size-adjust was
never locked, letting labels paint outside the chips. Move the override after
the base rules, lock text-size-adjust at the root, and harden chip wrapping
(line-height, balance, break-word).