Fix replace-all matching with reused full-file indexes - #737
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 42757299c5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
baron
left a comment
There was a problem hiding this comment.
Reviewed exact head 4275729 on the current-main synthetic merge, with a curated Fable 5 High second opinion.
The absolute line-coordinate conversion and search advancement are consistent, and downstream exact matching protects the strict-to-loose fallback. No blocking finding.
The only hosted failure is the unrelated CodeMapRootManifestStore atomic-snapshot concurrency test; please rerun to exact-head green before merge.
baron
left a comment
There was a problem hiding this comment.
Re-reviewed exact head 9f44d5018326e857f87ff2bcbaa9874a29a30e33 on the current-main synthetic merge 19d222f7d20eee3e9c0f1068bb3e02ca1a9ae643 (base cc9ff8f5901c2d511eef2e52d45cb21df780bace).
The implementation change correctly filters positions before minimumMatchIndex before consuming the fuzzy-probe budget in both the first- and second-line paths. Global coordinates, replace-all advancement, and cumulative offsets also look consistent. The focused DiffGenerationUtilityRoutingTests suite passed (3 tests, 0 failures), and hosted CI is green.
One blocker remains: please add a deterministic regression test for the corrected fuzzy-budget failure. The current tests use exact normalized keys and do not enter the fuzzy path; they also pass on the known-bad prior head 42757299. A focused test should place more than the probe budget of distinct keys only before minimumMatchIndex, then verify an eligible fuzzy-only match after the boundary is still found. This directly guards the false-negative fixed by the latest commit.
baron
left a comment
There was a problem hiding this comment.
Re-reviewed exact head e7d7b41960e7bed0d26759c17b89e5c40b72b53d on current-main synthetic merge f70e65bc10593bb34d6f99931db2a0f1b1c4366d. The production fuzzy-budget fix still looks correct, and the new test is aimed at the exact requested regression.
The new test does not compile: DiffGenerationUtilityRoutingTests.swift:45 accesses removedTagsHigh, which is internal to another module and inaccessible from this test target. This makes swift test list fail across all app shards and the Sentry build. Style also fails at line 48 for numeric-literal grouping (1_024).
Please construct the index keys through an API visible to this test target (or place the regression test in the owning module), run the formatter, and get exact-head CI green. I did not find a new blocker in the production change itself.
|
@baron Addressed in |
baron
left a comment
There was a problem hiding this comment.
Re-reviewed exact head 20bd84fa4de5f736a91ca15bbd8fb818c720e100 on the current-main synthetic merge (base 6f31d61ccb83dd9bd3d84421f352e4e04bb819b6).
The prior blocker remains. The revised test now builds the final index through buildLineIndexMapHigh, but lines 51-52 still directly access candidateLine.removedTagsHigh, which is internal to RepoPromptDomainRuntime. The exact-head Sentry build fails with: DiffGenerationUtilityRoutingTests.swift:51:42: error: removedTagsHigh is inaccessible due to internal protection level.
Please avoid reading LineData.removedTagsHigh from this test target entirely (or move the regression to the owning module), then obtain exact-head green CI. The production fuzzy-budget fix itself still looks correct.
Replace inaccessible removedTagsHigh reads with keys derived from buildLineIndexMapHigh, as requested by review. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
@baron Follow-up: the test-only compile blocker is corrected on the current head |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fdb128f711
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let orderedKeys = Array(candidateIndex.keys) | ||
| let positions = candidateKeys.compactMap { key in | ||
| orderedKeys.firstIndex(of: key) | ||
| } | ||
| return !positions.isEmpty && positions.allSatisfy { $0 >= 400 } |
There was a problem hiding this comment.
Make the fuzzy-probe boundary test deterministic
With Swift's randomized per-dictionary iteration order, this checks the candidate's position in a copied candidateIndex, but the matcher later receives a freshly rebuilt lineIndex whose key order can differ. Consequently XCTUnwrap can find no qualifying alias for some hash seeds, and when it does, the candidate may move inside the first 400 entries in the actual index, allowing the pre-fix implementation to pass. Construct and pass the same index whose ordering was inspected, or avoid depending on dictionary enumeration order.
Useful? React with 👍 / 👎.
|
one moment, lookign at this |
The fuzzy boundary test rebuilt the line index via buildLineIndexMapHigh after selecting a candidate, which produced a different key ordering than the index map inspected during selection. Pass the same candidateIndex into matchSelectorFast so the probe sees the ordering the test validated, removing the randomized-order mismatch. Apply numeric grouping and multiline formatting for CI conformance. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
@baron The test-target visibility issue is resolved on the PR head: it derives the fuzzy probe keys via The remaining failed CI run was unrelated to this PR: its synthetic merge picked up a broken transcript signature-cleanup change from |
|
Re-reviewed exact head |
baron
left a comment
There was a problem hiding this comment.
Approved on exact head 51f81de255f065d1e3e0da95325272f7aa240662. The prior deterministic regression is addressed by filtering candidates below minimumMatchIndex before charging the fuzzy-probe budget, and the test builds the inspected index through the production API with the valid candidate beyond the 400-key boundary. The two red hosted checks are outside this three-file diff, so they do not justify retaining a stale code-review rejection; they must still be rerun successfully before merge.
Audit disposition — merge candidate after exact-head validation (2026-08-14)Reusing one processed full-file representation and index while advancing an absolute minimum match position addresses both the skipped-later-match bug and repeated normalization/index construction. The reviewed strict, loose, and fuzzy candidate paths consistently apply the lower bound, and the focused tests cover the important nonzero-start and probe-budget cases. Please require exact-head CI, the stated large-file benchmark, and an ambiguity/overlapping-match regression on the final head. I did not find a code-level blocker. |
Deep-review assessment — 2026-08-14Disposition: merge candidate after final matcher/property coverage. Reusing one processed full-file representation and index, then advancing an absolute I did not find a blocker. Please complete exact-head Swift/macOS CI and include regressions for overlapping matches, replacement blocks that change line counts, selectors at the final boundary, fuzzy-only candidates, ambiguity behavior, and guaranteed forward progress/no infinite loop. With those gates, this is a focused correctness and performance fix. |
Summary
Replace-all now searches one processed full-file representation with an advancing absolute lower bound.
This fixes later matches being skipped when
DiffBatchGeneratorsupplies a full-file index and removes repeated suffix normalization and index construction.Change
Regression coverage
Tests cover a nonzero
searchStartLinewith a non-nil full-file index, the complete batch diff fallback route with separated matches, and a deterministic fuzzy-probe case with more than 400 distinct keys beforeminimumMatchIndex. The latter verifies that an eligible fuzzy-only match after the boundary is still found.For a synthetic 5,000-line/20-match case, source-level operation counting changes normalization from 60,460
processLinecalls to 5,000 and index construction from 21 suffix indexes to one full-file index.Validation
git diff --checkpassed.Fixes #729