Skip to content

Expose apply_patch preflight metadata#1634

Closed
kunpeng-ai-lab wants to merge 2 commits into
Hmbown:mainfrom
kunpeng-ai-lab:feature/apply-patch-preflight
Closed

Expose apply_patch preflight metadata#1634
kunpeng-ai-lab wants to merge 2 commits into
Hmbown:mainfrom
kunpeng-ai-lab:feature/apply-patch-preflight

Conversation

@kunpeng-ai-lab
Copy link
Copy Markdown

Summary

Adds a reusable no-mutation preflight surface for apply_patch inputs.

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

  • Add ApplyPatchPreflight and preflight_apply_patch(&serde_json::Value).
  • Report touched files, file count, hunk count, creates, deletes, path override, and header mismatch.
  • Attach apply_patch.preflight metadata to successful apply_patch tool results.
  • Reuse the same preflight parser for LSP post-edit path discovery instead of maintaining a separate lightweight diff-header parser.
  • Add tests for path override, changes-list input, multi-file create/delete patches, metadata, and LSP path extraction.

Validation

  • cargo fmt --check
  • cargo test -p deepseek-tui --bin deepseek-tui apply_patch
  • cargo test -p deepseek-tui --bin deepseek-tui edited_paths_for
  • cargo test -p deepseek-tui --bin deepseek-tui post_edit_hook
  • cargo check --workspace

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread crates/tui/src/tools/apply_patch.rs Outdated
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)?;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Comment thread crates/tui/src/tools/apply_patch.rs Outdated
}

Ok(ApplyPatchPreflight {
files_total: touched_files.len(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Comment thread crates/tui/src/tools/apply_patch.rs Outdated
}

Ok(ApplyPatchPreflight {
files_total: touched_files.len(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

@kunpeng-ai-lab kunpeng-ai-lab force-pushed the feature/apply-patch-preflight branch from 63fddaf to 28d76d6 Compare May 14, 2026 12:45
@kunpeng-ai-lab
Copy link
Copy Markdown
Author

Updated #1634 to address the review comments:

  • Avoided double-parsing patch inputs during apply_patch execution by introducing an internal preflight plan that carries the parsed Hunk / FilePatch data forward into execution.
  • Aligned files_total semantics between preflight metadata and final PatchResult:
    • changes inputs count entries, matching build_pending_writes_from_changes.
    • unified diff inputs count diff sections, matching build_pending_writes_from_patches.
    • touched_files remains deduplicated for policy/diagnostic consumers.
  • Added regression tests for duplicate changes paths and multiple diff sections targeting the same file.
  • Rebased onto latest upstream main.

Validation:

  • cargo fmt --check
  • cargo test -p deepseek-tui --bin deepseek-tui apply_patch (24 passed)
  • cargo test -p deepseek-tui --bin deepseek-tui edited_paths_for_apply_patch (2 passed)
  • cargo check --workspace

@kunpeng-ai-lab
Copy link
Copy Markdown
Author

Follow-up after an independent code quality review:

  • Switched preflight metadata serialization to reuse ApplyPatchPreflight serde output, so optional fields are omitted instead of emitted as null.
  • Added execution-level metadata assertions for changes and multi-file unified diff inputs.
  • Added coverage for header_path_mismatch in result metadata.
  • Added an edited_paths_for_tool("apply_patch", ...) regression test for invalid diffs returning no edited paths.

Validation rerun:

  • cargo fmt --check
  • cargo test -p deepseek-tui --bin deepseek-tui apply_patch (25 passed)
  • cargo test -p deepseek-tui --bin deepseek-tui edited_paths_for_apply_patch (3 passed)
  • cargo check --workspace

@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented May 23, 2026

This PR was opened before the v0.8.41 rebrand and is now stale. Feel free to rebase onto current main and reopen. 鲸鱼兄弟们等你 🐋

@kunpeng-ai-lab
Copy link
Copy Markdown
Author

Rebased onto current main and reopened as #1971: #1971

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants