P04-01: 同時発生の更新規約
This commit is contained in:
@@ -283,6 +283,15 @@ def supplied_file(directory, descriptor):
|
||||
support = directory / 'audit-support'
|
||||
roots = [support / n for n in ('p04-whole-closure-r01', 'native-first-current',
|
||||
'p04-current-native-series-r01', 'p04-r17-full-inputs-r01')]
|
||||
fresh_path = support / 'p04-fresh-runs.json'
|
||||
if fresh_path.is_file():
|
||||
fresh = load(fresh_path)
|
||||
require(fresh['protocol'] == 'p04-fresh-runs-v1', 'fresh material registry')
|
||||
roots.append(support / 'p04-fresh-context')
|
||||
for row in fresh['series'].values():
|
||||
relative = Path(row['run'])
|
||||
require(not relative.is_absolute() and '..' not in relative.parts, 'fresh material run path')
|
||||
roots.append(directory / relative)
|
||||
matches = [root for root in roots if path.is_relative_to(root)]
|
||||
require(len(matches) == 1, 'unsupplied external material: ' + name)
|
||||
path = safe(matches[0], path.relative_to(matches[0]).as_posix())
|
||||
@@ -356,6 +365,10 @@ def verify_roles(index, directory):
|
||||
composed = git_bytes('-c', 'rerere.enabled=false', 'merge-tree', '--write-tree',
|
||||
main, submitted).decode().strip()
|
||||
require(re.fullmatch('[0-9a-f]{40}', composed) is not None, 'conflicted composition')
|
||||
if 'fresh_run_bindings' in index:
|
||||
fresh = index['fresh_run_bindings']
|
||||
require((fresh['M'], fresh['S'], fresh['Q_tree']) == (main, submitted, composed),
|
||||
'fresh evidence does not bind recomputed Q')
|
||||
main_entries, patch, target = [tree_entries(t) for t in (main, submitted, composed)]
|
||||
anchor_entries = tree_entries(MAIN_ANCHOR)
|
||||
for path in main_entries.keys() | target.keys():
|
||||
@@ -1050,7 +1063,7 @@ def verify_shift_completion(base):
|
||||
return {'verified_conditions': ['shift_completion'], 'phases': points, 'transaction_id': transaction_id}
|
||||
|
||||
|
||||
def combine_native_series(directory, native):
|
||||
def combine_historical_native_series(directory, native):
|
||||
"""Independent R composition; rerun raw checks, never trust condition scalars.
|
||||
|
||||
The C verifier and its fixtures remain unchanged. This function does not
|
||||
@@ -1095,6 +1108,80 @@ def combine_native_series(directory, native):
|
||||
'stage_A': 'candidate binding stage A pending', 'formal_acceptance': False}
|
||||
|
||||
|
||||
def combine_native_series(directory, native):
|
||||
"""Fresh raw supplies conditions; historical collection is separate provenance."""
|
||||
import importlib.util
|
||||
def module(name, path):
|
||||
spec = importlib.util.spec_from_file_location(name, path)
|
||||
value = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(value)
|
||||
return value
|
||||
module_path = ROOT / DOC_SCOPE / 'p04_native_series.py'
|
||||
series = module('p04_fresh_series', module_path)
|
||||
root_bindings = series.fresh_bindings(directory)
|
||||
collection = root_bindings['collection']
|
||||
require(re.fullmatch(r'audit-support/p04-raw-collect-q[0-9]+', collection) is not None,
|
||||
'exclusive fresh collection name')
|
||||
base = directory / collection
|
||||
manifest_path = safe(base, 'MANIFEST.json')
|
||||
manifest = load(manifest_path)
|
||||
require(manifest['protocol'] == 'p04-fresh-native-series-collection-v1'
|
||||
and manifest['historical_merged'] is False
|
||||
and set(manifest['series']) == set(series.FRESH_RUNS), 'fresh series roster')
|
||||
verified, bindings, results, pids = set(), {}, {}, []
|
||||
for name in series.FRESH_RUNS:
|
||||
binding = manifest['series'][name]
|
||||
path = safe(base, binding['path'])
|
||||
require(path.name == name + '.json' and sha(path) == binding['sha256']
|
||||
and path.stat().st_size == binding['bytes'], 'fresh series collection pin')
|
||||
recorded = load(path)
|
||||
require(recorded['verifier_sha256'] == sha(module_path), 'fresh verifier drift')
|
||||
actual = getattr(series, 'verify_fresh_' + name)(directory)
|
||||
require({k: v for k, v in recorded.items() if k != 'verifier_sha256'} == actual, 'fresh raw recomputation drift')
|
||||
verified.update(actual['verified_conditions'])
|
||||
pids.extend(actual['owned_pids'])
|
||||
bindings[name], results[name] = binding['sha256'], actual
|
||||
require(len(pids) == len(set(pids)), 'fresh series PID reuse')
|
||||
order = results['s5']['facts']['order']['cases']
|
||||
gates = {
|
||||
'D05-P04-DESTRUCTION': [('S5C_DESTRUCTION_COMMAND', 'command_destruction_before_completion'),
|
||||
('S5D_DESTRUCTION_RAID', 'raid_sale_before_destruction'),
|
||||
('S5D_DESTRUCTION_RAID', 'raid_unfinished_release')],
|
||||
'D05-P04-MIDNIGHT-DAY': [('S5E_MIDNIGHT', 'midnight_close_upkeep_before_sale'),
|
||||
('S5E_MIDNIGHT', 'midnight_new_day_sale')],
|
||||
'D05-P04-EXIT': [('S5F_EXIT', 'command_exit_before_start'), ('S5F_EXIT', 'planned_exit_after_completion')],
|
||||
}
|
||||
for ref, pairs in gates.items():
|
||||
require(all(order[case][key] is True for case, key in pairs), 'S5 order gate: ' + ref)
|
||||
power = results['s5']['facts']['power']['cases']
|
||||
require(power['S5A_PURE']['measurements']['power_stop'] == REQUIRED['power_stop'][2]
|
||||
and power['S5B_DEPENDENCY']['measurements']['dependency_stop'] == REQUIRED['dependency_stop'][2],
|
||||
'S5 D05-P04-PAUSE-REASON gate')
|
||||
full_verifier = module('p04_full_verifier', ROOT / DOC_SCOPE / 'full_suite_verifier.py')
|
||||
full_binding = root_bindings['full_suite']
|
||||
full_run = directory / full_binding['run']
|
||||
require(not Path(full_binding['run']).is_absolute() and '..' not in Path(full_binding['run']).parts,
|
||||
'full run path')
|
||||
for leaf, key in [('runner-input.json', 'runner_input'), ('runner-ended.json', 'runner_ended')]:
|
||||
series.checked(safe(full_run, leaf).read_bytes(), full_binding[key], 'Root full receipt')
|
||||
full_inputs = load(safe(full_run, 'runner-input.json'))
|
||||
full = full_verifier.verify(Path(full_inputs['project_root']), full_run, REQUIRED)
|
||||
require(full['verified'] is True and set(full['conditions']) == set(REQUIRED) | {'EV'}, 'full condition membership')
|
||||
expected_source = {n: p['sha256'] for n, p in load(directory / root_bindings['series']['s5']['run'] / 'source_before.json').items()}
|
||||
require(full['source_sha256'] == expected_source, 'full and boundary exact same Q')
|
||||
history = safe(directory / 'audit-support/p04-raw-collect-r22', 'MANIFEST.json')
|
||||
c_base = directory / 'audit-support/native-first-current'
|
||||
require(native == verify_native(c_base), 'historical C provenance recomputation')
|
||||
return {'verified_conditions': sorted(verified), 'series_manifest_sha256': sha(manifest_path),
|
||||
'series_bindings': bindings, 'fresh_collection': collection, 'full_suite': full,
|
||||
'historical_collection': {'manifest_sha256': sha(history), 'merged': False},
|
||||
'C_source_manifest_sha256': sha(safe(c_base, 'SOURCE_MANIFEST.json')),
|
||||
'C_provenance_sha256': sha(safe(c_base, 'OWNERSHIP_RAW_PROVENANCE.json')),
|
||||
'missing_conditions': sorted((set(REQUIRED) | {'EV'}) - verified),
|
||||
'nativeWindows': {name: 'pending' for name in sorted(set(REQUIRED) | {'EV'})},
|
||||
'stage_A': 'candidate binding stage A pending', 'formal_acceptance': False}
|
||||
|
||||
|
||||
def verify(directory):
|
||||
# Contract hashes the supplied spec string, while the checked-in JSON has
|
||||
# one final LF. Accept only that exact representation difference.
|
||||
|
||||
Reference in New Issue
Block a user