Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions frontiers/downstream_gate_20260925/SOURCE_FILES.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
"sha256": "c444e6c347da680aff5bef7f43900e45d52a0cc45081fb7b4def45266d97aac1"
},
"test_transition_contract.py": {
"bytes": 12679,
"sha256": "ab69008b5c0c136dcdf742ecd1213e1c5b4b08e7aa4c9d0747037acaa8633c37"
"bytes": 12767,
"sha256": "c4bd9631e615bc5ebb393d5e131a7f5c213936577d8c21b6628509645fb327fe"
}
},
"meaning": "Exact identity, not theorem correctness",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand All @@ -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']
Expand Down
94 changes: 94 additions & 0 deletions tests/test_downstream_gate_git_isolation.py
Original file line number Diff line number Diff line change
@@ -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()
Loading