feat(client): render proposal diffs as readable field-level changes (#363) #367
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!367
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "363-readable-proposal-diffs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The chat confirmation card showed a proposed change's
diffas raw pretty-printed JSON. Replace it with a readable, human field-level diff, extracted into a shared component.What's in it
lib/agent/parseProposalDiff.ts— pure, node-tested interpreter that reads theProposedChange.diffshapes by structure (defensive against theunknownwire type):{ fields }→ updateold → newrows;{ after }→ create field rows;{ before }→ delete rows; anything else (merge/unknown/string) → the JSON fallback (preserving old behavior).lib/agent/ProposalDiff.tsx— shared presentational component (theme.tokens, destructive tinting, old values muted + strikethrough, new emphasized).chat.tsx—ProposalCardnow uses<ProposalDiff>; removed the localrenderDiff/DESTRUCTIVE_ACTIONS/ diff styles. Change confined to the card — the conversation switcher, message bubbles, composer, and streaming are untouched.chat.confirm.diff.{removing,noChanges}.Note
The agent found the activity undo card (#356/#357) isn't merged yet, so it doesn't exist on this branch's base — the shared component is wired into chat only. Once #357 lands, dropping
<ProposalDiff>into the activity card satisfies the "both places" intent (tiny follow-up).Verification (local, re-run in the worktree)
typecheck✓ ·lint✓ ·test✓ 162 (+8parseProposalDiffcases) · semgrep ✓ 0 findings ·en.jsonvalid⚠️ Needs maintainer verification
Visual rendering (create/update/delete + fallback, light + dark, strikethrough/arrow alignment, danger tinting) — client tests are
node-env.Closes #363
🤖 Generated with Claude Code
The chat confirmation card showed a proposed change's diff as raw pretty-printed JSON. Replace it with a readable, human diff and extract the rendering into a shared component the activity undo card can reuse. - lib/agent/parseProposalDiff.ts: pure, node-tested interpreter that reads the ProposedChange.diff shapes by structure (defensive against the unknown wire type) — {fields} → update old→new rows, {after} → create field rows, {before} → delete rows, anything else → JSON fallback. - lib/agent/ProposalDiff.tsx: shared presentational component (theme tokens, destructive tinting, strikethrough on old values). - chat.tsx ProposalCard uses <ProposalDiff>; removed the local renderDiff/DESTRUCTIVE_ACTIONS/diff styles (change confined to the card — switcher/bubbles/composer/streaming untouched). - i18n: chat.confirm.diff.{removing,noChanges}. The activity undo card (once #356 lands) drops in <ProposalDiff> to satisfy the "both places" intent. Closes #363 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>📊 Test coverage
Patch coverage: no testable lines changed.
Overall (
app/,lib/,db/, excluding UI per ADR-0019):Soft thresholds per ADR-0019. Coverage is informational and does not block merge.