Stop yamllint and markdownlint linting other sessions' worktrees - #316
Merged
Conversation
…ktrees `make validate` ended in `validation failed` on the deploy host for a completely clean change. Every finding was inside .claude/worktrees/<branch>/ — another Claude Code session's git worktree, which is an entire second checkout of this repository. That path is gitignored (.gitignore:72) and neither linter reads .gitignore, so CI never reproduces it. Green where nothing runs and red where everything does is the wrong way round. It is also the failure mode this repository already names twice: the deleted .gitleaksignore "was an acknowledgement, not a fix, and it existed because a CI job that is permanently red for a known reason gets ignored", and lint.sh's editorconfig-checker comment records the same shape when the checker walked the tree and found rendered secrets. An operator who learns to dismiss a red validate has stopped reading the one command that gates a deploy. The existing ignore entries do not cover it, and it is worth being precise about why: patterns containing a slash are anchored to the repository root the way .gitignore anchors them, so `secrets/*.sops.yaml` does not match `.claude/worktrees/<branch>/secrets/observability.sops.yaml`. Measured — 22 of the 23 findings were that one file's copy. markdownlint-cli2 had the same exposure and was not obviously going to: `**/*.md` matches dot directories, so it linted 114 files against 57 tracked. It passed only because a worktree holds a copy of this repository's own markdown. A branch under review carrying one lint error would have failed `make validate` on main, pointing at a file main does not have. The other three are clear, checked rather than assumed: shellcheck is handed one literal glob, editorconfig-checker is handed a `git ls-files` list built on the host (the fix already made for this exact class), and actionlint reads only <repo root>/.github/workflows — `-verbose` confirms 2 files linted with a worktree present, not 4. lint.sh's header now records all five, because "which files does this linter actually look at" is the question behind both incidents and it had no written answer. Verified by planting a file that fails both linters: it fails outside .claude/, passes under .claude/worktrees/ with these entries, and the whole tree goes red again with the two configs stashed. `make validate` now ends in `all checks passed` with zero skips on a host with two worktrees checked out. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
make validateended invalidation failedon the deploy host for a completely clean change. Every finding was inside.claude/worktrees/<branch>/— another Claude Code session's git worktree, which is an entire second checkout of this repository. That path is gitignored (.gitignore:72) and neither linter reads.gitignore, so CI never reproduces it.Green where nothing runs and red where everything does is the wrong way round. It is the failure mode this repo already names twice — the deleted
.gitleaksignore"was an acknowledgement, not a fix, and it existed because a CI job that is permanently red for a known reason gets ignored", andlint.sh'seditorconfig-checkercomment records the same shape when the checker walked the tree and found rendered secrets.Why the existing ignore entries did not already cover it
Worth being precise about, because it looks like they should. Patterns containing a slash are anchored to the repository root the way
.gitignoreanchors them, sosecrets/*.sops.yamldoes not match.claude/worktrees/<branch>/secrets/observability.sops.yaml. Measured: 22 of the 23 findings were that one file's copy.markdownlint-cli2 was exposed too
This was not obvious and I had it wrong at first.
**/*.mddoes match dot directories, so it linted 114 files against 57 tracked. It passed only because a worktree holds a copy of this repository's own markdown — a branch under review carrying one lint error would have failedmake validateonmain, pointing at a filemaindoes not have.The other three are clear — checked, not assumed
yamllint.markdownlint-cli2**/*.md, matches dot dirsshellcheckscripts/*.sh, one literal globactionlint<repo root>/.github/workflows—-verboseshows 2 files linted with a worktree present, not 4editorconfig-checkergit ls-fileslist built on the hostlint.sh's header now records all five, because "which files does this linter actually look at" is the question behind both incidents and it had no written answer. Theeditorconfig-checkerrow is called out as the shape to copy: a list built from git cannot drift, whereas these two carry an exclusion list that has to be extended by hand.Verification
Planted a file that genuinely fails both linters under this repo's own configs, then:
.claude/— fails both (so it is a valid control).claude/worktrees/with these entries — passes both./scripts/lint.shpasses all six checks with two worktrees checked out, and./scripts/validate.shends inall checks passedwith zero skips.These entries are no-ops in CI, which has no
.claude/worktrees/.🤖 Generated with Claude Code