* 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
Both flakes (CI run 29573675642, macos-swift) were the same mechanism:
fixture timestamps anchored to wall clock at test start, raced against
the optimistic user-echo timestamp captured later at send time. The
pending-run drain (clearPendingRunIfAssistantMessagePresent ->
assistantHapticEvent(after:)) only matches assistant rows timestamped
at or after the user echo, and the fake transports' default
waitForRunCompletion returns .unavailable, so this comparison is the
only drain path in both tests.
ChatHapticsTests "durable assistant failure fires run failed": the
durable failure row was stamped test start + 1000ms. Under CI load a
>1s stall between fixture creation and send() left the row permanently
older than the user echo, so .runFailed never fired for either
parameterized case. Fix: HapticsTestTransport now takes a history
closure and the test stamps the failure row at requestHistory time,
which is always post-send by event order.
ChatStreamReplayTests "reconnect mid-run converges via history
refetch": the completed transcript rows were stamped test start +
100/900ms; the scripted payload has no inFlightRun/sessionInfo, so the
foreground refetch cannot drain and only the pending-run owner's
timestamp comparison can. Bootstrap plus send taking >900ms made the
assistant row older than the echo and the run never drained. Fix:
anchor the reconnect transcript to a timestamp captured after the send
completed.
Proof: injecting a 1.5s/1.2s stall before send reproduced both CI
failures exactly (timeout after ~16.5s/16.2s, both haptics cases
failing); with the fixes the tests pass even with the stalls injected.
Full ChatHapticsTests + ChatStreamReplayTests suites green; both fixed
tests stressed 10x with zero failures.
The shared chat session sheet (iOS chat + macOS webchat) gains server-backed
search (sessions.list search param, 250ms debounce, cancellation-safe local
fallback when offline), an Active/Archived scope, swipe/context actions for
pin/rename/archive with optimistic updates and rollback, pin indicators, and
restore-on-open for archived rows. Archiving the open session switches back
to the main session so the composer never points at a send-rejecting session.
OpenClawChatTransport consolidates the two list requirements into canonical
listSessions(limit:search:archived:) with forwarding sugars (unreleased
internal API; all in-repo conformers updated: iOS gateway transport, demo and
fixture transports, previews, macOS webchat, test fakes). macOS webchat also
implements patchSession, giving the sheet's controls a live transport there.
OpenClawChatSessionEntry becomes var-based and gains pinnedAt/archivedAt;
the two full-init rebuild blocks in ChatViewModel collapse to copy-mutation
(the pattern that silently dropped newly added fields), preserving main's
model-identity/thinking-metadata semantics. A shared session list organizer
mirrors gateway ordering (pinnedAt desc, updatedAt desc, key) for cached and
offline lists, and pinned sessions survive the 24h recency cutoff in the
session picker.
Refs #100712