Commit Graph

71613 Commits

Author SHA1 Message Date
Peter Steinberger
bb657eec93 refactor(config): retire redundant settings (#113174)
* refactor(config): retire redundant settings

* style: apply current formatter

* chore: update plugin sdk baseline

* fix: keep Codex tool caps context-aware

* chore: remove stale imports

* test: align WhatsApp QA debounce config

* fix(config): clean up retired config checks

* fix(ci): align config cleanup checks
2026-07-23 17:45:02 -07:00
Peter Steinberger
1603781bb0 improve(ui): unify sidebar footer into a full-width identity card (#113156)
* feat(ui): unify sidebar footer into full-width identity card

Footer becomes one card (avatar + name + chevron) mirroring the top agent
card; identity menu gains email header, Settings (with platform shortcut
hint), and Usage; Usage leaves default sidebar pins; settings shortcut now
also binds Ctrl+Shift+Comma; offline state lives in the card subtitle and
menu retry action and the card persists while disconnected.

* test(ui): align persisted-sidebar fallback default with usage removal
2026-07-23 17:40:30 -07:00
Peter Steinberger
0dd9dcda2f refactor(auto-reply): normalize inbound text once (#113179)
* refactor(auto-reply): canonicalize inbound text once

* chore(plugin-sdk): refresh API baseline

* refactor(auto-reply): narrow finalized template context

* test(auto-reply): keep runner fixtures structurally compatible

* fix(auto-reply): guard optional post-command agent text

* fix(auto-reply): finalize intercepted gateway context

* fix(ci): register iOS release planner entries
2026-07-23 17:39:01 -07:00
Peter Steinberger
7915c44773 fix(ci): allow sticky writer rebuild to finish (#113175)
* fix(ci): allow sticky writer rebuild to finish

* test: register iOS release tooling ownership
2026-07-23 17:17:10 -07:00
Peter Steinberger
0d406a84db fix(docs-i18n): accept hyphenated numeric compounds 2026-07-23 20:14:49 -04:00
joshavant
090bdab5b8 fix(ci): register iOS release script entries 2026-07-23 19:08:40 -05:00
joshavant
ba09e05e97 refactor(ios): append unpadded App Store revisions 2026-07-23 18:42:16 -05:00
joshavant
0558831b92 fix(ios): normalize App Store build upload state 2026-07-23 18:26:29 -05:00
joshavant
b7d77b0f21 feat(ios): deterministically plan App Store releases 2026-07-23 18:18:32 -05:00
Peter Steinberger
af443b4384 refactor(agents): prepare hot-path runtime facts (#113167)
* perf(agents): prepare hot-path runtime facts

* fix(plugins): preserve catalog registry contracts
2026-07-23 16:14:22 -07:00
Peter Steinberger
b23c7bd0f8 feat(cron): convert heartbeat tasks: entries into independent cron jobs (#113165)
Each legacy heartbeat tasks: entry becomes an editable system-created cron
job (declaration key heartbeat-task:<agentId>:<hash>, per-occurrence
identity for duplicate names) that fires a guarded heartbeat wake carrying
the task prompt plus current monitor scratch context. Task cadence is now
independent of the base heartbeat interval; active-hours, busy-retry,
min-spacing, and flood guards are preserved, deferred payload-carrying
wakes are retained and retried after the spacing floor, and colliding
task/event wakes cannot starve each other.

openclaw doctor --fix migrates existing blocks: async parse/plan, then one
synchronous SQLite transaction that rereads the pinned scratch revision,
upserts job rows, and strips the tasks: block atomically — concurrent
doctors serialize on the database and a losing run aborts untouched.
Orphan fields, invalid intervals, and incomplete entries block migration
of their block with a clear finding instead of silent text loss. The
runtime tasks: parser is deleted; leftover text is ordinary scratch prose.

Nine Codex gpt-5.6-sol xhigh autoreview cycles; final verdict clean.
2026-07-23 16:13:08 -07:00
Peter Steinberger
b3b9e691bd fix(ci): rebuild sticky modules before snapshot refresh (#113155) 2026-07-23 15:56:49 -07:00
Jason (Json)
09c6d66d19 fix(ui): render managed chat media under base paths (#113163) 2026-07-23 16:49:14 -06:00
Peter Steinberger
7cbd24771f refactor(gateway): unify chat run state (#113157)
* refactor(gateway): unify chat run state

* test(gateway): align chat run fixtures
2026-07-23 15:45:06 -07:00
Peter Steinberger
083276eada fix(docs-i18n): mask composite numeric literals 2026-07-23 18:45:00 -04:00
Peter Steinberger
5fb3136be0 feat(telegram): render rich markdown lists natively (#113158) 2026-07-23 15:41:21 -07:00
Alex Markson
d2b4ec18c1 fix(cron): claim benign same-generation session updates (#113088)
* fix(cron): claim a same-generation session row instead of failing on benign concurrent writes

Under a large, busy session store, a concurrent write to a cron session
row that keeps the lifecycle revision unchanged (delivery/token/status
update) landing between session resolve and the run's first persist made
the claim guard reject the run with CronSessionLifecycleClaimError
"changed while starting work". canClaimInitialRevision required exact
ownership-field equality between the resolved snapshot and the freshest
row, so any drift aborted the run even though the unchanged lifecycle
revision proves no competing run had claimed it. The same guard shape
also aborts sessions_spawn subagent admission ("deleted while starting
work"). Store size amplifies the window: the full-store JSON
read-modify-write makes resolve->persist grow with entry count, so at
~22.5MB/576 entries every isolated run lost the claim continuously.

Allow the claim when the current row still carries the lifecycle revision
this run resolved from (same generation, no competing claim), still gated
by an inactive admission, and let the existing snapshot merge reconcile
the drifted fields. Genuine conflicts still fail hard: a different
revision claimed the row, or its revision is actively admitted.

Refs openclaw/openclaw#113085

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cron): keep session claims within one session id

Co-authored-by: Alex Markson <alex@metahacking.org>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-23 15:39:37 -07:00
Peter Steinberger
127b78142b refactor(auto-reply): split config dispatch pipeline (#113154)
* refactor(auto-reply): split config dispatch pipeline

* refactor(auto-reply): keep phase result types private
2026-07-23 15:31:02 -07:00
Josh Lehman
081b3ebc67 fix(state): support SQLite 3.51 migration (oc-224.1) (#113151) 2026-07-23 15:28:11 -07:00
Peter Steinberger
fc92b9fd91 feat(ui): merge creator avatar into sidebar leading slot, move creator filter into Threads menu (#113150)
* feat(ui): merge creator avatar into sidebar leading slot and move creator filter into Threads menu

The per-row creator chip previously rendered next to the leading state
indicator, so rows with a known creator started their titles at a
different x-offset than rows without one. The avatar now occupies the
single fixed leading slot: unread renders as a corner badge on it,
running as a spinner ring, and open/merged PR state as a colored corner
badge, while attention and pinned icons keep the slot. Child rows keep
their status badges and no longer render owner chips.

The standalone 'Filter by creator' select above the session list is
gone; the Threads funnel menu gains a People radio section with owner
chips, and the funnel trigger shows an accent dot while a creator
filter is active. The empty Threads header stays visible when ownership
chrome is active so the filter can always be cleared. Mock dev fixtures
gain two creator identities so the ownership chrome is demonstrable.

* test(ui): guard parent row spread in child-avatar ownership case
2026-07-23 15:26:56 -07:00
Gio Della-Libera
bd48b7b26b fix(marketplaces): allow trusted feed key rotation
* fix(marketplaces): allow trusted feed key rotation

* fix(feeds): reject same-sequence payload changes

* fix: fail closed on signed feed monotonicity

---------

Co-authored-by: Gio Della-Libera <giodl@microsoft.com>
2026-07-23 14:58:10 -07:00
zengLingbiao
796edc3b84 fix(agents): resolve trusted shell snapshot home (#113103)
* fix(agents): ignore blank HOME when resolving shell snapshot home

* test(agents): restore shell snapshot env

Co-authored-by: zenglingbiao <zenglingbiao@users.noreply.github.com>

* fix(agents): preserve nonblank shell home paths

Co-authored-by: zenglingbiao <zeng.lingbiao@xydigit.com>

* fix(agents): resolve trusted shell capture home

Co-authored-by: zenglingbiao <zeng.lingbiao@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: zenglingbiao <zenglingbiao@users.noreply.github.com>
2026-07-23 14:57:17 -07:00
Peter Steinberger
bec7d8a144 fix(gateway): preserve Control UI question access after upgrades (#113153) 2026-07-23 14:46:51 -07:00
Peter Steinberger
5efd616413 refactor(memory): drop media-marker text from LanceDB memory ingestion (#113145)
The memory plugin's LanceDB path no longer regex-extracts or rewrites
[media attached:] marker text. Media-note lines are classified as
presentation-only and dropped wholesale during capture/query ingestion
(bracket-safe classifier: filenames may contain ']'); captions and
non-media text are preserved; legacy inline tokens stay inert escaped text.

Recall-side neutralization is deleted deliberately: image discovery is
scoped to the current-turn imagePrompt, so recalled memory text (markers
or bare path-shaped tokens) never reaches attachment scanning. Regressions
prove that boundary at the embedded, CLI, and plugin-harness entry points.
2026-07-23 14:36:07 -07:00
joshavant
30395ba31b feat(ios): support App Store release revisions 2026-07-23 16:24:15 -05:00
Peter Steinberger
06776e707b refactor(cron): split timer lifecycle (#113141) 2026-07-23 14:14:58 -07:00
Peter Steinberger
8a2b2b35f5 fix(ci): rebuild stale sticky dependency snapshots (#113142) 2026-07-23 13:59:22 -07:00
Gio Della-Libera
03c9b22762 fix(feeds): accept standard DSSE envelopes
* fix(feeds): accept standard DSSE envelopes

* fix(feeds): limit beta envelopes to snapshots
2026-07-23 13:40:24 -07:00
Peter Steinberger
f9708083f8 refactor(imessage): unify outbound markdown ranges (#113138)
* refactor(imessage): use shared markdown ranges

* test(imessage): keep format profile private
2026-07-23 13:33:14 -07:00
Rafli Surya Wijaya
6224d7849d fix(infra): preserve large inode identity in session migrations (#112478)
* fix(infra): use bigint stat in resolveSessionStorePathRelationship to prevent inode precision loss on large-inode filesystems

fs.statSync() returns ino as a JS Number, which can only safely represent
integers up to 2^53.  On virtiofs / Kata Container filesystems (and any other
fs whose inodes exceed 2^53) two adjacent directory inodes — e.g.
72057594037932382 and 72057594037932383 — are both rounded to the same Number
value (72057594037932380), causing sameFileIdentity() to treat two distinct
paths as the same file object.

In resolveSessionStorePathRelationship() this manifests as a false-positive
alias detection: the agent state directory and its sessions/ child map to the
same inode Number, so the gateway migration refuses to continue and prints:

  Deferred session key migration in aliased store …; atomic replacement cannot
  update distinct filesystem aliases as one operation …

and the gateway refuses to start.  The fix is a one-line change: pass
{ bigint: true } to fs.statSync() so that ino is returned as a BigInt that
preserves the full 64-bit value.  FileIdentityStat already accepts bigint, and
sameFileIdentity already handles mixed number/bigint comparison, so no further
changes are needed.

Two regression tests are added to file-identity.test.ts documenting that
adjacent inodes above 2^53 are correctly distinguished when represented as
BigInt (the pre-fix Number path falsely collapses them).

Closes #112341

* test(infra): exercise bigint store identity

Co-authored-by: Rafli Surya Wijaya <260355617@qq.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-23 13:13:58 -07:00
Peter Steinberger
cbf94c0d8b feat(sessions): drafts UX — create-as-draft, promote, admin ghost treatment (#113127)
* feat(protocol): support draft session creation

* feat(ui): add draft session workflows

* docs: explain multi-user drafts

* test(ui): tighten draft ownership fixture

* test(ui): satisfy draft E2E lint

* test(ui): keep draft fixtures strictly typed

* docs: add drafts implementation report

* docs: clarify implementation LOC summary

* test: strengthen draft compatibility coverage

* docs: correct drafts cleanup report

* fix: harden draft availability policy

* docs: update draft policy review notes

* test(ui): type draft policy mock control

* fix: preserve keyed draft creation retries

* fix: keep disabled draft retries idempotent

* docs: finalize drafts cleanup report

* fix(ui): keep draft ownership helper internal

* docs: refresh drafts docs map
2026-07-23 13:06:35 -07:00
Peter Steinberger
95b86a3b2b refactor(heartbeat): make cron monitor rows own heartbeat cadence (#113135)
* refactor(heartbeat): make cron monitor rows own heartbeat cadence

agents.*.heartbeat.every stays the documented desired-state input; gateway
reconciliation and openclaw doctor --fix write it through into durable
system-owned cron monitor rows, and a scheduled monitor tick carries its
persisted everyMs/anchorMs as the authoritative cadence, which the runner
adopts for subsequent event cooldowns. Doctor gains a read-only cadence
preview (resolves the scheduler seed without creating device identity) and
an idempotent fix path that converges monitor rows per agent.

The cron-disabled fallback timer is deleted per its named removal plan
(#110950): gateways with cron.enabled=false or OPENCLAW_SKIP_CRON=1 log a
startup warning and get no scheduled heartbeats; manual and event-driven
wakes remain.

* fix(ci): drop unused requestHeartbeat import and refresh plugin SDK baseline
2026-07-23 12:56:54 -07:00
Peter Steinberger
4ab29c941d fix(docs-i18n): escape translated list ordinals 2026-07-23 15:46:21 -04:00
Peter Steinberger
c519e01a24 feat(gateway): chat.send expectedLeafEntryId precondition keeps stale panes off switched branches (#113073) 2026-07-23 12:33:31 -07:00
Peter Steinberger
73d279c232 fix(plugins): preserve shipped SDK and lifecycle state (#113101)
* fix(plugins): restore shipped channel compatibility

* docs(plugins): record shipped channel compatibility

* test(plugin-sdk): budget shipped channel compatibility

* docs(plugin-sdk): track shipped channel compat window

* test(plugins): align shipped compat guardrails
2026-07-23 12:30:54 -07:00
Patrick Erichsen
e567a5ffa0 fix: ClawHub plugin installs do not count as installs (#113133) 2026-07-23 12:30:15 -07:00
Peter Steinberger
197741ac4e refactor(zalouser): unify inline emphasis rendering (#113134) 2026-07-23 12:29:50 -07:00
Peter Steinberger
be815ae5c9 refactor(gateway): split session utilities (#113118)
* refactor(gateway): split session utilities

* fix(gateway): privatize thinking row projection
2026-07-23 12:26:10 -07:00
Peter Steinberger
2e4df03b30 test(discord): authorize voice e2e fixtures (#113132) 2026-07-23 12:20:10 -07:00
Peter Steinberger
913a6a83c5 fix(config): refresh docs baseline after help-text change 2026-07-23 11:58:42 -07:00
Peter Steinberger
13176b446a refactor(plugins): split gateway startup planning (#113129) 2026-07-23 11:50:17 -07:00
Peter Steinberger
c453c03979 refactor(media): delete internal MsgContext.Media* parallel fields for fact-only runtime (#113042)
* refactor(media): delete internal MsgContext.Media* parallel fields for fact-only runtime

Internal runtime now carries a fact-only RuntimeMsgContext: the legacy
MediaPath/MediaUrl/MediaType parallel fields (and plural/transcribed
variants), their alignment and default helpers, and bundled legacy payload
builders are removed from internal paths. Staging, hooks, Gateway, media
understanding, and the Telegram, QQ, Signal, Slack, iMessage, Discord, QA,
and Zalo plugins consume ordered MediaFact[] directly.

Retained boundaries per the program audit: public Plugin SDK MsgContext,
persisted transcript Media* rows, and documented template variables keep
working via projectMediaFacts at the five declared seams (fact owner,
channel payload, inbound-event, transcript persistence, SDK adapter).

Review-round hardening, each with regressions:
- hasStagedMediaProjection requires every path-bearing fact staged (was
  any-satisfied; mixed contexts skipped staging unstaged facts).
- finalizeInboundContext returns Omit<T, LegacyMediaContextKey> so deleted
  legacy fields leave the type when they leave the object.
- QQ image facts carry explicit kind: "image" (remote URLs have no MIME).
- resolveStagedMediaFacts adopts staged legacy paths positionally while
  retaining canonical fact metadata and cardinality (staged projections
  previously replaced canonical facts wholesale).

1,615 tests across 47 files; goldens untouched; delegated check:changed
green (run 30009882062).

* test(media): migrate remaining legacy Media* consumer suites to structured facts

Exact-head CI caught suites outside the curated affected set that still
asserted internal legacy fields. All were stale internal-field assertions
migrated to facts, except QA Channel, which had a real migration gap: it
still constructed the bundled legacy payload internally and now normalizes
saved attachments with toInboundMediaFacts and passes the declared media
parameter directly. Exhaustive rg sweep over every test referencing the
deleted fields (133 files, each run individually) is green.
2026-07-23 11:45:40 -07:00
Peter Steinberger
7d4a16c0a5 chore(docs-i18n): log opt-in rejected body 2026-07-23 14:42:36 -04:00
Peter Steinberger
129f86bbf5 feat: auto-collect durable meeting transcripts (#113122)
* feat(meetings): auto-collect durable transcripts

* chore(plugin-sdk): refresh meeting transcript API baseline

* fix(plugin-sdk): keep meeting transcript options implicit

* fix(meetings): satisfy transcript bridge typecheck

* fix(google-meet): preserve optional caption policy context

* fix(google-meet): retain caption mode callback type

* refactor(meetings): split transcript lifecycle helpers

* chore(plugin-sdk): refresh split meeting runtime baseline

* refactor(google-meet): split session helpers

* fix(meetings): decouple transcript retries from leave

* fix(meetings): isolate provider subscribers

* fix(meetings): harden capture lifecycle

* fix(meetings): preserve capture during storage outages

* fix(meetings): preserve pending transcript ordering

* fix(meetings): retry capture initialization

* test(agents): reflect default transcript registration
2026-07-23 11:41:08 -07:00
Peter Steinberger
6c3d8fc1b0 ci(release): honor candidate pnpm pin (#113110) 2026-07-23 11:32:04 -07:00
Peter Steinberger
da0a9e1531 refactor(signal): adopt format capability profile (#113120) 2026-07-23 11:31:06 -07:00
Peter Steinberger
4bd01bd4e1 fix(cli): restore macOS system CA trust (#113112)
* fix(cli): preserve macOS system CA trust

* test(cli): satisfy one-shot exit lint

* test(cli): cover finalizer through public lifecycle
2026-07-23 11:28:54 -07:00
Peter Steinberger
013b24dd6d feat(sessions): archive attribution (archivedBy) (#113116)
* feat(sessions): attribute archive transitions

* docs: add archive attribution report

* fix(sessions): restore alias layout after archive audit failure

* docs: update archive attribution report

* fix(sessions): isolate archive audit rollback

* docs: record final archive rollback design

* fix(sessions): make archive audit note best-effort

* docs: record best-effort archive audit policy

* chore: refresh native i18n baseline
2026-07-23 11:23:30 -07:00
Jason (Json)
2f5e7cfc5d fix(ui): prevent duplicate image prompt and flicker (#113113)
* fix(ui): stabilize initial image prompt handoff

* chore(protocol): refresh sessions create model

* chore(i18n): refresh native source inventory
2026-07-23 12:11:52 -06:00
Peter Steinberger
fefeff2b36 refactor(telegram): deduplicate polling session tests (#113117)
* test(telegram): deduplicate polling session scenarios

* test(telegram): type interleaving labels as tuples
2026-07-23 11:11:13 -07:00