P04-01: 同時発生の更新規約
This commit is contained in:
@@ -108,3 +108,36 @@ The preserved S1–S4, r22 index, old registered validation and f5 full178 run r
|
||||
The eleven phases remain APPLY_COMMANDS, TIME_BOUNDARIES, MANA, CONSTRUCTION, LOGISTICS, FACILITY_COMPLETION, VITALS_AND_ENVIRONMENT, INCIDENTS_AND_EVENTS, FACILITY_QUEUES, AI_DECISIONS, PUBLISH_SNAPSHOT. See the structured audit for preserved phase analysis and the new source manifest for exact M references.
|
||||
|
||||
See [CURRENT_STATUS.md](CURRENT_STATUS.md) and [REPAIR31_STATUS.md](REPAIR31_STATUS.md) before any Root execution.
|
||||
|
||||
## REPAIR50 source preparation (2026-10-18; no acceptance claim)
|
||||
|
||||
The commander handoff reports an identity order mutation on an all-equal array
|
||||
(`recent_events/17/payload/current_cell = [0,0,0]`), raw SHA prefix
|
||||
`bb0ccb1d…`, and 761.085 seconds elapsed. These are supplied observations,
|
||||
not measurements repeated by this worker; the full raw SHA/log remains Root
|
||||
material. The old control reversed every multi-element array and classified
|
||||
the resulting identical bytes as a negative. The oracle correctly accepted
|
||||
that identity. Existing failure records remain unchanged.
|
||||
|
||||
REPAIR50 separates byte-identical identity positives from negatives, swaps the
|
||||
first unequal typed byte pair, and lists collections with no genuine order
|
||||
variant. All AFTER keys/values, journal/body fields and both copied modes
|
||||
remain traversed. Type-invalid mutations still require ValueError rejection
|
||||
and are also listed as parser rejections; copied records contain the changed
|
||||
bytes in both AFTER and EXPECTED even when an intermediate parse is invalid.
|
||||
The oracle, adapters, public checker, native-series implementation and R49
|
||||
closure roster are unchanged. No Node patch optimization is used.
|
||||
|
||||
The temporary expected memo keys full BEFORE/command/guard bytes by SHA256
|
||||
and length plus oracle/parser source SHA256. Its cache contains only genuine
|
||||
derivation output bytes. It reconstructs fresh Nodes on each return, restores
|
||||
the wrapper with finally, and retains verify for each parseable mutation.
|
||||
Self-controls compare hit/nonmemo bytes for first/last and each mutated kind,
|
||||
require a one-byte BEFORE miss and reject, and check normal/exception cleanup.
|
||||
The SHA fixture now streams 1 MiB implementation chunks without changing
|
||||
file selection, traversal, relative keys or digest semantics.
|
||||
|
||||
Worker validation: AST parsing only; pure, stream, native and formal checks
|
||||
are unexecuted. See [REPAIR50_STATUS.md](REPAIR50_STATUS.md) for Root commands,
|
||||
static estimation and reuse prerequisites. Original 30/88, formal 16 and P04
|
||||
credit 0 remain unchanged; the whole unit is incomplete.
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# REPAIR50 source-ready handoff
|
||||
|
||||
Scope: control classification/memo, tree() read method only, stream equivalence
|
||||
control and documentation. No Git write, engine, Runner, integration or formal
|
||||
test was performed. Three changed/new Python sources passed AST parsing.
|
||||
|
||||
## Root-only execution and estimation
|
||||
|
||||
From this package directory, run the following pure controls once and retain
|
||||
their separate JSON output and external elapsed/RSS measurements:
|
||||
|
||||
```
|
||||
python3 s5/s5_order_adapter_controls.py --pure-only
|
||||
python3 repair50_stream_controls.py
|
||||
```
|
||||
|
||||
The first emits separate negative counts/lists, identity positive counts/lists,
|
||||
no-genuine-order lists, memo hit/miss, parser-rejection list and elapsed per
|
||||
guard. The second compares the complete whole-read and streamed SHA maps and
|
||||
key insertion order for empty, Unicode name/content, binary, sparse, chunk
|
||||
boundary -1/exact/+1, multiple chunks and nested files. It uses temporary
|
||||
synthetic files only and creates no native acceptance evidence.
|
||||
|
||||
Before heavy typed controls, parse each actual retained guard record with:
|
||||
|
||||
```
|
||||
python3 s5/s5_order_adapter_controls.py --estimate-record /absolute/path/to/guard.var
|
||||
```
|
||||
|
||||
This performs no derivation or verify: output includes record byte size,
|
||||
AFTER node count, kind histogram, replacement count and replacement count x2
|
||||
(including identities, never reported as negatives). Guard mutation disk
|
||||
estimate is zero; stream control logical fixture size is about 10 MiB, with
|
||||
the sparse part filesystem-dependent. Memory scales with retained parsed
|
||||
representatives (at most one per mutated kind, plus first/last), record bytes,
|
||||
parser overhead and output labels. Memo holds one pair of expected/result raw
|
||||
bytes for unchanged inputs; it never caches AFTER or recorded EXPECTED.
|
||||
Time scales with mutation count x record bytes: parse/verify still examine
|
||||
whole records. Use the synthetic run's external peak RSS and elapsed, together
|
||||
with its emitted counts/bytes, as an initial calibration; real record shape
|
||||
and source-derivation costs make this an estimate, not an ETA or resource cap.
|
||||
Actual guard bytes/counts and calibrated measurements are Root-pending.
|
||||
|
||||
## complete_B scope reuse remains conditional
|
||||
|
||||
The supplied commander handoff reports R49 session56645 exit 0, 49-file map,
|
||||
S5 facts/payload equality, no B changes, log SHA prefix bdef6715 and closure
|
||||
tree prefix b54a35ed. This worker has not independently verified that run.
|
||||
Root must mechanically compare its saved full raw map with the new tree and
|
||||
record only the authorized control/tree-read/new-control/document changes.
|
||||
Inspect import/exec and input closure for builder, collector, native-series,
|
||||
reader, oracle, wrapper, probe and helper; preserve S47 raw, 21pin, legacy5,
|
||||
full184 originals, oldQ source/engine SHA and public run_all_tests.py SHA.
|
||||
|
||||
Important: repair48_identity_controls.CLOSURE explicitly lists the changed
|
||||
order control, identity control and S5_ROOT_RUN.md as snapshot material.
|
||||
The roster is unchanged. Direct searches in builder/native-series/order
|
||||
adapter did not reference these names, but this is not a complete graph proof
|
||||
and does not establish reuse. Root must distinguish the actual two-directory
|
||||
analysis/payload execution/input closure from this snapshot roster and apply
|
||||
all commander conditions. If any condition fails, rerun complete_B once.
|
||||
No R49 closure bytes or raw evidence were rewritten to obtain reuse.
|
||||
|
||||
Then preserve the recorded Root order: pure controls → clean exact-Q check-only
|
||||
→ capacity/PID confirmation → fresh native6 → reader/collector → all eight
|
||||
full exact-source reuse conditions (failure means one full run) → index → one
|
||||
registered p04-acceptance validation → independent whole-unit review → normal
|
||||
gates/RootDB join/ledger/main push. Only whole-unit acceptance awards credit.
|
||||
+9
-2
@@ -30,8 +30,15 @@ def rejects(call):
|
||||
|
||||
|
||||
def tree(root):
|
||||
return {p.relative_to(root).as_posix(): hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
for p in root.rglob('*') if p.is_file()}
|
||||
rows = {}
|
||||
for p in root.rglob('*'):
|
||||
if p.is_file():
|
||||
digest = hashlib.sha256()
|
||||
with p.open('rb') as source:
|
||||
for chunk in iter(lambda: source.read(1024 * 1024), b''):
|
||||
digest.update(chunk)
|
||||
rows[p.relative_to(root).as_posix()] = digest.hexdigest()
|
||||
return rows
|
||||
|
||||
|
||||
# Explicit audited package-local closure; see REPAIR49_STATUS.md.
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Root-only engine-free whole-read/stream SHA equivalence controls."""
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
|
||||
def main():
|
||||
started = time.monotonic()
|
||||
path = Path(__file__).with_name('repair48_identity_controls.py')
|
||||
spec = importlib.util.spec_from_file_location('r50_identity', path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
exec(compile(path.read_bytes(), str(path), 'exec'), module.__dict__)
|
||||
chunk = 1024 * 1024 # Implementation boundary, never an acceptance limit.
|
||||
with tempfile.TemporaryDirectory(prefix='p04-r50-stream-') as directory:
|
||||
root = Path(directory)
|
||||
(root / 'empty').write_bytes(b'')
|
||||
(root / '日本語🌳').write_bytes('木と水\n🌳'.encode())
|
||||
(root / 'binary').write_bytes(bytes(range(256)) * 5)
|
||||
for size in (chunk - 1, chunk, chunk + 1, chunk * 3 + 17):
|
||||
(root / str(size)).write_bytes((bytes(range(256)) * (size // 256 + 1))[:size])
|
||||
with (root / 'sparse').open('wb') as stream:
|
||||
stream.seek(chunk * 4 + 3)
|
||||
stream.write(b'\xff')
|
||||
nested = root / 'nested'
|
||||
nested.mkdir()
|
||||
(nested / '全bytes').write_bytes(b'\x00\xff\x80\n')
|
||||
whole = {p.relative_to(root).as_posix(): hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
for p in root.rglob('*') if p.is_file()}
|
||||
streamed = module.tree(root)
|
||||
assert list(streamed) == list(whole), 'same traversal/key insertion order'
|
||||
assert streamed == whole, 'complete SHA map equality'
|
||||
print(json.dumps({'stream_equivalence': 'pass', 'files': whole,
|
||||
'elapsed': time.monotonic() - started, 'formal_acceptance': False}, sort_keys=True))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -359,3 +359,25 @@ Runtime helper fingerprints and source/provenance guards bind the actual Q.
|
||||
No full regression, 15+EV batch or original credit is claimed. The S5
|
||||
destruction/midnight/exit drivers, S1–S4/collector fresh Q, derived 184 suites /
|
||||
329 parse, truthful index and Root exact-candidate qualification remain pending.
|
||||
|
||||
## REPAIR50 preparation (2026-10-18)
|
||||
|
||||
Commander-reported prior observation: all-equal array reversal produced
|
||||
identical bytes (raw SHA prefix `bb0ccb1d…`), correctly accepted by the oracle;
|
||||
the old control incorrectly required reject. Reported elapsed: 761.085 seconds.
|
||||
This worker has not rerun that observation and does not supply a full SHA
|
||||
from the abbreviated handoff. Earlier failure records are preserved.
|
||||
|
||||
The order control now records identity accept separately, swaps unequal typed
|
||||
bytes, lists no-genuine-order cases, avoids duplicate parsing of the uncopied
|
||||
record and memoizes only genuine BEFORE/command/guard derivations under strict
|
||||
source-bound keys with finally restoration. Both copied modes and all
|
||||
AFTER/journal/body traversal remain. Negative rejection is still ValueError;
|
||||
parser rejection is separately visible. Synthetic equal-array, swap, type,
|
||||
value, AFTER-copy and memo controls are prepared in --pure-only.
|
||||
|
||||
repair48_identity_controls.tree now hashes fixed-size chunks; its roster and
|
||||
all other fixture logic remain unchanged. Root must run the new
|
||||
repair50_stream_controls.py equivalence control. Only AST parse was performed
|
||||
by this worker. No pure/native/formal pass, reuse approval or credit is claimed.
|
||||
See ../REPAIR50_STATUS.md before running the existing Root sequence.
|
||||
|
||||
+176
-15
@@ -1,10 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Root-only typed mutations against fresh native S5 raw; never synthetic positives."""
|
||||
import argparse
|
||||
from contextlib import contextmanager
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import struct
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
import s5_order_adapter as a
|
||||
@@ -13,6 +16,70 @@ mutation = a.module('order_typed_mutation', Path(__file__).with_name('s5_power_a
|
||||
BUILD = Path('/Users/korizatou114/Projects/TheTree-managed-worktrees/p04-01/.runtime/P04-01/build')
|
||||
|
||||
|
||||
def order_variant(node):
|
||||
"""Swap the first unequal typed byte pair, preserving the header."""
|
||||
rows = [r.raw if node.kind == 28 else r[0].raw + r[1].raw for r in node.value]
|
||||
for i in range(len(rows)):
|
||||
for j in range(i + 1, len(rows)):
|
||||
if rows[i] != rows[j]:
|
||||
header = len(node.raw) - sum(map(len, rows))
|
||||
rows[i], rows[j] = rows[j], rows[i]
|
||||
return node.raw[:header] + b''.join(rows)
|
||||
return None
|
||||
|
||||
|
||||
def static_estimate(record):
|
||||
kinds, nodes, candidates = {}, 0, 0
|
||||
|
||||
def visit(node):
|
||||
nonlocal nodes, candidates
|
||||
nodes += 1
|
||||
kinds[str(node.kind)] = kinds.get(str(node.kind), 0) + 1
|
||||
candidates += (2 if node.kind in (4, 21, 2) else 1 if node.kind == 1 else
|
||||
int(bool(node.value)) + int(len(node.value) > 1) if node.kind == 28 else
|
||||
int(len(node.value) > 1) if node.kind == 27 else 0)
|
||||
if node.kind == 28:
|
||||
for child in node.value:
|
||||
visit(child)
|
||||
elif node.kind == 27:
|
||||
for key, child in node.value:
|
||||
visit(key)
|
||||
visit(child)
|
||||
visit(record.at('after'))
|
||||
return {'record_bytes': len(record.raw), 'after_nodes': nodes, 'kind_counts': kinds,
|
||||
'candidate_count': candidates, 'verify_mutations': candidates * 2,
|
||||
'disk_mutation_bytes': 0,
|
||||
'memory_model': 'O(record_bytes * (mutated_kinds + 2) + after_nodes + output_labels); parser overhead unmeasured',
|
||||
'time_model': 'O(verify_mutations * record_bytes); calibrate with --pure-only; not a measured ETA'}
|
||||
|
||||
|
||||
@contextmanager
|
||||
def expected_memo(stats, guard_raw):
|
||||
oracle = a.guard_oracle
|
||||
original = oracle.expected
|
||||
sources = tuple(hashlib.sha256(Path(m.__file__).read_bytes()).digest()
|
||||
for m in (oracle, a.series))
|
||||
cache = {}
|
||||
|
||||
def wrapped(before, command, guard, parse, require):
|
||||
require(parse(guard_raw).value == guard, 'memo exact guard binding')
|
||||
blobs = (before.raw, command.raw, guard_raw)
|
||||
key = (tuple((len(b), hashlib.sha256(b).digest()) for b in blobs), sources)
|
||||
if key not in cache:
|
||||
stats['miss'] += 1
|
||||
tree, result = original(before, command, guard, parse, require)
|
||||
cache[key] = (tree.raw, result.raw)
|
||||
else:
|
||||
stats['hit'] += 1
|
||||
return tuple(parse(b) for b in cache[key])
|
||||
|
||||
oracle.expected = wrapped
|
||||
try:
|
||||
yield original
|
||||
finally:
|
||||
oracle.expected = original
|
||||
|
||||
|
||||
def guard_mutations(record):
|
||||
"""All typed AFTER nodes are tested, including every changed journal field.
|
||||
|
||||
@@ -20,11 +87,20 @@ def guard_mutations(record):
|
||||
must still reject it. No native evidence is produced by these controls.
|
||||
"""
|
||||
oracle = a.guard_oracle
|
||||
estimate = static_estimate(record)
|
||||
a.require(oracle.verify(record, a.series.variant, a.require), 'guard control prerequisite')
|
||||
checks = []
|
||||
started = time.monotonic()
|
||||
checks, identities, no_order = [], [], []
|
||||
stats = {'hit': 0, 'miss': 0}
|
||||
kinds, nodes, candidates = {}, 0, 0
|
||||
representatives, first_last = {}, []
|
||||
parser_rejections = []
|
||||
after = record.at('after')
|
||||
|
||||
def visit(node, path):
|
||||
nonlocal nodes, candidates
|
||||
nodes += 1
|
||||
kinds[str(node.kind)] = kinds.get(str(node.kind), 0) + 1
|
||||
replacements = []
|
||||
if node.kind in (4, 21):
|
||||
replacements = [('value', oracle.atom(node.kind, node.value + '.mutated')),
|
||||
@@ -40,30 +116,101 @@ def guard_mutations(record):
|
||||
replacements.append(('extra-row', node.raw[:start-4] + struct.pack('<I', len(node.value)+1)
|
||||
+ node.raw[start:] + node.value[-1].raw))
|
||||
if len(node.value) > 1:
|
||||
replacements.append(('unsorted', node.raw[:start] + b''.join(r.raw for r in reversed(node.value))))
|
||||
encoded = order_variant(node)
|
||||
if encoded is None:
|
||||
no_order.append(path + ':order-no-genuine-variant')
|
||||
replacements.append(('identity-order' if encoded is None else 'unsorted',
|
||||
node.raw if encoded is None else encoded))
|
||||
for i, child in enumerate(node.value):
|
||||
visit(child, path + '/' + str(i))
|
||||
elif node.kind == 27:
|
||||
if len(node.value) > 1:
|
||||
replacements.append(('unsorted', oracle.dictionary([(k.raw, v.raw) for k, v in reversed(node.value)])))
|
||||
encoded = order_variant(node)
|
||||
if encoded is None:
|
||||
no_order.append(path + ':order-no-genuine-variant')
|
||||
replacements.append(('identity-order' if encoded is None else 'unsorted',
|
||||
node.raw if encoded is None else encoded))
|
||||
for key, child in node.value:
|
||||
visit(key, path + '/key:' + str(key.value))
|
||||
visit(child, path + '/' + str(key.value))
|
||||
for label, encoded in replacements:
|
||||
candidates += 1
|
||||
identity = encoded == node.raw
|
||||
changed_after = mutation.replace(after, node, encoded)
|
||||
changed_bytes = mutation.replace(record, after, changed_after)
|
||||
try:
|
||||
changed = a.series.variant(changed_bytes)
|
||||
except ValueError:
|
||||
if identity:
|
||||
raise
|
||||
changed = None
|
||||
for copied in (False, True):
|
||||
changed_record = mutation.replace(record, after, changed_after)
|
||||
name = path + ':' + label + (':AFTER-copy' if copied else '')
|
||||
# Copy even malformed typed AFTER bytes into EXPECTED, without
|
||||
# parsing the invalid intermediate record a second time.
|
||||
copied_bytes = (record.raw[:8] + b''.join(
|
||||
k.raw + (changed_after if v is after or v is record.at('expected') else v.raw)
|
||||
for k, v in record.value)) if copied else None
|
||||
try:
|
||||
changed = a.series.variant(changed_record)
|
||||
if copied:
|
||||
changed_record = mutation.replace(changed, changed.at('expected'), changed_after)
|
||||
oracle.verify(a.series.variant(changed_record), a.series.variant, a.require)
|
||||
tested = a.series.variant(copied_bytes) if copied else changed
|
||||
except ValueError:
|
||||
checks.append(path + ':' + label + (':AFTER-copy' if copied else ''))
|
||||
continue
|
||||
raise ValueError('guard mutation accepted: ' + path + ':' + label)
|
||||
visit(after, 'after')
|
||||
return checks
|
||||
if identity:
|
||||
raise
|
||||
tested = None
|
||||
if tested is None:
|
||||
checks.append(name)
|
||||
parser_rejections.append(name)
|
||||
# Derivation inputs remain the original record's inputs.
|
||||
tested = record
|
||||
elif identity:
|
||||
a.require(oracle.verify(tested, a.series.variant, a.require), 'identity accepted')
|
||||
identities.append(name)
|
||||
else:
|
||||
try:
|
||||
oracle.verify(tested, a.series.variant, a.require)
|
||||
except ValueError:
|
||||
checks.append(name)
|
||||
else:
|
||||
raise ValueError('guard mutation accepted: ' + name)
|
||||
representatives.setdefault(node.kind, tested)
|
||||
first_last[:] = [first_last[0] if first_last else tested, tested]
|
||||
original = oracle.expected
|
||||
with expected_memo(stats, record.at('guard').raw) as derive:
|
||||
visit(after, 'after')
|
||||
for tested in first_last + list(representatives.values()):
|
||||
args = (tested.at('before'), tested.at('command'), tested.at('guard').value,
|
||||
a.series.variant, a.require)
|
||||
hit, plain = oracle.expected(*args), derive(*args)
|
||||
a.require(tuple(n.raw for n in hit) == tuple(n.raw for n in plain), 'memo bytes')
|
||||
before = record.at('before')
|
||||
target = before.at('systems').at('runtime').at('next_command_id')
|
||||
bad = bytearray(target.raw)
|
||||
bad[4] ^= 1
|
||||
changed_before = a.series.variant(mutation.replace(before, target, bytes(bad)))
|
||||
changed_record = a.series.variant(mutation.replace(record, before, changed_before.raw))
|
||||
misses = stats['miss']
|
||||
try:
|
||||
oracle.verify(changed_record, a.series.variant, a.require)
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
raise ValueError('one-byte BEFORE mutation accepted')
|
||||
a.require(stats['miss'] == misses + 1, 'one-byte BEFORE cache miss')
|
||||
a.require(oracle.expected is original, 'memo wrapper restored')
|
||||
try:
|
||||
with expected_memo({'hit': 0, 'miss': 0}, record.at('guard').raw):
|
||||
raise ValueError('cleanup sentinel')
|
||||
except ValueError:
|
||||
pass
|
||||
a.require(oracle.expected is original, 'exceptional memo wrapper restored')
|
||||
a.require(estimate['verify_mutations'] == candidates * 2 and estimate['after_nodes'] == nodes
|
||||
and estimate['kind_counts'] == kinds, 'static enumeration agrees')
|
||||
return {'negative_controls': checks, 'negative_count': len(checks),
|
||||
'identity_positive_count': len(identities), 'identity_positive_list': identities,
|
||||
'no_genuine_order_variant': no_order, 'memo': stats,
|
||||
'parser_rejections': parser_rejections,
|
||||
'elapsed': time.monotonic() - started,
|
||||
'static_estimate': estimate}
|
||||
|
||||
|
||||
def pure_controls():
|
||||
@@ -82,7 +229,9 @@ def pure_controls():
|
||||
('id_generator', d([('version', atom(2, 1)), ('counters', d([('domain_event', atom(2, 2))]))])),
|
||||
('domain_events', d([('version', atom(2, 1)), ('published_ids', arr([atom(4, 'domain_event.000000000001'), atom(4, 'domain_event.000000000002')], 4)), ('recent_events', arr([], 27))])),
|
||||
('operations', d([('enabled', atom(1, 0))])),
|
||||
('business', d([('wallet', atom(2, 100)), ('reservations', arr([], 27))]))])
|
||||
('business', d([('wallet', atom(2, 100)), ('reservations', arr([], 27)),
|
||||
('equal_array', arr([atom(2, 0)] * 3, 2)),
|
||||
('swap_array', arr([atom(2, 1), atom(2, 2)], 2))]))])
|
||||
before = a.series.variant(d([('systems', d([('runtime', runtime)]))]))
|
||||
results = {}
|
||||
for guard in ('G1', 'G2'):
|
||||
@@ -102,17 +251,25 @@ def pure_controls():
|
||||
record = a.series.variant(d([('before', before.raw), ('command', command.raw), ('guard', atom(4, guard)),
|
||||
('expected', expected.raw), ('after', expected.raw), ('result', result.raw)]))
|
||||
results[guard] = guard_mutations(record)
|
||||
report = results[guard]
|
||||
a.require(any('equal_array:identity-order' in x for x in report['identity_positive_list']), 'equal array positive')
|
||||
for label in ('swap_array:unsorted', 'wallet:value', 'wallet:int-float', 'wallet:value:AFTER-copy'):
|
||||
a.require(any(label in x for x in report['negative_controls']), 'synthetic coverage: ' + label)
|
||||
return {'synthetic_serializer_controls_only': True, 'negative_controls': results, 'formal_acceptance': False}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--pure-only', action='store_true')
|
||||
parser.add_argument('--estimate-record', type=Path, help='parse one guard record and print static estimate only')
|
||||
parser.add_argument('--raw-root', type=Path)
|
||||
parser.add_argument('--writer-sha256')
|
||||
parser.add_argument('--reader-sha256')
|
||||
parser.add_argument('--scratch', type=Path)
|
||||
args = parser.parse_args()
|
||||
if args.estimate_record:
|
||||
print(json.dumps(static_estimate(a.series.variant(args.estimate_record.read_bytes())), sort_keys=True))
|
||||
return
|
||||
if args.pure_only:
|
||||
print(json.dumps(pure_controls(), sort_keys=True))
|
||||
return
|
||||
@@ -133,6 +290,7 @@ def main():
|
||||
cases[case] = ({k: raw.typed(v) for k, v in branch['points'].items()},
|
||||
[raw.typed(r) for r in branch['phases']])
|
||||
checks = []
|
||||
guard_reports = {}
|
||||
|
||||
def negative(label, case, owner, target, replacement):
|
||||
points, phases = cases[case]
|
||||
@@ -202,7 +360,9 @@ def main():
|
||||
for case in ('S5D_DESTRUCTION_RAID', 'S5D_IN_FLIGHT'):
|
||||
branch = raw.reference(writer['branches'][case])
|
||||
for label, reference in branch['guards'].items():
|
||||
checks.extend(label + ':' + name for name in guard_mutations(raw.typed(reference)))
|
||||
report = guard_mutations(raw.typed(reference))
|
||||
guard_reports[case + ':' + label] = report
|
||||
checks.extend(label + ':' + name for name in report['negative_controls'])
|
||||
command = 'S5C_DESTRUCTION_COMMAND'
|
||||
points, phases = cases[command]
|
||||
end = points['held']
|
||||
@@ -251,6 +411,7 @@ def main():
|
||||
start = 12 if ledger.raw[:4] == struct.pack('<I', 65564) else 8
|
||||
negative('replay-extra-row', midnight, replay, ledger, ledger.raw[:start-4] + struct.pack('<I', len(ledger.value)+1) + ledger.raw[start:] + ledger.value[-1].raw)
|
||||
print(json.dumps({'positive_cases': list(positive['cases']), 'negative_controls': checks,
|
||||
'negative_count': len(checks), 'guard_reports': guard_reports,
|
||||
'formal_acceptance': False}, sort_keys=True))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user