coulomb-social/tests/test_bubble_body_resources.py
tegwick 6e07f572a8
Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 6m58s
Verify captured body links and retain unresolved scrap relations
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
2026-10-31 15:13:45 +01:00

65 lines
2.8 KiB
Python

"""Body-resource evidence must bind both source bytes and the prepared pages."""
import hashlib
import importlib.util
import json
from pathlib import Path
import pytest
from tests.test_bubble_visuals import PNG, bundle, visuals
SPEC = importlib.util.spec_from_file_location(
'body_resources',
Path(__file__).resolve().parents[1] / 'scripts/verify-bubble-body-resources.py')
resources = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(resources)
def prepared(tmp_path):
source, report, _ = bundle(tmp_path)
raw = json.dumps({'missing': {}}).encode()
visuals.publish(source, 'source-capture/retained_spaces.json', raw)
report['source_sha256']['retained_spaces'] = hashlib.sha256(raw).hexdigest()
(source / 'reconciliation.json').write_text(json.dumps(report))
out = tmp_path / 'visual'
visuals.capture(source, out, lambda _: (PNG, 'png'))
return source, out
def test_resource_proof_preserves_scope_and_never_accepts_productive_fidelity(tmp_path):
source, out = prepared(tmp_path)
summary, private = resources.verify(source, out)
assert summary['captured_articles'] == 3
assert summary['source_bodies_verified'] == 3
assert summary['prepared_pages_verified'] == 2
assert summary['network_requests'] == 0
assert not summary['productive_fidelity_accepted']
assert not summary['live_destinations_checked']
assert not summary['production_imported']
assert len(private['fresh_space_blockers']) == 2
@pytest.mark.parametrize('defect', ['source-drift', 'sidecar-drift', 'prepared-body-drift',
'original-report-drift', 'original-draft-drift'])
def test_resource_proof_refuses_source_or_prepared_drift(tmp_path, defect):
source, out = prepared(tmp_path)
if defect == 'source-drift':
(source / 'source-capture/articles.json').write_text('{}')
elif defect == 'sidecar-drift':
next((source / 'source-bodies').glob('*.txt')).write_text('Changed')
elif defect == 'original-draft-drift':
next((source / 'review-trees').glob('*/pages/*.md')).write_text('Changed')
elif defect == 'original-report-drift':
p = source / 'reconciliation.json'
p.write_text(p.read_text() + '\n')
else:
report = json.loads((out / 'reconciliation.json').read_text())
name = next(p['file'] for s in report['spaces'] for p in s['articles'] if p['file'])
changed = (out / name).read_bytes() + b'Changed'
(out / name).write_bytes(changed)
# Even a matching prepared-file hash cannot authorize a changed source body.
report['file_sha256'][name] = hashlib.sha256(changed).hexdigest()
(out / 'reconciliation.json').write_text(json.dumps(report))
with pytest.raises(ValueError):
resources.verify(source, out)