File edit/diff tracking: per-turn rollup + tested shared diff util#83
File edit/diff tracking: per-turn rollup + tested shared diff util#83armstrongsamr wants to merge 1 commit into
Conversation
…llup Implements issue #80: per-turn edit/diff rollup + tested shared diff util. Changes: - shared/edit-diff.ts: new pure module with computeDiffLines (LCS/block fallback), computeEditStat, buildEditSummary, isEditToolName, baseFileName. Ports Myers/LCS algorithm from ToolGroup.tsx; caps DP-table allocation at BLOCK_DIFF_THRESHOLD (400 combined lines); block-diff path sets truncated:true with code comments explaining over-report behaviour. - electron/__tests__/edit-diff.test.ts: ~100% unit coverage of shared module; tests for isEditToolName, baseFileName, computeDiffLines (LCS + block fallback), computeEditStat (all edge cases), buildEditSummary (dedup, gross sums, hasTruncated, non-quadratic stress test with 50 edits), and desktopConfigPayload round-trip asserting ui.editDiffSummary.enabled. - electron/config/schema.ts: ui.editDiffSummary.enabled (default true). - electron/ipc/config.ts: default value; desktopConfigPayload already passes ui: config.ui so the new field auto-persists. - src/components/thread/ToolGroup.tsx: EditInlineView now consumes computeEditStat (no visual regression to +N/−N badges); ToolGroup computes buildEditSummary over successful edit parts and renders EditDiffSummary footer; adds useConfig for the enabled flag. - src/components/thread/EditDiffSummary.tsx: FC rendering "N file(s) changed · +X −Y" with truncation hint; diff content as React text children only (no dangerouslySetInnerHTML). - src/components/thread/__tests__/EditDiffSummary.component.test.tsx: render, config-off, zero-files, singular/plural, truncation hint, XSS-literal-text (img onerror + </script> payload stays literal text). Acceptance criteria met: AC1 (shared util + no visual regression), AC2 (turn rollup), AC3 (config + round-trip test), AC4 (XSS literal-text), AC5 (non-quadratic stress test), AC6 (truncated flag + UI hint + comments), AC7 (baseFileName both separators), AC8 (edge cases), AC9 (test files). Co-Authored-By: Claude <noreply@anthropic.com>
14408c4 to
3506813
Compare
Coverage reportProject-wide coverage (reporting only — no gate):
No baseline available — first run, missing artifact, or fetch failed. Changed-file coverage (3 of 5 files instrumented; 2 not in unit slice) Per-file table
Coverage is reporting-only. No thresholds, no merge gate. |
Review: please split this PRThe in-scope #80 feature is clean and would be approvable on its own — What's blocking is everything else that rode along (all out of #80 scope):
Recommendation: land #80 as just the diff util + |
Closes #80
Implemented autonomously by the Sandcastle harness from issue #80, then rebased onto current
main(the agent's sandbox was based on a stale local checkout; cleaned to the 7 feature files only).What this does
ToolGroup.tsxinto a pure, testedshared/edit-diff.ts(computeDiffLines/computeEditStat/buildEditSummary/isEditToolName).EditDiffSummary.tsx) under each assistant turn's tool group: "N files changed · +X −Y".ui.editDiffSummary.enabled(default true), wired into both the schema and thedesktopConfigPayload()allowlist.Host-side validation (macOS)
pnpm type-check(tsc --noEmit): cleanelectron/__tests__/edit-diff.test.ts: 34 passedsrc/components/thread/__tests__/EditDiffSummary.component.test.tsx: 12 passedSecurity
Design-level Cerberus pass (APPROVE) folded its hardening into the issue ACs; covered here: diff rendered as React text children only (no
dangerouslySetInnerHTML— XSS-literal-text test included), non-quadratic rollup, truncation flag for >400-line block fallback,/+\separator-safe basename.