Close local review loose ends and record blocked workplan gates
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e241-8285-7a63-8c0c-51c9cb824dc3
This commit is contained in:
parent
bcdb02323c
commit
7295172f1e
20 changed files with 510 additions and 95 deletions
|
|
@ -1,4 +1,5 @@
|
|||
"""Reject broken preview contracts before publishing generated references."""
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
|
@ -48,16 +49,18 @@ def test_duplicate_identity(copy):
|
|||
preview.build(copy)
|
||||
|
||||
|
||||
def test_stale_candidate(copy):
|
||||
def test_live_candidate_change_does_not_break_frozen_preview(copy):
|
||||
with (copy / 'research/candidates/ConflictCopy.md').open('a') as f:
|
||||
f.write('\nChanged contract.\n')
|
||||
with pytest.raises(ValueError, match='Stale candidate'):
|
||||
preview.build(copy)
|
||||
assert preview.build(copy) == preview.build(ROOT)
|
||||
import research_evolution as evolution
|
||||
with pytest.raises(ValueError, match='Stale profile'):
|
||||
evolution.validate(evolution.load(copy), copy)
|
||||
|
||||
|
||||
def test_escaping_reference(copy):
|
||||
mutate(copy, lambda m: m['entrypoints'].update(start='/etc/passwd'))
|
||||
with pytest.raises(ValueError, match='Invalid reference'):
|
||||
with pytest.raises(ValueError, match='Published manifest changed'):
|
||||
preview.build(copy)
|
||||
|
||||
|
||||
|
|
@ -68,3 +71,44 @@ def test_missing_metadata(copy):
|
|||
path.write_text(json.dumps(data))
|
||||
with pytest.raises((ValueError, KeyError)):
|
||||
preview.build(copy)
|
||||
|
||||
|
||||
def test_legitimate_new_research_remains_separate_from_old_release(copy):
|
||||
import research_evolution as evolution
|
||||
candidate = copy / 'research/candidates/ConflictCopy.md'
|
||||
candidate.write_text(candidate.read_text() + '\nNew research clarification.\n')
|
||||
digest = hashlib.sha256(candidate.read_bytes()).hexdigest()
|
||||
profiles = copy / 'research/evolution/profiles.json'
|
||||
data = json.loads(profiles.read_text())
|
||||
data['profiles'][0]['sha256'] = digest
|
||||
profiles.write_text(json.dumps(data))
|
||||
classes = copy / 'research/catalog/ClassificationCoverage.json'
|
||||
data = json.loads(classes.read_text())
|
||||
next(c for c in data['candidates'] if c['path'] == 'research/candidates/ConflictCopy.md')['sha256'] = digest
|
||||
classes.write_text(json.dumps(data))
|
||||
evolution.validate(evolution.load(copy), copy)
|
||||
assert preview.build(copy, '0.1') == preview.build(ROOT, '0.1')
|
||||
|
||||
|
||||
def test_unknown_version_and_forged_release_pin(copy):
|
||||
with pytest.raises(ValueError, match='Unknown'):
|
||||
preview.build(copy, '9.9')
|
||||
path = copy / 'reference/releases.json'
|
||||
data = json.loads(path.read_text())
|
||||
data['releases']['0.1']['manifest_sha256'] = '0' * 64
|
||||
path.write_text(json.dumps(data))
|
||||
with pytest.raises(ValueError, match='digest mismatch'):
|
||||
preview.build(copy)
|
||||
|
||||
|
||||
def test_published_cases_cannot_be_rewritten(copy):
|
||||
path = copy / 'reference/0.1/development-cases.json'
|
||||
path.write_text('{}')
|
||||
with pytest.raises(ValueError, match='Published artifact changed'):
|
||||
preview.build(copy)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('path', ['/etc/passwd', '../README.md', 'research/../README.md', 'research//README.md'])
|
||||
def test_git_blob_rejects_escaping_paths(path):
|
||||
with pytest.raises(ValueError, match='Invalid reference'):
|
||||
preview.git_blob(ROOT, '0' * 40, path)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ def test_current_records_and_report_are_consistent(data):
|
|||
|
||||
|
||||
@pytest.mark.parametrize('mutation,match', [
|
||||
(lambda d: d['profiles']['profiles'][0]['review'].update(last_substantive_review_date='2099-01-01'), 'Review date exceeds'),
|
||||
(lambda d: d['profiles']['profiles'][0]['review'].update(substantive_review_ref=None), 'needs provenance'),
|
||||
(lambda d: d['profiles']['profiles'][0]['review'].update(substantive_review_scope=''), 'needs provenance'),
|
||||
(lambda d: d['profiles']['profiles'][0].update(sha256='0'*64), 'Stale profile'),
|
||||
(lambda d: d['profiles']['profiles'].pop(), 'inventory mismatch'),
|
||||
(lambda d: d['profiles']['profiles'][1].update(id='CAND-0001'), 'Duplicate candidate'),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue