Skip to content

Keep an Inherited GIT_DIR From Rerooting the Prose Gate's Subdirectory Git Reads - #3831

Merged
ptr727 merged 2 commits into
developfrom
burndown/3821-prose-gate-git-env
Nov 2, 2026
Merged

ptr727 merged 2 commits into
developfrom
burndown/3821-prose-gate-git-env

Conversation

@ptr727

@ptr727 ptr727 commented Nov 2, 2026

Copy link
Copy Markdown
Owner

Summary

A hook in a linked worktree inherits GIT_DIR. Under GIT_DIR with no GIT_WORK_TREE, git takes the directory a command starts in as the work tree's top level. So a run naming a subdirectory, such as prose_lint.py sub, read git -C sub ls-files as though sub/ were the root, and the top level's ignores lapsed.

  • The reads of the scanned tree now run under a new tree_env(). These are tracked_paths, untracked_paths, shallow_checkout, git_bytes, and the dead-path rule's once_tracked. tree_env() drops the location variables as git_env() does for repo_root and provenance. once_tracked reads the same tree through the same git -C, so it is the same class and moves with the rest.
  • tree_env() keeps GIT_INDEX_FILE. Measured on git 2.47, git commit -a hands the hook index.lock, and git commit <paths> hands it next-index-*.lock. That index is what the commit records, and the checkout's own index is not, so dropping it would make the gate read the wrong one. A plain commit in the main worktree hands the hook a relative .git/index with GIT_DIR unset, which was already inherited and is unchanged.

Tests

The tests are built from the issue's constructed repro, with temporary repositories and synthetic content only.

  • test_a_hook_in_a_linked_worktree_names_a_subdirectory: under GIT_DIR, an ignored file in the named subdirectory stays unread.
  • test_each_scanned_tree_read_answers_for_the_directory_it_names: with GIT_DIR naming a different, shallow repository, each of the five reads answers for the directory it names. Reverting any one call site alone fails this case, checked site by site.
  • test_a_commit_naming_paths_keeps_the_index_it_hands_its_hook: a real git commit <paths> in a linked worktree runs a pre-commit hook that lists a subdirectory. The listing holds the file the commit's index still tracks and the checkout's index dropped. It fails both when the whole environment is inherited and when GIT_INDEX_FILE is dropped with GIT_DIR. It is skipped off POSIX, as the textconv-driver case is, since the hook is written for a POSIX shell.

prose_lint.py grows by 14 lines and no ceiling moves.

Local review

Two recorded local-strict-review passes. The first raised one introduced finding, the real-hook case running unguarded on the Windows leg, which was fixed in f47ab60. The second raised none.

Pre-existing findings, not filed

  • .github/actions/prose-gate/prose_lint.py GIT_LOCATION, consolidation: its list differs from spec/git_env.py's GIT_LOCATION_VARS, for example in GIT_SHALLOW_FILE and GIT_GRAFT_FILE. No hook sets the missing ones, and the gate cannot import spec/.

Closes on promotion: #3821

🤖 Generated with Claude Code

ptr727 and others added 2 commits November 2, 2026 12:03
…y Git Reads

A hook in a linked worktree inherits GIT_DIR, under which git takes the
directory a command starts in as the work tree's top level. The scanned-tree
reads (tracked and untracked paths, the shallow check, the diff, and the
dead-path history lookup) now drop the location variables as repo_root does.

They keep GIT_INDEX_FILE, since `git commit -a` and `git commit <paths>`
hand the hook the index that commit records rather than the checkout's own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Does

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings November 2, 2026 20:09
@ptr727

ptr727 commented Nov 2, 2026

Copy link
Copy Markdown
Owner Author

A recorded local strict-review pass covers head f47ab6001af0bb9a3721aec4cd2ecfe6d864fb5b, the content this pull request carries at that commit against develop, and it recorded 0 findings.

@coderabbitai

coderabbitai Bot commented Nov 2, 2026

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Copilot AI 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.

🟢 Approval recommended

No active issues remain, and the reviewed changes stop an inherited GIT_DIR from altering the scanned-tree git reads while keeping GIT_INDEX_FILE, which commit hooks rely on.

No open issues 🎉

What changed in this PR

The prose gate runs git reads against a directory it is scanning. When a hook in a linked worktree runs it, git passes in GIT_DIR. Under that variable, git treats the directory a command starts in as the top of the work tree, so a subdirectory scan could ignore the real top-level ignore rules. This PR gives those reads their own environment that drops the location variables. It keeps GIT_INDEX_FILE, because a commit hands its hook that index, and the commit records it.

Changes:

  • Adds tree_env(), which drops the location variables but keeps GIT_INDEX_FILE, and uses it for the five reads of the scanned tree.
  • Adds three tests: one for a subdirectory under GIT_DIR, one that checks each of the five reads against a different shallow repository, and one that runs a real git commit <paths> with a pre-commit hook.
File Description
tests/​test_prose_lint.py Adds three regression tests covering the subdirectory case, the five scanned-tree reads, and the commit index handed to a hook.
.github/​actions/​prose-gate/​prose_lint.py Adds tree_env() and applies it to the scanned-tree git reads, so an inherited GIT_DIR no longer changes their answers.

Review effort: Lite

@codecov

codecov Bot commented Nov 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.91%. Comparing base (b38e084) to head (f47ab60).
⚠️ Report is 78 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #3831      +/-   ##
===========================================
+ Coverage    81.60%   82.91%   +1.30%     
===========================================
  Files           26       29       +3     
  Lines         9070     9750     +680     
===========================================
+ Hits          7402     8084     +682     
+ Misses        1668     1666       -2     
Flag Coverage Δ
python-3.13 82.91% <ø> (+1.30%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ptr727
ptr727 merged commit 49c58a2 into develop Nov 2, 2026
14 checks passed
@ptr727
ptr727 deleted the burndown/3821-prose-gate-git-env branch November 2, 2026 20:18
ptr727 added a commit that referenced this pull request Nov 3, 2026
…rge on a Running Hosted Review, and Gate Skill Description Length (#3843)

Promotes the changes merged into `develop` since promotion #3797 to
`main`, the end of an away-mode backlog burndown.

- [#3803](#3803) exempts
the Roslyn embedded-language marker (`// lang=json`, `language=`) from
the prose gate's comment rules as a tool directive.
- [#3807](#3807) has
`local_review.py record` take `--report`, the file the reviewer wrote,
bind the pass to its sha256, and derive the finding count from it.
`status` gains `reportPath`.
- [#3809](#3809) holds
`pr_review.py merge` while a hosted review is still running on the head,
and routes a declined Qodo finding to a dismiss request.
- [#3811](#3811) dates an
anchored `intentRef` by the section its anchor names, and lets a
`driftNote` acknowledge a verified intent advisory.
- [#3816](#3816) moves the
null GraphQL node check into the shared `gh_graphql` transport as
`NullNodeError`.
- [#3818](#3818) explains
the workspace-edit default in `GOVERNANCE.md` and names the aggregator's
expression form.
- [#3822](#3822) moves the
abandon discard to the `backlog-burndown` orchestrator, aligns the
abandoned-branch delete, and holds a grown agent-safety set.
- [#3823](#3823) scopes
the Husky prose gate to staged paths and adds `--skip-generated` so a
named file inside a generated tree is skipped.
- [#3828](#3828) reads
Copilot's `Open findings:` label, drops the duplicate `null_node`, and
matches `scripts/README.md` to the Merge Gate.
- [#3829](#3829) bumps the
two stale hub caller snippet pins and documents the fallback's
mixed-pair refusal.
- [#3831](#3831) keeps an
inherited `GIT_DIR` from rerooting the prose gate's subdirectory git
reads.
- [#3832](#3832) gives
`backlog-burndown` a disposition for a worker's standalone clone and
keeps the agent-safety hold past a park.
- [#3835](#3835) makes
`carry.py check-sections` refuse what `apply-sections` would, and name
an open fence.
- [#3836](#3836) pins the
reusable-workflow stubs by placeholder and ticks the PlexCleaner gates
item.
- [#3838](#3838) has the
`runtime-secrets` audit dimension detect a bare `secrets/` directory
from the tracked files that name it.
- [#3839](#3839) gates
skill descriptions at the 1024-character limit and trims every one over
it.
- [#3846](#3846) fixes an
adjacent doc, an in-file pre-existing defect, and an edge case on new
code in the open pull request instead of filing an issue for each, and
keeps filing for code that runs elsewhere.
- [#3847](#3847) refuses
skill frontmatter that parses to a list or a scalar, so the description
length gate cannot be bypassed.

Fixes #3770
Fixes #3699
Fixes #3705
Fixes #3789
Fixes #1819
Fixes #727
Fixes #3710
Fixes #3706
Fixes #3623
Fixes #3687
Fixes #3617
Fixes #3757
Fixes #3790
Fixes #3786
Fixes #3785
Fixes #3772
Fixes #1657
Fixes #3443
Fixes #3824
Fixes #3817
Fixes #3805
Fixes #1666
Fixes #3700
Fixes #3821
Fixes #3771
Fixes #3794
Fixes #3825
Fixes #3690
Fixes #1472
Fixes #3813
Fixes #3719
Fixes #1592
Fixes #3845

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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