Skip to content

Make tests hermetic against global and system git config - #181

Merged
seathatflowsinourveins merged 1 commit into
mainfrom
claude/hermetic-test-git-20260924
Sep 24, 2026
Merged

seathatflowsinourveins merged 1 commit into
mainfrom
claude/hermetic-test-git-20260924

Conversation

@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator

Summary

Tests no longer read the developer's global or system git configuration. tests/__init__.py points GIT_CONFIG_GLOBAL at an empty temp file (this replaces both ~/.gitconfig and $XDG_CONFIG_HOME/git/config) and sets GIT_CONFIG_NOSYSTEM=1 (skips the system file, including Apple Git's bundled one). CI runners already have no global config, so local runs now match CI.

Fixes #179 (foundation-lane decision: keep the global gitleaks hook strict; fix repo-side).

Evidence (macOS 26.5.1, git 2.50.1 Apple)

  • Before: python3 -m unittest tests.test_catalog_freshness_propose → 76 tests, 2 errors (both setUpClass scratch commits blocked by the global pre-commit hook).
  • After: the nine modules that commit into scratch repos (test_catalog_freshness_propose, test_claude_lane, test_blind_checkout, test_release_pin_contents, test_gitleaks_config, test_host_receipts, test_saturation_ledger, test_workflow_hardening, test_verdict_review_gate) plus the new test ran together: 496 tests; the one failure was the publication hash of tests/__init__.py, fixed in manifests/evidence.json. Rerun of test_hermetic_git + test_catalog_freshness_propose: 83 tests OK.
  • python3 scripts/validate.py: passed (5235 hashed files); scripts/evidence_manifest.py --check: ordered.

New test

tests/test_hermetic_git.py: the environment points at an empty global file with no system file; no global setting (incl. core.hooksPath) is visible; a hostile HOME/XDG_CONFIG_HOME config whose core.hooksPath pre-commit exits 1 cannot block a scratch commit.

🤖 Generated with Claude Code

Scratch repositories created by the tests inherited the developer's global
git configuration. On hosts that install a global core.hooksPath (the
agent-ecosystem gitleaks pre-commit hook), two setUpClass commits in
test_catalog_freshness_propose failed. The tests package now points
GIT_CONFIG_GLOBAL at an empty file and sets GIT_CONFIG_NOSYSTEM=1, which
matches CI runners; test_hermetic_git asserts it, including a hostile
HOME/XDG config that cannot block a scratch commit. The evidence manifest
records the new tests/__init__.py bytes.

Fixes #179

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Sep 24, 2026
@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.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@seathatflowsinourveins
seathatflowsinourveins merged commit 6f7a77c into main Sep 24, 2026
22 checks passed
@seathatflowsinourveins
seathatflowsinourveins deleted the claude/hermetic-test-git-20260924 branch September 24, 2026 14:08
seathatflowsinourveins added a commit that referenced this pull request Sep 24, 2026
…hdog (Jetsam 2026-09-24) (#193)

* Bound gitleaks scans on macOS: per-user lock and 6 GiB footprint watchdog

The 2026-09-24 09:45/09:46 Jetsam events (three gitleaks processes at 52.8,
then 58.2 GiB) came from gitleaks 8.30.1 redaction: filter() calls
Finding.Redact for every finding, and Redact copies the finding's whole line.
A git-mode hunk holds whole lines, so the generated explorer's 2,335 findings
on one 12.9 MB line retain about 28 GiB. The global pre-commit hook hit it on
test scratch commits (before #181); the recipe's all-refs history scan hits it
on the 240 commits that touch the explorer.

adoption/tools/gitleaks-guarded-macos gives macOS the Linux launcher's caps
without a cgroup: one scan per user through a flock that waits up to 60 s
(exit 75), a watchdog that sums the scan tree's physical footprint every 50 ms
and kills it above 6 GiB (exit 137) or after 600 s (exit 124), and refusals
(exit 78) before any scan. Gitleaks arguments, output and exit codes are
otherwise unchanged. --max-target-megabytes and path exclusions were measured
and rejected: the size skip turned 2,335 findings into "no leaks found".

Before/after peaks for every candidate invocation on this Mac are in
evidence/receipts/gitleaks-macos-memory-bound-20260924.json. The global hook
belongs to agent-ecosystem and is handed off to its owner, not edited here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Keep the macOS gitleaks receipt out of the component's evidence_ids

tests/test_stack_lifecycle requires every stack.json evidence id to appear in
the token-native saturation audit's public_receipts row, which another lane
owns. The receipt stays registered in manifests/evidence.json on its own;
stack.json is back to its base bytes and hash.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: seathatflowsinourveins <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
seathatflowsinourveins added a commit that referenced this pull request Sep 24, 2026
…lobal git hooks (#204)

On a host with a global core.hooksPath and ignore file (a managed
~/.config/git), clean main failed locally: 46 errors in
tests.test_verdict_review_gate and 1 failure in tests.test_claude_lane.
CI runners have no global git config and stayed green.

GateFixture.git and the read tracer dropped every inherited GIT_* variable,
including the GIT_CONFIG_GLOBAL and GIT_CONFIG_NOSYSTEM that #181 sets. So
fixture commits ran the global gitleaks pre-commit hook, which flagged
synthetic fixture digests as generic-api-key. The gate's own
git_environment() drops them as well, so its head worktree ran the global
post-checkout hook. The claude-lane failure is not a hook. Git reads
$XDG_CONFIG_HOME/git/ignore as the default core.excludesFile whatever
GIT_CONFIG_GLOBAL says. The managed ignore file lists
.claude/settings.local.json, which hid the test's local settings file from
claude_lane.py's git status check.

tests/__init__.py now sets core.excludesFile and core.attributesFile to
/dev/null in the hermetic global file. It also provides
hermetic_git_environment(), which drops inherited GIT_* routing variables
but keeps the hermetic configuration. The gate tests use it for their
helpers and patch gate.git_environment with it. Production code and the
global hooks are unchanged. test_hermetic_git gains a reusable hostile HOME
(hooks that all exit 1, an ignore file matching everything, a hostile
attributes file) and a non-vacuous control. It runs the gate's
head-worktree test and the claude-lane BIND-R4-8 test under that HOME. The
evidence manifest records the new tests/__init__.py bytes.

Refs #179, #181

Co-authored-by: seathatflowsinourveins <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scratch-repo tests inherit global git hooks (gitleaks pre-commit) and fail on hosts that adopt them

1 participant