Skip to content

fix: respect Python indentation significance in Apply diff pipeline#12597

Open
rodboev wants to merge 1 commit into
continuedev:mainfrom
rodboev:pr/python-apply-indentation
Open

fix: respect Python indentation significance in Apply diff pipeline#12597
rodboev wants to merge 1 commit into
continuedev:mainfrom
rodboev:pr/python-apply-indentation

Conversation

@rodboev

@rodboev rodboev commented Jun 10, 2026

Copy link
Copy Markdown

Fixes #12455

Summary

"Apply" silently fails on Python files because the diff pipeline treats indentation differences as cosmetic. For Python, indentation is syntax, so changes to nesting depth or tabs-vs-spaces are real structural edits that get discarded.

Root cause

core/diff/util.ts:matchLine() has a permissiveAboutIndentation path that returns the old line's content when two lines differ only in leading whitespace. This is correct for C++ and JS where indentation is cosmetic, but wrong for Python where indentation defines block structure. When an LLM produces Python code with different indentation, the diff sees every line as "same" and produces a no-op edit. The buffer stays unchanged despite the highlight appearing briefly.

Additionally, core/edit/lazy/deterministic.ts:shouldRejectDiff() has a 30% removal threshold that Python indentation diffs routinely exceed (every re-indented line counts as a removal + addition), forcing a fallback to the non-instant path where the indentation permissiveness then discards the changes entirely.

Changes

  • core/diff/util.ts: add filename parameter to matchLine(), skip permissiveAboutIndentation for .py files
  • core/diff/streamDiff.ts: thread filename through to matchLine()
  • core/edit/lazy/streamLazyApply.ts: pass filename through to streamDiff()
  • core/edit/streamDiffLines.ts: pass options.fileUri through to streamDiff() so the LLM-assisted edit path also respects Python indentation
  • core/edit/lazy/deterministic-python.vitest.ts: new test verifying streamDiff preserves Python indentation changes

Prior work

PR #11289 (merged 2026-03-24) fixed indentation corruption in the search-and-replace fallback path by adding adjustReplacementIndentation(). That fix covers the searchAndReplace code path where trimmedMatch / whitespaceIgnoredMatch strategies apply. This PR addresses a different code path: deterministicApplyLazyEditshouldRejectDiff → non-instant fallback, where matchLine()'s permissiveAboutIndentation discards Python indentation changes before the search-and-replace path is ever reached.

What this doesn't change

The 30% removal threshold is untouched. Indentation permissiveness for non-Python files is unchanged. The VerticalDiffHandler UI layer and the search-and-replace path (including the #11289 fix) are not modified.

Checklist

  • I've read the contributing guide
  • The relevant docs, if any, have been updated or created
  • The relevant tests, if any, have been updated or created

Screen recording or screenshot

N/A — the fix is in the diff pipeline, not the UI.

Tests

  • cd core && npx vitest run edit/lazy/deterministic-python.vitest.ts — new test verifying streamDiff preserves Python indentation changes
  • cd core && npx vitest run diff/streamDiff.vitest.ts — existing fastapi-tabs-vs-spaces test still passes, confirming no regression

Summary by cubic

Fixes silent no-ops when applying edits to Python files by treating indentation changes as real diffs. Threads the filename through the diff pipeline and disables indentation permissiveness for .py, leaving other languages unchanged.

  • Bug Fixes
    • core/diff/util.ts: add filename to matchLine() and skip indentation permissiveness for .py.
    • core/diff/streamDiff.ts, core/edit/lazy/streamLazyApply.ts, core/edit/streamDiffLines.ts: pass filename/fileUri through to ensure Python indentation is respected in all paths.
    • Add core/edit/lazy/deterministic-python.vitest.ts to verify Python indentation diffs; existing JS indentation test still passes.

Written for commit cc579d9. Summary will update on new commits.

Review in cubic

@rodboev rodboev requested a review from a team as a code owner June 10, 2026 23:47
@rodboev rodboev requested review from sestinj and removed request for a team June 10, 2026 23:47
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jun 10, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

No issues found across 5 files

Re-trigger cubic

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

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

"Apply" on python code not working

1 participant