Expose apply_patch preflight metadata#1634
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a preflight mechanism for the apply_patch tool, enabling the identification of affected files and hunks before execution. This logic is integrated into the tool's execution flow to provide metadata and replaces redundant parsing in LSP hooks. Feedback from the review focuses on performance inefficiencies caused by double-parsing the patch text during both preflight and execution. Additionally, the reviewer pointed out inconsistencies in the files_total metric calculation between the preflight summary and the final execution results when dealing with duplicate paths or multiple diff sections.
| let fuzz = optional_u64(&input, "fuzz", MAX_FUZZ as u64).min(MAX_FUZZ as u64); | ||
| let fuzz = usize::try_from(fuzz).unwrap_or(MAX_FUZZ); | ||
| let create_if_missing = optional_bool(&input, "create_if_missing", false); | ||
| let preflight = preflight_apply_patch(&input)?; |
There was a problem hiding this comment.
Calling preflight_apply_patch at the beginning of execute introduces significant redundancy. The preflight function already parses the entire patch text and validates its shape, but the execute method then repeats these exact same operations (e.g., calling inspect_patch_shape, validate_patch_shape, and parse_unified_diff_files again starting at line 261). For large patches, this double-parsing is inefficient. Consider refactoring preflight_apply_patch to return the parsed FilePatch or Hunk objects so they can be reused during execution.
| } | ||
|
|
||
| Ok(ApplyPatchPreflight { | ||
| files_total: touched_files.len(), |
There was a problem hiding this comment.
There is a discrepancy in the definition of files_total between the preflight summary and the tool's execution result. In this preflight path, files_total is calculated as the number of unique files via touched_files.len(). However, the execution logic in build_pending_writes_from_patches (line 838) sets files_total to file_patches.len(), which represents the number of diff sections in the patch. If a patch contains multiple sections for the same file, the metadata and the final result will report different counts. It is recommended to align these definitions.
| } | ||
|
|
||
| Ok(ApplyPatchPreflight { | ||
| files_total: touched_files.len(), |
There was a problem hiding this comment.
The calculation of files_total here is inconsistent with the execution logic for the changes input. In preflight_changes, files_total is the count of unique paths. In contrast, build_pending_writes_from_changes (line 814) increments files_total for every entry in the changes array. If the input contains duplicate paths, the ApplyPatchPreflight metadata will report a different file count than the PatchResult returned by the tool.
63fddaf to
28d76d6
Compare
|
Updated #1634 to address the review comments:
Validation:
|
|
Follow-up after an independent code quality review:
Validation rerun:
|
|
This PR was opened before the v0.8.41 rebrand and is now stale. Feel free to rebase onto current |
Summary
Adds a reusable no-mutation preflight surface for
apply_patchinputs.This is intentionally separate from #1585. It does not include the file policy engine; it only exposes structured patch intent so later harness layers such as policy, audit, diagnostics, and undo planning can reason about target files before mutation.
Changes
ApplyPatchPreflightandpreflight_apply_patch(&serde_json::Value).apply_patch.preflightmetadata to successfulapply_patchtool results.Validation
cargo fmt --checkcargo test -p deepseek-tui --bin deepseek-tui apply_patchcargo test -p deepseek-tui --bin deepseek-tui edited_paths_forcargo test -p deepseek-tui --bin deepseek-tui post_edit_hookcargo check --workspace