fix: report what the repair took, and fold case on root instruction files - #34
Merged
Conversation
…iles Automatic repair restores staged deletions it cannot rule out as the source of a rename Git did not detect. That sweep is deliberate and stays. What was missing is that it never said so: the summary named only the blocked paths, and when the index ended up empty it claimed nothing else had been staged. A developer who had run `git rm --cached legacy.txt` got a clean `git status` afterwards, the file still tracked, and a commit message describing an untracking the commit did not carry. The repair now returns what it took beyond the blocked paths, names those paths with the reason, and gives the command to stage the removal again. Two tests asserted the old claim on runs that did have collateral; they now assert what the run actually did. Root instruction files also matched case-sensitively while every sibling path rule folds case. On APFS and NTFS `claude.md` is the same file as `CLAUDE.md`, so the guarded spelling was one keystroke from being skipped. The root patterns now carry case classes. Paths deeper in the tree stay case-sensitive, where these names are ordinary documentation.
rmyndharis
force-pushed
the
fix/repair-and-rule-coverage
branch
from
August 12, 2026 09:40
c5aff1c to
b447d6f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The repair took staged work and said nothing
When automatic repair unstages a blocked path,
stagedRenameSourcesalsorestores any staged deletion it cannot rule out as the source of a rename Git
did not detect. That sweep is deliberate — the comment at
src/gitx.mjs:296sets out the trade-off, and
tests/cli.test.mjspins the zero-similarity case —and it stays.
What was missing is that the tool never said so. The summary named only the
blocked paths, and when the index ended up empty it added "nothing else was
staged". That clause was printed on runs where something else had in fact been
staged and had just been taken.
The sharpest shape is
git rm --cached legacy.txtalongside a blocked artifact.Restoring the index entry makes it match HEAD, so
git statusafterwards isempty, the file is still tracked, and the developer commits a message describing
an untracking the commit does not carry.
repairStagedBlocksnow returns{ emptied, collateral }.emptiedkeeps itsmeaning and its derivation.
collateralis everything the repair took beyondthe blocked paths.
cmdPrecommitnames those paths, says why they were taken,and gives the command to stage the removal again. The empty-index clause no
longer claims nothing else was staged when something was.
Narrowing the sweep itself was considered and dropped. Pairing on blob oid adds
nothing that
--find-renames=1%does not already pair, and removing the breadthreintroduces the committed half-rename the sweep exists to prevent.
Two existing tests asserted the old clause on runs that did have collateral.
They now assert what the run actually did, including the path it restored.
Root instruction files matched case-sensitively
generic.agent-instructionswas the only path rule inrules/paths.jsonwithout case folding. On APFS and NTFS
claude.mdis the same file asCLAUDE.md, and Git records the case the caller typed, so the guarded spellingwas one keystroke from being skipped — a lost review on
clean, a defeated hardblock on
strictandcompliance.The root patterns now carry case classes (
[Cc][Ll][Aa][Uu][Dd][Ee].[Mm][Dd]and the rest).
globToRegExpalready supports character classes, and.is aliteral token, so
agentsxmddoes not match.Splitting the rule in two — one case-sensitive, one folded — was the obvious
shape and does not work. Rule ids must be unique, so a split forces a second id,
and reviews bind to exactly one id:
aimhooman review AGENTS.mdwould stopclearing the block and root instruction files would become unshippable under
strict. Keeping one id keeps the escape hatch.Patterns deeper in the tree stay case-sensitive.
docs/claude.mdandwebsite/content/blog/agents.mdare ordinary documentation and keep committingfreely; the near-miss control test covers them.
Tests
The case test now covers four root spellings plus
.github/Copilot-Instructions.md,and adds
agentsxmdto the near-misses. A new precommit test stages agit rm --cachedalongside a blocked artifact and asserts the report names therestored path.
Full suite green,
npm run checkgreen.