* feat(anthropic): add Claude Opus 5 model support
Wire claude-opus-5 through the Claude 5 contract seams: adaptive-by-default
thinking with the full low..max effort range, default-sampling and prefill
stripping, streaming refusal contract, model-bound thinking replay, and 1M/128k
catalog metadata across anthropic, claude-cli, Vertex, Bedrock, and Mantle.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(anthropic-vertex): normalize explicit Vertex Opus 5 model rows
Extend normalizeAnthropicVertexResolvedModel so user-configured Vertex Opus 5
rows regain reasoning, image input, 1M/128k limits, and the native thinking
map; update the live-model priority expectation and regenerate docs_map.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(gateway): add web-only incognito sessions held in process memory
* feat(ui): add incognito toggle and badges to the web new-session flow
* fix(sessions): classify incognito by key shape, fail closed on stale keys, and gate memory writes
* fix(codex): start harness threads ephemeral for incognito sessions
* fix(sessions): reshape internal-effects incognito keys and add doctor repair for reserved key collisions
* refactor(plugin-sdk): export canonical incognito key classifier and guard the sentinel path
* fix(state): classify incognito DB handles from the recorded open-time set
* fix(gateway): isolate incognito sessions from durable lineage and allocation on read-only misses
* docs(sessions): pin the reserved incognito namespace ownership decision
* feat(gateway): admin-scope incognito visibility and incognito-blind cross-session surfaces
* fix(ci): repair kysely guardrails, dead export, docs map, protocol bindings, and ACP reset rotation
* fix(gateway): remove non-admin observability side channels for incognito sessions
* fix(gateway): enforce admin-scope incognito access and cover all parent-reference creation paths
* feat(sessions): enforce visibility and membership
* feat(ui): add session sharing controls
* docs: add session sharing implementation report
* refactor(sessions): use canonical creator identity
* fix(sessions): adopt creator ownership contract
* docs: refresh session sharing rebase report
* docs: record final creator integration proof
* docs: record final main rebase
* chore: drop worktree report artifact
* fix(sessions): keep drafts owner-only
* fix(ui): preserve redacted session restrictions
* fix(sessions): preserve scoped sharing authorization
* fix(sessions): re-verify session instance inside sharing mutation queue
* test(sessions): cover stale sharing mutation
* fix(sessions): bind membership to session instance, gate absence blocking on sharing
* fix(sessions): preserve entry normalization on rebase
* fix(sessions): atomic visibility instance guard, reset visibility on recreate
* docs(ui): name the absence-heuristic tradeoff and link follow-up
* feat(protocol): expose session sharing row state
* docs: note generated creator identity type
* fix(sessions): bind member writes and visibility rollback to session instance
* fix(ui): discard stale-connection sharing loads; drop worktree scratch files
* fix(ui): block composer only on observed sharing state, never on list absence
* fix(gateway): authorize agent runs against the resolved session (close keyless bypass)
* chore(protocol): allowlist Control UI-only session.sharing event for mobile
* test(config): record session.sharing keys in common-tier snapshot
* refactor(sessions): unexport internal sharing helpers
* test(gateway): update sessions changed routing assertions
* fix(sessions): align sharing identity with created actor
* fix(sessions): align membership identities and storage keys
* fix(gateway): re-filter drafts against fresh sharing state in sessions.list
* fix(gateway): drafts stay owner+admin only in the sessions.list fresh filter
* fix(ui): re-export sharing protocol types for the Control UI
* fix(ui): keep SessionSharingRole internal to satisfy deadcode gate
* fix(gateway): read runtime config lazily in session-mutation authorization
authorizeSessionMutation ran on every gateway request but eagerly called
context.getRuntimeConfig() — a non-trivial config resolve — for methods that
are never session mutations. Read config only once a real session-mutation
target is resolved. Also register the four session sharing methods in the
2026.7 release-train inventory test.
* fix(gateway): share one config snapshot across session-mutation authorization
Group rename/delete discovery and the authorization loop were each resolving
runtime config separately after the lazy-read change. Memoize the resolve so
non-session requests still pay nothing, while any session mutation resolves
config at most once and both discovery and authorization use that single
snapshot (no double reload, no mid-request config-change split).
* fix(gateway): resolve session-sharing CI gates
- isGatewayAdmin: null-safe connect access so internal/plugin-runtime runs
(which reach authorization with a connect-less client) do not crash.
- emitSessionsChanged: scope only to a concrete session key; a [undefined]
sessionKeys scope filters nothing correctly and would strip draft gating.
- session stores: mark the sync TOCTOU re-read and the sqlite_master
existence probe as narrowly-justified raw SQLite primitives.
- tests: provide getRuntimeConfig to the session-action contract context,
drop a shadowed 'call' binding, use structuredClone, and assert the
agent-scoped sessions.changed broadcast shape.
* docs(gateway): note best-effort participation gate + refresh native i18n baseline
Session ownership/visibility are usability features, not a security boundary
(docs/concepts/multi-user.md, SECURITY.md); document that the pre-dispatch
authorization is intentionally not commit-bound to the resolved instance.
Also refresh apps/.i18n/native-source.json after the session-sharing protocol
codegen shifted line numbers of existing native strings (position-only).
* test(gateway): reset session sharing snapshots
* style(gateway): format sharing reset import
* fix(ui): disable the thread-changes button when the workspace is not a git checkout
* chore(protocol): regenerate Swift gateway models for sessions.files.list gitCheckout
* feat(cron): system-owned heartbeat monitor jobs replace the interval scheduler
- new internal cron payload kind {kind:"heartbeat"}: execution pokes
requestHeartbeat({source:"interval"}); reported in the protocol job
schema, not accepted from client create/patch
- gateway converges one declaration-keyed monitor job per heartbeat-enabled
agent (schedule every+deterministic phase anchor) at startup and on
config reload; removes monitors for unconfigured agents
- heartbeat runner loses its interval setTimeout machinery; nextDueMs
stays as the cooldown gate, event wakes unchanged
* test(cron): heartbeat monitor regressions; docs for cron-owned cadence
- converge/prune/failure-containment tests for heartbeat monitor jobs
- heartbeat payload run fires an interval wake, no system event
- scheduler tests converted from timer self-fire to wake-queue pokes;
timer-mechanics-only tests deleted with the timer
- persisted-shape accepts the heartbeat payload kind
- docs: heartbeat cadence ownership + system payload kind
* fix(cron): heartbeat monitor review round 1
- targeted cron-monitor interval ticks use the full per-agent path so
due-commitment sessions still deliver
- cron-disabled gateways keep a local fallback interval timer (shipped
cron.enabled=false contract; removed when heartbeat config folds into
cron in #110950)
- heartbeat job reconciliations serialize with latest-wins epochs and a
bounded 30s retry after a failed convergence pass
* fix(cron): chain clamped fallback heartbeat timers past the setTimeout cap
* fix(cron): heartbeat monitor review round 3
- targeted monitor redirect skips wakes carrying heartbeat overrides and
surfaces the per-agent terminal skip reason instead of not-due
- cron-disabled fallback timer re-arms with a 1s floor after each firing
so a dropped wake cannot end the chain
- heartbeat payloads are system-owned at the service boundary: add requires
the gateway opt-in, patches to the kind are rejected
* fix(cron): heartbeat monitor review round 4 — full ownership enforcement
- prune only jobs proven to be monitors (prefix AND heartbeat payload)
- existing monitors reject every update patch; declarative upserts on the
monitor key require the gateway opt-in even with a different payload
* fix(cron): complete heartbeat monitor ownership boundary
- converge scopes declarative matching to real monitors so a colliding
user job with the same key is never adopted or overwritten
- monitor removal requires the gateway systemOwned opt-in; ad-hoc
API/CLI deletion is rejected, reconciliation cleanup still prunes
* docs(cron): record intentional enrollment-snapshot semantics for monitor ticks
* fix(cron): repair heartbeat monitor CI gates
The root package.json shipped "author": "", so npm showed no author for the
published openclaw package, and the three published workspace packages had no
author field at all. Set all four to the Foundation, matching the LICENSE
copyright holder and the openclaw.ai footer.
Also name the Foundation on the docs homepage, which never said who develops
OpenClaw even though the README and website footer now do.
Personal credits in docs/reference/credits.md, docs/start/lore.md, and the site
footer stay as authorship history; they are not org attribution.
* feat(ui): redesign session observer HUD with labeled status and visibility-gated digests
* chore(protocol): regenerate app protocol bindings for sessions.observer.visibility
* feat(sessions): first-class archived-session handling
Archived sessions are now exempt from every automatic maintenance path
(age prune, entry cap, model-run prune, disk budget, cleanup repairs);
only explicit sessions.delete removes them. sessions.list gains an
additive tri-state archived filter (true | false | "all"). The sidebar
gets a persisted Active/Archived/All status filter with inline dimmed
archived rows, replacing the nav-away View-archived button; the Sessions
page toggle becomes the same tri-state with dimmed+badged rows in All
mode; the chat composer's archived notice becomes a full-width banner
with an Unarchive action.
* chore(protocol): regenerate Swift gateway models for tri-state archived filter
* fix(memory): keep canonical rows when same-file legacy memory tables diverge
* fix(memory): keep canonical-owned sources' chunk sets coherent during legacy import
* fix(memory): import legacy chunks when canonical source has no chunks
The same-file legacy migration excluded a legacy chunk from import whenever the
canonical index already had a source row for its (path, source). That stranded a
file whose canonical source was registered but had no chunks yet (indexing
interrupted before chunks were written, or embedding pending/failed): the legacy
chunks were its only searchable content, and the matching source hash stops sync
from re-indexing, so the file went silently unsearchable.
Re-key the chunk-coherence exclusion on canonical chunk ownership instead:
snapshot the (path, source) pairs that already have canonical chunks before the
import and skip legacy chunks only for those. A source with a canonical row but
no chunks now imports its legacy chunks. The snapshot is taken pre-insert because
the exclusion predicate reads the chunks table the import writes to.
Add regressions: legacy chunks import for a chunk-less canonical source while a
chunk-owning source still drops its stale legacy chunk; and restore abort
coverage for the meta and chunks copy assertions (previously only files was
exercised).
* fix(memory): harden same-file legacy conflict recovery
* fix(memory): rebuild ambiguous partial legacy sources
* fix(memory): reconcile migrated derived indexes
* fix(memory): close migrated index ownership gaps
* test(memory): align migration expectations
* test(tooling): match routed test order
* test(memory): exercise vector reload cleanup
* test(memory): prove real vector reload cleanup
* fix(memory): make migrated indexes converge
---------
Co-authored-by: Serhii Leniv <leniv.tech@gmail.com>
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* refactor(gateway): declare spawn lineage explicitly at sessions.create
Spawn depth is now a declared fact, never inferred from parentSessionKey.
sessions.create accepts an optional spawnDepth (requires parentSessionKey) that
spawn-owned creations pass; every other fresh session persists spawnDepth 0,
making operator chats and UI forks spawn-capable roots. The visible spawn tool
declares callerDepth + 1, and subagent depth recovery no longer walks
parentSessionKey, which is UI threading only.
Accepted tradeoff (documented inline): pre-upgrade visible children whose only
lineage was parentSessionKey resolve as roots; the transient population may
spawn one extra generation, still capped by maxChildrenPerAgent.
* chore(protocol): regenerate Swift gateway models for sessions.create spawnDepth
* feat(gateway,ui): ask-the-observer card input over sessions.observer.ask
* refactor(ui): single home for observer run-identity helper after restack
* test(ui): drop duplicated observer hud test after restack
* test(ui): give the observer ask flow its own colocated suite
* refactor(gateway): leaf observer contract and ask module split for ci gates
* refactor(gateway): drop observer contract re-export shims
* fix(ui): allow direct sessions in non-Git folders
* test: align New Session fixtures with place picker
* fix(ui): preserve worktree intent on Git probe failures
* fix(types): keep worktree status alias internal
* feat(ui): session observer HUD, subtitle integration, and settings
* test(ui): observer demo fixtures for the mock control-ui harness
* fix(ui): satisfy lint and deadcode gates for observer surfaces
* test(ui): adopt renamed pull-request summary api after rebase
* fix(ui): clean rebase artifacts in observer test files