* feat(apps): migrate iOS/macOS plan surface to the durable progress card
Replace the legacy stream:"plan" agent-event pipeline (runId-scoped state,
run-gated pill) with the sessionKey-scoped progress-card store: the shared
chat surface now renders progressCard.get snapshots, refetches on
progressCard.changed pokes with revision dedupe, clears on null-revision
pokes, and persists the card after the run completes. The card renders
markdown through the shared markdown view plus typed steps. Legacy Apple-side
plan handling (agent-event case, run-snapshot plan reconciliation,
OpenClawChatPlanStep parsing) is deleted; gateway emission stays for Android.
Removes the ios progressCard.changed coverage allowlist entry so the check
enforces the handler.
* chore(i18n): refresh native inventory for the progress-card rename
* fix(apps): keep the last progress card when a refresh fails
A transient progressCard.get failure no longer clears an already-rendered
durable card; only a successful null fetch or a null-revision poke clears it.
* fix(ui): fork active sessions from stable history
* fix(protocol): align active fork types
* test(ui): match main-session fork routing
* fix(sessions): unify stable fork admission
* fix(native): fork active sessions from stable history
* fix(android): fork active sessions from stable history
* style(android): simplify active fork result handling
* fix(native): preserve legacy fork transport API
* test(native): complete legacy fork transport stub
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat(apps): adopt the system-notice family in Apple chat (OpenClawChatUI)
Decode internal_system provenance and __openclaw history markers, classify
once into message/notice/divider rows (web-parity kinds), render minimal
hairline notice/divider SwiftUI rows, preserve metadata through history
reconciliation, live transport, and the transcript cache, and align the
transcript exporter with visible classification instead of leaking raw
[System] prompts.
* fix(apps): satisfy OpenClawKit periphery gate
Remove the dead visibleMessages projection (rows path replaced its
consumers) and annotate the provenance test-fixture initializer with the
repo-standard periphery:ignore rationale.
* fix(apps): refresh native i18n inventory after periphery cleanup
* fix(chat): close disclosures in coalesced HTML
Keep model-authored details closers visible to the shared disclosure contract when CommonMark absorbs them into type-6 HTML blocks across the Control UI and native apps.
* refactor(apps): isolate disclosure unfolding
Keep the native disclosure segmenter below its lint complexity and type-size limits, and refresh the source-owned native i18n inventory after the move.
* fix(apps): align disclosure helper visibility
Keep the extracted same-file helper compatible with Swift access control while leaving its implementation types hidden outside the source file.
* fix(apps): align source replacement visibility
Keep the source replacement helper at the same file-private boundary as the extracted disclosure unfolding types.
* feat(chat): show live run telemetry across clients
* fix(chat): satisfy native validation gates
* fix(chat): settle advertised terminal runs
* fix(android): clear stale run usage on gaps
* chore(i18n): align native source inventory
* fix(chat): reconcile telemetry with current projections
* refactor(chat): keep run state in owner extensions
* chore(i18n): refresh native source inventory
* test(ui): expect persistent working telemetry through streaming
Add agent ownership to observer digests, scope global observer delivery and reconciliation, and centralize application session selection across navigation and reconnects.
Co-authored-by: xbrxr03 <abrarhabib03@gmail.com>
* fix(ui): keep stable chat rows in insertion order and only sort live tool/stream items by timestamp
* fix(ui): keep live rows within current turn
* fix(ui): keep current work above queued turns
* fix(ui): keep streamed replies above queued turns
* fix(ui): preserve reconnecting run order
* fix(ui): preserve causal terminal ordering
* fix(ui): bound replay rows to owning turns
* fix(ui): keep question summaries in owning turns
* fix(ui): scope question run ownership to session
* fix(ui): restore reconnecting chat run identity
* fix(ui): remove unused chatItemTimestamp import in chat-thread-build.ts
* fix(ui): correlate question summaries with agent runs
Co-authored-by: Peter Lee <li.xialong@xydigit.com>
* chore(i18n): refresh native source baseline
Co-authored-by: Peter Lee <li.xialong@xydigit.com>
* fix(ui): remove unused chatItemTimestamp export and split tool-stream test file
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* refactor(prompt): plain inbound context labels with a provenance marker
Replaces trust-worded inbound context labels ("(untrusted metadata)",
"(untrusted, for context)") with plain labels plus a fixed provenance
marker suffix appended to every OpenClaw-injected context header.
Detection keys on the marker, not label text, so strippers stay correct
across UI, TUI, replay, /trace segmentation, memory recall, and the Swift
chat preprocessor. Drops sanitizeInboundSystemTags in favor of the marker
boundary plus trusted system-prompt narration.
Renames the untrusted-named plugin SDK context identifiers to
channel-provenance names, keeping deprecated aliases registered for
removal after 2026-09-08.
Adds `openclaw doctor --fix` migrations that rewrite legacy inbound
labels in stored SQLite transcripts and purge legacy envelope-
contaminated LanceDB recall rows.
* fix(ci): resolve gate failures for plain inbound context labels
- doctor sqlite readers: open read-only connections via openNodeSqliteDatabase
so the Kysely connection-boundary guardrail holds; unexport the now-internal
transcript snapshot type (Knip unused-export gate).
- compat registry: split the record table into registry-records.ts and
plugin-sdk-subpath-records.ts. The new compat record pushed registry.ts past
the 700-line oxlint cap; suppressions are disallowed, so follow the existing
sibling record-module pattern. Public exports and PluginCompatCode literals
unchanged.
- acp-runtime test: assert current finalization behavior (newline normalization
only). The bracket de-fang and System: rewrite it expected were removed with
sanitizeInboundSystemTags; forged system lines are neutralized at the
system-event queue, the single chokepoint feeding the System:-per-line render.
- regenerate docs_map and the plugin SDK API baseline manifest.
* fix(prompt): harden inbound context label migration and drop in-band sanitizer
Review follow-ups on the plain-label + provenance-marker change:
- Remove src/security/system-tags.ts. Rewriting inbound text to neutralize
look-alike `System:`/`[System]` markers corrupted legitimate user text and is
not a real injection boundary; role separation plus external-content wrapping
is. Explicit product decision, recorded at the system-event queue.
- Narrow the LanceDB legacy-row purge so it cannot delete benign memories. It
now requires a complete known legacy sentinel line, a legacy label followed by
a fenced JSON body, or the complete legacy external-content header. The prior
predicates matched ordinary prose such as `Notes (untrusted metadata):`, and
deletion is irreversible.
- Make explicit-empty canonical ChannelStructuredContext win over the deprecated
alias via a present/absent result instead of collapsing `[]` to undefined.
- Keep `\r?` in the active-memory doctor rule. It is the only rule spanning the
header's line break, migrated assistant rows skip newline normalization, and
without it the marked-header replace wins and the body strips to empty. Added
a CRLF regression test.
- Fix stale comments that described removed behavior, and cover the Swift
prose-block strip path.
Claude-Session: https://claude.ai/code/session_01WNzsPddQmxy9Y7jKD4wAxH
* feat(apple): add rare working claw stances
Add zen, drummer, and peekaboo animations to the shared iOS and macOS working indicator, with deterministic stance and pose coverage.
* chore(i18n): refresh native source anchors
Branch menu (list/switch) for macOS+iOS shared chat via sessions.branches.*;
rewind/fork/switch gated on run activity and pending outbox work through a
durable session-mutation lease; outbox rows carry branch-epoch ownership with
local-only flush checks, atomic confirm/park transitions, attempt-versioned
delivery callbacks, fresh retry identity for possibly-accepted rows, and
epoch-guarded branch evidence; 21-locale native translations for new strings.
* feat(chat): add native working progress state
* feat(chat): port working claw indicator to Apple
* fix(apple): isolate generated locale catalog
* style(apple): use doc comments on ChatWorkingPhrase API declaration