Skip to content

fix(ci): root-cleanliness guards assumed .git is always a directory - #291

Merged
beyondnetPeru merged 1 commit into
developfrom
claude/recursing-carson-721318
Jul 30, 2026
Merged

fix(ci): root-cleanliness guards assumed .git is always a directory#291
beyondnetPeru merged 1 commit into
developfrom
claude/recursing-carson-721318

Conversation

@beyondnetPeru

Copy link
Copy Markdown
Contributor

Summary

  • .git at a git-worktree root is a plain redirect file, not a directory — two guards assumed otherwise and broke in a worktree checkout: 02-optimize-repo.mjs (the pre-push hook's cleanup step, which crashed with ENOTDIR, and once patched past that, quarantined .git itself, severing the worktree from git) and 03-validate-root-cleanliness.mjs (independently, same root cause, own duplicated allowlist).
  • Both now exclude .git unconditionally by name before the directory/file allowlist check. 02-optimize-repo.mjs also resolves the real writable git-dir via git rev-parse --git-dir (path.resolve, not path.join, since that command prints an absolute path in a worktree) instead of assuming .git itself is where the quarantine subtree lives.
  • Also added two legitimately-tracked root files (evolith.yaml, commitlint.config.mjs) that were missing from 02-optimize-repo.mjs's allowlist, clearing an unrelated warning noticed along the way.
  • No blast radius in CI itself: actions/checkout always produces a normal (non-worktree) checkout, so neither guard has ever hit this there. This is a local-development-in-a-worktree fix.

Test plan

  • node .harness/scripts/ci/02-optimize-repo.mjs — 0 quarantined, .git untouched, git log/git status still functional afterward
  • node .harness/scripts/ci/03-validate-root-cleanliness.mjs — passes (32 root entries inspected)
  • node .harness/scripts/ci/01-validate-docs.mjs — 1491 files, unaffected
  • node .harness/scripts/ci/08-validate-tracking.mjs — 635 gaps, 577 closure records, unaffected

🤖 Generated with Claude Code

…ectory

`git push` crashed inside the pre-push hook's repo-optimization step, in this
worktree specifically: `fs.mkdirSync ENOTDIR '.../recursing-carson-721318/.git/
evolith-quarantine/69e8ec9d'`. `.git` at a worktree's root is a plain text
redirect file (`gitdir: <real-gitdir>`), not a directory, and
02-optimize-repo.mjs assumed otherwise in two places:

1. `path.join(root, ".git", "evolith-quarantine")` assumed `.git` was always a
   writable directory to build a subtree under. Fixed by resolving the real
   git-dir via `git rev-parse --git-dir` -- which is `.git` in a normal
   checkout and the per-worktree directory under `.git/worktrees/<name>` here
   -- with `path.resolve`, not `path.join`: `--git-dir` prints a RELATIVE path
   in a normal checkout but an ABSOLUTE one in a worktree, and `path.join`
   would have mangled the absolute case by concatenating it onto `root`.

2. Fixing (1) surfaced a worse defect, verified live: once the crash stopped,
   the quarantine loop saw `.git` itself as an unrecognised untracked FILE
   (only `allowedDirectories` lists it, not `allowedFiles`) and moved it into
   quarantine -- severing this worktree from git entirely. Recoverable, since
   quarantine moves rather than deletes, but confirmed by reproducing it and
   then restoring `.git` by hand before writing the real fix: exclude `.git`
   unconditionally, by name, before the directory/file allowlist split.

The identical root cause was independently present in
03-validate-root-cleanliness.mjs, a separate script with its own duplicated
allowlist -- confirmed failing in this same worktree ("Unauthorized file
found in root: .git") before the same by-name exclusion fixed it too. Lower
blast radius than the pre-push script (CI always checks out fresh, never a
worktree, so this specific guard never hits it there), but the same class of
bug and already fully understood, so fixed alongside it.

Also added two legitimately-tracked root files the first script's allowlist
was missing (evolith.yaml, commitlint.config.mjs), clearing an unrelated
warning this same run surfaced.

Re-verified: both scripts pass clean in this worktree (0 quarantined, 32 root
entries inspected), 01-validate-docs (1491 files) and 08-validate-tracking
(635 gaps, 577 closure records) unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@beyondnetPeru
beyondnetPeru requested a review from a team as a code owner July 30, 2026 13:41
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions

Copy link
Copy Markdown

📊 Bilingual Coverage Impact

PR Changes

  • Paired EN/ES files modified: 6
  • New EN files needing ES translation: 3

Repository Coverage

Metric Value
Total EN files 524
Total ES files 498
Paired files 0
Coverage 0%

⚠️ Action required: 3 new EN file(s) added without ES counterparts.

To create skeletons:

node .harness/scripts/generate-es-skeleton.mjs <file.md>

Generated by GitHub Actions

@beyondnetPeru
beyondnetPeru merged commit 70eecf7 into develop Jul 30, 2026
32 checks passed
@beyondnetPeru
beyondnetPeru deleted the claude/recursing-carson-721318 branch July 30, 2026 14:04
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.

1 participant