* feat(agents): authoritative write diffs end to end
The write tool now reports what actually happened: no-op (changed:false),
created files (created:true with a bounded numbered diff), and overwrites
(created:false with a real old-to-new diff when the old content is
readable text within byte, line, and edit-distance budgets — unknown
removals are never fabricated). The gateway history projection forwards
the changed/created flags, the web and iOS write rows prefer the
authoritative diff and suppress the +N -0 stat when creation is not
proven, and the iOS transcript cache persists one bounded apply_patch
envelope so patch diffs survive cold opens.
* chore(i18n): sync native inventory
* feat(chat-ui): tool-diff follow-ups from PR review
Persist bounded applied-diff details in the transcript cache so cold
opens keep inline diffs; parse apply_patch envelopes into per-file diff
sections with stats; thread tool-result isError so failed calls suppress
proposal diffs and read as failures; replace per-line truncation with
horizontal scrolling for long diff lines.
* chore(i18n): sync native inventory for tool-diff follow-ups
* fix(chat-ui): render move-only patches and drop zero diffstats
* feat(chat-ui): inline diffs for edit and write tool rows
Port the web Control UI's kind-aware diff rendering to the shared SwiftUI
tool rows: persisted details.diff parses into numbered add/del/ctx lines,
edit/write/text-editor args fall back to a local capped line diff, the
collapsed row shows a +N/-M diffstat, and the expanded surface renders the
diff with the result summary or error diagnostic beneath it.
* fix(chat-ui): preserve tool-result details through message reconciliation
Canonical-adoption rebuilds enumerated message fields and silently dropped
details, so inline diffs vanished after cache-warm history reconciliation
(every app relaunch). Carry details through adoptingCanonicalMessage and
messageWithTimestampIfNeeded and lock it in with regression tests.
* chore(i18n): sync native inventory for tool diff rows
* fix(chat-ui): render diffstat and line numbers as verbatim text
* fix(chat-ui): use theme tokens for diff colors
* refactor(chat-ui): drop test-only parseDetailsDiff wrapper
* fix(chat-ui): address diff-row review findings
Interpret details.diff only for edit/write/patch tool names so plugin
detail schemas stay opaque; number write previews from line 1 with an
80-line cap and a subtractive char budget while keeping the exact stat;
bound per-line rendering to 2000 unicode scalars; announce add/del rows
and collapsed skip markers to assistive tech.
* chore(i18n): sync native artifacts for diff-row labels
* fix(chat-ui): announce diff line numbers to assistive tech