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
14 changes: 14 additions & 0 deletions research/isolated-descendant-bytecode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,20 @@ registered commands, verifier and `RESULT.json` are retained unchanged.
This metadata correction was prepared for roger-sato with substantial OpenAI
Codex assistance; Arham Tahir's original work and source credit are retained.

The `tests/test_research_source_history.py` row likewise authenticates the
original test copied by `pinned_sources()` from the exact base-commit Git blob;
the verifier does not import the live test file. Its original commit, blob and
SHA256 remain unchanged. Classifying that row as provenance permits the live
test's disposable Git fixtures to disable automatic maintenance, preventing
detached writers from racing temporary-directory cleanup. `VERIFY.json` still
declares the current test as a planner and publication input. The original
sixteen-run differential, verifier, commands and result remain unchanged.
Regression controls require the historical replay to pass even when a live
test copy cannot import, retain rejection of original pin corruption, and
confirm live changes still select replay and fail uncommitted-byte checks.
This fixture repair was prepared by Clear1nsight with substantial OpenAI
Codex assistance; it changes no source-history validation or research claim.

```sh
python3.12 -B scripts/research_package.py --package research/isolated-descendant-bytecode --check-only
python3.12 -B scripts/research_package.py --package research/isolated-descendant-bytecode
Expand Down
2 changes: 1 addition & 1 deletion research/isolated-descendant-bytecode/SOURCES.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
{
"path": "tests/test_research_source_history.py",
"usage": "input",
"usage": "provenance",
"git_blob": "9c52884a4663c089e2331b769b50d14da4575d9f",
"sha256": "2b974b7c1f5fcb1994c2b76be32554378cec91871224fca0af011d0640dc5514"
}
Expand Down
63 changes: 60 additions & 3 deletions tests/test_research_descendant_source_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
ORIGINAL = '20ecf2891d80b5acf18d980b2164fb44ea7faa90'
PACKAGE = 'research/isolated-descendant-bytecode'
HELPER = 'scripts/research_package.py'
HISTORY_TEST = 'tests/test_research_source_history.py'


def git(root, *args):
Expand Down Expand Up @@ -64,15 +65,17 @@ def cli(self, script='research_package.py', arguments=None):

def test_only_source_role_changes_and_frozen_evidence_is_retained(self):
expected = copy.deepcopy(self.original)
row = next(row for row in expected['files'] if row['path'] == HELPER)
self.assertEqual(row['usage'], 'input')
row['usage'] = 'provenance'
for name in (HELPER, HISTORY_TEST):
row = next(row for row in expected['files'] if row['path'] == name)
self.assertEqual(row['usage'], 'input')
row['usage'] = 'provenance'
self.assertEqual(json.loads((ROOT / PACKAGE / 'SOURCES.json').read_bytes()), expected)
for name in ('VERIFY.json', 'TASK.json', 'verify.py', 'RESULT.json'):
with self.subTest(name=name):
self.assertEqual((ROOT / PACKAGE / name).read_bytes(),
git(ROOT, 'show', ORIGINAL + ':' + PACKAGE + '/' + name))
self.assertIn(HELPER, self.manifest['inputs'])
self.assertIn(HISTORY_TEST, self.manifest['inputs'])
self.assertEqual(len(self.manifest['commands']), 3)

def test_original_gate_rejects_but_correct_role_accepts_current_helper(self):
Expand All @@ -89,6 +92,60 @@ def test_original_gate_rejects_but_correct_role_accepts_current_helper(self):
self.assertEqual(after.returncode, 0, after.stderr)
self.assertIn('PASS_PACKAGE_METADATA_AND_PINS', after.stdout)

def test_live_history_guard_is_not_a_historical_source_substitution(self):
# An unimportable live test must not replace the authenticated original
# test copied by verify.py's pinned_sources() into the historical runs.
live = self.root / HISTORY_TEST
live.write_bytes(live.read_bytes() + b'\nraise RuntimeError("LIVE_HISTORY_SENTINEL")\n')
result = self.cli(arguments=['--package', PACKAGE])
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn('PASS_ISOLATED_DESCENDANT_BYTECODE', result.stdout)
self.assertIn('PASS_REGISTERED_RESEARCH_PACKAGE', result.stdout)
self.assertNotIn('LIVE_HISTORY_SENTINEL', result.stderr)

def test_original_history_input_role_rejects_live_guard_successor(self):
migrated = json.loads((self.root / PACKAGE / 'SOURCES.json').read_bytes())
original_role = copy.deepcopy(migrated)
next(row for row in original_role['files']
if row['path'] == HISTORY_TEST)['usage'] = 'input'
self.write_sources(original_role)
before = self.cli()
self.assertNotEqual(before.returncode, 0)
self.assertIn('working source drift: ' + HISTORY_TEST, before.stderr)
self.write_sources(migrated)
after = self.cli()
self.assertEqual(after.returncode, 0, after.stderr)

def test_historical_history_test_pin_corruption_rejects(self):
sources = json.loads((self.root / PACKAGE / 'SOURCES.json').read_bytes())
for field, value, message in (
('git_blob', '0' * 40, 'source blob provenance mismatch'),
('sha256', '0' * 64, 'source SHA256 provenance mismatch')):
with self.subTest(field=field):
corrupted = copy.deepcopy(sources)
next(row for row in corrupted['files']
if row['path'] == HISTORY_TEST)[field] = value
self.write_sources(corrupted)
result = self.cli()
self.assertNotEqual(result.returncode, 0)
self.assertIn(message + ': ' + HISTORY_TEST, result.stderr)
self.assertNotIn('PASS_PACKAGE', result.stdout)

def test_live_history_test_remains_a_planner_and_publication_input(self):
base = git(self.root, 'rev-parse', 'HEAD').decode().strip()
live = self.root / HISTORY_TEST
live.write_bytes(live.read_bytes() + b'\n# maintenance guard successor\n')
result = self.cli('check_research_commit.py', ['--package', PACKAGE])
self.assertNotEqual(result.returncode, 0)
self.assertIn('working/commit bytes differ: ' + HISTORY_TEST, result.stderr)
self.commit()
explanation = self.root / 'history-plan.json'
result = self.cli(arguments=['--changed-since', base, '--explain-plan', str(explanation)])
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(json.loads(result.stdout), {'include': [{'package': PACKAGE}]})
causes = json.loads(explanation.read_bytes())['selected'][0]['causes']
self.assertEqual(causes['declared_inputs'], [HISTORY_TEST])

def test_historical_blob_and_hash_corruption_still_rejects(self):
sources = json.loads((self.root / PACKAGE / 'SOURCES.json').read_bytes())
for field, value, message in (
Expand Down
34 changes: 33 additions & 1 deletion tests/test_research_source_history.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Publication history controls use synthetic Git objects, without remote fetches."""
import json
import os
import subprocess
import sys
import tempfile
Expand Down Expand Up @@ -33,7 +34,9 @@ def setUp(self):
self.base = self.git('rev-parse', 'HEAD').strip()

def git(self, *args, data=None):
result = subprocess.run(['git', *args], cwd=self.root, input=data,
# Fixture commits must not leave maintenance writing during cleanup.
result = subprocess.run(['git', '-c', 'maintenance.auto=false', '-c', 'gc.auto=0',
*args], cwd=self.root, input=data,
capture_output=True, text=True, timeout=30, check=True)
return result.stdout

Expand Down Expand Up @@ -61,6 +64,35 @@ def test_base_and_explicit_ancestor_pins_are_deduplicated(self):
self.assertEqual(self.check(history=False),
{'commit': head, 'files': 3, 'package': self.package})

def test_fixture_git_never_starts_automatic_maintenance(self):
# Force automatic work even in this small fixture. The positive
# control stays in the foreground so it cannot race temp cleanup.
for key, value in {
'maintenance.auto': 'true', 'maintenance.autoDetach': 'false',
'gc.autoDetach': 'false', 'maintenance.commit-graph.enabled': 'true',
'maintenance.commit-graph.auto': '-1', 'gc.auto': '1',
}.items():
self.git('config', key, value)
with tempfile.TemporaryDirectory() as directory:
trace = Path(directory) / 'git-trace.jsonl'

def maintenance_children():
return [event for line in trace.read_text(encoding='utf-8').splitlines()
if (event := json.loads(line)).get('event') == 'child_start'
and any(arg in {'maintenance', 'gc'}
for arg in event.get('argv', []))]

with patch.dict(os.environ, {'GIT_TRACE2_EVENT': str(trace)}):
self.git('commit', '-qm', 'guarded fixture', '--allow-empty')
self.assertEqual(maintenance_children(), [])

trace.unlink()
with patch.dict(os.environ, {'GIT_TRACE2_EVENT': str(trace)}):
subprocess.run(['git', '-c', 'core.hooksPath=/dev/null', 'commit', '-qm',
'unguarded control', '--allow-empty'], cwd=self.root,
check=True, capture_output=True, timeout=30)
self.assertTrue(maintenance_children(), 'positive control must start maintenance')

def test_cached_side_commit_passes_bytes_but_not_publication_history(self):
tree = self.git('rev-parse', self.base + '^{tree}').strip()
foreign = self.git('commit-tree', tree, '-p', self.base,
Expand Down