From 6f4d3bec4e6f69c950371fa275db863e367ca8b4 Mon Sep 17 00:00:00 2001 From: Grok Bot agent 10 Date: Sat, 17 Oct 2026 11:58:48 -0500 Subject: [PATCH] Keep automatic Git maintenance out of downstream-gate disposable fixtures (R80) Bounded Math-#397 mitigation candidate activated in main#419 6237052185 (CoS R80 6237088023), from proposal Math-#397 6164700599 and static assessment 6175978883. - test_transition_contract.py: repository-local maintenance.auto=false after init/user config at the two fixture init sites (:140, :158). - SOURCE_FILES.json: recompute only the test_transition_contract.py entry (12679/ab69008b... -> 12767/c4bd9631...). - tests/test_downstream_gate_git_isolation.py: Trace2 regression running the actual four Git fixture tests with emptied global/system config and no GIT_* overrides; fails if the insertions are reverted; includes a default-maintenance positive control. Claim bounded to that effective configuration. Engineering mitigation only: no attribution of the historical Errno 39, no change to cleanup/error refusal, 71 methods / 24 mutants / two modes, historical manifests or C183 fixtures. Math-#397 HOLD/NOT_READY/NO_MERGE unchanged. Rollback: revert this commit. --- .../SOURCE_FILES.json | 4 +- .../test_transition_contract.py | 4 +- tests/test_downstream_gate_git_isolation.py | 94 +++++++++++++++++++ 3 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 tests/test_downstream_gate_git_isolation.py diff --git a/frontiers/downstream_gate_20260925/SOURCE_FILES.json b/frontiers/downstream_gate_20260925/SOURCE_FILES.json index 62c6c137d..1fc4ed2bd 100644 --- a/frontiers/downstream_gate_20260925/SOURCE_FILES.json +++ b/frontiers/downstream_gate_20260925/SOURCE_FILES.json @@ -45,8 +45,8 @@ "sha256": "c444e6c347da680aff5bef7f43900e45d52a0cc45081fb7b4def45266d97aac1" }, "test_transition_contract.py": { - "bytes": 12679, - "sha256": "ab69008b5c0c136dcdf742ecd1213e1c5b4b08e7aa4c9d0747037acaa8633c37" + "bytes": 12767, + "sha256": "c4bd9631e615bc5ebb393d5e131a7f5c213936577d8c21b6628509645fb327fe" } }, "meaning": "Exact identity, not theorem correctness", diff --git a/frontiers/downstream_gate_20260925/test_transition_contract.py b/frontiers/downstream_gate_20260925/test_transition_contract.py index fca3ee258..92e06f618 100644 --- a/frontiers/downstream_gate_20260925/test_transition_contract.py +++ b/frontiers/downstream_gate_20260925/test_transition_contract.py @@ -137,7 +137,7 @@ def test_git_source_only_change_on_real_commits(self): repo = Path(tmp) def run(*args): return subprocess.run(['git', '-C', tmp, *args], check=True, capture_output=True).stdout.decode().strip() - run('init', '-q'); run('config', 'user.name', 'local test'); run('config', 'user.email', 'test@example.invalid') + run('init', '-q'); run('config', 'user.name', 'local test'); run('config', 'user.email', 'test@example.invalid'); run('config', 'maintenance.auto', 'false') (repo/'GRAPH.json').write_text(json.dumps(graph())); (repo/'lemma.md').write_text('first statement') run('add', '.'); run('commit', '-qm', 'baseline'); old = run('rev-parse', 'HEAD') (repo/'lemma.md').write_text('changed statement') @@ -155,7 +155,7 @@ def _live_fixture(self, tmp, graph_obj): repo = Path(tmp) def run(*args): return subprocess.run(['git', '-C', tmp, *args], check=True, capture_output=True).stdout.decode().strip() - run('init', '-q'); run('config', 'user.name', 'local test'); run('config', 'user.email', 'test@example.invalid') + run('init', '-q'); run('config', 'user.name', 'local test'); run('config', 'user.email', 'test@example.invalid'); run('config', 'maintenance.auto', 'false') (repo/GRAPH_REL).parent.mkdir(parents=True, exist_ok=True) (repo/GRAPH_REL).write_text(json.dumps(graph_obj)) paths = list(D1_COMPONENT_FILES) + ['UNRELATED.md'] diff --git a/tests/test_downstream_gate_git_isolation.py b/tests/test_downstream_gate_git_isolation.py new file mode 100644 index 000000000..4eeb6bcd7 --- /dev/null +++ b/tests/test_downstream_gate_git_isolation.py @@ -0,0 +1,94 @@ +"""Real-Git lifecycle regression for the downstream-gate disposable fixtures. + +The actual fixture tests in frontiers/downstream_gate_20260925/test_transition_contract.py +run in a child interpreter under Trace2. Global and system Git configuration +are emptied and every inherited GIT_* variable is removed, so the effective +maintenance.auto value is Git's default unless the fixture sets it +repository-locally. No maintenance setting is forced at command or environment +scope: the claim is bounded to that effective configuration and says nothing +about runners with higher-priority overrides. No fixture, checker or +subprocess is mocked. +""" +import json +import os +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest + + +ROOT = Path(__file__).resolve().parents[1] +GATE = ROOT / 'frontiers/downstream_gate_20260925' +FIXTURE_TESTS = ( + 'test_git_source_only_change_on_real_commits', + 'test_git_d1_component_change_revalidates_d1_d2_d3', + 'test_git_unrelated_edit_does_not_revalidate_d1', + 'test_git_pre_repair_graph_misses_component_change', +) + + +def trace_environment(trace): + env = {key: value for key, value in os.environ.items() + if not key.startswith('GIT_')} + env.update(GIT_CONFIG_NOSYSTEM='1', GIT_CONFIG_GLOBAL=os.devnull, + GIT_TRACE2_EVENT=str(trace.resolve())) + return env + + +def read_events(trace): + return [json.loads(line) for line in trace.read_text().splitlines() if line] + + +def maintenance_commands(events): + return [event.get('argv', []) for event in events + if event.get('event') == 'child_start' + and 'maintenance' in event.get('argv', []) and '--auto' in event.get('argv', [])] + + +def commit_starts(events): + return [event for event in events if event.get('event') == 'start' + and 'commit' in event.get('argv', [])] + + +class DownstreamGateGitIsolationTests(unittest.TestCase): + def test_actual_gate_fixtures_never_launch_automatic_maintenance(self): + flags = ['-B', '-O', '-S'] if sys.flags.optimize else ['-B', '-S'] + names = ['test_transition_contract.TransitionContract.' + name for name in FIXTURE_TESTS] + with tempfile.TemporaryDirectory() as td: + trace = Path(td) / 'git-trace.jsonl' + result = subprocess.run([sys.executable, *flags, '-m', 'unittest', *names], + cwd=GATE, env=trace_environment(trace), + capture_output=True, text=True, timeout=120) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertIn(f'Ran {len(FIXTURE_TESTS)} tests', result.stderr) + self.assertNotIn('skipped=', result.stderr) + self.assertNotIn('\nERROR:', result.stderr) + events = read_events(trace) + self.assertGreaterEqual(len(commit_starts(events)), len(FIXTURE_TESTS), + 'trace must observe the real fixture commits') + self.assertEqual(maintenance_commands(events), [], + 'gate fixture commit launched automatic maintenance before cleanup') + + def test_trace_detects_default_maintenance_in_positive_control(self): + with tempfile.TemporaryDirectory() as td: + folder = Path(td) + root = folder / 'positive-control' + root.mkdir() + trace = folder / 'positive-trace.jsonl' + env = trace_environment(trace) + unset = subprocess.run(['git', 'config', '--get', 'maintenance.auto'], + cwd=folder, env=env, capture_output=True, timeout=30) + self.assertEqual(unset.returncode, 1, 'effective maintenance.auto must be Git default here') + (root / 'payload').write_bytes(b'synthetic positive control\n') + for command in (['git', 'init', '-q'], ['git', 'add', '.'], + ['git', '-c', 'user.name=Gate Fixture', + '-c', 'user.email=fixture@example.invalid', + '-c', 'commit.gpgsign=false', 'commit', '-qm', 'positive control']): + subprocess.run(command, cwd=root, env=env, check=True, capture_output=True, timeout=30) + self.assertEqual(len(maintenance_commands(read_events(trace))), 1, + 'positive control must start automatic maintenance under the default') + + +if __name__ == '__main__': + unittest.main()