diff --git a/research/scalar-audit-identity-gap/README.md b/research/scalar-audit-identity-gap/README.md new file mode 100644 index 0000000000..87f56d3dad --- /dev/null +++ b/research/scalar-audit-identity-gap/README.md @@ -0,0 +1,96 @@ +# The selected artifact identity drops the scalar-frame audit + +**Audit of one comparison. No new κ, no supplier edit, no selected-frontier change.** + +`research/complex-sw4-frame8/code/generated_identity.py` is the selected +generated-artifact identity (Git blob `c8af22719c0f3097a991a3f6ccac8f090afd2faba554745733d9ea88f2c25708`, +the same bytes as the historical owner-repair copy). Its docstring says gzip +identity is the decompressed payload and that JSON identity keeps every field +except the root `seconds` value of `CLIFFORD-REVIEW.json`. The function's +`FILES` tuple never names `SCALAR-FRAME-AUDIT.json`. + +On the committed #626 provider directories `ck` and `jp8`, that receipt still +holds a non-timing scalar-operation count. The count is not stored under that +key in the seven files the identity reads. Adding one to it changes the audit +file's SHA-256 and leaves every returned identity equal to the untouched +directory. The same invisibility holds for a `seconds` edit of that receipt. +A `frames` edit of `CLIFFORD-REVIEW.json` changes only that file's identity, +and deleting `CANONICAL-WORD.json.gz` is rejected. Phase `seconds` stays +excluded, which is the exclusion the identity actually implements. + +`local_rank_mass` on these two receipts equals the weighted sum of +`local_profile`, so that integer is redundant with the profile. The profile +itself is also outside this identity map. This package's executed witness is +`scalar_operations`, because that key does not occur in the seven hashed files. + +## Reproduce + +From the repository root, with `PYTHONOPTIMIZE` unset: + +```sh +python3 -B research/scalar-audit-identity-gap/verify.py +python3 scripts/research_package.py --package research/scalar-audit-identity-gap +``` + +Expected last line: + +```text +PASS_SCALAR_AUDIT_IDENTITY_GAP providers=2 omitted_non_timing_fields=22 +``` + +Observed environment: Linux, CPython 3.12.3, `PYTHONOPTIMIZE` unset, +g++ 13.3.0 and Boost 1.83 headers present and unused by this standard-library +check. The command copies the two provider +directories into temporary directories, mutates the copies, and deletes them. +It does not rewrite committed bytes and it does not run `make frontier1094-verify` +or `make frontier626-verify`. + +## What this does not show + +The invoice artifact map still stores a whole-file SHA-256 of +`SCALAR-FRAME-AUDIT.json`. A checker that requires that raw digest sees the +scalar-count edit, and it also sees a timing edit, because `seconds` is inside +the same file. This audit does not say the selected replay accepts a wrong +scalar count. It says the portable identity named above cannot see one. + +Rohan Guliani's hash-substitution note +(`research/pr695-digest-audit`) and the frontier #799 review already record +that a non-timing edit of this file can follow a whole-file digest through +that substitution. The preserved #806 control adds a synthetic key. Adam Gall's +PR #1912 audits the seven files inside this same identity and finds that only +root phase `seconds` is dropped from those trees. That census does not open +`SCALAR-FRAME-AUDIT.json`. This package names the committed fields of that +sibling receipt and checks the selected identity on the committed `ck` and +`jp8` directories. It does not reproduce the historical CI payloads from run +38317651752, and it does not decide whether those missing payloads differed +only in timing. + +The ancestral SW4 linker in `research/complex-sw4-frame8/verify.py` compares +this receipt after removing only `seconds`. That comparison would see +`scalar_operations`. The identity function audited here does not. + +## Open next questions + +`WRAPPER-CHECKS.json` is in the #626 invoice artifact map and is also absent +from `artifact_identities`. Its committed `ck` object carries +`hyperplane_end_pairs` and `cold_hyperplane_end_pairs`. The same one-field +mutation used here would tell whether those fields are invisible to the +identity. This package stops after the scalar-frame receipt. Adopting a +seconds-stripped digest of either file into the selected identity would change +pinned semantic hashes, so that adoption is a separate supplier change. + +## Credit + +The identity and the #626 provider receipts are the selected-source and +owner-repair lineage (Douglas Colkitt, Chafik Boukhalfa, and the predecessors +credited in the selected review). Joshua Snider preserved the three omitted +#626 assembly digests. Rohan Guliani traced their whole-file propagation. +Maxime Fleury and Antoine Olivier recorded the payload-versus-container +convention used to choose this comparison. + +Prepared by hevlyo with substantial AI assistance. Apache-2.0. This is not +independent human peer review and not a multiplication theorem. + +A finding post to the CrocSwap discussion board was refused with +`Resource not accessible by integration`. That refusal is recorded here and +was not retried. diff --git a/research/scalar-audit-identity-gap/SOURCES.json b/research/scalar-audit-identity-gap/SOURCES.json new file mode 100644 index 0000000000..e5552e3769 --- /dev/null +++ b/research/scalar-audit-identity-gap/SOURCES.json @@ -0,0 +1,120 @@ +{ + "schema_version": 1, + "base_commit": "ef5f39403610d231a0c27e8a6b4f08c10209bcd6", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "ae6a99f28aa468649eb66a361e764d769363bf11", + "sha256": "10b9e340fd8e354a37a0c4813c90e5de1dd42044b5f6aca4a3fc5a42b685fa32" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "c05fafaa25ba95b2d5af86b1800427198e3d20eb", + "sha256": "89b5928bc92c81e2647b6d702a7ad85a6795b8f44e2eb267b2ff3145d8f2b2ce" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/CANONICAL-WORD.json.gz", + "usage": "input", + "git_blob": "58cd1be8f28b74bea83c435eee1f52b36a274281", + "sha256": "ae3018c0646be06f47d345bb8baf0e6ea9220096a949fa30a8f7656aa4ad6f45" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/CLIFFORD-RECIPES.json", + "usage": "input", + "git_blob": "cb967b1c348e25fd622996deb1317c2fb78f93fc", + "sha256": "dfb64e71409a395f9375d9cc2258365d462bab2d28b707dcfba38994dd5aa0b9" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/CLIFFORD-REVIEW.json", + "usage": "input", + "git_blob": "dd1de6ce85bc491905763ddfe695d3537565a835", + "sha256": "35591083acb26fad551358b9fd1efc3a3a825fff02b1b51403bc2b8934b09faf" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/INDEPENDENT-LOCAL-REPLAY.json", + "usage": "input", + "git_blob": "ec8d742c3d932160fac10d0d9befdd2056cb240e", + "sha256": "ecefb9e661301d8081522be68bbe6640e175c011eb1177f643383d193c6fb2f0" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/LOCAL-CHECKS.json", + "usage": "input", + "git_blob": "d2b8854114b19b88e14d2af0dd84ad79e9eedbaa", + "sha256": "059c4e59142bdf5c19dc7c0afebcddfec28e6e60cbc7299b8bdcc624afbc0cbe" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/LOCAL-PROGRAMS.json.gz", + "usage": "input", + "git_blob": "61ef73c1f958e0d26f3e7a3a82bc3826b7098c93", + "sha256": "b5da54e049cc127a1065190a647cb71cac0c6ba03d9ccdb71719f4fcbfa886f3" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/RESIDUAL-ADAPTERS.json", + "usage": "input", + "git_blob": "59803cd4fe44c3f0088b2de9b5e15a9089b221e4", + "sha256": "4697965c1b466fd3eaf37fa1fbbd45bb06c78cb0fe0b3a253744efb4013581b9" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/SCALAR-FRAME-AUDIT.json", + "usage": "input", + "git_blob": "5b7e998f36685c605324625ce888c4376af88b1e", + "sha256": "9a2972bed8a6a66f3716b50a5b325095e86f0904581256ac10127ee672886f61" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/CANONICAL-WORD.json.gz", + "usage": "input", + "git_blob": "7fd7cd1fefbb8b0e12397b355d9f6e227813bd58", + "sha256": "7a3fec1022d3b2b1bd986302a327735ec521d17b043f4a5acb96253a56f6193c" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/CLIFFORD-RECIPES.json", + "usage": "input", + "git_blob": "3b03cb85329f614f324de1c4b56ac99b2de0c2cb", + "sha256": "2799d73dd08c4435e5900ff2ae6ebc7f34535c153e173ab88d66d1f0b5e6dcde" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/CLIFFORD-REVIEW.json", + "usage": "input", + "git_blob": "5b647d19c19e1731d4116ba6998af4d291853645", + "sha256": "c134b7ce364791051d755c4d91e1c594215302b3ebffb807fdb41aff325f97a1" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/INDEPENDENT-LOCAL-REPLAY.json", + "usage": "input", + "git_blob": "19a4edfa2091d4cf38db49d7a780d29232badb49", + "sha256": "cb2f99ed351925dd35434b73de16f4085884fe81a35a69e1c7ce2d5e96cb975b" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/LOCAL-CHECKS.json", + "usage": "input", + "git_blob": "0d84d903086993330ddcd871e66b15854f0c3ccd", + "sha256": "0fad744aa863eedb288a9f87b1c23225a36b316b6275cc3b1bcedd42afe28a67" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/LOCAL-PROGRAMS.json.gz", + "usage": "input", + "git_blob": "e22169a1633638213a5c63425a1919c7185f4c43", + "sha256": "fa0c196f65bd6ec1424fdf7d789f6972075c7bb02bf43f573ea85eafab31be98" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/RESIDUAL-ADAPTERS.json", + "usage": "input", + "git_blob": "0b49f9749b7f8d945342f90e2880f0b6d4689542", + "sha256": "bdb44cf523636f307ebb3617da548f2e3a8af74321eabe24aef40186e280a917" + }, + { + "path": "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/SCALAR-FRAME-AUDIT.json", + "usage": "input", + "git_blob": "098ef1ac708e7e23aceb5545d836637428c44ccd", + "sha256": "3ff147ad8378bc356970868c69b422febfcbe018515a2d8de5db59581f1b614e" + }, + { + "path": "research/complex-sw4-frame8/code/generated_identity.py", + "usage": "input", + "git_blob": "74a9b604793f21a9f064c78874341e287ded7a68", + "sha256": "c8af22719c0f3097a991a3f6ccac8f090afd2faba554745733d9ea88f2c25708" + } + ] +} diff --git a/research/scalar-audit-identity-gap/TASK.json b/research/scalar-audit-identity-gap/TASK.json new file mode 100644 index 0000000000..fc10934a33 --- /dev/null +++ b/research/scalar-audit-identity-gap/TASK.json @@ -0,0 +1,60 @@ +{ + "schema_version": 1, + "task_id": "portable-replay", + "priority_revision": 2, + "base_commit": "ef5f39403610d231a0c27e8a6b4f08c10209bcd6", + "original_card": { + "id": "portable-replay", + "question": "Can one reproducible environment or artifact-comparison failure be repaired?", + "starting_points": [ + "research/gzip-container-reproducibility/README.md", + "docs/ci-verification.md" + ], + "methods": [ + "Reproduce one portability failure and add a minimal cross-environment fix.", + "Audit one canonical-payload comparison for omitted proof-relevant fields." + ], + "acceptance_gate": "Preserve immutable source hashes and proof-relevant content; a different compressed byte stream alone is not a mathematical mismatch.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Read the gzip-container reproducibility examples and distinguish frozen source bytes from regenerated payloads.", + "scope": "Positive control / source-bound orientation only; this is not a new construction or full cold replay." + }, + "first_experiment": "Reproduce one specific mismatch or audit one canonical comparison for omitted proof-relevant fields.", + "bottleneck_link": "Portable exact checks prevent environment failures from blocking valid contributions.", + "allowed_variations": [ + "One interpreter/version mismatch or one payload field comparison." + ], + "scope_change_triggers": [ + "Removing immutable-source pins because generated compressed bytes differ." + ], + "overlap_terms": [ + "gzip container", + "reproducibility", + "canonical payload" + ] + }, + "scope_status": "refined", + "actual_scope": "On the committed #626 ck and jp8 provider directories, does the selected artifact_identities comparison omit proof-relevant fields of SCALAR-FRAME-AUDIT.json, in particular scalar_operations?", + "scope_change_reason": "The portable-replay card allows one payload-field comparison. This audits that comparison on the selected generated_identity.py blob. It does not repair an interpreter mismatch and it does not edit the identity.", + "bottleneck_link": "Portable exact checks are how a later supplier replay can ignore container and timing bytes without also ignoring a scalar-operation count. This is a verifier gap on the current identity, not a new primitive budget.", + "budget_minutes": 60, + "stop_rule": "Stop after both committed providers, one non-timing scalar-audit field, the declared phase-seconds exclusion, one visible phase field, and one missing-file rejection. Do not rerun a cold supplier replay or edit the identity.", + "outcome": "completed", + "evidence": "python3 -B research/scalar-audit-identity-gap/verify.py prints PASS_SCALAR_AUDIT_IDENTITY_GAP providers=2 omitted_non_timing_fields=22. scalar_operations is absent from the seven identity inputs, and adding one leaves every returned identity unchanged. A CrocSwap discussion post was refused with Resource not accessible by integration and was not retried.", + "author": "hevlyo", + "ai_assistance": "Substantial AI assistance was used to prepare this package. No coding-agent product is named.", + "open_questions": [ + { + "question": "Does a one-field change to hyperplane_end_pairs in the committed ck WRAPPER-CHECKS.json also leave artifact_identities unchanged?", + "why_it_matters": "That file is in the #626 invoice artifact map and outside the same identity tuple, so the scalar-audit gap may not be the only dropped receipt.", + "first_step": "Copy the ck provider directory, increment hyperplane_end_pairs, and compare artifact_identities with the untouched directory.", + "blocked_by": "This package stops at SCALAR-FRAME-AUDIT.json. Putting either receipt into the selected identity would change pinned semantic hashes and is a separate supplier edit." + } + ] +} diff --git a/research/scalar-audit-identity-gap/VERIFY.json b/research/scalar-audit-identity-gap/VERIFY.json new file mode 100644 index 0000000000..7b96e3830d --- /dev/null +++ b/research/scalar-audit-identity-gap/VERIFY.json @@ -0,0 +1,36 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [ + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/CANONICAL-WORD.json.gz", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/CLIFFORD-RECIPES.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/CLIFFORD-REVIEW.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/INDEPENDENT-LOCAL-REPLAY.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/LOCAL-CHECKS.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/LOCAL-PROGRAMS.json.gz", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/RESIDUAL-ADAPTERS.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/ck/SCALAR-FRAME-AUDIT.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/CANONICAL-WORD.json.gz", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/CLIFFORD-RECIPES.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/CLIFFORD-REVIEW.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/INDEPENDENT-LOCAL-REPLAY.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/LOCAL-CHECKS.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/LOCAL-PROGRAMS.json.gz", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/RESIDUAL-ADAPTERS.json", + "research/community-k492-audit/pr626/replay/mixed-global/base/providers/jp8/SCALAR-FRAME-AUDIT.json", + "research/complex-sw4-frame8/code/generated_identity.py" + ], + "commands": [ + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "Both committed providers: scalar_operations is invisible to artifact_identities, phase seconds stays excluded, a phase frame edit is visible, and a missing canonical word is rejected." + } + ] +} diff --git a/research/scalar-audit-identity-gap/verify.py b/research/scalar-audit-identity-gap/verify.py new file mode 100644 index 0000000000..bc6a262097 --- /dev/null +++ b/research/scalar-audit-identity-gap/verify.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +"""Audit one canonical identity for fields it never reads. + +The selected generated-artifact identity hashes seven provider files. It +excludes only the root ``seconds`` field of ``CLIFFORD-REVIEW.json``. The +sibling receipt ``SCALAR-FRAME-AUDIT.json`` is not in that map, so a change +to its scalar-operation count leaves every returned identity unchanged. + +This does not edit the identity, rerun a supplier, or change kappa. +Standard library only. Refuses to run with assertions disabled. +""" +import gzip +import hashlib +import importlib.util +import json +import shutil +import sys +import tempfile +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +IDENTITY_PATH = ROOT / 'research/complex-sw4-frame8/code/generated_identity.py' +REPLAY = ROOT / 'research/community-k492-audit/pr626/replay/mixed-global/base/providers' +PROVIDERS = ('ck', 'jp8') +PROOF_FIELDS = ( + 'scalar_operations', + 'local_profile', + 'local_rank_mass', + 'widths', + 'hyperplane_ended_helpers', + 'canonical_content_sha256', +) + + +def require(ok, message): + if not ok: + raise ValueError(message) + + +def digest(data): + return hashlib.sha256(data).hexdigest() + + +def load_identity(): + spec = importlib.util.spec_from_file_location('selected_generated_identity', IDENTITY_PATH) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def read_json(path): + raw = path.read_bytes() + if path.suffix == '.gz': + raw = gzip.decompress(raw) + return json.loads(raw) + + +def contains_key(value, key): + if isinstance(value, dict): + return key in value or any(contains_key(item, key) for item in value.values()) + if isinstance(value, list): + return any(contains_key(item, key) for item in value) + return False + + +def write_json(path, value): + path.write_text(json.dumps(value, indent=2) + '\n', encoding='utf-8') + + +def copy_provider(source): + temporary = Path(tempfile.mkdtemp(prefix='scalar-audit-identity-')) + destination = temporary / source.name + shutil.copytree(source, destination) + return temporary, destination + + +def identities_of(module, directory): + return module.artifact_identities(directory) + + +def main(): + require(sys.flags.optimize == 0 and __debug__, 'PYTHONOPTIMIZE must be unset so identity assertions stay enabled') + module = load_identity() + require(module.FILES == ( + 'CANONICAL-WORD.json.gz', 'LOCAL-PROGRAMS.json.gz', 'LOCAL-CHECKS.json', + 'INDEPENDENT-LOCAL-REPLAY.json', 'CLIFFORD-RECIPES.json', + 'CLIFFORD-REVIEW.json', 'RESIDUAL-ADAPTERS.json'), + 'Selected identity file list changed') + require('SCALAR-FRAME-AUDIT.json' not in module.FILES, 'Scalar audit unexpectedly entered the identity list') + + reports = [] + for name in PROVIDERS: + directory = REPLAY / name + audit_path = directory / 'SCALAR-FRAME-AUDIT.json' + audit = read_json(audit_path) + require(set(PROOF_FIELDS) <= set(audit) and 'seconds' in audit, name + ' scalar audit is missing a named field') + require(isinstance(audit['scalar_operations'], int), name + ' scalar_operations is not an integer') + mass = sum(int(rank) * count for rank, count in audit['local_profile'].items()) + require(mass == audit['local_rank_mass'], name + ' local_rank_mass is not the profile mass') + for sibling in directory.iterdir(): + if sibling.name == 'SCALAR-FRAME-AUDIT.json' or sibling.suffix not in {'.json', '.gz'}: + continue + require(not contains_key(read_json(sibling), 'scalar_operations'), + name + ' stores scalar_operations outside the scalar audit: ' + sibling.name) + + baseline = identities_of(module, directory) + require(set(baseline) == set(module.FILES), name + ' identity map has unexpected keys') + require('SCALAR-FRAME-AUDIT.json' not in baseline, name + ' identity reads the scalar audit') + + scratch, copied = copy_provider(directory) + try: + changed = read_json(copied / 'SCALAR-FRAME-AUDIT.json') + changed['scalar_operations'] += 1 + write_json(copied / 'SCALAR-FRAME-AUDIT.json', changed) + require(digest((copied / 'SCALAR-FRAME-AUDIT.json').read_bytes()) != digest(audit_path.read_bytes()), + name + ' scalar mutation did not change the file') + require(identities_of(module, copied) == baseline, + name + ' scalar_operations change moved a canonical identity') + finally: + shutil.rmtree(scratch) + + scratch, copied = copy_provider(directory) + try: + changed = read_json(copied / 'SCALAR-FRAME-AUDIT.json') + changed['seconds'] = float(changed['seconds']) + 1.0 + write_json(copied / 'SCALAR-FRAME-AUDIT.json', changed) + require(identities_of(module, copied) == baseline, + name + ' scalar-audit seconds change moved a canonical identity') + finally: + shutil.rmtree(scratch) + + scratch, copied = copy_provider(directory) + try: + phase = read_json(copied / 'CLIFFORD-REVIEW.json') + phase['seconds'] = float(phase['seconds']) + 1.0 + write_json(copied / 'CLIFFORD-REVIEW.json', phase) + require(identities_of(module, copied) == baseline, + name + ' phase seconds change moved a canonical identity') + finally: + shutil.rmtree(scratch) + + scratch, copied = copy_provider(directory) + try: + phase = read_json(copied / 'CLIFFORD-REVIEW.json') + phase['frames'] = int(phase['frames']) + 1 + write_json(copied / 'CLIFFORD-REVIEW.json', phase) + shifted = identities_of(module, copied) + require(shifted['CLIFFORD-REVIEW.json'] != baseline['CLIFFORD-REVIEW.json'], + name + ' phase frame count was invisible') + require(all(shifted[key] == baseline[key] for key in baseline if key != 'CLIFFORD-REVIEW.json'), + name + ' phase frame count moved an unrelated identity') + finally: + shutil.rmtree(scratch) + + scratch, copied = copy_provider(directory) + try: + (copied / 'CANONICAL-WORD.json.gz').unlink() + try: + identities_of(module, copied) + except (AssertionError, FileNotFoundError, OSError): + pass + else: + raise ValueError(name + ' identity accepted a provider with no canonical word') + finally: + shutil.rmtree(scratch) + + omitted = sorted(key for key in audit if key != 'seconds') + reports.append({ + 'provider': name, + 'scalar_operations': audit['scalar_operations'], + 'local_rank_mass': audit['local_rank_mass'], + 'omitted_non_timing_fields': omitted, + 'identity_files': list(module.FILES), + }) + + require(reports[0]['omitted_non_timing_fields'] == reports[1]['omitted_non_timing_fields'], + 'ck and jp8 omit different scalar-audit fields') + report = { + 'status': 'PASS_SCALAR_AUDIT_IDENTITY_GAP', + 'providers': [row['provider'] for row in reports], + 'omitted_non_timing_field_count': len(reports[0]['omitted_non_timing_fields']), + 'omitted_non_timing_fields': reports[0]['omitted_non_timing_fields'], + 'scalar_operations_invisible': True, + 'phase_seconds_excluded': True, + 'phase_frames_visible': True, + 'missing_canonical_word_rejected': True, + 'providers_detail': reports, + } + print(json.dumps(report, indent=2)) + print(report['status'], + 'providers=%d' % len(reports), + 'omitted_non_timing_fields=%d' % report['omitted_non_timing_field_count']) + + +if __name__ == '__main__': + main()