Skip to content

Apply hardening: fuzzy edit matching and per-edit outcomes #399

Description

@jamesrochabrun

Parent: #398

Goal

Make pending edit previews resilient when agent-provided old_string text has whitespace drift, escaped characters, or minor stale context. Preserve exact-match behavior first, then use a confidence-gated fuzzy fallback.

Implementation Notes

Target area: app/modules/AgentHubCore/Sources/AgentHub/Services/PendingChangesPreviewService.swift.

Current behavior uses exact range(of:) / replacingOccurrences, so single edits can fail and MultiEdit can silently skip changes.

Add pure, testable apply utilities, preferably isolated from UI and libgit2:

  • EditApplyOutcome / EditApplyResult for per-edit status
  • exact-match-first replacement
  • escape fallback for \n, \t, \r, \", \\
  • fuzzy match over line blocks using n-gram coarse search plus local similarity scoring
  • indentation-aware replacement so fuzzy matches preserve local indent style
  • sequential MultiEdit application that records failures without aborting the whole batch

Suggested statuses: exact, fuzzy(confidence), failed(reason), rejected(reason). Rejection can be filled by the separate artifact guard issue.

Acceptance Criteria

  • Exact-match edits still produce identical preview output to today.
  • An edit with only leading whitespace/indent drift previews successfully as a fuzzy match.
  • A MultiEdit with one bad edit still previews the successful edits and reports the failed edit.
  • Fuzzy matches expose confidence and matched line range for UI consumption.
  • Low-confidence fuzzy matches fail with an explicit reason instead of modifying the preview.

Tests

Add/extend PendingChangesPreviewServiceTests with deterministic fixtures for exact, escaped, fuzzy, and partial MultiEdit cases.

Run:

cd app/modules/AgentHubCore && xcodebuild test -scheme AgentHubCore-Tests -destination 'platform=macOS' -test-timeouts-enabled YES -skipPackagePluginValidation -only-testing:AgentHubTests/PendingChangesPreviewServiceTests

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions