Skip to content

fix(copier-update): take the new template version for a conflicted file the project never edited (AI-CLI-sds5) - #420

Merged
sergeiwallace merged 3 commits into
mainfrom
wt/ai-cli-mac-1/ai-cli-sds5-unchanged-conflicts
Oct 22, 2026
Merged

sergeiwallace merged 3 commits into
mainfrom
wt/ai-cli-mac-1/ai-cli-sds5-unchanged-conflicts

Conversation

@sergeiwallace

Copy link
Copy Markdown
Owner

What

A scheduled ai copier-update conflicted on files that no project had edited. This takes the new template version for exactly those files and leaves every real conflict alone.

Why

Copier renders the old copy of a template using the new template's _exclude rules. When a new rule excludes a file behind a question the old template never declared, the old copy lacks that file. Copier then reads the update as a file addition and conflicts with the identical file already in the project. A project recorded before the question was added conflicts on every run until someone merges the file by hand. A control project recorded after the boundary updates cleanly.

How

After a conflicted update, render the previous and current template versions with the project's recorded answers. A conflicted file whose committed bytes equal the previous render was never edited, so it takes the new render. A file that differs by one byte stays a conflict.

  • The backup anchor is taken before any file is written.
  • Each resolved path is printed in the run output.
  • If either render fails, or the anchor cannot be taken, nothing is written.
  • The resolved file is left as an ordinary unstaged change so the existing parity check sees it.

Tests

New tests use real Copier and a real two-commit template that crosses the boundary: unedited file takes the new version, a backup anchor survives, a one-byte edit stays a conflict, a mixed case reports only the real conflict, a template shaped like a test-plugin exclusion, and the main tree is untouched. The recovery tests' Copier double now answers only update (reason in the commit).

Full suite: 5576 passed, 23 skipped before the double fix; the affected files re-run green (112 passed).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Y23LPSiKBWEaNYrtaqUn7W

vsajan and others added 3 commits October 22, 2026 03:45
…le the project never edited (AI-CLI-sds5)

Copier renders the old copy of a template with the new template's _exclude
rules. When a new rule excludes a file behind a question the old template
never declared, the old copy lacks that file, Copier reads the update as a
file addition, and it conflicts with the identical file already in the
project. A scheduled run then reports a conflict for a file nobody edited.

After a conflicted update, render the previous and the current template
versions with the project's recorded answers. A conflicted file whose
committed bytes equal the previous render was never edited, so it takes the
new render. A file that differs by even one byte stays a conflict. The backup
anchor is taken before any file is written, each resolved path is printed, and
the resolved path is left as an ordinary unstaged change so the parity check
sees it. If either render fails, or the anchor cannot be taken, nothing is
written.

Test-edit-reason: the recovery tests' Copier double answered every invocation as
an update; it now answers only "update" and fails a render, which is the
condition those tests assume (conflicts stay).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y23LPSiKBWEaNYrtaqUn7W
Provenance-schema: aih-commit/v2
Provenance-tool: aih-commit/0.1.0
Authoring-session: ai-cli-mac-1
Authoring-machine: machine-a55de1a7d9c6e9a8
Authoring-class: ai
Authoring-family: claude
Authoring-model: Sonnet
Authoring-effort: medium
Authoring-profile: interactive
Authoring-run-id: claude-run:4f57d1268b6334762f885771212fc582
Delegated-to: none
…LF renders match (AI-CLI-sds5)

The previous commit compared a conflicted file's committed bytes with the
previous template render. On Windows Copier writes the render with CRLF line
endings while Git stores the committed file with LF, so an unedited file never
matched and stayed a conflict (three tests failed on the Windows runner).

Compare the way Git stores the content: the committed blob id against the id
Git computes for the rendered copy at the same path, which applies the same
line-ending conversion. A new test renders a CRLF template into a project that
normalises line endings and reproduces the failure on any platform.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y23LPSiKBWEaNYrtaqUn7W
Provenance-schema: aih-commit/v2
Provenance-tool: aih-commit/0.1.0
Authoring-session: ai-cli-mac-1
Authoring-machine: machine-a55de1a7d9c6e9a8
Authoring-class: ai
Authoring-family: claude
Authoring-model: Sonnet
Authoring-effort: medium
Authoring-profile: interactive
Authoring-run-id: claude-run:4f57d1268b6334762f885771212fc582
Delegated-to: none
@sergeiwallace
sergeiwallace merged commit 8a9bfd6 into main Oct 22, 2026
7 checks passed
@sergeiwallace
sergeiwallace deleted the wt/ai-cli-mac-1/ai-cli-sds5-unchanged-conflicts branch October 22, 2026 10:10
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