From a8cf650b7435ccea237084e491e339f725c0a35b Mon Sep 17 00:00:00 2001 From: Chris R Date: Mon, 2 Nov 2026 20:08:27 +1100 Subject: [PATCH] Audit V03 parent-domain incompatibility and recover source closure --- .../ARTIFACTS.json | 160 ++ .../INDEPENDENT-REVIEW.json | 20 + .../README.md | 37 + .../SOURCE-FINDINGS.json | 160 ++ .../SOURCE-ORIGIN.json | 71 + .../SOURCES.json | 18 + .../TASK.json | 60 + .../VALIDATION.json | 29 + .../VERIFY.json | 19 + .../evidence/INPUT-PINS.json | 897 ++++++++ .../evidence/PACKAGE-METADATA-FAILURE-v1.json | 18 + .../evidence/PACKAGE-METADATA-FAILURE-v2.json | 18 + .../evidence/PACKAGE-METADATA-FAILURE-v3.json | 18 + .../evidence/PARENT-SOURCE-RECOVERY.json | 69 + .../evidence/PR-COVERAGE.json | 309 +++ .../evidence/RECEIVER-SOURCE-MAP.json | 385 ++++ .../evidence/SOURCE-GATE-CLOSE.json | 23 + .../evidence/SOURCE-MANIFEST.json | 183 ++ .../evidence/UNIT-PLAN.json | 20 + .../evidence/initial-copy-name-collision.txt | 158 ++ .../snapshot/epoch_copy_v5.py.txt | 1897 +++++++++++++++++ .../snapshot/epoch_parent_v5.py.txt | 466 ++++ .../snapshot/epoch_schema_v5.py.txt | 676 ++++++ ...gative-epoch-v5--SOURCE-READINESS.json.txt | 153 ++ ...t-completion-v2--SOURCE-READINESS.json.txt | 158 ++ .../snapshot/group01_evidence_v1.py.txt | 256 +++ .../snapshot/h25_parent_supervisor.py.txt | 475 +++++ .../snapshot/native_tcb_v1.py.txt | 202 ++ .../snapshot/parent_closure_v1.py.txt | 270 +++ .../snapshot/parent_completion_v1.py.txt | 880 ++++++++ .../snapshot/parent_domain_v1.py.txt | 450 ++++ .../verify.py | 47 + 32 files changed, 8602 insertions(+) create mode 100644 research/h25-c05-v03-parent-interface-audit/ARTIFACTS.json create mode 100644 research/h25-c05-v03-parent-interface-audit/INDEPENDENT-REVIEW.json create mode 100644 research/h25-c05-v03-parent-interface-audit/README.md create mode 100644 research/h25-c05-v03-parent-interface-audit/SOURCE-FINDINGS.json create mode 100644 research/h25-c05-v03-parent-interface-audit/SOURCE-ORIGIN.json create mode 100644 research/h25-c05-v03-parent-interface-audit/SOURCES.json create mode 100644 research/h25-c05-v03-parent-interface-audit/TASK.json create mode 100644 research/h25-c05-v03-parent-interface-audit/VALIDATION.json create mode 100644 research/h25-c05-v03-parent-interface-audit/VERIFY.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/INPUT-PINS.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v1.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v2.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v3.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/PARENT-SOURCE-RECOVERY.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/PR-COVERAGE.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/RECEIVER-SOURCE-MAP.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/SOURCE-GATE-CLOSE.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/SOURCE-MANIFEST.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/UNIT-PLAN.json create mode 100644 research/h25-c05-v03-parent-interface-audit/evidence/initial-copy-name-collision.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/epoch_copy_v5.py.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/epoch_parent_v5.py.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/epoch_schema_v5.py.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/field-negative-epoch-v5--SOURCE-READINESS.json.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/field-parent-completion-v2--SOURCE-READINESS.json.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/group01_evidence_v1.py.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/h25_parent_supervisor.py.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/native_tcb_v1.py.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/parent_closure_v1.py.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/parent_completion_v1.py.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/snapshot/parent_domain_v1.py.txt create mode 100644 research/h25-c05-v03-parent-interface-audit/verify.py diff --git a/research/h25-c05-v03-parent-interface-audit/ARTIFACTS.json b/research/h25-c05-v03-parent-interface-audit/ARTIFACTS.json new file mode 100644 index 0000000000..dfbd8b4e3e --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/ARTIFACTS.json @@ -0,0 +1,160 @@ +{ + "schema": "source-archive-exact-bytes-v1", + "files": [ + { + "path": "INDEPENDENT-REVIEW.json", + "bytes": 937, + "sha256": "20bbf9fd7812a0ebe84ffb95fc82fdaefb5450f752c7dba6ac43ba52957bc749" + }, + { + "path": "README.md", + "bytes": 6595, + "sha256": "b86b6b59e5961ec44a6617091869be386e9809b2b5f3b756835ec6ca6cf2934f" + }, + { + "path": "SOURCE-FINDINGS.json", + "bytes": 4930, + "sha256": "8156af0a05e1354f65061dd97704dd749a8387b825798ddf089235980b3b26bc" + }, + { + "path": "SOURCE-ORIGIN.json", + "bytes": 3468, + "sha256": "311faf6bedf41c5cb7ebf965029bd2c999963d68a800af760fc5b9b9a617ae56" + }, + { + "path": "SOURCES.json", + "bytes": 584, + "sha256": "911ffe8b456c49ccd19ee42c8e21b226a56dacba515e857300aa28cc1db87be7" + }, + { + "path": "TASK.json", + "bytes": 4079, + "sha256": "fcfc16a88d6b663f139c6cbe62a3d056c957c373c95a8878532f5c7a6f6c7407" + }, + { + "path": "VALIDATION.json", + "bytes": 1005, + "sha256": "8e766f0dcaa9e8ccb6734eecf849d3770c1b726679804d8165bfcdaa463995c4" + }, + { + "path": "VERIFY.json", + "bytes": 394, + "sha256": "678f6e84b7f6975f8d32d72a8f98075c95e226b03229a3c7990555ca99e8ca52" + }, + { + "path": "evidence/INPUT-PINS.json", + "bytes": 48454, + "sha256": "c8dc314f3330819c4d9cb8183532f4f5d90f2a1229a4b1202d2ccba6dac0ee33" + }, + { + "path": "evidence/PACKAGE-METADATA-FAILURE-v1.json", + "bytes": 611, + "sha256": "489cce094e2c2108d8944f19399bf567cb5a9dde99614fea3ddcd132c099bb35" + }, + { + "path": "evidence/PACKAGE-METADATA-FAILURE-v2.json", + "bytes": 597, + "sha256": "82861b9cbc8c87896672dfa2c2517b35defa249e69452aba72523a4f172e4d22" + }, + { + "path": "evidence/PACKAGE-METADATA-FAILURE-v3.json", + "bytes": 484, + "sha256": "d57d69b3c5cf9fab3fdf78f39f0ff54f1c9795a8d859cdff0faef9a5705fda4e" + }, + { + "path": "evidence/PARENT-SOURCE-RECOVERY.json", + "bytes": 3292, + "sha256": "539937886f7b74cff4f3369050b33e0061004b70abdf01c7f75850110a195835" + }, + { + "path": "evidence/PR-COVERAGE.json", + "bytes": 11316, + "sha256": "752e6f03be4566548793a830f7322eaa58d6ca72d94d65026ea84cd93d269031" + }, + { + "path": "evidence/RECEIVER-SOURCE-MAP.json", + "bytes": 20868, + "sha256": "532733f4d78fc327f00851f33e1db20ae8ef34fd904fc56327d44a4ebea11067" + }, + { + "path": "evidence/SOURCE-GATE-CLOSE.json", + "bytes": 1279, + "sha256": "3abffbf85adae35018eab393d403493990640df862752e730445944d7764368a" + }, + { + "path": "evidence/SOURCE-MANIFEST.json", + "bytes": 5849, + "sha256": "574d9b20f139847728be65d8aec10c375b866b51f32e20dfdd603804c2d34c42" + }, + { + "path": "evidence/UNIT-PLAN.json", + "bytes": 1541, + "sha256": "dadd09d1e34e07e2f69574c159db01668d01bf79dd53844a0c67ba9f0cc928d9" + }, + { + "path": "evidence/initial-copy-name-collision.txt", + "bytes": 6046, + "sha256": "5c5b3509ec8eff3fe2e8fe5e7b1e95c7790a964fb0fe401ed5c0049d88ea6520" + }, + { + "path": "snapshot/epoch_copy_v5.py.txt", + "bytes": 82957, + "sha256": "4f459d0336d59975df787c24373e18dad4044c3a24137392e890115f811b3211" + }, + { + "path": "snapshot/epoch_parent_v5.py.txt", + "bytes": 26833, + "sha256": "058059912144863a4b2bfe4fc9ffc5233b4ab20ee5a7355bde66f4d3f6f28712" + }, + { + "path": "snapshot/epoch_schema_v5.py.txt", + "bytes": 30668, + "sha256": "b89a789654be87bde40a47300f4d9702dce2b90e6ab3be9a2025f6d8041b3e9a" + }, + { + "path": "snapshot/field-negative-epoch-v5--SOURCE-READINESS.json.txt", + "bytes": 6055, + "sha256": "611a9dff18b50442fe61702655180d69790746dc3c8154b9ff25098c5c5c6714" + }, + { + "path": "snapshot/field-parent-completion-v2--SOURCE-READINESS.json.txt", + "bytes": 6046, + "sha256": "5c5b3509ec8eff3fe2e8fe5e7b1e95c7790a964fb0fe401ed5c0049d88ea6520" + }, + { + "path": "snapshot/group01_evidence_v1.py.txt", + "bytes": 15610, + "sha256": "05ec6a63c57340ba929aea1fab71b096efc143e099346640f6def41310bd3e25" + }, + { + "path": "snapshot/h25_parent_supervisor.py.txt", + "bytes": 23047, + "sha256": "cfb09a18dd10b597cc6d5a8139ee769bef679bc44ae029329755e3d97b055075" + }, + { + "path": "snapshot/native_tcb_v1.py.txt", + "bytes": 11353, + "sha256": "865943df5cfdbf9383362d7fb2b76c6d0fd895cf0a0e20d550a26b579606b5d7" + }, + { + "path": "snapshot/parent_closure_v1.py.txt", + "bytes": 13400, + "sha256": "2d831cff8bd444de2d6941645d571e07618ede404a1f45692b557f61494b334a" + }, + { + "path": "snapshot/parent_completion_v1.py.txt", + "bytes": 54168, + "sha256": "d4ee1b7ce4a42b73261984ffb1b9ceb5bb0165223e04a253588f83b99f6981a5" + }, + { + "path": "snapshot/parent_domain_v1.py.txt", + "bytes": 20456, + "sha256": "9205e14d6661fb5df0597f0ad7b2206006f2d31f01f784805f64c13875663282" + }, + { + "path": "verify.py", + "bytes": 2724, + "sha256": "c3ac137a61e2ee0f8cd31a0789254255732312c77b20afe16efb8c956f468b32" + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/INDEPENDENT-REVIEW.json b/research/h25-c05-v03-parent-interface-audit/INDEPENDENT-REVIEW.json new file mode 100644 index 0000000000..00c294855d --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/INDEPENDENT-REVIEW.json @@ -0,0 +1,20 @@ +{ + "reviewer": "v03_source_route_review,SolMax", + "scope": "Independent read-only original source/profile/domain/closure findings; not human/kernel/full original qualification", + "original_source_findings_accepted": true, + "publication_export_review": "PASS adjusted source-audit export subject to final manifest regeneration and replay", + "original_modules_imported": false, + "full_C05": false, + "full_V03": false, + "publication_reviewer": "c05_component_review,SolMax", + "corrections": [ + "Restrict mapped-inode scope to declared file-backed executable mappings", + "Restrict deep-mutation claim to captured literal data and preserve gate suffix exemptions" + ], + "source_copies_verified": 11, + "scope_exclusions": [ + "No original runtime/source acceptance or universal Python theorem", + "New PR metadata graph is reporting/provenance, not source-depth acceptance" + ], + "final_manifest_and_replay_by": "root" +} diff --git a/research/h25-c05-v03-parent-interface-audit/README.md b/research/h25-c05-v03-parent-interface-audit/README.md new file mode 100644 index 0000000000..8511eedd9a --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/README.md @@ -0,0 +1,37 @@ +# C05/V03: exact parent, domain and copied-runtime compatibility audit + +The proposed V03 prefix driver is **not a drop-in for the unchanged parent-completion route**. This source audit recovers the missing ordinary parent/domain/closure/epoch/supervisor libraries and records concrete predicates that require an explicit control-only successor. It does not implement or admit that successor, complete C05/V03, run the original modules, or claim a generic impossibility. + +## Exact findings + +The original parent validates the original `variant_driver_v1.py`, its 26-file/two-build evidence contract and producer order. Its completion path requires empty stderr, then the full receiver, then source/stage/closure checks before production completion. A prefix source refusal with a traceback cannot pass that unchanged path. + +The recovered domain adds two further restrictions: `terminal_facts` requires actual returncode zero along with complete owned cleanup, and `create_domain` permits fewer than four existing domains. The proposed 89 DATA cases per profile (178 in total) are not 178 admissible launches in one unchanged parent. No registry reset or cap increase is justified. + +The receiver closure captures namespace size, bindings and literal data, with a source-fixed mutable-registry allowlist. Adding prefix functions after capture or mutating an unlisted control registry captured as literal data violates those checks. A successor must define/capture its complete namespace and preserve all original production checks. + +The copied filesystem is only conditionally compatible. The native TCB compares every declared file-backed executable mapping's device/inode with the actual opened pathname. Pivoting an already running host-mapped process and hashing new copied inodes is insufficient. A fresh interpreter/loader exec inside the copied view is required, with genuine proc and exact original paths, before actual Root launch. This is a necessary source condition, not an executed namespace result. + +The exact supervisor requires the original three system sys.path entries, six-entry environment, interpreter flags and one task. Its subreaper install authenticates fixed native files and uses real same-process prctl with a retained native keeper. No clean executable parent bootstrap was found in the bounded supplied snapshots. The recovered readiness explicitly labels the full orchestrator EXTERNAL_UNIMPLEMENTED; recovering these libraries does not construct it. + +## Source and provenance + +Base `7c49fe32c55de02c2c873655c804b16e4c3fef0a`; canonical investigation [PR6321](https://github.com/CrocSwap/integer-mult-bounds/pull/6321). [PR6352](https://github.com/CrocSwap/integer-mult-bounds/pull/6352) preserves the earlier parent snapshot and entry questions; [PR6362](https://github.com/CrocSwap/integer-mult-bounds/pull/6362), head `120072d58ddb46f0e02886756243174d41fce42e`, supplies the partial new input-edge/prefix/data helpers. Those scopes remain unchanged. Other provenance follows the23-node bounded PR metadata graph in evidence/PR-COVERAGE.json. This explicitly exports the local graph that was mistakenly referenced as an exported file in the earlier PR6362 prompt/body; the prior access gap remains recorded. Current metadata does not mean all current-head source was rereviewed. + +SOURCE-ORIGIN.json maps each exact local ordinary source to this inert .txt copy and hash. Parent/domain/closure/group01 and three epoch copies match their respective historical source manifests. Parent completion is byte-identical to PR6352's d4ee1b7c snapshot. Supervisor's exact path/hash is named by the parent's RECEIVER-SOURCE-MAP and INPUT-PINS, copied here. The source-only readiness records retain null approvals and open cost/qualification. No protected runtime directory or old conversation was read. + +SOURCE-FINDINGS.json supplies function/line/anchor references. verify.py authenticates the packet and checks the stated anchors in AST-located functions; it does not execute those functions or provide a general Python semantic proof. This registered replay is source-archive verification only. No original/native/compiler/process/mount workload is in VERIFY.json. + +## Open next questions + +A separately reviewed prefix-control owner may preserve the original Popen/domain/resource/first-error/raw machinery, with a distinct expected-outcome terminal accessor and control reservation. It must never mint an original production completion or weaken original two-build/empty-stderr criteria. Review any new registry and source-closure treatment explicitly. Reconstruct genuine live capabilities after a clean parent exec; a serialized lease or keeper is not authority. + +Complete effective GCC configuration, source-derived lookup closure, actual input interval, caps/cost bill and independent stage/command/funding/execution admissions remain open. The original 512 source rows, 64MiB/file,256MiB/capture and all other limits are fixed. Source blocks from Pro's namespace answer remain unadopted. + +## Timebox, verification and credit + +The next integration unit ran its source gate from08:31:54 to08:46:20UTC on2026-11-02 and closed before its08:46:54 deadline, with no implementation or tests. Concrete parent-interface findings prevented opening implementation. This audit/export is a separate publication disposition, not an hour extension or automatic retry. Subsequent Pro4 completed before its wait deadline and confirmed the parent correction. It identified the exact same-build plugin package and final-stage build data as the next distinct GCC dependency; no source from that answer is adopted in this audit. Full C05/V03 remain false; original43.5%,22/49,stage2/10,milestones1/10,24components and52helpers are unchanged. Recorded guard debit94.550533479/2400 is not complete physical cost; preparation/review/publication/final costs remain OPEN_NOT_ZERO. The goal service was separately observed paused. + +Run `python3 scripts/research_package.py --package research/h25-c05-v03-parent-interface-audit` for the source-only check. Exact observed results are in VALIDATION.json; proposed target work is not included. + +Chris R/Clear1nsight with substantial ChatGPT Pro/Codex/Sol Max assistance and independent agent source audit. Preserve original source authors, PR6321/6029/5864 lineage, unpaidmoon/Cursor Grok for PR6339 and Douglas R.Colkitt's native/circuit/verification lineage. Inert originals retain their source notices; package/new verification code Apache-2.0. Agent/source/archive acceptance is distinct from human, native or original scientific qualification. diff --git a/research/h25-c05-v03-parent-interface-audit/SOURCE-FINDINGS.json b/research/h25-c05-v03-parent-interface-audit/SOURCE-FINDINGS.json new file mode 100644 index 0000000000..d6d971fbe0 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/SOURCE-FINDINGS.json @@ -0,0 +1,160 @@ +{ + "schema": "c05-v03-parent-interface-audit-v1", + "scope": "Pinned source/structural audit; not original execution or general semantic proof", + "anchors": [ + { + "id": "P01", + "path": "snapshot/parent_completion_v1.py.txt", + "function": "_validate_plan", + "function_line": 314, + "line": 392, + "literal": "args[6] == integration + '/variant_driver_v1.py'", + "meaning": "Original driver spelling is fixed" + }, + { + "id": "P02", + "path": "snapshot/parent_completion_v1.py.txt", + "function": "_validate_plan", + "function_line": 314, + "line": 395, + "literal": "evidence['raw_file_names'] == list(VARIANT_FILES)", + "meaning": "Full raw inventory expectation is fixed" + }, + { + "id": "P03", + "path": "snapshot/parent_completion_v1.py.txt", + "function": "run_producer", + "function_line": 541, + "line": 547, + "literal": "producer_role == schema.PRODUCERS[state['next']]", + "meaning": "Producer order is fixed" + }, + { + "id": "P04", + "path": "snapshot/parent_completion_v1.py.txt", + "function": "accept_producer", + "function_line": 763, + "line": 778, + "literal": "schema.need(stderr['bytes'] == 0", + "meaning": "Production completion requires empty stderr" + }, + { + "id": "D01", + "path": "snapshot/parent_domain_v1.py.txt", + "function": "create_domain", + "function_line": 188, + "line": 190, + "literal": "schema.need(_LEN(_DOMAINS) < 4", + "meaning": "Four-domain bound" + }, + { + "id": "D02", + "path": "snapshot/parent_domain_v1.py.txt", + "function": "terminal_facts", + "function_line": 414, + "line": 419, + "literal": "state['returncode'] == 0", + "meaning": "Unchanged terminal facts reject nonzero refusal exits" + }, + { + "id": "D03", + "path": "snapshot/parent_domain_v1.py.txt", + "function": "terminal_facts", + "function_line": 414, + "line": 420, + "literal": "state['final_rows'] == () and not state['after_root'] and not state['reaped']", + "meaning": "Other cleanup predicates must be retained" + }, + { + "id": "C01", + "path": "snapshot/parent_closure_v1.py.txt", + "function": "bind_receivers", + "function_line": 131, + "line": 213, + "literal": "key in _MUTABLE_NAMES.get(name, ())", + "meaning": "Source-selected mutable names and gate suffixes are exempt from literal capture; other captured literal data remains fixed" + }, + { + "id": "C02", + "path": "snapshot/parent_closure_v1.py.txt", + "function": "check_receivers", + "function_line": 242, + "line": 245, + "literal": "_LEN(namespace) == _LEN(original_items)", + "meaning": "Namespace census cannot change after capture" + }, + { + "id": "C03", + "path": "snapshot/parent_closure_v1.py.txt", + "function": "check_receivers", + "function_line": 242, + "line": 248, + "literal": "namespace.get(key) is expected", + "meaning": "Binding identity cannot change after capture" + }, + { + "id": "N01", + "path": "snapshot/native_tcb_v1.py.txt", + "function": "verify_native_tcb", + "function_line": 158, + "line": 174, + "literal": "row[2] == observed['device_minor'] and row[3] == observed['inode']", + "meaning": "Mapped inode must match actual pathname object" + }, + { + "id": "S01", + "path": "snapshot/h25_parent_supervisor.py.txt", + "function": "launch_contract", + "function_line": 45, + "line": 51, + "literal": "need(tuple(sys.path) == ('/usr/lib/python312.zip', '/usr/lib/python3.12',", + "meaning": "No project sys.path insertion in clean parent" + }, + { + "id": "S02", + "path": "snapshot/h25_parent_supervisor.py.txt", + "function": "install_subreaper", + "function_line": 143, + "line": 173, + "literal": "return {'pid': os.getpid()", + "meaning": "Subreaper state belongs to actual clean parent process" + }, + { + "id": "S03", + "path": "snapshot/h25_parent_supervisor.py.txt", + "function": "install_subreaper", + "function_line": 143, + "line": 175, + "literal": "(library, call)", + "meaning": "Native keeper retained in process" + } + ], + "constants": [ + { + "path": "snapshot/epoch_schema_v5.py.txt", + "name": "PRODUCERS", + "expected": [ + "group01", + "failure_variants" + ] + }, + { + "path": "snapshot/parent_completion_v1.py.txt", + "name": "VARIANT_FILES", + "expected_length": 26 + }, + { + "path": "snapshot/parent_closure_v1.py.txt", + "name": "MAX_MODULES", + "expected": 48 + }, + { + "path": "snapshot/parent_closure_v1.py.txt", + "name": "MAX_GLOBALS", + "expected": 512 + } + ], + "full_C05": false, + "full_V03": false, + "original_execution": false +} diff --git a/research/h25-c05-v03-parent-interface-audit/SOURCE-ORIGIN.json b/research/h25-c05-v03-parent-interface-audit/SOURCE-ORIGIN.json new file mode 100644 index 0000000000..442417a9e7 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/SOURCE-ORIGIN.json @@ -0,0 +1,71 @@ +{ + "scope": "exact inert source copies; no admission from hashes", + "files": [ + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/field-negative-epoch-v5--SOURCE-READINESS.json.txt", + "path": "snapshot/field-negative-epoch-v5--SOURCE-READINESS.json.txt", + "bytes": 6055, + "sha256": "611a9dff18b50442fe61702655180d69790746dc3c8154b9ff25098c5c5c6714" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/field-negative-epoch-v5--epoch_copy_v5.py.txt", + "path": "snapshot/epoch_copy_v5.py.txt", + "bytes": 82957, + "sha256": "4f459d0336d59975df787c24373e18dad4044c3a24137392e890115f811b3211" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/field-negative-epoch-v5--epoch_parent_v5.py.txt", + "path": "snapshot/epoch_parent_v5.py.txt", + "bytes": 26833, + "sha256": "058059912144863a4b2bfe4fc9ffc5233b4ab20ee5a7355bde66f4d3f6f28712" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/field-negative-epoch-v5--epoch_schema_v5.py.txt", + "path": "snapshot/epoch_schema_v5.py.txt", + "bytes": 30668, + "sha256": "b89a789654be87bde40a47300f4d9702dce2b90e6ab3be9a2025f6d8041b3e9a" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/field-parent-completion-v2--SOURCE-READINESS.json.txt", + "path": "snapshot/field-parent-completion-v2--SOURCE-READINESS.json.txt", + "bytes": 6046, + "sha256": "5c5b3509ec8eff3fe2e8fe5e7b1e95c7790a964fb0fe401ed5c0049d88ea6520" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/field-parent-completion-v2--group01_evidence_v1.py.txt", + "path": "snapshot/group01_evidence_v1.py.txt", + "bytes": 15610, + "sha256": "05ec6a63c57340ba929aea1fab71b096efc143e099346640f6def41310bd3e25" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/field-parent-completion-v2--parent_closure_v1.py.txt", + "path": "snapshot/parent_closure_v1.py.txt", + "bytes": 13400, + "sha256": "2d831cff8bd444de2d6941645d571e07618ede404a1f45692b557f61494b334a" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/field-parent-completion-v2--parent_completion_v1.py.txt", + "path": "snapshot/parent_completion_v1.py.txt", + "bytes": 54168, + "sha256": "d4ee1b7ce4a42b73261984ffb1b9ceb5bb0165223e04a253588f83b99f6981a5" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/field-parent-completion-v2--parent_domain_v1.py.txt", + "path": "snapshot/parent_domain_v1.py.txt", + "bytes": 20456, + "sha256": "9205e14d6661fb5df0597f0ad7b2206006f2d31f01f784805f64c13875663282" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/unit02/prerequisite-source/h25_parent_supervisor.py.txt", + "path": "snapshot/h25_parent_supervisor.py.txt", + "bytes": 23047, + "sha256": "cfb09a18dd10b597cc6d5a8139ee769bef679bc44ae029329755e3d97b055075" + }, + { + "from": "outputs/c05-v03-completion-20261102T055710Z/prerequisite-source/native_tcb_v1.py.txt", + "path": "snapshot/native_tcb_v1.py.txt", + "bytes": 11353, + "sha256": "865943df5cfdbf9383362d7fb2b76c6d0fd895cf0a0e20d550a26b579606b5d7" + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/SOURCES.json b/research/h25-c05-v03-parent-interface-audit/SOURCES.json new file mode 100644 index 0000000000..594089b9c7 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/SOURCES.json @@ -0,0 +1,18 @@ +{ + "schema_version": 1, + "base_commit": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "d59b5035e7b4cbaa9d688a1d32dd0d6eb79c466a", + "sha256": "9b8d0eea95b3bf0dfcb7938a732a6439b87a2685dec2a5ab9e525b3b34debbfa" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "3404fbdd5e7529a0674eef26114b5071e4586cec", + "sha256": "ead6cdc9d0af6d58e8a49744d8ec8c7c15e13d2ba93c276c434bcf9b51b93a81" + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/TASK.json b/research/h25-c05-v03-parent-interface-audit/TASK.json new file mode 100644 index 0000000000..db245046cc --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/TASK.json @@ -0,0 +1,60 @@ +{ + "schema_version": 1, + "task_id": "portable-replay", + "priority_revision": 8, + "base_commit": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "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_selected_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Resolve the current selected review, separate complex/ordinary BIT/admitted BIT/outer budgets, and compare the card against live handoffs before starting. Historical ceilings require exact source/model equivalence.", + "scope": "Source-binding orientation only; not a scientific replay or all-size proof. Materialize selected inputs if this checkout is sparse." + }, + "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": "changed", + "actual_scope": "Source-pinned negative interface audit of proposed V03 prefix against original parent, domain and receiver closure; recover ordinary prerequisite source and derive copied-runtime necessary conditions. No new runtime or C05/V03 completion.", + "scope_change_reason": "Parent source gate exposed hard original driver, inventory, exit, domain-count and closure predicates. Audit the incompatibility before constructing a successor; preserve the original full activity.", + "bottleneck_link": "Source-bound verifier qualification prerequisites; no change to the multiplication supplier, selected result or framework assumptions.", + "budget_minutes": 60, + "stop_rule": "Unit02 gate08:31:54-08:46:54UTC; closed08:46:20 without source implementation or tests. Do not extend/retry integration; publication source-archive checks are separate. No original/native/compiler/namespace execution or new budget.", + "outcome": "partial", + "evidence": "Exact inert source recovery with manifest matches, source-bound parent/domain/closure incompatibilities and copied-runtime necessary conditions; README, SOURCE-FINDINGS, SOURCE-ORIGIN and INDEPENDENT-REVIEW.", + "author": "Chris R / Clear1nsight", + "ai_assistance": "ChatGPT Pro source consultation and substantial OpenAI Codex source-audit/verification assistance. These are agent-assisted findings, not human or proof-kernel acceptance.", + "open_questions": [ + { + "question": "Can an explicit clean authenticated parent/control-domain/closure successor and actual compiler query frontier complete C05/fullV03?", + "why_it_matters": "The unchanged original parent cannot accept this prefix and no clean executable bootstrap is established. Complete C05 still requires source-derived witness closure and immutable interval.", + "first_step": "Assess Pro4 and recovered source, construct and independently review concrete successor while retaining original production checks.", + "blocked_by": "Effective installed GCC configuration, parent bootstrap, concrete control-domain ownership and genuine runtime/source/stage/funding admission." + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/VALIDATION.json b/research/h25-c05-v03-parent-interface-audit/VALIDATION.json new file mode 100644 index 0000000000..9924279b39 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/VALIDATION.json @@ -0,0 +1,29 @@ +{ + "observed_utc": "2026-11-02T09:06:48.861257+00:00", + "scope": "Post-independent-review exact archive/source anchor verification only; no original execution", + "results": [ + { + "command": [ + "python3", + "scripts/research_package.py", + "--package", + "research/h25-c05-v03-parent-interface-audit", + "--check-only" + ], + "returncode": 0, + "stdout": "PASS_PACKAGE_METADATA_AND_PINS (not a mathematical acceptance check)\n", + "stderr": "" + }, + { + "command": [ + "python3", + "scripts/research_package.py", + "--package", + "research/h25-c05-v03-parent-interface-audit" + ], + "returncode": 0, + "stdout": "CHECK Exact archive identities and AST-located source anchors only; no original import or runtime qualification\nPASS_SOURCE_IDENTITIES_AND_PINNED_ANCHORS 31 14\nPASS_REGISTERED_RESEARCH_PACKAGE research/h25-c05-v03-parent-interface-audit outcome=partial\n", + "stderr": "" + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/VERIFY.json b/research/h25-c05-v03-parent-interface-audit/VERIFY.json new file mode 100644 index 0000000000..e32e74870a --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/VERIFY.json @@ -0,0 +1,19 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [], + "commands": [ + { + "argv": [ + "{python}", + "-I", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 30, + "checks": "Exact archive identities and AST-located source anchors only; no original import or runtime qualification" + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/INPUT-PINS.json b/research/h25-c05-v03-parent-interface-audit/evidence/INPUT-PINS.json new file mode 100644 index 0000000000..9e7967e9eb --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/INPUT-PINS.json @@ -0,0 +1,897 @@ +{ + "count": 148, + "frozen_v1_files": 33, + "images": [ + { + "bytes": 3525, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-header-custody-v3/REQUIRED-NATIVE-PREMISES.json", + "sha256": "161bd504c2f3d0e051f0e37c47e28ef287eef8a239456696ebd42ad96a8b7afb" + }, + { + "bytes": 2875, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/ADDED-CONTROLS.json", + "sha256": "0b97eb3532c5286ee2e693147331f2cc9a1ea13753e6ec30fe55743c8f2bb1ac" + }, + { + "bytes": 548, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/AUTHORING-NOTES.json", + "sha256": "e5d01891f4d241853f3bcbd8373cc710f882ec9007058c04fc47de0d01259b55" + }, + { + "bytes": 1384, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/COST-DELTA.json", + "sha256": "85a4d29de7286d931d5e180629af9576029c1ee9ddab5a148befd9a55dfecb57" + }, + { + "bytes": 4745, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/FINAL-READBACK.json", + "sha256": "2ef1bd754d9ca7a7716d7916b8156d8ceaabdacafc53cce84005f507a6a5b10e" + }, + { + "bytes": 9792, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/INPUT-PINS.json", + "sha256": "a8f64891afcb901c6008c4122c5e14be68c43aff0df8fe0e2802101443f8de57" + }, + { + "bytes": 2179, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/LOCAL-CURRENT-TASK.md", + "sha256": "2fe4f49ec38573df5c3627566b18702128303030a9a46b379d73a3fd0058c98f" + }, + { + "bytes": 9282, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/OLD-EXPECTATION-DISPOSITIONS.json", + "sha256": "b2ab3dc9982755f29442c4891b545b928320a0fdb24434020153a12b8efcaa3d" + }, + { + "bytes": 53, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/PASSIVE-ATTEMPTS.jsonl", + "sha256": "fbea1df6969452b0ef56e118dfc328226ffd6c8c7b93c81b20765d45338dd599" + }, + { + "bytes": 28293, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/PASSIVE-CHECKS.json", + "sha256": "129cbeb1dfbce1f49cdcdea18411b9c68c85464ff4f0ab9985b4d52167f02afd" + }, + { + "bytes": 4616, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/README.md", + "sha256": "a0e6646d891ad36ce5d1de0363b554be251284744bc59022215e94c20fb01e64" + }, + { + "bytes": 2113, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/SHA256SUMS", + "sha256": "a49aa9b5cf0979d41a60ed9f90ac5b60204ac7673e5aec893fa2af227b260c8b" + }, + { + "bytes": 10994, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/SOURCE-INVERSE-v5.json", + "sha256": "0e88ab806783b29a38d213cf648ac2450edb58c43361f32379f72be47d969a78" + }, + { + "bytes": 3931, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/SOURCE-MANIFEST.json", + "sha256": "e3e1f06f3830658f11f1fa2ed6252240f57414a6f6dd1f219c91a1770aacffbf" + }, + { + "bytes": 6055, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/SOURCE-READINESS.json", + "sha256": "611a9dff18b50442fe61702655180d69790746dc3c8154b9ff25098c5c5c6714" + }, + { + "bytes": 11078, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/adverse_protocol_controls_v5.py", + "sha256": "85534e666301f6a394be6197913477c433299350baa0fe15bd104c034262f424" + }, + { + "bytes": 8647, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/anti_replay_data_controls_v5.py", + "sha256": "e831b92d8fe81427d7fed30bcb59dc31e457a5df4cbaa37930a821d760121f1c" + }, + { + "bytes": 2825, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/author_source_v5.py", + "sha256": "7b7c059fb69b8f837918e239fd2bf3c302a8899671db061c0d9cae56178f2ada" + }, + { + "bytes": 82957, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_copy_v5.py", + "sha256": "4f459d0336d59975df787c24373e18dad4044c3a24137392e890115f811b3211" + }, + { + "bytes": 4807, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_import_claim_v5.py", + "sha256": "69a8c1570e6cf521d7a17bda59748578043410a718691e154fc50681e6262095" + }, + { + "bytes": 26833, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_parent_v5.py", + "sha256": "058059912144863a4b2bfe4fc9ffc5233b4ab20ee5a7355bde66f4d3f6f28712" + }, + { + "bytes": 30668, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_schema_v5.py", + "sha256": "b89a789654be87bde40a47300f4d9702dce2b90e6ab3be9a2025f6d8041b3e9a" + }, + { + "bytes": 8205, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_stop_v5.py", + "sha256": "5b10c9d72dd0e646652a73b6ffe9ba870762d6bc2f7432bc6b06571a1b7d2a6f" + }, + { + "bytes": 6998, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/finalize_v5.py", + "sha256": "4806a120f9f0863d049de242344e39551adc22136b8a9c354258aebbaac0be85" + }, + { + "bytes": 16024, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/original_build_provenance_v5.py", + "sha256": "bd5ffd9a1c221e0945527fc8fa8d0ad4eb36b9a8884503451c1b6b12d00007ea" + }, + { + "bytes": 17396, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/prepare_and_check_v5.py", + "sha256": "b005d0b9ce71677162c916d01256b43a6fc35accc139eea6730c703e36e154d3" + }, + { + "bytes": 12594, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/repair_control_sources_v5.py", + "sha256": "6dd9569acc6ac50983acd7f86e7346504eef40a545e65be2f0d885efb5cc0270" + }, + { + "bytes": 5896, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/API-AND-GATES.json", + "sha256": "aee96bd512037357357699760635552d96208846ecb620d30f537203f1ea0af3" + }, + { + "bytes": 2489, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/AUTHORING-ERRORS.json", + "sha256": "748f65dbe65ced84a722abd114cf8599c6e8650e5bf95fd58c570e18d6ed6357" + }, + { + "bytes": 5011, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/COMPLETE-COST-BILL.json", + "sha256": "4059aafa89f6ec899d30219a984b1c396aacd09051eb2e56d4ecbc69e0f7c44f" + }, + { + "bytes": 11736, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/CONDITIONS.json", + "sha256": "f05600d6470c1bc4fc42b9234035698bf804c1fe101fe757466ad7d3729d589f" + }, + { + "bytes": 818, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/FINAL-READBACK.json", + "sha256": "d6329b8caf90cfccd60a9c0f05610987210c870d0db138bce17ff27aa1e39157" + }, + { + "bytes": 67420, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/INPUT-PINS.json", + "sha256": "d81bc374ae3f7013646181cd65eb730da1842b025dfc32f898e9cfbc411b7859" + }, + { + "bytes": 639, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/INSPECTOR-ATTEMPTS.json", + "sha256": "ca068e1a4f0b2eccb361e4bba2f55d8b4c0fa1dbd019c0c7c53e0d758a872836" + }, + { + "bytes": 4251, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/INTERFACE-DRAFT.json", + "sha256": "7aec0232c559184e9159a19a5dcb3d42b0ca245886dce06ff61e08b2a89a5fa5" + }, + { + "bytes": 2474, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/LOCAL-CURRENT-TASK.md", + "sha256": "47cc398e2a25bdc00cd909f420072dd39f0357298ce9b3a5930dad60e6710607" + }, + { + "bytes": 3712, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/OBSERVATION-TYPE-REPAIR.json", + "sha256": "36a8c429507d4f07b0ce4b92fec5bd0c8087b5a176abe54975a1caefd86b52c2" + }, + { + "bytes": 87953, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/PASSIVE-CHECKS-attempt2.json", + "sha256": "2cc1efe5a023921821e84f430fcad3a02f5247bd176fbe2de1c9995e5165f8f2" + }, + { + "bytes": 87855, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/PASSIVE-CHECKS.json", + "sha256": "6c2cdd4d4a2674a537e60b47db2c50a2931551b1d12330066003f5a020d69f2e" + }, + { + "bytes": 14009, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/PASSIVE-REPAIRS-v1.json", + "sha256": "39945d2b44583ba6249ccfc4b053a101bb731eb4cfff3aa5b37f1a03d20c18b4" + }, + { + "bytes": 5813, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/README.md", + "sha256": "109c56ccb600f808371aff19c54807c5ea8c72c76ec324e52611b659a93280ae" + }, + { + "bytes": 12228, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/RECEIVER-SOURCE-MAP.json", + "sha256": "2dfcf2efc85e4fe0e95cde496d548aeee683bc30c239b176b60e18debb47a210" + }, + { + "bytes": 2750, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/SHA256SUMS", + "sha256": "0927e86d7dc65964e38a83c9a731cd4668611b372b79cd103fd0c56e8b3f8ca2" + }, + { + "bytes": 32982, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/SOURCE-INVERSE.json", + "sha256": "12f4422ad39cc61b5a8dfe25c1044c3b247f26896e2422c26dfc539f012a7cd5" + }, + { + "bytes": 5175, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/SOURCE-MANIFEST.json", + "sha256": "a26471f1c5a1391d4efe79c946829e30ba0c34a1e04e8e437c2432695bac392b" + }, + { + "bytes": 5577, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/SOURCE-READINESS.json", + "sha256": "68ee02d81fffad3b1f5f67c549b91fb48994223a8f858dc3cb1cb97939b74643" + }, + { + "bytes": 6136, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/SOURCE-TEST-RECIPES.json", + "sha256": "14edfce324723379e74efb9adb9e78a0dc69cf6dc4165a4825ee4c1f59aa6fb7" + }, + { + "bytes": 3454, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/author_group01_source.py", + "sha256": "838bca5ce46c9822839d328eb3679722b01eec4d7e3a9e59b5a33d98e7dc1384" + }, + { + "bytes": 9271, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/finalize_packet.py", + "sha256": "1873a18d7c51effe816f24d0dfadd8743ec9cc985e3d2accd58eeb23c1be709e" + }, + { + "bytes": 15083, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/group01_evidence_v1.py", + "sha256": "960997faefe053d5026582309f5248162ce6eae7abb3783716d0649de34826ba" + }, + { + "bytes": 23224, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/group01_original_predicates_v1.py", + "sha256": "894219d9caae63cc3cb39cf8611d494d1676828cce55cbf851f98d6dae7d62a7" + }, + { + "bytes": 9794, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/inspect_sources.py", + "sha256": "9940f5053e85c76acc628303d69e700c6e3b178933f175b6b3055e2cc0212257" + }, + { + "bytes": 9625, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/inspect_sources_attempt1.py.txt", + "sha256": "867e41baf4b04d2db64ac07d5b7d2da8fb8b99f9f169170b43ed47ea9d0f448b" + }, + { + "bytes": 9682, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/inspect_sources_attempt2.py.txt", + "sha256": "259ae1024160672514aa5465a143196088ec16f82f2056037cf027eec283343f" + }, + { + "bytes": 13400, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/parent_closure_v1.py", + "sha256": "131f4632dd13dbe06af06c6ff3a4eee04dcf403ed1d76d627ff3c3a29ed6fba4" + }, + { + "bytes": 48816, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/parent_completion_v1.py", + "sha256": "3ed30810bfffc15a43e6150689f20dc21bbd668fc3a3ff51bd808382556b717c" + }, + { + "bytes": 15374, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/parent_domain_v1.py", + "sha256": "0c4d3541b0d5cd9d091e02ccdfa4665909a775acfd3f24e8c28d6c7902d2a827" + }, + { + "bytes": 21125, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/prepare_packet.py", + "sha256": "47f444df1b57649366c63e4e36c70a206ffdacec42d8f8ed2798fb8d442bf29f" + }, + { + "bytes": 3336, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/repair_observation_types.py", + "sha256": "67b5ac145c4369552bfcda7fbce163360d4d455941a7198f8f9c7cf4a5b3b77c" + }, + { + "bytes": 12852, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/repair_source_v1.py", + "sha256": "cb5f5dfddf6a965ff225967f37d655250a8ccd22fe6b689f66193aa968d301b2" + }, + { + "bytes": 28931, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/COMPARISON-REPLACEMENTS.json", + "sha256": "9ef333f01bf34ddd2e88194eaddff1e0c8bb89058c24571c22e3d614ad76508e" + }, + { + "bytes": 6940, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/CONDITIONS.json", + "sha256": "70e237d6ee4ac2ccaadf01615e8106999718eb1fbb3cf7644c9fc6d3fd4463fe" + }, + { + "bytes": 5019, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/COST.json", + "sha256": "f105a08394752a10034a03223e75d0014cdf19248acc0ff64c0bf12d18ab8fb9" + }, + { + "bytes": 17331, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/DERIVATION.json", + "sha256": "7a8f4a62f8b3c00a4be75635251875185f326820f9adb1b877ccdbf61123e322" + }, + { + "bytes": 6956, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/INTERFACE.json", + "sha256": "30820f1f2d27d4d4306d8ba63db5329f89182912f7f915aede35b9ce62359491" + }, + { + "bytes": 4691, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/LOCAL-CURRENT-TASK.md", + "sha256": "a4df6edecf117dd451a18055bb75e4cb2f8c48cd8aa61d19fe07be9f40d189bc" + }, + { + "bytes": 4307, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/MANIFEST.json", + "sha256": "f75f1971eda3d8664b705ca2a1eaaa6fede6df797449281da1a8f2c9678381ad" + }, + { + "bytes": 4730, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/REPORT.md", + "sha256": "6c1fb1cf7ab1188a26688491ef42efe729aad3e8d4ed5f600045335f3aab6c1e" + }, + { + "bytes": 1641, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/RESOLUTION.json", + "sha256": "79b57957a0b4b6d379f02f003f26fc932fc107dc75c0ea9692a2244e456f473f" + }, + { + "bytes": 1808, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/SHA256SUMS", + "sha256": "296e097ee05b355c2c804026486e67c65dbc7f4760ed3041326abd102868a538" + }, + { + "bytes": 6185, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/SOURCE-PINS.json", + "sha256": "c387cee4bd7993107c353a01c2ea942c6376975a23b996cf6727267f14aa40cf" + }, + { + "bytes": 3993, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/SOURCE-READINESS.json", + "sha256": "2dc010c488c0bc8ef7ddbb639a126d468278fc8dc3795379cff13c9556ef2726" + }, + { + "bytes": 16819, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/STATIC-AUDIT.json", + "sha256": "6c4d41810c8924500c9bddd48755e59f8e3b38c5c65f11b440ae92e6f3c5f674" + }, + { + "bytes": 9519, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/UNEXECUTED-CONTROLS.json", + "sha256": "8e9104d57ec46b27ffeb4caec4be62a51e6d5873a2682947dcb9759f1e7d4507" + }, + { + "bytes": 53151, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/V1-BYTE-INVERSES.json", + "sha256": "1a3cf4c62757c4b655252776db26dce8ccbefca6114dc616a59cb4861cd48114" + }, + { + "bytes": 4796, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/derive_variant_driver_v1.py", + "sha256": "bc1726c80a17c067de6549aeb262159ec63efc6ea4a5482558f558147d7d7fef" + }, + { + "bytes": 14549, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/driver_body_v1.txt", + "sha256": "74876f4dc35bdf027c51c5822fabd76f44c86d7850bb6c354c41c32d1ec9f9d4" + }, + { + "bytes": 12795, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/driver_prelude_v1.txt", + "sha256": "c8e3455620189df58e81476e7b39b2d264766bb86404e048d4291050eb3e02ec" + }, + { + "bytes": 2849, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/exact_tree_comparison_v2.txt", + "sha256": "b174c40bd3ecbf6dc775b5d55ebaa48bca7428078489d2bd58d3c5983338141a" + }, + { + "bytes": 13135, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/original_driver_prefix.txt", + "sha256": "effc6327c67d40fbe3069d90f14d7f312125778f17f045bf9ae259e5577d51ca" + }, + { + "bytes": 5416, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/prepare_v2_source.py", + "sha256": "55a458a33e1e7811ae0eda3c44d336e7bc98dee932fbcaa895d017bbd748e7dc" + }, + { + "bytes": 41337, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/variant_driver_v1.py", + "sha256": "cdb1479253358508088f8aa0e1e92e6c75ffcc127e54552698598a02de061254" + }, + { + "bytes": 31791, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/variant_validation_v1.py", + "sha256": "5e099fbe13f9e6f548a36ba2202bceef2f5d479bed85529ce57b26654f7c0a98" + }, + { + "bytes": 6450, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/control/EXPLICIT-TRUST-SELECTION-v1.json", + "sha256": "a64b59374b6666884af8000eb38792e97c9960bb21ec78dde8051a8cb2d1125b" + }, + { + "bytes": 23047, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/execution-guards/build-log-queue-v2/supervisor.py", + "sha256": "cfb09a18dd10b597cc6d5a8139ee769bef679bc44ae029329755e3d97b055075" + }, + { + "bytes": 6949, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/close_model_controls_v5.py", + "sha256": "9beda1b7555959eb9b6b6aa558f29655146ff8067fc7496059ba13b7843f0b60" + }, + { + "bytes": 11877, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/collector_controls_v1.py", + "sha256": "094f345a4f69b2d1aa648e40315a000ad3dfeeb929218475b0164629c24c4b5a" + }, + { + "bytes": 5230, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/driver_model_body_sources_v3.py", + "sha256": "f36e5cf59ee68b271f3d207fe0eca6f5f7503511ca4062b5681275f713e30a8a" + }, + { + "bytes": 6301, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/elf_controls_v1.py", + "sha256": "306eec9c04be89dc9cbdbf8ed3ad804a9a664abce5b2c30036c6008434f046c8" + }, + { + "bytes": 32860, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/elf_extended_controls_v2.py", + "sha256": "e55ab5f1ea7a7a9d64a9847695b68abd09518431a6016c9ddb70b469002fdaa7" + }, + { + "bytes": 6825, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/elf_literal_fixture_v1.py", + "sha256": "9a1f1105cea03f187efc2bdb65dd7b00e0111517f5043ef29005511018aaa5a2" + }, + { + "bytes": 9265, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/elf_literal_fixture_v2.py", + "sha256": "dc4854a6ac50f025399dec823c658f24bfb22ada4a6d60c317a49ec7a110e0ce" + }, + { + "bytes": 18794, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/group_evidence_v5.py", + "sha256": "206802db0f9af87ab3c0edb2dd48d3257ddc9012fe0fcdfc4df73b04c56bf37c" + }, + { + "bytes": 18126, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/loader_model_controls_v1.py", + "sha256": "3686813f7267a2f843ed5f35090d73b26c14cf3f350a8f664cdfc5dd34726fdd" + }, + { + "bytes": 36286, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/loader_model_controls_v3.py", + "sha256": "2c324511d4ab6f27a9ce8bf9717476c9c6e474101e0ed090d19dc951b8d04c02" + }, + { + "bytes": 18980, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/native_field_controls_v1.py", + "sha256": "a9a4904c41c490509b0033bc8be2536a81aff68232f068ab884f614e7b51e64e" + }, + { + "bytes": 11654, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/projection_model_controls_v5.py", + "sha256": "668bde5f7998bf9e49817019b4c53c2d8e16aaf027fc5e9d96c4c213103f8686" + }, + { + "bytes": 9283, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/provider_controls_v1.py", + "sha256": "8478395c16fcc8ab2443f8934c77bb9589bdc4cf981e73101de28df08c198ab9" + }, + { + "bytes": 3592, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/receipt_contract_v1.py", + "sha256": "f7064029c55923114c5fc96c06ec0bc06825661a51cbce5a2a7cb932d9f13bb6" + }, + { + "bytes": 5843, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/restoration_contract_v1.py", + "sha256": "2cfe462e75aef8b25c5b0556226f15e93e9ebab1433aae92ef5ddfaffbdcfe6c" + }, + { + "bytes": 15650, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/root_model_body_sources_v3.py", + "sha256": "0e4a79dac6bb07a62e6624a07ad7f2e0b534d8cda42b7ef1b787a7d64de7b99b" + }, + { + "bytes": 26939, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/run_controls_v5.py", + "sha256": "0e6c8a82c4902f2de707b1ceb1eb19932cd5607645bfb0cdd08c1eef715946aa" + }, + { + "bytes": 2735, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/run_pure_controls_v1.py", + "sha256": "7c6cfbaaec2959ad81262ea1caec39526405b83fa47876872b0a145a5e81abc2" + }, + { + "bytes": 3911, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/run_pure_controls_v2.py", + "sha256": "d64578b222facd38e69d362ed564702e8a10a95d3606cc4047d47c51d87c7ccd" + }, + { + "bytes": 4272, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/transport_controls_v1.py", + "sha256": "c79942bbdd9460f79e100d85302e8d472cce896bb94a7f91cec7fdad039ce0f4" + }, + { + "bytes": 76453, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/elf/sealed_elf_profile_v2.py", + "sha256": "89ed8c777e6b72af2d6a3595037e7e92385924c6087d88010a27192633391016" + }, + { + "bytes": 80483, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/wiring/data_adapters_fields_v1.py", + "sha256": "3451b5facc18b2591469933386b463517c340accbd8820007cf7bebcf8353901" + }, + { + "bytes": 2122, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/CONDITIONS.json", + "sha256": "931da1a21a7de2d242a6c763b445818fb5bb543390a46240fd44b9fc711e4a55" + }, + { + "bytes": 1998, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/FINAL-MANIFEST.json", + "sha256": "95ba1343049831cf93e1af2e5801b2e47ff0d077df6bbe44c6d1c5fadb937a53" + }, + { + "bytes": 536, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/FINDINGS.json", + "sha256": "aceb3309efdf61bf2e83b60d2b2a5dc04af59e0ba55cc3576c89f1a745f3bb54" + }, + { + "bytes": 37732, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/INPUT-READBACK.json", + "sha256": "c2401850cb7a876419fbf125ea822c91ccc54737b91f8b5b1e8ddd0bd07d870c" + }, + { + "bytes": 3858, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/INVERSE-RESULTS.json", + "sha256": "856ae9af5e5c8dd236bb282f74d67b46704fdb730cfdef15f618a19b381ab47f" + }, + { + "bytes": 5197, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/LOCAL-CURRENT-TASK.md", + "sha256": "862abfc7d11c6698792066e3bd12b58052144d40edfb552f72d6746468615e8e" + }, + { + "bytes": 4291, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/REVIEW.json", + "sha256": "f7384b9a28904b71bcf4f3c5f668442da1b7725f38c554ebdfb15c9580100b07" + }, + { + "bytes": 4759, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/REVIEW.md", + "sha256": "468d6be158d9a9c925baa61cc7fa33e3f43087de1999af1173dd1fa3a0c8d54d" + }, + { + "bytes": 77281, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/SOURCE-CHECKS.json", + "sha256": "618e4a30d19c4483983e300d8bd9a896b9b0e0085f24c1a2d9795edef1e35909" + }, + { + "bytes": 51687, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/SOURCE-PINS.json", + "sha256": "db9fe805e7895ec9fd23177138a2897f18d4bf93225c31c401a91fba5cee3059" + }, + { + "bytes": 6869, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/finalize_review.py", + "sha256": "abe3fed5c4a1773e8f36cf40843a00d6f33ad4101321fd0b224f624880d78d12" + }, + { + "bytes": 11029, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-negative-epoch-source-v5/inspect_source.py", + "sha256": "784f2d7a8fb6efccfed7913352f941f5717dc9df17e789135dede9fff0f67c9b" + }, + { + "bytes": 13251, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-parent-completion-source-v1/CHECKS.json", + "sha256": "a286b7c21c25f6a16915cae0257c1a9b24d26249e8b88ab784ef7bd675d9f60c" + }, + { + "bytes": 643, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-parent-completion-source-v1/FINAL-READBACK.json", + "sha256": "3081597eb53d5e122f6e04261bf1c457fab0284b67ba37209c1a94daf7bf4deb" + }, + { + "bytes": 563, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-parent-completion-source-v1/LOCAL-CURRENT-TASK.md", + "sha256": "cb6278d117682fdc38bd918c470d3e1a704cd4e081680c198e4f1587632b56b2" + }, + { + "bytes": 3382, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-parent-completion-source-v1/PINS.json", + "sha256": "ccb4020610ffad3c8fe8952d16e379973b9d076a770c06bbec7799cd1db80b0d" + }, + { + "bytes": 4486, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-parent-completion-source-v1/README.md", + "sha256": "9eef824a2bf77a65e6da09d42e4fe2580ea6ea19f33b2ecd99be9435c6f6cf05" + }, + { + "bytes": 3680, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-parent-completion-source-v1/REVIEW.json", + "sha256": "c05392fcb818bf5af31e7dd6fc2f397e615532bfb8991e52b8c9f621c421c9e8" + }, + { + "bytes": 563, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-parent-completion-source-v1/SHA256SUMS", + "sha256": "70526ff8d2a6d7e6e491b1d287854b049bd17ae14b6db255205fb1023281d7f8" + }, + { + "bytes": 1189, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-parent-completion-source-v1/SOURCE-MANIFEST.json", + "sha256": "d2f4dcec1877389c8b916c140bf3a65136a5539c639a42c05b9e7df0f8ca2113" + }, + { + "bytes": 1412, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-parent-completion-source-v1/TASKCARD.json", + "sha256": "78ab8c3c37bfa107ff0dee35a86bc603a854be6d8e6b899fd793d61b2e29f936" + }, + { + "bytes": 3849, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/COMPARATOR-PROOF.json", + "sha256": "72ad5d9b5dab31e304609373142c1dc9b2cee454fecf76163ce20690fc65bc6a" + }, + { + "bytes": 8747, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/CONDITIONS.json", + "sha256": "a1ce263371e21db3159d3042fab7c1708a11d8854b82e6d97ae50c0a4c9b3a4e" + }, + { + "bytes": 11694, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/FINAL-READBACK.json", + "sha256": "90c1f599765e97e8812cc1b3fa69eac0b6a8e644d8239face36830b027ba6abd" + }, + { + "bytes": 864, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/FINDINGS.json", + "sha256": "983be9f3dccdef58a1783f9c009a1b878c6b82b4d34f1f78c5078c25f45f25e7" + }, + { + "bytes": 3085, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/INVERSE-AND-DELTA-attempt1.json", + "sha256": "58949d26b6bbd657958aeded29e7eb7409bb8619f97b949326db11092e8cb865" + }, + { + "bytes": 3085, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/INVERSE-AND-DELTA.json", + "sha256": "58949d26b6bbd657958aeded29e7eb7409bb8619f97b949326db11092e8cb865" + }, + { + "bytes": 2507, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/LOCAL-CURRENT-TASK.md", + "sha256": "73e9ad8e6c1b171dec90dffebadd5cd16ec522a4931a6d4bb6f45caa0589e354" + }, + { + "bytes": 4759, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/MANIFEST.json", + "sha256": "c7466eecba745649c422e962bb81de529dc4dba145fc0e191d49993603b2e4c8" + }, + { + "bytes": 5172, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/REVIEW.json", + "sha256": "38ae1b74c363ac4c6afaddbf268b777cd9c9c17162f78bb0a2d34d3c3f0fbfef" + }, + { + "bytes": 4526, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/REVIEW.md", + "sha256": "4a9ca62cc7d0aec8429511a5942b9dc3569f36e2082eef8bf2fa9db5d5e7e0dc" + }, + { + "bytes": 911, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/REVIEWER-ATTEMPTS.json", + "sha256": "7dc7afe307b29472188b1a55b45667c22f7dec66f450e5575970155763b2328f" + }, + { + "bytes": 1640, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/SHA256SUMS", + "sha256": "9dba0a14ef2e143cf1011de973ed555f138e44e3895c82ee10b5050a4e3ef44a" + }, + { + "bytes": 33720, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/SOURCE-EVIDENCE-attempt1.json", + "sha256": "5d1aba006a983657df3985dfb97333888bc2d53ff499bdfa43475f576f7313f4" + }, + { + "bytes": 33654, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/SOURCE-EVIDENCE.json", + "sha256": "0190e865657c595c06ada130e7e59fbf3d13be18ae1894c97247cda54f0a238b" + }, + { + "bytes": 22044, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/SOURCE-PINS-attempt1.json", + "sha256": "2b3f58612c01b452a7a432575cdea2dd5bd818307bcc24a75415f6bfa2d422f6" + }, + { + "bytes": 22044, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/SOURCE-PINS.json", + "sha256": "2b3f58612c01b452a7a432575cdea2dd5bd818307bcc24a75415f6bfa2d422f6" + }, + { + "bytes": 6469, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/finalize_review.py", + "sha256": "47e232583856d484b2191a5d9b17966e22e9fe25124094bcfd15c96ae15c8f52" + }, + { + "bytes": 17165, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/inspect_source.py", + "sha256": "25932fb39cbd320703f24411aedd2fe93de01a40756ed77fe745c439c95f96f8" + }, + { + "bytes": 17002, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/inspect_source_attempt1.py.txt", + "sha256": "62e1cbf264e8b54cbb8caf5a55d65c600b6a06353c9a72dcf015c81e5877aeae" + }, + { + "bytes": 10943, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/review/field-variant-producer-source-v2/write_review.py", + "sha256": "f7f07598ea769b016a9ca06807c418c0964f842daf6ff502bc3b4197bc57a948" + } + ], + "no_ancestor_tree_copies": true, + "schema": "h25-parent-v2-consulted-input-images", + "source_data_only": true +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v1.json b/research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v1.json new file mode 100644 index 0000000000..7fd5c799d3 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v1.json @@ -0,0 +1,18 @@ +{ + "observed_utc": "2026-11-02T08:55:04.946940+00:00", + "scope": "Only archive bytes and AST located literal source anchors; no original runtime", + "results": [ + { + "command": [ + "python3", + "scripts/research_package.py", + "--package", + "research/h25-c05-v03-parent-interface-audit", + "--check-only" + ], + "returncode": 1, + "stdout": "", + "stderr": "TASK.json.scope_status must be unchanged, refined or changed; found \"Assigned C05/fullV03; scoped parent/domain/source-closure incompatibility audit only; no activity completion\"\n" + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v2.json b/research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v2.json new file mode 100644 index 0000000000..bbe8b5d8a3 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v2.json @@ -0,0 +1,18 @@ +{ + "observed_utc": "2026-11-02T08:55:43.227962+00:00", + "scope": "Only archive bytes and AST located literal source anchors; no original runtime", + "results": [ + { + "command": [ + "python3", + "scripts/research_package.py", + "--package", + "research/h25-c05-v03-parent-interface-audit", + "--check-only" + ], + "returncode": 1, + "stdout": "", + "stderr": "TASK.json.evidence must be a non-empty string without TODO; found list: [\"README.md\", \"SOURCE-FINDINGS.json\", \"SOURCE-ORIGIN.json\", \"INDEPENDENT-REVIEW.json\"]\n" + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v3.json b/research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v3.json new file mode 100644 index 0000000000..8662f7589e --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/PACKAGE-METADATA-FAILURE-v3.json @@ -0,0 +1,18 @@ +{ + "observed_utc": "2026-11-02T08:56:39.819827+00:00", + "scope": "Only archive bytes and AST located literal source anchors; no original runtime", + "results": [ + { + "command": [ + "python3", + "scripts/research_package.py", + "--package", + "research/h25-c05-v03-parent-interface-audit", + "--check-only" + ], + "returncode": 1, + "stdout": "", + "stderr": "README.md needs an \"## Open next questions\" section\n" + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/PARENT-SOURCE-RECOVERY.json b/research/h25-c05-v03-parent-interface-audit/evidence/PARENT-SOURCE-RECOVERY.json new file mode 100644 index 0000000000..cacca871af --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/PARENT-SOURCE-RECOVERY.json @@ -0,0 +1,69 @@ +{ + "observed_utc": "2026-11-02T08:41:50.736231+00:00", + "scope": "Bounded recovery of named ordinary source files only; not original import, execution, source admission or global census", + "files": [ + { + "path": "outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/parent_completion_v1.py", + "copy": "unit02/prerequisite-source/field-parent-completion-v2--parent_completion_v1.py.txt", + "bytes": 54168, + "sha256": "d4ee1b7ce4a42b73261984ffb1b9ceb5bb0165223e04a253588f83b99f6981a5", + "available": true + }, + { + "path": "outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/parent_domain_v1.py", + "copy": "unit02/prerequisite-source/field-parent-completion-v2--parent_domain_v1.py.txt", + "bytes": 20456, + "sha256": "9205e14d6661fb5df0597f0ad7b2206006f2d31f01f784805f64c13875663282", + "available": true + }, + { + "path": "outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/parent_closure_v1.py", + "copy": "unit02/prerequisite-source/field-parent-completion-v2--parent_closure_v1.py.txt", + "bytes": 13400, + "sha256": "2d831cff8bd444de2d6941645d571e07618ede404a1f45692b557f61494b334a", + "available": true + }, + { + "path": "outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/group01_evidence_v1.py", + "copy": "unit02/prerequisite-source/field-parent-completion-v2--group01_evidence_v1.py.txt", + "bytes": 15610, + "sha256": "05ec6a63c57340ba929aea1fab71b096efc143e099346640f6def41310bd3e25", + "available": true + }, + { + "path": "outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/SOURCE-READINESS.json", + "copy": "unit02/prerequisite-source/field-parent-completion-v2--SOURCE-READINESS.json.txt", + "bytes": 6046, + "sha256": "5c5b3509ec8eff3fe2e8fe5e7b1e95c7790a964fb0fe401ed5c0049d88ea6520", + "available": true + }, + { + "path": "outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_schema_v5.py", + "copy": "unit02/prerequisite-source/field-negative-epoch-v5--epoch_schema_v5.py.txt", + "bytes": 30668, + "sha256": "b89a789654be87bde40a47300f4d9702dce2b90e6ab3be9a2025f6d8041b3e9a", + "available": true + }, + { + "path": "outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_copy_v5.py", + "copy": "unit02/prerequisite-source/field-negative-epoch-v5--epoch_copy_v5.py.txt", + "bytes": 82957, + "sha256": "4f459d0336d59975df787c24373e18dad4044c3a24137392e890115f811b3211", + "available": true + }, + { + "path": "outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_parent_v5.py", + "copy": "unit02/prerequisite-source/field-negative-epoch-v5--epoch_parent_v5.py.txt", + "bytes": 26833, + "sha256": "058059912144863a4b2bfe4fc9ffc5233b4ab20ee5a7355bde66f4d3f6f28712", + "available": true + }, + { + "path": "outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/SOURCE-READINESS.json", + "copy": "unit02/prerequisite-source/field-negative-epoch-v5--SOURCE-READINESS.json.txt", + "bytes": 6055, + "sha256": "611a9dff18b50442fe61702655180d69790746dc3c8154b9ff25098c5c5c6714", + "available": true + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/PR-COVERAGE.json b/research/h25-c05-v03-parent-interface-audit/evidence/PR-COVERAGE.json new file mode 100644 index 0000000000..a32e18d7b0 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/PR-COVERAGE.json @@ -0,0 +1,309 @@ +{ + "observed_utc": "2026-11-02 09:05:30 UTC", + "scope": "23 declared C05/full named V03 dependency nodes; metadata refreshed, source depth limited to exact named bodies and prior reviewed source snapshots, not global source exhaustiveness", + "base": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "PRs": [ + { + "number": 6321, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6321", + "title": "Archive H25 cache source components and hand off N22, P07 and P02", + "state": "closed", + "draft": false, + "merged": true, + "head": "ca9d90e93dc495e1e5e5ef6d271ff1e4f089cd0c", + "base": "2485805a6d47f36ea83ddde6327d453ac82d44dc", + "files": 117, + "commits": 1, + "updated_at": "2026-11-02T08:44:27Z" + }, + { + "number": 6339, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6339", + "title": "Cursor/h25 g12 identity cleanup 5d9d", + "state": "closed", + "draft": false, + "merged": true, + "head": "608ad23adc6c01264c8195daf7f18e29c17464a7", + "base": "626e936ce4d61f2584316914fc71baf96940c512", + "files": 9, + "commits": 3, + "updated_at": "2026-11-02T01:56:46Z" + }, + { + "number": 6346, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6346", + "title": "Repair bounded G12 custody cleanup and publication-size checks", + "state": "open", + "draft": true, + "merged": false, + "head": "abff67b31fa781e950c82d95eccb6f168950943c", + "base": "626e936ce4d61f2584316914fc71baf96940c512", + "files": 14, + "commits": 1, + "updated_at": "2026-11-02T00:10:29Z" + }, + { + "number": 6347, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6347", + "title": "Record G12 acquisition and raw-error delivery boundaries", + "state": "open", + "draft": true, + "merged": false, + "head": "59140439e7f791876159e2f3838f1dead2e54953", + "base": "626e936ce4d61f2584316914fc71baf96940c512", + "files": 9, + "commits": 2, + "updated_at": "2026-11-02T00:12:34Z" + }, + { + "number": 6316, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6316", + "title": "Bound retained-log memory and preserve fast-exit output-cap checks", + "state": "closed", + "draft": false, + "merged": true, + "head": "f99829cfc669c0aa61d7d505b0a58f7e697c6582", + "base": "2485805a6d47f36ea83ddde6327d453ac82d44dc", + "files": 21, + "commits": 1, + "updated_at": "2026-10-31T04:04:55Z" + }, + { + "number": 6317, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6317", + "title": "Add lossless evidence archive and exact restoration controls", + "state": "closed", + "draft": false, + "merged": true, + "head": "336015471e4f1bb95998f293aa76823fe11e33d5", + "base": "2485805a6d47f36ea83ddde6327d453ac82d44dc", + "files": 15, + "commits": 1, + "updated_at": "2026-10-31T04:04:54Z" + }, + { + "number": 6326, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6326", + "title": "Extract bounded H25 serializer with 140 finite controls and retained failure evidence", + "state": "open", + "draft": true, + "merged": false, + "head": "90df75ee32d0c51acbcc5b63ebbe6f26011ee92b", + "base": "a7638a4ce2a29947457ae8d6bf8cd70a234dfeac", + "files": 103, + "commits": 2, + "updated_at": "2026-10-31T05:00:03Z" + }, + { + "number": 6328, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6328", + "title": "Tooling: reuse same-call inventory SHA with retained checks", + "state": "open", + "draft": true, + "merged": false, + "head": "c95f76dfad324e6488a88dab9988ce534ee2a481", + "base": "a7638a4ce2a29947457ae8d6bf8cd70a234dfeac", + "files": 191, + "commits": 2, + "updated_at": "2026-10-31T06:07:38Z" + }, + { + "number": 6332, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6332", + "title": "Add authentic H25 serializer sources and retain first runtime authentication failure", + "state": "open", + "draft": true, + "merged": false, + "head": "85fa502d063c132a48eadeb4dc8a188e668a88e0", + "base": "a7638a4ce2a29947457ae8d6bf8cd70a234dfeac", + "files": 134, + "commits": 2, + "updated_at": "2026-10-31T08:57:51Z" + }, + { + "number": 6335, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6335", + "title": "Archive O03 W1-W4 source repair and retained timing-review history", + "state": "open", + "draft": true, + "merged": false, + "head": "d34b84f1e1d9fb4bdcf26eda8817c3603fea3051", + "base": "626e936ce4d61f2584316914fc71baf96940c512", + "files": 575, + "commits": 1, + "updated_at": "2026-11-01T09:22:12Z" + }, + { + "number": 6344, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6344", + "title": "Record that the PR6335 W2/W4 identities do not close N1.", + "state": "closed", + "draft": false, + "merged": true, + "head": "5778b35a4ca2453e4955e8203a1a3b1cfeb5935b", + "base": "626e936ce4d61f2584316914fc71baf96940c512", + "files": 12, + "commits": 1, + "updated_at": "2026-11-02T01:56:46Z" + }, + { + "number": 6029, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6029", + "title": "Reduce complete H25 bookkeeping time by 21%", + "state": "closed", + "draft": false, + "merged": true, + "head": "e05aad954689d0ee21baff19b4674f1fcb2e838f", + "base": "19fdb086ea96af9a9f87936a2b888e10af4ed810", + "files": 378, + "commits": 3, + "updated_at": "2026-10-28T00:24:31Z" + }, + { + "number": 5995, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/5995", + "title": "Reduce complete H25 certificate qualification time by 28%", + "state": "closed", + "draft": false, + "merged": true, + "head": "4f4159820c37f01d245784d1186bd51fcbc8ebb6", + "base": "19fdb086ea96af9a9f87936a2b888e10af4ed810", + "files": 125, + "commits": 2, + "updated_at": "2026-10-28T00:24:32Z" + }, + { + "number": 5929, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/5929", + "title": "Reduce H25 side-verification time by 29% with exact native GF(2)", + "state": "closed", + "draft": false, + "merged": true, + "head": "a456c246ec72a23f327d4b1394fbb3bf7087a65c", + "base": "aacce1a2c411a2f083b5fd5f1cdcf87661267ca3", + "files": 113, + "commits": 3, + "updated_at": "2026-10-28T00:24:33Z" + }, + { + "number": 5972, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/5972", + "title": "Archive complete verification keys and negative 15% cost screen", + "state": "closed", + "draft": false, + "merged": true, + "head": "1018e3751fce3aacf99a5dbdc05d387fb63b6672", + "base": "19fdb086ea96af9a9f87936a2b888e10af4ed810", + "files": 275, + "commits": 2, + "updated_at": "2026-10-28T00:24:32Z" + }, + { + "number": 5908, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/5908", + "title": "Archive C verification batching and failed complete speed gates", + "state": "closed", + "draft": false, + "merged": true, + "head": "4b6d9c0d630b7809e43651eadcb4921ea5dbde56", + "base": "de5ec2e7a6074068452f45b1a191b5c72832df4a", + "files": 128, + "commits": 7, + "updated_at": "2026-10-27T13:54:41Z" + }, + { + "number": 5864, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/5864", + "title": "Reduce complete precision qualification time by 19% with C bookkeeping", + "state": "closed", + "draft": false, + "merged": true, + "head": "3f15c943e4ad6479f03e674c80fff1269a16ccfe", + "base": "de5ec2e7a6074068452f45b1a191b5c72832df4a", + "files": 166, + "commits": 4, + "updated_at": "2026-10-27T13:41:53Z" + }, + { + "number": 5875, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/5875", + "title": "Archive scoped negative native Fraction score-dispatch probe", + "state": "closed", + "draft": false, + "merged": true, + "head": "3ed05e3ebf48c0ea507b9819dad30898942d4ca8", + "base": "de5ec2e7a6074068452f45b1a191b5c72832df4a", + "files": 55, + "commits": 3, + "updated_at": "2026-10-27T13:41:53Z" + }, + { + "number": 6351, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6351", + "title": "Clarify original G12 caught-primary and accounting scope", + "state": "open", + "draft": true, + "merged": false, + "head": "1e9db2d08be4551ffe0bcfc573574851530eb4ca", + "base": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "files": 7, + "commits": 1, + "updated_at": "2026-11-02T03:27:57Z" + }, + { + "number": 6352, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6352", + "title": "Resolve V03 entry preflight and dependency source questions", + "state": "open", + "draft": true, + "merged": false, + "head": "b280be8dab15359159538e639b1d8c7deafc0612", + "base": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "files": 21, + "commits": 1, + "updated_at": "2026-11-02T03:27:58Z" + }, + { + "number": 6354, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6354", + "title": "Construct C05 source roots and conditional header prefixes", + "state": "open", + "draft": true, + "merged": false, + "head": "b3771dbc5f713ba3e90170c1dc3321e653222c65", + "base": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "files": 19, + "commits": 1, + "updated_at": "2026-11-02T04:20:04Z" + }, + { + "number": 6358, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6358", + "title": "Observe C05 namespace prefixes through owned descriptors", + "state": "open", + "draft": true, + "merged": false, + "head": "84b0e70ba4da44b7904fe8d13903c26a3a8239e1", + "base": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "files": 10, + "commits": 1, + "updated_at": "2026-11-02T05:42:06Z" + }, + { + "number": 6362, + "url": "https://github.com/CrocSwap/integer-mult-bounds/pull/6362", + "title": "C05/V03: add input-edge constructors and genuine source-control drafts", + "state": "open", + "draft": true, + "merged": false, + "head": "120072d58ddb46f0e02886756243174d41fce42e", + "base": "7c49fe32c55de02c2c873655c804b16e4c3fef0a", + "files": 232, + "commits": 1, + "updated_at": "2026-11-02T08:48:51Z" + } + ], + "search_scope": "Preserved 22-node previous task dependency graph plus new PR6362; no unrelated upstream research or old conversation census", + "earlier_publication_gap": "PR6362 body/Pro prompt referenced PR-COVERAGE in that package, but file was local session material, not actually exported. This is the explicit public coverage export; earlier gap preserved.", + "source_depth": "Current metadata does not imply re-review of all current-head source; SOURCE-ORIGIN/source findings name actual inspected bytes" +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/RECEIVER-SOURCE-MAP.json b/research/h25-c05-v03-parent-interface-audit/evidence/RECEIVER-SOURCE-MAP.json new file mode 100644 index 0000000000..7de7bb0a1c --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/RECEIVER-SOURCE-MAP.json @@ -0,0 +1,385 @@ +{ + "count": 33, + "initial_trust": "Original trusted parent bootstrap must authenticate exact named modules before this component; source-byte pins cannot authenticate a hostile interpreter or privileged host.", + "modules": { + "close_model_controls_v5": { + "bytes": 6949, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/close_model_controls_v5.py", + "sha256": "9beda1b7555959eb9b6b6aa558f29655146ff8067fc7496059ba13b7843f0b60" + }, + "collector_controls_v1": { + "bytes": 11877, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/collector_controls_v1.py", + "sha256": "094f345a4f69b2d1aa648e40315a000ad3dfeeb929218475b0164629c24c4b5a" + }, + "driver_model_body_sources_v3": { + "bytes": 5230, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/driver_model_body_sources_v3.py", + "sha256": "f36e5cf59ee68b271f3d207fe0eca6f5f7503511ca4062b5681275f713e30a8a" + }, + "elf_controls_v1": { + "bytes": 6301, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/elf_controls_v1.py", + "sha256": "306eec9c04be89dc9cbdbf8ed3ad804a9a664abce5b2c30036c6008434f046c8" + }, + "elf_extended_controls_v2": { + "bytes": 32860, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/elf_extended_controls_v2.py", + "sha256": "e55ab5f1ea7a7a9d64a9847695b68abd09518431a6016c9ddb70b469002fdaa7" + }, + "elf_literal_fixture_v1": { + "bytes": 6825, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/elf_literal_fixture_v1.py", + "sha256": "9a1f1105cea03f187efc2bdb65dd7b00e0111517f5043ef29005511018aaa5a2" + }, + "elf_literal_fixture_v2": { + "bytes": 9265, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/elf_literal_fixture_v2.py", + "sha256": "dc4854a6ac50f025399dec823c658f24bfb22ada4a6d60c317a49ec7a110e0ce" + }, + "epoch_copy_v5": { + "bytes": 82957, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_copy_v5.py", + "sha256": "4f459d0336d59975df787c24373e18dad4044c3a24137392e890115f811b3211" + }, + "epoch_parent_v5": { + "bytes": 26833, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_parent_v5.py", + "sha256": "058059912144863a4b2bfe4fc9ffc5233b4ab20ee5a7355bde66f4d3f6f28712" + }, + "epoch_schema_v5": { + "bytes": 30668, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_schema_v5.py", + "sha256": "b89a789654be87bde40a47300f4d9702dce2b90e6ab3be9a2025f6d8041b3e9a" + }, + "epoch_stop_v5": { + "bytes": 8205, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_stop_v5.py", + "sha256": "5b10c9d72dd0e646652a73b6ffe9ba870762d6bc2f7432bc6b06571a1b7d2a6f" + }, + "group01_evidence_v1": { + "bytes": 15610, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/group01_evidence_v1.py", + "sha256": "05ec6a63c57340ba929aea1fab71b096efc143e099346640f6def41310bd3e25" + }, + "group01_original_predicates_v1": { + "bytes": 23224, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/group01_original_predicates_v1.py", + "sha256": "fb9e6e11b39b76ab8652c546fd76c06d662ea4116376abcc2a6267bb4783dbfd" + }, + "group_evidence_v5": { + "bytes": 18794, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/group_evidence_v5.py", + "sha256": "206802db0f9af87ab3c0edb2dd48d3257ddc9012fe0fcdfc4df73b04c56bf37c" + }, + "h25_parent_supervisor": { + "bytes": 23047, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/execution-guards/build-log-queue-v2/supervisor.py", + "sha256": "cfb09a18dd10b597cc6d5a8139ee769bef679bc44ae029329755e3d97b055075" + }, + "loader_model_controls_v1": { + "bytes": 18126, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/loader_model_controls_v1.py", + "sha256": "3686813f7267a2f843ed5f35090d73b26c14cf3f350a8f664cdfc5dd34726fdd" + }, + "loader_model_controls_v3": { + "bytes": 36286, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/loader_model_controls_v3.py", + "sha256": "2c324511d4ab6f27a9ce8bf9717476c9c6e474101e0ed090d19dc951b8d04c02" + }, + "native_field_controls_v1": { + "bytes": 18980, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/native_field_controls_v1.py", + "sha256": "a9a4904c41c490509b0033bc8be2536a81aff68232f068ab884f614e7b51e64e" + }, + "original_build_provenance_v5": { + "bytes": 16024, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/original_build_provenance_v5.py", + "sha256": "bd5ffd9a1c221e0945527fc8fa8d0ad4eb36b9a8884503451c1b6b12d00007ea" + }, + "parent_closure_v1": { + "bytes": 13400, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/parent_closure_v1.py", + "sha256": "2d831cff8bd444de2d6941645d571e07618ede404a1f45692b557f61494b334a" + }, + "parent_completion_v1": { + "bytes": 54168, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/parent_completion_v1.py", + "sha256": "d4ee1b7ce4a42b73261984ffb1b9ceb5bb0165223e04a253588f83b99f6981a5" + }, + "parent_domain_v1": { + "bytes": 20456, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/parent_domain_v1.py", + "sha256": "9205e14d6661fb5df0597f0ad7b2206006f2d31f01f784805f64c13875663282" + }, + "projection_model_controls_v5": { + "bytes": 11654, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/projection_model_controls_v5.py", + "sha256": "668bde5f7998bf9e49817019b4c53c2d8e16aaf027fc5e9d96c4c213103f8686" + }, + "provider_controls_v1": { + "bytes": 9283, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/provider_controls_v1.py", + "sha256": "8478395c16fcc8ab2443f8934c77bb9589bdc4cf981e73101de28df08c198ab9" + }, + "receipt_contract_v1": { + "bytes": 3592, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/receipt_contract_v1.py", + "sha256": "f7064029c55923114c5fc96c06ec0bc06825661a51cbce5a2a7cb932d9f13bb6" + }, + "restoration_contract_v1": { + "bytes": 5843, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/restoration_contract_v1.py", + "sha256": "2cfe462e75aef8b25c5b0556226f15e93e9ebab1433aae92ef5ddfaffbdcfe6c" + }, + "root_model_body_sources_v3": { + "bytes": 15650, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/root_model_body_sources_v3.py", + "sha256": "0e4a79dac6bb07a62e6624a07ad7f2e0b534d8cda42b7ef1b787a7d64de7b99b" + }, + "run_controls_v5": { + "bytes": 26939, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/run_controls_v5.py", + "sha256": "0e6c8a82c4902f2de707b1ceb1eb19932cd5607645bfb0cdd08c1eef715946aa" + }, + "run_pure_controls_v1": { + "bytes": 2735, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/run_pure_controls_v1.py", + "sha256": "7c6cfbaaec2959ad81262ea1caec39526405b83fa47876872b0a145a5e81abc2" + }, + "run_pure_controls_v2": { + "bytes": 3911, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/run_pure_controls_v2.py", + "sha256": "d64578b222facd38e69d362ed564702e8a10a95d3606cc4047d47c51d87c7ccd" + }, + "sealed_elf_profile_v2": { + "bytes": 76453, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/elf/sealed_elf_profile_v2.py", + "sha256": "89ed8c777e6b72af2d6a3595037e7e92385924c6087d88010a27192633391016" + }, + "transport_controls_v1": { + "bytes": 4272, + "mode": "0o664", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/integration-drafts/native-fields-v1/controls/transport_controls_v1.py", + "sha256": "c79942bbdd9460f79e100d85302e8d472cce896bb94a7f91cec7fdad039ce0f4" + }, + "variant_validation_v1": { + "bytes": 31791, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/variant_validation_v1.py", + "sha256": "5e099fbe13f9e6f548a36ba2202bceef2f5d479bed85529ce57b26654f7c0a98" + } + }, + "runtime_authority": null, + "schema": "h25-parent-v2-receiver-source-map", + "scope": "Exact selected source map only; all installed plans, policy, profiles and gates absent.", + "source_pin_deltas": [ + { + "new": { + "bytes": 82957, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_copy_v5.py", + "sha256": "4f459d0336d59975df787c24373e18dad4044c3a24137392e890115f811b3211" + }, + "new_name": "epoch_copy_v5", + "old": { + "bytes": 15914, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v3/epoch_copy_v3.py", + "sha256": "329a9cf9eb4324260771291521182e559fd7b1abc1331d4aa042efa7e36d6cff" + }, + "old_name": "epoch_copy_v3" + }, + { + "new": { + "bytes": 26833, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_parent_v5.py", + "sha256": "058059912144863a4b2bfe4fc9ffc5233b4ab20ee5a7355bde66f4d3f6f28712" + }, + "new_name": "epoch_parent_v5", + "old": { + "bytes": 24004, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v3/epoch_parent_v3.py", + "sha256": "fc5f567e343fad1158c01855beb57baa71f3757d2e649ecb8821108471bad92c" + }, + "old_name": "epoch_parent_v3" + }, + { + "new": { + "bytes": 30668, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_schema_v5.py", + "sha256": "b89a789654be87bde40a47300f4d9702dce2b90e6ab3be9a2025f6d8041b3e9a" + }, + "new_name": "epoch_schema_v5", + "old": { + "bytes": 26841, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v3/epoch_schema_v3.py", + "sha256": "1ed5ff525e09c5b956fb44bbaa2e19f2695586c981c70830b4621c50c96fb27b" + }, + "old_name": "epoch_schema_v3" + }, + { + "new": { + "bytes": 8205, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/epoch_stop_v5.py", + "sha256": "5b10c9d72dd0e646652a73b6ffe9ba870762d6bc2f7432bc6b06571a1b7d2a6f" + }, + "new_name": "epoch_stop_v5", + "old": { + "bytes": 6928, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v3/epoch_stop_v3.py", + "sha256": "89e436b7fe3ff78ad684e95bc5e697a9e8a759c29030b47e06ebcf31e006ea4b" + }, + "old_name": "epoch_stop_v3" + }, + { + "new": { + "bytes": 15610, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/group01_evidence_v1.py", + "sha256": "05ec6a63c57340ba929aea1fab71b096efc143e099346640f6def41310bd3e25" + }, + "new_name": "group01_evidence_v1", + "old": { + "bytes": 15083, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/group01_evidence_v1.py", + "sha256": "960997faefe053d5026582309f5248162ce6eae7abb3783716d0649de34826ba" + }, + "old_name": "group01_evidence_v1" + }, + { + "new": { + "bytes": 23224, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/group01_original_predicates_v1.py", + "sha256": "fb9e6e11b39b76ab8652c546fd76c06d662ea4116376abcc2a6267bb4783dbfd" + }, + "new_name": "group01_original_predicates_v1", + "old": { + "bytes": 23224, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/group01_original_predicates_v1.py", + "sha256": "894219d9caae63cc3cb39cf8611d494d1676828cce55cbf851f98d6dae7d62a7" + }, + "old_name": "group01_original_predicates_v1" + }, + { + "new": { + "bytes": 16024, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v5/original_build_provenance_v5.py", + "sha256": "bd5ffd9a1c221e0945527fc8fa8d0ad4eb36b9a8884503451c1b6b12d00007ea" + }, + "new_name": "original_build_provenance_v5", + "old": { + "bytes": 16024, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v3/original_build_provenance_v3.py", + "sha256": "7869a5041edbdcd2c5aa38455ac70a18f0dde7ed9643dfb11758502af41966bf" + }, + "old_name": "original_build_provenance_v3" + }, + { + "new": { + "bytes": 13400, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/parent_closure_v1.py", + "sha256": "2d831cff8bd444de2d6941645d571e07618ede404a1f45692b557f61494b334a" + }, + "new_name": "parent_closure_v1", + "old": { + "bytes": 13400, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/parent_closure_v1.py", + "sha256": "131f4632dd13dbe06af06c6ff3a4eee04dcf403ed1d76d627ff3c3a29ed6fba4" + }, + "old_name": "parent_closure_v1" + }, + { + "new": { + "bytes": 54168, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/parent_completion_v1.py", + "sha256": "d4ee1b7ce4a42b73261984ffb1b9ceb5bb0165223e04a253588f83b99f6981a5" + }, + "new_name": "parent_completion_v1", + "old": { + "bytes": 48816, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/parent_completion_v1.py", + "sha256": "3ed30810bfffc15a43e6150689f20dc21bbd668fc3a3ff51bd808382556b717c" + }, + "old_name": "parent_completion_v1" + }, + { + "new": { + "bytes": 20456, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v2/parent_domain_v1.py", + "sha256": "9205e14d6661fb5df0597f0ad7b2206006f2d31f01f784805f64c13875663282" + }, + "new_name": "parent_domain_v1", + "old": { + "bytes": 15374, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-parent-completion-v1/parent_domain_v1.py", + "sha256": "0c4d3541b0d5cd9d091e02ccdfa4665909a775acfd3f24e8c28d6c7902d2a827" + }, + "old_name": "parent_domain_v1" + }, + { + "new": { + "bytes": 31791, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v2/variant_validation_v1.py", + "sha256": "5e099fbe13f9e6f548a36ba2202bceef2f5d479bed85529ce57b26654f7c0a98" + }, + "new_name": "variant_validation_v1", + "old": { + "bytes": 27812, + "mode": "0o444", + "path": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-variant-producer-v1/variant_validation_v1.py", + "sha256": "6ce69709e8831e7aa0b2850154ab26d11ff76c933c878c17ffbde065eaf6f4f9" + }, + "old_name": "variant_validation_v1" + } + ] +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/SOURCE-GATE-CLOSE.json b/research/h25-c05-v03-parent-interface-audit/evidence/SOURCE-GATE-CLOSE.json new file mode 100644 index 0000000000..1a022b7886 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/SOURCE-GATE-CLOSE.json @@ -0,0 +1,23 @@ +{ + "phase": "closed_at_source_gate_no_implementation", + "closed_utc": "2026-11-02T08:46:20.430497+00:00", + "reason": "Concrete source gate cannot yet admit integration: exact clean executable parent bootstrap is unimplemented; actual parent/domain/closure incompatibilities need an explicit successor and Pro4 assessment. No source implementation extension or automatic retry.", + "independently_accepted_complete_unit_milestones": 0, + "conditional_source_findings": [ + "fresh copied native mappings compatible only after fresh runtime exec", + "unchanged parent hardcodes original driver/inventory/two-build/empty-stderr receiver", + "unchanged domain terminal_facts requires returncode0 and caps4domains", + "closure namespace census/mutability allowlist constrains any successor" + ], + "new_implementation_files": 0, + "new_tests_executed": 0, + "original_execution": false, + "full_C05": false, + "full_V03": false, + "runtime_qualification": false, + "agents_requested_stop": [ + "c05_header_closure", + "c05_elf_input_edges" + ], + "next_exact_dependency": "Capture and assess Pro4; establish concrete source-admitted successor/bootstrap and actual compiler configuration/query frontier. Publication of resolved source audit is a separate disposition." +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/SOURCE-MANIFEST.json b/research/h25-c05-v03-parent-interface-audit/evidence/SOURCE-MANIFEST.json new file mode 100644 index 0000000000..0799fe0bf4 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/SOURCE-MANIFEST.json @@ -0,0 +1,183 @@ +{ + "excluded_self_seal_files": [ + "SOURCE-MANIFEST.json", + "SHA256SUMS", + "FREEZE-READBACK.json" + ], + "files": { + "ANCESTOR-PINS.json": { + "bytes": 5410, + "mode": "0444", + "sha256": "0be7424adf511090a77899c33cf2d9ae9b570a803dcf8133d0e78b14df07dd47" + }, + "API-AND-GATES.json": { + "bytes": 1729, + "mode": "0444", + "sha256": "066ecc151356d3253c5cdc0081e339857fef6c0b2f32e8b0d863e2eaace6bebf" + }, + "COMPLETE-COST-BILL.json": { + "bytes": 6223, + "mode": "0444", + "sha256": "8f570c18c286a7d4fc962358f798b83a41fa2f508c40335cdf9277844203a3ea" + }, + "CONDITIONS.json": { + "bytes": 3590, + "mode": "0444", + "sha256": "3333cab0bedefa9f9f78df49fc82c4521ee755cf6c6e3d460a5130b8e511b7ed" + }, + "DEPENDENCY-SELECTION.json": { + "bytes": 1544, + "mode": "0444", + "sha256": "4cfa1ce08239756fef77bbdde27b18a3c85765e82da7e4e2ad3785e9b7a1a22d" + }, + "FINAL-READBACK.json": { + "bytes": 53251, + "mode": "0444", + "sha256": "dabae2bf52d60062c7b7783ff3f99687ce794ca29558206cf5e540027fd60669" + }, + "INPUT-PINS.json": { + "bytes": 48454, + "mode": "0444", + "sha256": "c8dc314f3330819c4d9cb8183532f4f5d90f2a1229a4b1202d2ccba6dac0ee33" + }, + "INSPECTOR-ATTEMPTS.json": { + "bytes": 901, + "mode": "0444", + "sha256": "3183dfe1e5b4c21c27e33c64b5c92f79cb8a2f9b399149e393744cd071626b59" + }, + "LOCAL-CURRENT-TASK.md": { + "bytes": 11051, + "mode": "0444", + "sha256": "a8286d32d630db6235e8ddcba77aba291948fcf8c078fa6336c88e7f23346366" + }, + "OLD-EXPECTATION-DISPOSITIONS.json": { + "bytes": 1552, + "mode": "0444", + "sha256": "fe7b6f28f2c9f094f9edcda26ee4a852f6a5c54a72767b694a9ef8945816c49e" + }, + "PASSIVE-ATTEMPT-01.log": { + "bytes": 496, + "mode": "0444", + "sha256": "2c124d62a824e4139bfd9f6eee223e0f243e199989c9e0eb17ac00f0d5df1c4f" + }, + "PASSIVE-ATTEMPT-02.log": { + "bytes": 935, + "mode": "0444", + "sha256": "1fd99c7b753a691e90bcd97fa6eb24fe32a9dd11b6f1fae6f8db7e25bdb22c58" + }, + "PASSIVE-ATTEMPT-03.log": { + "bytes": 890, + "mode": "0444", + "sha256": "8e6ba537ac0a3a5d9ce23c980c4c656980097d4625f88ecc0789e3b3674c475e" + }, + "PASSIVE-CHECKS-attempt02.json": { + "bytes": 42825, + "mode": "0444", + "sha256": "3c3524ce7011d163311080441e1946438bc29e9b480da3766479c5b3e039e4ca" + }, + "PASSIVE-CHECKS.json": { + "bytes": 42824, + "mode": "0444", + "sha256": "753fe95f3121160940d136ec21efeef3679c0249dce82efc43b41e0b46defdc6" + }, + "README.md": { + "bytes": 5269, + "mode": "0444", + "sha256": "398302226937d4e8671a0121f6a6f46d2de8fa513a5da5e0f89220fb4f5e67cd" + }, + "RECEIVER-SOURCE-MAP.json": { + "bytes": 20868, + "mode": "0444", + "sha256": "532733f4d78fc327f00851f33e1db20ae8ef34fd904fc56327d44a4ebea11067" + }, + "REPAIR-CLAIMS.json": { + "bytes": 2260, + "mode": "0444", + "sha256": "77846b667bfbba00292e51e327b386b6b960cc94e64e5c9732658caae0ae4729" + }, + "SOURCE-DELTA.json": { + "bytes": 16159, + "mode": "0444", + "sha256": "7c16f7698cb13581dea2156ad3bf6f3e1f73f8fb040df9e9f45990deeb6226c3" + }, + "SOURCE-INVERSE.json": { + "bytes": 39088, + "mode": "0444", + "sha256": "558ffcc429835537fcb430881226aa7e2bc065d2934ee62b716dde8605e42409" + }, + "SOURCE-READINESS.json": { + "bytes": 6046, + "mode": "0444", + "sha256": "5c5b3509ec8eff3fe2e8fe5e7b1e95c7790a964fb0fe401ed5c0049d88ea6520" + }, + "SOURCE-TEST-RECIPES.json": { + "bytes": 13798, + "mode": "0444", + "sha256": "354a116c8dd252ff39494de020058561aa62cda92731f96cc6e26993192fe54c" + }, + "TYPE-ENVELOPE.json": { + "bytes": 2096, + "mode": "0444", + "sha256": "b7fa437cf53e8798eb62e603fbc4f94daf20e9a10c6529dd5bb6a9f2c6f090e1" + }, + "final_readback.py": { + "bytes": 5164, + "mode": "0444", + "sha256": "0053aafd37f97b5c72aa4b034ce7a8f71b06369cbc79455c5c7553cecf1cbb1a" + }, + "group01_evidence_v1.py": { + "bytes": 15610, + "mode": "0444", + "sha256": "05ec6a63c57340ba929aea1fab71b096efc143e099346640f6def41310bd3e25" + }, + "group01_original_predicates_v1.py": { + "bytes": 23224, + "mode": "0444", + "sha256": "fb9e6e11b39b76ab8652c546fd76c06d662ea4116376abcc2a6267bb4783dbfd" + }, + "parent_closure_v1.py": { + "bytes": 13400, + "mode": "0444", + "sha256": "2d831cff8bd444de2d6941645d571e07618ede404a1f45692b557f61494b334a" + }, + "parent_completion_v1.py": { + "bytes": 54168, + "mode": "0444", + "sha256": "d4ee1b7ce4a42b73261984ffb1b9ceb5bb0165223e04a253588f83b99f6981a5" + }, + "parent_domain_v1.py": { + "bytes": 20456, + "mode": "0444", + "sha256": "9205e14d6661fb5df0597f0ad7b2206006f2d31f01f784805f64c13875663282" + }, + "prepare_packet-attempt01.py": { + "bytes": 15815, + "mode": "0444", + "sha256": "0c3895f6dd74a5968417f9951f1df0f064b529da28bd064e0fb4602c9cb6c879" + }, + "prepare_packet-attempt02.py": { + "bytes": 15799, + "mode": "0444", + "sha256": "d2492abf2693131b884b9f022002153ba6896972a0ae456ba49a058b172a7225" + }, + "prepare_packet.py": { + "bytes": 15903, + "mode": "0444", + "sha256": "7f65510b16f7d8c378a879b274cefce0afdf0b6319ef3a4237e7d8c2f7010c0e" + }, + "seal_packet.py": { + "bytes": 2847, + "mode": "0444", + "sha256": "0f872376aa918341604c6b81535431117f7863b3cc76ec4b17590763178e0327" + }, + "write_metadata.py": { + "bytes": 24273, + "mode": "0444", + "sha256": "863a862acc30f740573f1b7ccca932a2dbaeb1658094bbfa3d6fa598dcd0927e" + } + }, + "input_images_separately_bound": 148, + "schema": "h25-parent-v2-source-manifest", + "source_only": true, + "target_execution": 0 +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/UNIT-PLAN.json b/research/h25-c05-v03-parent-interface-audit/evidence/UNIT-PLAN.json new file mode 100644 index 0000000000..0edd037867 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/UNIT-PLAN.json @@ -0,0 +1,20 @@ +{ + "unit": "02_integrated_copied_input_owner", + "started_utc": "2026-11-02T08:31:54.986977+00:00", + "input_gate_deadline_utc": "2026-11-02T08:46:54.986977+00:00", + "initial_no_progress_deadline_utc": "2026-11-02T09:01:54.986977+00:00", + "hard_deadline_utc": "2026-11-02T09:31:54.986977+00:00", + "scope": "Distinct integration unit after Unit01 source freeze and PR6362 submission. Concrete descriptor-retaining acquisition/private installation/shared first-error/witness shards plus conditional mount-transition and clean-parent handoff. No original/native/compiler/namespace execution.", + "source_gate": "Exact recovered native profile must permit fresh copy; concrete retained-ownership clean-parent interface, no fabricated Root or substituted pid; stop implementation if no concrete interface by15minutes.", + "mechanism_selection": "Source-only fresh private copied filesystem requiring FUTURE explicit privileged setup admission. This choice grants no CAP_SYS_ADMIN or native execution authority. No arbitrary supplied lease/success boolean.", + "milestones": [ + "independently verified native/profile + parent interface", + "retained descriptor acquisition + installation verified on fresh owned fixtures", + "conditional concrete mount/clean-parent handoff source independently reviewed", + "complete source/bounds/error review and retained final validation" + ], + "one_repair_max_minutes": 15, + "no_automatic_extension": true, + "original_C05_and_V03_remain_open": true, + "old_units_and_pauses_unchanged": true +} diff --git a/research/h25-c05-v03-parent-interface-audit/evidence/initial-copy-name-collision.txt b/research/h25-c05-v03-parent-interface-audit/evidence/initial-copy-name-collision.txt new file mode 100644 index 0000000000..8cfb166357 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/evidence/initial-copy-name-collision.txt @@ -0,0 +1,158 @@ +{ + "actual_native_profile_and_semantic_configuration_linkage": null, + "additive_parent_recipe_families": 20, + "all38_parent_recipes_unexecuted": true, + "artifacts": { + "API-AND-GATES.json": { + "bytes": 1729, + "path": "API-AND-GATES.json", + "sha256": "066ecc151356d3253c5cdc0081e339857fef6c0b2f32e8b0d863e2eaace6bebf" + }, + "COMPLETE-COST-BILL.json": { + "bytes": 6223, + "path": "COMPLETE-COST-BILL.json", + "sha256": "8f570c18c286a7d4fc962358f798b83a41fa2f508c40335cdf9277844203a3ea" + }, + "CONDITIONS.json": { + "bytes": 3590, + "path": "CONDITIONS.json", + "sha256": "3333cab0bedefa9f9f78df49fc82c4521ee755cf6c6e3d460a5130b8e511b7ed" + }, + "DEPENDENCY-SELECTION.json": { + "bytes": 1544, + "path": "DEPENDENCY-SELECTION.json", + "sha256": "4cfa1ce08239756fef77bbdde27b18a3c85765e82da7e4e2ad3785e9b7a1a22d" + }, + "INPUT-PINS.json": { + "bytes": 48454, + "path": "INPUT-PINS.json", + "sha256": "c8dc314f3330819c4d9cb8183532f4f5d90f2a1229a4b1202d2ccba6dac0ee33" + }, + "INSPECTOR-ATTEMPTS.json": { + "bytes": 901, + "path": "INSPECTOR-ATTEMPTS.json", + "sha256": "3183dfe1e5b4c21c27e33c64b5c92f79cb8a2f9b399149e393744cd071626b59" + }, + "OLD-EXPECTATION-DISPOSITIONS.json": { + "bytes": 1552, + "path": "OLD-EXPECTATION-DISPOSITIONS.json", + "sha256": "fe7b6f28f2c9f094f9edcda26ee4a852f6a5c54a72767b694a9ef8945816c49e" + }, + "PASSIVE-CHECKS.json": { + "bytes": 42824, + "path": "PASSIVE-CHECKS.json", + "sha256": "753fe95f3121160940d136ec21efeef3679c0249dce82efc43b41e0b46defdc6" + }, + "README.md": { + "bytes": 5269, + "path": "README.md", + "sha256": "398302226937d4e8671a0121f6a6f46d2de8fa513a5da5e0f89220fb4f5e67cd" + }, + "RECEIVER-SOURCE-MAP.json": { + "bytes": 20868, + "path": "RECEIVER-SOURCE-MAP.json", + "sha256": "532733f4d78fc327f00851f33e1db20ae8ef34fd904fc56327d44a4ebea11067" + }, + "REPAIR-CLAIMS.json": { + "bytes": 2260, + "path": "REPAIR-CLAIMS.json", + "sha256": "77846b667bfbba00292e51e327b386b6b960cc94e64e5c9732658caae0ae4729" + }, + "SOURCE-DELTA.json": { + "bytes": 16159, + "path": "SOURCE-DELTA.json", + "sha256": "7c16f7698cb13581dea2156ad3bf6f3e1f73f8fb040df9e9f45990deeb6226c3" + }, + "SOURCE-INVERSE.json": { + "bytes": 39088, + "path": "SOURCE-INVERSE.json", + "sha256": "558ffcc429835537fcb430881226aa7e2bc065d2934ee62b716dde8605e42409" + }, + "SOURCE-TEST-RECIPES.json": { + "bytes": 13798, + "path": "SOURCE-TEST-RECIPES.json", + "sha256": "354a116c8dd252ff39494de020058561aa62cda92731f96cc6e26993192fe54c" + }, + "TYPE-ENVELOPE.json": { + "bytes": 2096, + "path": "TYPE-ENVELOPE.json", + "sha256": "b7fa437cf53e8798eb62e603fbc4f94daf20e9a10c6529dd5bb6a9f2c6f090e1" + } + }, + "command": null, + "complete_V1_byte_inverses": 5, + "complete_cost_fit_gain": "UNMEASURED_UNFUNDED_NO_GAIN", + "configuration": null, + "decision": "AUTHORED_B01_B02_CORRECTIVE_SOURCE_PENDING_INDEPENDENT_REVIEW", + "epoch7old12V4_5V5_and_variant33_specs_unexecuted": true, + "epoch92target104raw_per_mode_retained": true, + "epoch_gates_None": 20, + "execution": null, + "final_passive_checks_before_seal": 360, + "final_readback_sha256": "dabae2bf52d60062c7b7783ff3f99687ce794ca29558206cf5e540027fd60669", + "fixed_receiver_modules": 33, + "funding": null, + "handoff_words": 694, + "old_parent_recipe_families": 18, + "original_predicate_body_byte_identical": true, + "original_public_signatures_unchanged": true, + "own_gates_None": 6, + "owner": "/root/astra_composition_cost", + "passive_checks": 376, + "passive_failures": 0, + "policy_exec_domain_persistent_replay_full_orchestrator": "EXTERNAL_UNIMPLEMENTED", + "predecessor_readiness_sha256": "68ee02d81fffad3b1f5f67c549b91fb48994223a8f858dc3cb1cb97939b74643", + "predecessor_review_sha256": "c05392fcb818bf5af31e7dd6fc2f397e615532bfb8991e52b8c9f621c421c9e8", + "preserved_V1_files": 33, + "raw_before_compare_original_Root_API4_guards_oracles_events_unchanged": true, + "reviewed_source_selection_count": 1, + "runtime_modules": { + "group01_evidence_v1.py": { + "bytes": 15610, + "path": "group01_evidence_v1.py", + "sha256": "05ec6a63c57340ba929aea1fab71b096efc143e099346640f6def41310bd3e25" + }, + "group01_original_predicates_v1.py": { + "bytes": 23224, + "path": "group01_original_predicates_v1.py", + "sha256": "fb9e6e11b39b76ab8652c546fd76c06d662ea4116376abcc2a6267bb4783dbfd" + }, + "parent_closure_v1.py": { + "bytes": 13400, + "path": "parent_closure_v1.py", + "sha256": "2d831cff8bd444de2d6941645d571e07618ede404a1f45692b557f61494b334a" + }, + "parent_completion_v1.py": { + "bytes": 54168, + "path": "parent_completion_v1.py", + "sha256": "d4ee1b7ce4a42b73261984ffb1b9ceb5bb0165223e04a253588f83b99f6981a5" + }, + "parent_domain_v1.py": { + "bytes": 20456, + "path": "parent_domain_v1.py", + "sha256": "9205e14d6661fb5df0597f0ad7b2206006f2d31f01f784805f64c13875663282" + } + }, + "runtime_source_byte_delta": 10961, + "schema": "h25-parent-completion-source-readiness-v2", + "seal_files": [ + "SOURCE-MANIFEST.json", + "SHA256SUMS", + "FINAL-READBACK.json", + "FREEZE-READBACK.json" + ], + "selected_B_parent_adopted": true, + "selected_epoch": "V5 source acceptance only", + "selected_variant": "V2 source acceptance only", + "source_repairs": [ + "B01 own iterator uncertainty, original V5 state propagation, early-constructor and cross-mode quarantine; no fresh acquisition after uncertainty", + "B02 new exact-int scalar envelope plus typed independent pins; original predicate body preserved" + ], + "source_review": null, + "stage": null, + "stage_ledger_Git_browser_network_subagent_activity": 0, + "target_import_call_compile_parser_fixture_control_native_syscall_experiment_science_timing": 0, + "unchanged_input_images": 148, + "variant_gates_None": 12, + "whole_handler_or_native_release_proof": false +} diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/epoch_copy_v5.py.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/epoch_copy_v5.py.txt new file mode 100644 index 0000000000..0573ab23a5 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/epoch_copy_v5.py.txt @@ -0,0 +1,1897 @@ +"""Bounded exclusive copy source with opaque error ownership; never executed here.""" +import hashlib +import os +import stat +import epoch_schema_v5 as schema + +COPY_CONFIGURATION = None +COPY_EXECUTION_APPROVAL = None +COPY_FUNDING = None +_TYPE, _LEN = type, len +_OPEN, _CLOSE, _READ, _WRITE = os.open, os.close, os.read, os.write +_FSTAT, _STAT, _LSEEK, _FSYNC = os.fstat, os.stat, os.lseek, os.fsync +_SCANDIR, _STAT_RESULT = os.scandir, os.stat_result + + +def _gate() -> None: + schema.exact(COPY_CONFIGURATION, ('leaf_policy_sha256', 'configuration_sha256', 'scandir_release_premise_sha256')) + schema.exact(COPY_EXECUTION_APPROVAL, ('external_launch_policy_sha256',)) + schema.exact(COPY_FUNDING, ('reservation_sha256',)) + for values in (COPY_CONFIGURATION, COPY_EXECUTION_APPROVAL, COPY_FUNDING): + for value in values.values(): + schema.digest(value) + + +def _fd(value) -> None: + schema.integer(value, 0, (1 << 31) - 1) + + +def _identity(info) -> dict: + schema.need(_TYPE(info) is _STAT_RESULT, 'exact native stat result required') + row = dict(zip(schema.IDENTITY_KEYS, (info.st_dev, info.st_ino, info.st_mode, info.st_nlink, + info.st_uid, info.st_gid, info.st_size, info.st_mtime_ns, info.st_ctime_ns))) + for value in row.values(): + schema.integer(value, 0, (1 << 127) - 1) + return row + + + + + +def _parent(path: str, owner, fd_slots: list, destination: int) -> str: + """Fill the caller-owned slot; caller's finally owns all five slots. + + No descriptor tuple crosses the helper return boundary. The fifth slot + owns the next ancestor until its transfer; any helper-entry/body failure + leaves all known descriptors reachable to the caller's inline cleanup. + """ + schema.path(path) + _state = schema.owner_state(owner) + _primary, _secondary, _phases, _uncertain = _state[0], _state[1], _state[2], _state[3] + _counts, _overflow, _io = _state[4], _state[5], _state[7] + _attempt_digits, _confirmed_digits = _io[7], _io[8] + _successors = schema.CUSTODY_SUCCESSORS + _quarantine_error = schema.IO_QUARANTINE_ERROR + _base_error, _close_native = BaseException, _CLOSE + _error_index = _digit = 0 + _owned_fd = _close_error = _acquisition_error = None + cleanup_primary = operation_primary = None + schema.need(_TYPE(fd_slots) is list and _LEN(fd_slots) == 5, 'internal FD slots differ') + schema.integer(destination, 0, 3) + schema.need(fd_slots[destination] is None and fd_slots[4] is None, 'parent slots already owned') + parts = path.split('/') + name = parts[-1] + flags = os.O_RDONLY | os.O_CLOEXEC | os.O_NOFOLLOW | os.O_DIRECTORY + if _io[0] or _io[1] or _io[10] or _overflow[1] or _attempt_digits[4] == 1: + raise _quarantine_error + _io[1] = True + try: + fd_slots[destination] = _OPEN('/', flags) + except _base_error as _acquisition_error: + if _io[3] is None: + _io[3] = _acquisition_error + _io[0] = True + _io[2] = True + _io[4] = True + raise + _io[1] = False + _fd(fd_slots[destination]) + for part in parts[1:-1]: + if _io[0] or _io[1] or _io[10] or _overflow[1] or _attempt_digits[4] == 1: + raise _quarantine_error + _io[1] = True + try: + fd_slots[4] = _OPEN(part, flags, dir_fd=fd_slots[destination]) + except _base_error as _acquisition_error: + if _io[3] is None: + _io[3] = _acquisition_error + _io[0] = True + _io[2] = True + _io[4] = True + raise + _io[1] = False + _fd(fd_slots[4]) + previous = fd_slots[destination] + fd_slots[destination] = fd_slots[4] + fd_slots[4] = None + _owned_fd = previous + previous = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + if cleanup_primary is not None: + raise cleanup_primary + return name + +def _hash_fd(descriptor: int, limit: int) -> tuple[str, int]: + _fd(descriptor) + schema.integer(limit, 0, schema.FILE_BYTES) + digest, total, read_calls = hashlib.sha256(), 0, 0 + position = _LSEEK(descriptor, 0, os.SEEK_SET) + schema.integer(position, 0, 0) + while True: + read_calls += 1 + schema.need(read_calls <= schema.MAX_READ_CALLS, 'hash read-call bound exceeded') + raw = _READ(descriptor, min(schema.CHUNK_BYTES, limit + 1 - total)) + schema.need(_TYPE(raw) is bytes, 'native read returned foreign data') + if _LEN(raw) == 0: + break + total += _LEN(raw) + schema.need(total <= limit, 'file exceeds copy/hash bound') + digest.update(raw) + return digest.hexdigest(), total + + +def inspect(path: str, limit: int = schema.FILE_BYTES, *, error_owner) -> dict: + schema.owner_state(error_owner) + schema.path(path) + schema.integer(limit, 0, schema.FILE_BYTES) + _gate() + _state = schema.owner_state(error_owner) + _primary, _secondary, _phases, _uncertain = _state[0], _state[1], _state[2], _state[3] + _counts, _overflow, _io = _state[4], _state[5], _state[7] + _attempt_digits, _confirmed_digits = _io[7], _io[8] + _successors = schema.CUSTODY_SUCCESSORS + _quarantine_error = schema.IO_QUARANTINE_ERROR + _base_error, _close_native = BaseException, _CLOSE + _error_index = _digit = 0 + _owned_fd = _close_error = _acquisition_error = None + cleanup_primary = operation_primary = None + _fd_slots = [None] * 5 + _iterator = _owned_iterator = None + try: + name = _parent(path, error_owner, _fd_slots, 1) + parent = _fd_slots[1] + if _io[0] or _io[1] or _io[10] or _overflow[1] or _attempt_digits[4] == 1: + raise _quarantine_error + _io[1] = True + try: + _fd_slots[0] = _OPEN(name, os.O_RDONLY | os.O_CLOEXEC | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=parent) + except _base_error as _acquisition_error: + if _io[3] is None: + _io[3] = _acquisition_error + _io[0] = True + _io[2] = True + _io[4] = True + raise + _io[1] = False + descriptor = _fd_slots[0] + _fd(descriptor) + before = _identity(_FSTAT(descriptor)) + schema.need(stat.S_ISREG(before['mode']) and before['links'] == 1 and before['size'] <= limit, + 'file kind/link/size differs') + digest, count = _hash_fd(descriptor, limit) + after = _identity(_FSTAT(descriptor)) + named = _identity(_STAT(name, dir_fd=parent, follow_symlinks=False)) + schema.need(before == after == named and count == before['size'], 'file changed during bounded snapshot') + result = {'path': path, 'sha256': digest, 'bytes': count, 'identity': after} + schema.blob(result, limit) + return result + except _base_error as operation_error: + operation_primary = operation_error + if _primary[0] is None: + _primary[0] = operation_error + _primary[1] = 'inspect' + _primary[2] = None + elif _primary[0] is not operation_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = operation_error + _phases[_error_index] = 'inspect' + _uncertain[_error_index] = None + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = operation_error + raise + finally: + _owned_fd = _fd_slots[0] + _fd_slots[0] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[1] + _fd_slots[1] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[2] + _fd_slots[2] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[3] + _fd_slots[3] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[4] + _fd_slots[4] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + if operation_primary is None and cleanup_primary is not None: + raise cleanup_primary + +def verify(expected: dict, limit: int = schema.FILE_BYTES, *, error_owner) -> None: + schema.owner_state(error_owner) + schema.blob(expected, limit) + schema.need(inspect(expected['path'], limit, error_owner=error_owner) == expected, + 'current source/store custody differs') + + +def copy_once(source: dict, destination: str, occupied_inodes: tuple, *, error_owner) -> dict: + schema.owner_state(error_owner) + schema.blob(source) + schema.path(destination) + schema.need(_TYPE(occupied_inodes) is tuple and _LEN(occupied_inodes) <= 51, 'inode collection differs') + for pair in occupied_inodes: + schema.need(_TYPE(pair) is tuple and _LEN(pair) == 2, 'inode pair differs') + schema.integer(pair[0], 0, (1 << 127) - 1) + schema.integer(pair[1], 1, (1 << 127) - 1) + schema.need(source['path'] != destination, 'copy path aliases source') + _gate() + verify(source, error_owner=error_owner) + _state = schema.owner_state(error_owner) + _primary, _secondary, _phases, _uncertain = _state[0], _state[1], _state[2], _state[3] + _counts, _overflow, _io = _state[4], _state[5], _state[7] + _attempt_digits, _confirmed_digits = _io[7], _io[8] + _successors = schema.CUSTODY_SUCCESSORS + _quarantine_error = schema.IO_QUARANTINE_ERROR + _base_error, _close_native = BaseException, _CLOSE + _error_index = _digit = 0 + _owned_fd = _close_error = _acquisition_error = None + cleanup_primary = operation_primary = None + _fd_slots = [None] * 5 + _iterator = _owned_iterator = None + try: + source_name = _parent(source['path'], error_owner, _fd_slots, 3) + source_parent = _fd_slots[3] + target_name = _parent(destination, error_owner, _fd_slots, 2) + target_parent = _fd_slots[2] + if _io[0] or _io[1] or _io[10] or _overflow[1] or _attempt_digits[4] == 1: + raise _quarantine_error + _io[1] = True + try: + _fd_slots[1] = _OPEN(source_name, os.O_RDONLY | os.O_CLOEXEC | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=source_parent) + except _base_error as _acquisition_error: + if _io[3] is None: + _io[3] = _acquisition_error + _io[0] = True + _io[2] = True + _io[4] = True + raise + _io[1] = False + source_fd = _fd_slots[1] + _fd(source_fd) + before = _identity(_FSTAT(source_fd)) + schema.need(before == source['identity'], 'source changed before copy') + if _io[0] or _io[1] or _io[10] or _overflow[1] or _attempt_digits[4] == 1: + raise _quarantine_error + _io[1] = True + try: + _fd_slots[0] = _OPEN(target_name, os.O_RDWR | os.O_CREAT | os.O_EXCL | os.O_CLOEXEC | os.O_NOFOLLOW, 0o600, dir_fd=target_parent) + except _base_error as _acquisition_error: + if _io[3] is None: + _io[3] = _acquisition_error + _io[0] = True + _io[2] = True + _io[4] = True + raise + _io[1] = False + target_fd = _fd_slots[0] + _fd(target_fd) + initial = _identity(_FSTAT(target_fd)) + schema.need(stat.S_ISREG(initial['mode']) and initial['links'] == 1 and initial['size'] == 0 and + stat.S_IMODE(initial['mode']) == 0o600 and + (initial['device'], initial['inode']) not in occupied_inodes and + (initial['device'], initial['inode']) != schema.inode(source), 'exclusive destination alias') + digest, count, write_calls, read_calls = hashlib.sha256(), 0, 0, 0 + while True: + read_calls += 1 + schema.need(read_calls <= schema.MAX_READ_CALLS, 'copy read-call bound exceeded') + raw = _READ(source_fd, min(schema.CHUNK_BYTES, source['bytes'] + 1 - count)) + schema.need(_TYPE(raw) is bytes, 'native copy read returned foreign data') + if _LEN(raw) == 0: + break + count += _LEN(raw) + schema.need(count <= source['bytes'], 'source grew during copy') + digest.update(raw) + offset = 0 + while offset < _LEN(raw): + write_calls += 1 + schema.need(write_calls <= schema.MAX_WRITE_CALLS, 'copy write-call bound exceeded') + written = _WRITE(target_fd, raw[offset:]) + schema.integer(written, 1, _LEN(raw) - offset) + offset += written + schema.need(count == source['bytes'] and digest.hexdigest() == source['sha256'] and + _identity(_FSTAT(source_fd)) == source['identity'] and + _identity(_STAT(source_name, dir_fd=source_parent, follow_symlinks=False)) == source['identity'], + 'copy source custody/bytes differ') + _FSYNC(target_fd) + _FSYNC(target_parent) + before_readback = _identity(_FSTAT(target_fd)) + read_sha, read_size = _hash_fd(target_fd, schema.FILE_BYTES) + after = _identity(_FSTAT(target_fd)) + named = _identity(_STAT(target_name, dir_fd=target_parent, follow_symlinks=False)) + schema.need(read_sha == source['sha256'] and read_size == source['bytes'] and after['links'] == 1 and + (after['device'], after['inode']) == (initial['device'], initial['inode']) and + before_readback == after == named, 'destination readback/custody differs') + result = {'path': destination, 'sha256': read_sha, 'bytes': read_size, 'identity': after} + schema.blob(result) + verify(source, error_owner=error_owner) + schema.need(inspect(destination, error_owner=error_owner) == result, 'destination path changed after copy') + return result + except _base_error as operation_error: + operation_primary = operation_error + if _primary[0] is None: + _primary[0] = operation_error + _primary[1] = 'copy_once' + _primary[2] = None + elif _primary[0] is not operation_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = operation_error + _phases[_error_index] = 'copy_once' + _uncertain[_error_index] = None + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = operation_error + raise + finally: + _owned_fd = _fd_slots[0] + _fd_slots[0] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[1] + _fd_slots[1] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[2] + _fd_slots[2] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[3] + _fd_slots[3] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[4] + _fd_slots[4] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + if operation_primary is None and cleanup_primary is not None: + raise cleanup_primary + +def write_once(path: str, raw: bytes, *, error_owner) -> dict: + schema.owner_state(error_owner) + schema.path(path) + schema.need(_TYPE(raw) is bytes, 'exact record bytes required') + schema.need(0 < _LEN(raw) <= schema.RECORD_BYTES, 'record bound differs') + _gate() + _state = schema.owner_state(error_owner) + _primary, _secondary, _phases, _uncertain = _state[0], _state[1], _state[2], _state[3] + _counts, _overflow, _io = _state[4], _state[5], _state[7] + _attempt_digits, _confirmed_digits = _io[7], _io[8] + _successors = schema.CUSTODY_SUCCESSORS + _quarantine_error = schema.IO_QUARANTINE_ERROR + _base_error, _close_native = BaseException, _CLOSE + _error_index = _digit = 0 + _owned_fd = _close_error = _acquisition_error = None + cleanup_primary = operation_primary = None + _fd_slots = [None] * 5 + _iterator = _owned_iterator = None + try: + name = _parent(path, error_owner, _fd_slots, 1) + parent = _fd_slots[1] + if _io[0] or _io[1] or _io[10] or _overflow[1] or _attempt_digits[4] == 1: + raise _quarantine_error + _io[1] = True + try: + _fd_slots[0] = _OPEN(name, os.O_RDWR | os.O_CREAT | os.O_EXCL | os.O_CLOEXEC | os.O_NOFOLLOW, 0o600, dir_fd=parent) + except _base_error as _acquisition_error: + if _io[3] is None: + _io[3] = _acquisition_error + _io[0] = True + _io[2] = True + _io[4] = True + raise + _io[1] = False + descriptor = _fd_slots[0] + _fd(descriptor) + initial = _identity(_FSTAT(descriptor)) + schema.need(stat.S_ISREG(initial['mode']) and initial['links'] == 1 and initial['size'] == 0 and + stat.S_IMODE(initial['mode']) == 0o600, 'exclusive record file differs') + offset, calls = 0, 0 + while offset < _LEN(raw): + calls += 1 + schema.need(calls <= schema.MAX_RECORD_WRITE_CALLS, 'record write-call bound exceeded') + written = _WRITE(descriptor, raw[offset:offset + schema.CHUNK_BYTES]) + schema.integer(written, 1, min(schema.CHUNK_BYTES, _LEN(raw) - offset)) + offset += written + _FSYNC(descriptor) + _FSYNC(parent) + owned = _identity(_FSTAT(descriptor)) + result = inspect(path, schema.RECORD_BYTES, error_owner=error_owner) + schema.need(result['identity'] == owned and + (owned['device'], owned['inode']) == (initial['device'], initial['inode']) and + result['sha256'] == schema.sha(raw) and result['bytes'] == _LEN(raw), 'record readback differs') + return result + except _base_error as operation_error: + operation_primary = operation_error + if _primary[0] is None: + _primary[0] = operation_error + _primary[1] = 'write_once' + _primary[2] = None + elif _primary[0] is not operation_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = operation_error + _phases[_error_index] = 'write_once' + _uncertain[_error_index] = None + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = operation_error + raise + finally: + _owned_fd = _fd_slots[0] + _fd_slots[0] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[1] + _fd_slots[1] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[2] + _fd_slots[2] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[3] + _fd_slots[3] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[4] + _fd_slots[4] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + if operation_primary is None and cleanup_primary is not None: + raise cleanup_primary + +def read_verified(expected: dict, limit: int = schema.RECORD_BYTES, *, error_owner) -> bytes: + schema.owner_state(error_owner) + schema.integer(limit, 1, schema.RAW_RESULT_BYTES) + schema.blob(expected, limit) + _gate() + verify(expected, limit, error_owner=error_owner) + _state = schema.owner_state(error_owner) + _primary, _secondary, _phases, _uncertain = _state[0], _state[1], _state[2], _state[3] + _counts, _overflow, _io = _state[4], _state[5], _state[7] + _attempt_digits, _confirmed_digits = _io[7], _io[8] + _successors = schema.CUSTODY_SUCCESSORS + _quarantine_error = schema.IO_QUARANTINE_ERROR + _base_error, _close_native = BaseException, _CLOSE + _error_index = _digit = 0 + _owned_fd = _close_error = _acquisition_error = None + cleanup_primary = operation_primary = None + _fd_slots = [None] * 5 + _iterator = _owned_iterator = None + try: + name = _parent(expected['path'], error_owner, _fd_slots, 1) + parent = _fd_slots[1] + if _io[0] or _io[1] or _io[10] or _overflow[1] or _attempt_digits[4] == 1: + raise _quarantine_error + _io[1] = True + try: + _fd_slots[0] = _OPEN(name, os.O_RDONLY | os.O_CLOEXEC | os.O_NOFOLLOW | os.O_NONBLOCK, dir_fd=parent) + except _base_error as _acquisition_error: + if _io[3] is None: + _io[3] = _acquisition_error + _io[0] = True + _io[2] = True + _io[4] = True + raise + _io[1] = False + descriptor = _fd_slots[0] + _fd(descriptor) + schema.need(_identity(_FSTAT(descriptor)) == expected['identity'], 'evidence changed before read') + chunks, count, calls = [], 0, 0 + while True: + calls += 1 + schema.need(calls <= schema.MAX_READ_CALLS, 'evidence read-call bound exceeded') + raw = _READ(descriptor, min(schema.CHUNK_BYTES, limit + 1 - count)) + schema.need(_TYPE(raw) is bytes, 'native evidence read returned foreign data') + if _LEN(raw) == 0: + break + count += _LEN(raw) + schema.need(count <= limit, 'evidence byte bound exceeded') + chunks.append(raw) + result = b''.join(chunks) + schema.need(count == expected['bytes'] and schema.sha(result) == expected['sha256'] and + _identity(_FSTAT(descriptor)) == expected['identity'] and + _identity(_STAT(name, dir_fd=parent, follow_symlinks=False)) == expected['identity'], + 'retained evidence bytes/custody differ') + verify(expected, limit, error_owner=error_owner) + return result + except _base_error as operation_error: + operation_primary = operation_error + if _primary[0] is None: + _primary[0] = operation_error + _primary[1] = 'read_verified' + _primary[2] = None + elif _primary[0] is not operation_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = operation_error + _phases[_error_index] = 'read_verified' + _uncertain[_error_index] = None + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = operation_error + raise + finally: + _owned_fd = _fd_slots[0] + _fd_slots[0] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[1] + _fd_slots[1] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[2] + _fd_slots[2] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[3] + _fd_slots[3] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[4] + _fd_slots[4] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + if operation_primary is None and cleanup_primary is not None: + raise cleanup_primary + +def require_entries(directory: str, expected_names: tuple[str, ...], *, error_owner) -> None: + schema.owner_state(error_owner) + schema.path(directory) + schema.need(_TYPE(expected_names) is tuple and _LEN(expected_names) <= 7, 'census tuple differs') + # Validate all names before hashing, equality, membership, or set creation. + for name in expected_names: + schema.text(name, 256) + schema.need(0 < _LEN(name) and '/' not in name and name not in ('.', '..'), 'census name differs') + schema.need(_LEN(set(expected_names)) == _LEN(expected_names), 'duplicate census name') + _gate() + _state = schema.owner_state(error_owner) + _primary, _secondary, _phases, _uncertain = _state[0], _state[1], _state[2], _state[3] + _counts, _overflow, _io = _state[4], _state[5], _state[7] + _attempt_digits, _confirmed_digits = _io[7], _io[8] + _successors = schema.CUSTODY_SUCCESSORS + _quarantine_error = schema.IO_QUARANTINE_ERROR + _base_error, _close_native = BaseException, _CLOSE + _error_index = _digit = 0 + _owned_fd = _close_error = _acquisition_error = None + cleanup_primary = operation_primary = None + _fd_slots = [None] * 5 + _iterator = _owned_iterator = None + try: + name = _parent(directory, error_owner, _fd_slots, 1) + parent = _fd_slots[1] + if _io[0] or _io[1] or _io[10] or _overflow[1] or _attempt_digits[4] == 1: + raise _quarantine_error + _io[1] = True + try: + _fd_slots[0] = _OPEN(name, os.O_RDONLY | os.O_CLOEXEC | os.O_NOFOLLOW | os.O_DIRECTORY, dir_fd=parent) + except _base_error as _acquisition_error: + if _io[3] is None: + _io[3] = _acquisition_error + _io[0] = True + _io[2] = True + _io[4] = True + raise + _io[1] = False + descriptor = _fd_slots[0] + _fd(descriptor) + before = _identity(_FSTAT(descriptor)) + schema.need(stat.S_ISDIR(before['mode']), 'copy root is not a directory') + names = [] + if _io[0] or _io[1] or _io[10] or _overflow[1] or _attempt_digits[4] == 1: + raise _quarantine_error + _io[1] = True + try: + _iterator = _SCANDIR(descriptor) + except _base_error as _acquisition_error: + if _io[3] is None: + _io[3] = _acquisition_error + _io[0] = True + _io[2] = True + _io[4] = True + raise + _io[1] = False + for entry in _iterator: + # Exact native entry guard remains before its attribute access. + schema.need(_TYPE(entry) is os.DirEntry, 'native directory entry type differs') + entry_name = entry.name + schema.text(entry_name, 256) + names.append(entry_name) + schema.need(_LEN(names) <= 7, 'copy root entry bound exceeded') + _owned_iterator = _iterator + _iterator = None + if _owned_iterator is not None: + try: + _owned_iterator.close() + except _base_error as _close_error: + if _io[5] is None: + _io[5] = _owned_iterator + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'scandir-close' + _primary[2] = None + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'scandir-close' + _uncertain[_error_index] = None + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + # A normal/no-op return after a delivered body error cannot + # invoke the selected release premise or clear uncertainty. + if operation_primary is None and not _io[0] and _io[5] is None: + _io[9] = True + _io[4] = True + if cleanup_primary is not None: + raise cleanup_primary + schema.need(set(names) == set(expected_names) and before == _identity(_FSTAT(descriptor)) == + _identity(_STAT(name, dir_fd=parent, follow_symlinks=False)), 'copy root entries/custody differ') + except _base_error as operation_error: + operation_primary = operation_error + # Any body failure may follow an ignored closedir result, including + # iterator OSError/MemoryError before an explicit close becomes a no-op. + # Root the exact error first; quarantine and retain stream uncertainty + # before cleanup or any optional helper/reporting can run. + _io[0] = True + _io[4] = True + if _io[5] is None: + if _iterator is not None: + _io[5] = _iterator + elif _owned_iterator is not None: + _io[5] = _owned_iterator + if _primary[0] is None: + _primary[0] = operation_error + _primary[1] = 'require_entries' + _primary[2] = None + elif _primary[0] is not operation_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = operation_error + _phases[_error_index] = 'require_entries' + _uncertain[_error_index] = None + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = operation_error + raise + finally: + _owned_iterator = _iterator + _iterator = None + if _owned_iterator is not None: + try: + _owned_iterator.close() + except _base_error as _close_error: + if _io[5] is None: + _io[5] = _owned_iterator + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'scandir-close' + _primary[2] = None + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'scandir-close' + _uncertain[_error_index] = None + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + # A normal/no-op return after a delivered body error cannot + # invoke the selected release premise or clear uncertainty. + if operation_primary is None and not _io[0] and _io[5] is None: + _io[9] = True + _io[4] = True + _owned_fd = _fd_slots[0] + _fd_slots[0] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[1] + _fd_slots[1] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[2] + _fd_slots[2] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[3] + _fd_slots[3] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + _owned_fd = _fd_slots[4] + _fd_slots[4] = None + if _owned_fd is not None: + if _attempt_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _attempt_digits[_digit] == 255: + _attempt_digits[_digit] = 0 + _digit = _successors[_digit] + _attempt_digits[_digit] = _successors[_attempt_digits[_digit]] + try: + _close_native(_owned_fd) + except _base_error as _close_error: + _io[0] = True + _io[4] = True + if cleanup_primary is None: + cleanup_primary = _close_error + if _primary[0] is None: + _primary[0] = _close_error + _primary[1] = 'close' + _primary[2] = _owned_fd + elif _primary[0] is not _close_error: + _error_index = _counts[0] + if _error_index < 64: + _secondary[_error_index] = _close_error + _phases[_error_index] = 'close' + _uncertain[_error_index] = _owned_fd + _counts[0] = _successors[_error_index] + else: + _overflow[1] = True + _io[0] = True + _io[4] = True + if _overflow[0] is None: + _overflow[0] = _close_error + else: + if _confirmed_digits[4] == 1: + _io[6] = True + _io[0] = True + _io[4] = True + else: + _digit = 0 + while _digit < 4 and _confirmed_digits[_digit] == 255: + _confirmed_digits[_digit] = 0 + _digit = _successors[_digit] + _confirmed_digits[_digit] = _successors[_confirmed_digits[_digit]] + if operation_primary is None and cleanup_primary is not None: + raise cleanup_primary \ No newline at end of file diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/epoch_parent_v5.py.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/epoch_parent_v5.py.txt new file mode 100644 index 0000000000..7fb46f3cf3 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/epoch_parent_v5.py.txt @@ -0,0 +1,466 @@ +"""Parent-only single-attempt epoch source; no execution authority is configured. + +Parent authority and run tickets are identity capabilities in the trusted parent +process. They are never serialized or sent to a child. This is not a Python +sandbox against code already executing inside that trusted parent. The future +source-fixed supervisor must authenticate original compiler/terminal/raw data +before submitting a completion; a child JSON object or saved PASS is not that +call. The missing supervisor adapter is an explicit independent-review blocker. +""" +from dataclasses import dataclass +import epoch_schema_v5 as schema +import epoch_copy_v5 as copying +import epoch_stop_v5 as stopping + +CONFIGURATION = None +SOURCE_REVIEW = None +EXECUTION_APPROVAL = None +FUNDING = None +_RESERVED_EPOCHS = set() +_PARENT_OWNERS = [] +_TYPE = type + + +@dataclass(frozen=True, slots=True) +class ParentCompletion: + """In-memory result of the separately pinned parent evidence checker. + + Cannot be reconstructed from a child report as authority. All raw evidence + remains referenced by producer_record and must be re-read by each consumer. + Whole-domain closure is stronger than a compiler's direct-child wait. + """ + producer_ticket: object + checker_sha256: str + observation_sha256: str + generation: str + mode: str + producer_role: str + process_id: int + process_start_ticks: int + direct_child_reaped: bool + whole_process_domain_closed: bool + own_in_process_obligations_authenticated: bool + original_attempts_and_logs_authenticated: bool + final_source_custody_authenticated: bool + returned_groups_captured: bool + + +def _gate() -> None: + schema.exact(CONFIGURATION, ('parent_checker_sha256', 'configuration_sha256')) + schema.exact(SOURCE_REVIEW, ('review_sha256',)) + schema.exact(EXECUTION_APPROVAL, ('external_launch_policy_sha256',)) + schema.exact(FUNDING, ('reservation_sha256',)) + for record in (CONFIGURATION, SOURCE_REVIEW, EXECUTION_APPROVAL, FUNDING): + for value in record.values(): + schema.digest(value) + + +_COMPLETION_FIELDS = ('producer_ticket', 'checker_sha256', 'observation_sha256', 'generation', 'mode', + 'producer_role', 'process_id', 'process_start_ticks', 'direct_child_reaped', 'whole_process_domain_closed', + 'own_in_process_obligations_authenticated', 'original_attempts_and_logs_authenticated', + 'final_source_custody_authenticated', 'returned_groups_captured') +_COMPLETION_GETTERS = tuple(ParentCompletion.__dict__[name].__get__ for name in _COMPLETION_FIELDS) + + +def _completion_values(observation) -> dict: + schema.need(_TYPE(observation) is ParentCompletion, 'exact parent completion type required') + values = {name: getter(observation, ParentCompletion) + for name, getter in zip(_COMPLETION_FIELDS, _COMPLETION_GETTERS)} + schema.need(_TYPE(values['producer_ticket']) is object, 'exact opaque producer ticket required') + schema.digest(values['checker_sha256']) + schema.digest(values['observation_sha256']) + schema.label(values['generation']) + schema.choice(values['mode'], ('normal', 'optimized')) + schema.choice(values['producer_role'], schema.PRODUCERS) + schema.integer(values['process_id'], 1, (1 << 31) - 1) + schema.integer(values['process_start_ticks'], 1, (1 << 64) - 1) + for name in _COMPLETION_FIELDS[8:]: + schema.boolean(values[name]) + return values + + +def _clone(value: dict) -> dict: + return schema.decode(schema.canonical(value)) + + +def _plan(value: dict, role: str) -> None: + schema.choice(role, schema.PRODUCERS) + schema.exact(value, ('role', 'generation', 'stage_sha256', 'command_sha256', 'root_sha256', + 'artifact_plans')) + schema.choice(value['role'], schema.PRODUCERS) + schema.need(value['role'] == role, 'planned producer role differs') + schema.label(value['generation']) + for key in ('stage_sha256', 'command_sha256', 'root_sha256'): + schema.digest(value[key]) + roles = schema.ROLES[:3] if role == 'group01' else schema.ROLES[3:] + schema.need(type(value['artifact_plans']) is list and len(value['artifact_plans']) == len(roles), + 'planned build count differs') + for artifact_role, row in zip(roles, value['artifact_plans']): + schema.exact(row, ('role', 'command_sha256', 'profile', 'original_output_path')) + schema.choice(row['role'], schema.ROLES) + schema.need(row['role'] == artifact_role, 'planned artifact role differs') + schema.digest(row['command_sha256']) + schema.profile(row['profile']) + schema.path(row['original_output_path']) + + +_STATE_KEYS = ('_authority', '_bytes', '_children', '_copies', '_directory', '_epoch_id', '_error_owner', '_failure_fallback', '_generations', '_intent_file', '_manifest', '_manifest_file', '_mode', '_occupied_inodes', '_occupied_paths', '_plans', '_processes', '_producers', '_state', '_stop', '_tickets') + + +def _registry() -> list: + schema.need(_TYPE(_PARENT_OWNERS) is list and len(_PARENT_OWNERS) <= 2, + 'original parent registry shape differs') + for record in _PARENT_OWNERS: + schema.need(_TYPE(record) is tuple and len(record) == 2, 'original parent registry row differs') + schema.need(_TYPE(record[0]) is ParentEpoch, 'original parent registry identity differs') + schema.exact(record[1], _STATE_KEYS) + return _PARENT_OWNERS + + +def _constructor_identity(owner) -> None: + schema.need(_TYPE(owner) is ParentEpoch, 'exact parent owner required') + records = _registry() + schema.need(len(records) < 2 and not any(owner is record[0] for record in records), + 'parent constructor instance reused or finite bound exceeded') + + +def _registered_parent(owner) -> tuple: + # Identity only. Never read owner.__dict__ or dispatch owner helpers. + schema.need(_TYPE(owner) is ParentEpoch, 'exact parent owner required') + for original in _registry(): + if owner is original[0]: + return original # Canonical constructor-held object and state. + raise schema.EpochStop('parent was not original constructor instance') + + +def _entry_state(owner, authority) -> dict: + canonical, state = _registered_parent(owner) + _gate() + schema.need(authority is state['_authority'], 'parent capability differs') + schema.need(state['_stop'][1] is None, 'epoch has a retained terminal failure') + schema.choice(state['_state'], ('RESERVED', 'PRODUCERS_PENDING', 'EXPORT_READY', + 'EXPORT_ATTEMPT_CONSUMED', 'COMMITTED', 'STOP', 'CLOSED')) + schema.need(state['_state'] not in ('STOP', 'CLOSED'), 'epoch is terminal') + return state + + +def _failed_state(state, operation: str, error) -> None: + # Only a source-owned registry sidecar is used. The supplied instance's + # _owner/_failed attributes are never looked up, even on failure paths. + schema.need(any(state is record[1] for record in _registry()), 'failure state not owned') + schema.text(operation, 96) + state['_state'] = 'STOP' + if state['_stop'][1] is error: + try: + schema.retain_primary(state['_error_owner'], error, operation) + except BaseException as custody_failure: + if state['_failure_fallback'][0] is None: + state['_failure_fallback'][0] = custody_failure + return + try: + stopping.retain_stop(state['_directory'], operation, state['_error_owner']) + except BaseException as evidence_failure: + if state['_failure_fallback'][1] is None: + state['_failure_fallback'][1] = evidence_failure + try: + schema.retain_secondary(state['_error_owner'], evidence_failure, 'stop-capture', None) + except BaseException as custody_failure: + if state['_failure_fallback'][2] is None: + state['_failure_fallback'][2] = custody_failure + + +class ParentEpoch: + """One parent instance; two producers, five exports, thirteen child attempts. + + Any caught operational failure moves state to STOP permanently. Tickets are + burned before validation/I/O. No serialized-state restore or retry exists. + The constructor does not create directories; the supervised parent must own + fresh exclusive directories and charge their creation/retention separately. + """ + def __init__(self, authority: object, epoch_id: str, mode: str, + export_directory: str, producer_plans: list[dict]): + _constructor_identity(self) + _gate() + schema.need(_TYPE(authority) is object, 'trusted parent capability must be exact object') + schema.label(epoch_id) + schema.choice(mode, ('normal', 'optimized')) + schema.path(export_directory) + schema.need(epoch_id not in _RESERVED_EPOCHS and len(_RESERVED_EPOCHS) < 2, + 'parent epoch reused or finite mode count exceeded') + # Reservation precedes all further work; invalid construction burns id. + _RESERVED_EPOCHS.add(epoch_id) + state = {} + state['_state'] = 'RESERVED' + state['_authority'] = authority + state['_epoch_id'], state['_mode'] = epoch_id, mode + state['_directory'] = export_directory + state['_plans'], state['_tickets'], state['_producers'] = {}, {}, {} + state['_children'], state['_generations'], state['_processes'] = {}, set(), set() + state['_occupied_paths'], state['_occupied_inodes'] = set(), set() + state['_copies'], state['_bytes'] = 0, 0 + state['_manifest'] = state['_manifest_file'] = state['_intent_file'] = None + state['_stop'] = [None, None] + state['_failure_fallback'] = [None, None, None, None] + state['_error_owner'] = schema.make_error_owner() + _PARENT_OWNERS.append((self, state)) + _stop_slots, _fallback_slots = state['_stop'], state['_failure_fallback'] + try: + schema.need(type(producer_plans) is list and len(producer_plans) == 2, 'two producer plans required') + for role, plan in zip(schema.PRODUCERS, producer_plans): + _plan(plan, role) + schema.need(plan['generation'] not in state['_generations'], 'producer generation reused') + state['_generations'].add(plan['generation']) + state['_plans'][role] = _clone(plan) + copying.require_entries(state['_directory'], (), error_owner=state['_error_owner']) + intent = {'schema': 'h25-negative-epoch-intent-v3', 'epoch_id': epoch_id, 'mode': mode, + 'producer_plans': [state['_plans'][role] for role in schema.PRODUCERS], + 'restore_or_retry_allowed': False} + state['_intent_file'] = copying.write_once(state['_directory'] + '/epoch-intent.json', schema.canonical(intent), error_owner=state['_error_owner']) + state['_state'] = 'PRODUCERS_PENDING' + except BaseException as error: + if _stop_slots[1] is None: + _stop_slots[1] = error + _stop_slots[0] = 'constructor' + try: + _failed_state(state, 'constructor', error) + except BaseException as helper_error: + if _fallback_slots[3] is None: + _fallback_slots[3] = helper_error + raise + + def _owner(self, authority: object) -> None: + _entry_state(self, authority) + + def _failed(self, operation: str, error: BaseException) -> None: + canonical, state = _registered_parent(self) + stop_slots, fallback_slots = state['_stop'], state['_failure_fallback'] + if stop_slots[1] is None: + stop_slots[1] = error + stop_slots[0] = operation + try: + _failed_state(state, operation, error) + except BaseException as helper_error: + if fallback_slots[3] is None: + fallback_slots[3] = helper_error + + + def reserve_producer(self, authority: object, role: str) -> object: + state = _entry_state(self, authority) + _stop_slots, _fallback_slots = state['_stop'], state['_failure_fallback'] + try: + schema.choice(role, schema.PRODUCERS) + schema.need(state['_state'] == 'PRODUCERS_PENDING' and role in schema.PRODUCERS and + role not in state['_tickets'], 'producer attempt already consumed/unknown') + ticket = object() + state['_tickets'][role] = {'ticket': ticket, 'state': 'ATTEMPT_RESERVED'} + return ticket + except BaseException as error: + if _stop_slots[1] is None: + _stop_slots[1] = error + _stop_slots[0] = 'reserve_producer' + try: + _failed_state(state, 'reserve_producer', error) + except BaseException as helper_error: + if _fallback_slots[3] is None: + _fallback_slots[3] = helper_error + raise + + def accept_completed_producer(self, authority: object, ticket: object, + observation: ParentCompletion, producer_record: dict) -> None: + state = _entry_state(self, authority) + _stop_slots, _fallback_slots = state['_stop'], state['_failure_fallback'] + try: + matches = [role for role, row in state['_tickets'].items() if row['ticket'] is ticket] + schema.need(len(matches) == 1, 'unknown producer attempt capability') + role = matches[0] + attempt = state['_tickets'][role] + schema.need(attempt['state'] == 'ATTEMPT_RESERVED', 'producer completion replay') + attempt['state'] = 'COMPLETION_CONSUMED' + observed = _completion_values(observation) + schema.need(observed['producer_ticket'] is ticket, + 'serialized/replayed completion is not this parent attempt') + schema.need(observed['checker_sha256'] == CONFIGURATION['parent_checker_sha256'], + 'parent completion checker source differs') + schema.digest(observed['observation_sha256']) + schema.integer(observed['process_id'], 1, (1 << 31) - 1) + schema.integer(observed['process_start_ticks'], 1, (1 << 64) - 1) + process_key = (observed['process_id'], observed['process_start_ticks']) + schema.need(process_key not in state['_processes'], 'producer process generation reused') + state['_processes'].add(process_key) + plan = state['_plans'][role] + schema.need(observed['generation'] == plan['generation'] and observed['mode'] == state['_mode'] and + observed['producer_role'] == role, 'terminal observation independent role/generation differs') + for value in (observed['direct_child_reaped'], observed['whole_process_domain_closed'], + observed['own_in_process_obligations_authenticated'], + observed['original_attempts_and_logs_authenticated'], + observed['final_source_custody_authenticated'], observed['returned_groups_captured']): + schema.need(value is True, 'parent completion obligation absent') + schema.producer(producer_record) + record = _clone(producer_record) + schema.need(record['completion_checker_sha256'] == observed['checker_sha256'] and + record['parent_observation']['sha256'] == observed['observation_sha256'], + 'parent observation bytes/checker binding differs') + for key in ('role', 'generation', 'stage_sha256', 'command_sha256', 'root_sha256'): + schema.need(record[key] == plan[key], 'producer independent plan differs') + for item, planned in zip(record['builds'], plan['artifact_plans']): + schema.need(item['role'] == planned['role'] and item['command_sha256'] == planned['command_sha256'] and + item['profile'] == planned['profile'] and + item['original_output']['path'] == planned['original_output_path'], + 'build original command/source/profile/path differs') + for key, bound in (('original_output', schema.FILE_BYTES), ('original_receipt', 65536), + ('attempt', 65536), ('journal', schema.JOURNAL_BYTES), + ('stdout', schema.LOG_BYTES), ('stderr', schema.LOG_BYTES)): + copying.verify(item[key], bound, error_owner=state['_error_owner']) + original = item['original_output'] + schema.need(original['path'] not in state['_occupied_paths'] and + schema.inode(original) not in state['_occupied_inodes'], 'producer output aliases another role') + state['_occupied_paths'].add(original['path']) + state['_occupied_inodes'].add(schema.inode(original)) + for key in ('terminal', 'raw_result', 'raw_groups', 'final_source_custody', 'parent_observation'): + copying.verify(record[key], schema.RAW_RESULT_BYTES, error_owner=state['_error_owner']) + # No control/PASS/native result is returned to a child as authority. + state['_producers'][role] = record + attempt['state'] = 'AUTHENTICATED_COMPLETED' + if len(state['_producers']) == 2: + state['_state'] = 'EXPORT_READY' + except BaseException as error: + if _stop_slots[1] is None: + _stop_slots[1] = error + _stop_slots[0] = 'accept_completed_producer' + try: + _failed_state(state, 'accept_completed_producer', error) + except BaseException as helper_error: + if _fallback_slots[3] is None: + _fallback_slots[3] = helper_error + raise + + def commit_exports(self, authority: object) -> dict: + state = _entry_state(self, authority) + _stop_slots, _fallback_slots = state['_stop'], state['_failure_fallback'] + try: + schema.need(state['_state'] == 'EXPORT_READY', 'partial/failed producer epoch cannot export') + state['_state'] = 'EXPORT_ATTEMPT_CONSUMED' + copying.verify(state['_intent_file'], schema.RECORD_BYTES, error_owner=state['_error_owner']) + copying.require_entries(state['_directory'], ('epoch-intent.json',), error_owner=state['_error_owner']) + exports = [] + for parent in (state['_producers'][role] for role in schema.PRODUCERS): + for item in parent['builds']: + destination = state['_directory'] + '/' + item['role'] + '.artifact' + schema.need(destination not in state['_occupied_paths'], 'export path alias') + copy = copying.copy_once(item['original_output'], destination, tuple(state['_occupied_inodes']), error_owner=state['_error_owner']) + state['_bytes'] += copy['bytes'] + schema.need(state['_bytes'] <= schema.MAX_EPOCH_FILE_BYTES, 'aggregate copy payload bound exceeded') + state['_occupied_paths'].add(copy['path']) + state['_occupied_inodes'].add(schema.inode(copy)) + exports.append({'role': item['role'], 'build_sha256': schema.sha(schema.canonical(item)), 'file': copy}) + manifest = {'schema': schema.SCHEMA, 'epoch_id': state['_epoch_id'], 'mode': state['_mode'], + 'publication_state': 'COMMITTED', 'intent': state['_intent_file'], + 'producers': [state['_producers'][role] for role in schema.PRODUCERS], + 'exports': exports, 'not_runtime_authority': True} + schema.epoch(manifest) + # Recheck every source/store before the publication write. + for producer in manifest['producers']: + for item in producer['builds']: + copying.verify(item['original_output'], error_owner=state['_error_owner']) + for row in exports: + copying.verify(row['file'], error_owner=state['_error_owner']) + raw = schema.canonical(manifest) + published = copying.write_once(state['_directory'] + '/epoch.json', raw, error_owner=state['_error_owner']) + copying.require_entries(state['_directory'], tuple(role + '.artifact' for role in schema.ROLES) + ('epoch.json', 'epoch-intent.json'), error_owner=state['_error_owner']) + state['_manifest'], state['_manifest_file'] = manifest, published + state['_state'] = 'COMMITTED' + return _clone(published) + except BaseException as error: + if _stop_slots[1] is None: + _stop_slots[1] = error + _stop_slots[0] = 'commit_exports' + try: + _failed_state(state, 'commit_exports', error) + except BaseException as helper_error: + if _fallback_slots[3] is None: + _fallback_slots[3] = helper_error + raise + + def claim_child(self, authority: object, group: str, generation: str, + launch_binding: dict, private_directory: str) -> tuple[dict, dict]: + state = _entry_state(self, authority) + _stop_slots, _fallback_slots = state['_stop'], state['_failure_fallback'] + try: + schema.need(state['_state'] == 'COMMITTED', 'uncommitted epoch cannot be consumed') + roles = schema.required_roles(group) + schema.label(generation) + schema.need(group not in state['_children'] and generation not in state['_generations'], + 'child group/generation replay') + # Burn group/generation before any caller data check or filesystem IO. + state['_children'][group] = {'generation': generation, 'state': 'ATTEMPT_CONSUMED'} + state['_generations'].add(generation) + schema.launch(launch_binding) + schema.path(private_directory) + copying.require_entries(private_directory, (), error_owner=state['_error_owner']) + copying.require_entries(state['_directory'], tuple(role + '.artifact' for role in schema.ROLES) + ('epoch.json', 'epoch-intent.json'), error_owner=state['_error_owner']) + copying.verify(state['_intent_file'], schema.RECORD_BYTES, error_owner=state['_error_owner']) + copying.verify(state['_manifest_file'], schema.RECORD_BYTES, error_owner=state['_error_owner']) + for row in state['_manifest']['exports']: + copying.verify(row['file'], error_owner=state['_error_owner']) + copies = [] + for role in roles: + source = next(row for row in state['_manifest']['exports'] if row['role'] == role) + destination = private_directory + '/' + role + '.artifact' + schema.need(destination not in state['_occupied_paths'] and state['_copies'] < schema.MAX_PRIVATE_COPIES, + 'private path/copy bound differs') + state['_copies'] += 1 + copy = copying.copy_once(source['file'], destination, tuple(state['_occupied_inodes']), error_owner=state['_error_owner']) + state['_bytes'] += copy['bytes'] + schema.need(state['_bytes'] <= schema.MAX_EPOCH_FILE_BYTES, 'aggregate copy payload bound exceeded') + state['_occupied_paths'].add(copy['path']) + state['_occupied_inodes'].add(schema.inode(copy)) + copies.append({'role': role, 'build_sha256': source['build_sha256'], + 'source': source['file'], 'destination': copy}) + claim = {'schema': schema.CLAIM_SCHEMA, 'epoch_id': state['_epoch_id'], 'mode': state['_mode'], + 'group': group, 'generation': generation, 'manifest_sha256': state['_manifest_file']['sha256'], + 'launch': _clone(launch_binding), 'copies': copies, 'local_compilations': 0, + 'not_runtime_authority': True, 'admission': 'CURRENT_CHILD_CHECKS_REQUIRED'} + schema.claim(claim, state['_manifest'], launch_binding, group, generation, private_directory) + published = copying.write_once(private_directory + '/import-claim.json', schema.canonical(claim), error_owner=state['_error_owner']) + copying.require_entries(private_directory, tuple(role + '.artifact' for role in roles) + ('import-claim.json',), error_owner=state['_error_owner']) + copying.require_entries(state['_directory'], tuple(role + '.artifact' for role in schema.ROLES) + ('epoch.json', 'epoch-intent.json'), error_owner=state['_error_owner']) + state['_children'][group]['state'] = 'CLAIM_ISSUED' + state['_children'][group]['claim'] = published + return _clone(claim), _clone(published) + except BaseException as error: + if _stop_slots[1] is None: + _stop_slots[1] = error + _stop_slots[0] = 'claim_child' + try: + _failed_state(state, 'claim_child', error) + except BaseException as helper_error: + if _fallback_slots[3] is None: + _fallback_slots[3] = helper_error + raise + + def close(self, authority: object) -> dict: + state = _entry_state(self, authority) + _stop_slots, _fallback_slots = state['_stop'], state['_failure_fallback'] + try: + schema.need(state['_state'] == 'COMMITTED' and tuple(sorted(state['_children'])) == schema.GROUPS and + all(row['state'] == 'CLAIM_ISSUED' for row in state['_children'].values()) and + state['_copies'] == schema.MAX_PRIVATE_COPIES, 'core epoch claim schedule incomplete') + state['_state'] = 'CLOSED' + return {'schema': 'h25-negative-epoch-accounting-v3', 'epoch_id': state['_epoch_id'], 'mode': state['_mode'], + 'exports': 5, 'private_copies': state['_copies'], 'copy_payload_bytes': state['_bytes'], + 'child_runtime_results': 'NOT_ADMITTED_BY_THIS_API', 'complete_cost': None} + except BaseException as error: + if _stop_slots[1] is None: + _stop_slots[1] = error + _stop_slots[0] = 'close' + try: + _failed_state(state, 'close', error) + except BaseException as helper_error: + if _fallback_slots[3] is None: + _fallback_slots[3] = helper_error + raise + + def stop_evidence(self, authority: object) -> tuple: + canonical, state = _registered_parent(self) + schema.need(authority is state['_authority'], 'parent capability differs') + return state['_stop'], state['_error_owner'], state['_failure_fallback'] diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/epoch_schema_v5.py.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/epoch_schema_v5.py.txt new file mode 100644 index 0000000000..b95c2385a9 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/epoch_schema_v5.py.txt @@ -0,0 +1,676 @@ +"""Finite negative-only data records. No import/load/compile/runtime authority. + +Source draft: no target execution has been authorized. These functions are not +run during source checks. Every caller must be a separately reviewed fixed +parent/child source; JSON never creates a parent capability. +""" +import hashlib +import json + +SCHEMA = 'h25-negative-build-epoch-v3' +CLAIM_SCHEMA = 'h25-negative-import-claim-v3' +ROLES = ('production', 'watcher', 'bounds', 'pyinit_failure', 'exec_failure') +PRODUCERS = ('group01', 'failure_variants') +GROUPS = ('02', '03', '04', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16') +PROFILE_KEYS = ('source_manifest_sha256', 'project_headers_sha256', 'system_headers_sha256', + 'compiler_link_sha256', 'link_profile_sha256') +LAUNCH_KEYS = ('configuration_sha256', 'root_sha256', 'stage_sha256', 'command_sha256', + 'startup_tcb_sha256', 'expected_history_sha256') +FILE_BYTES = 64 * 1024 * 1024 +RECORD_BYTES = 1024 * 1024 +RAW_RESULT_BYTES = 4 * 1024 * 1024 +LOG_BYTES = 2 * 1024 * 1024 +JOURNAL_BYTES = 3 * 65536 +CHUNK_BYTES = 65536 +PATH_BYTES = 4096 +MAX_PATH_COMPONENTS = 64 +MAX_READ_CALLS = 8192 +MAX_WRITE_CALLS = 8192 +MAX_RECORD_WRITE_CALLS = 4096 +MAX_PRIVATE_COPIES = 41 +MAX_EXPORTS = 5 +MAX_EPOCH_FILE_BYTES = 46 * FILE_BYTES +IDENTITY_KEYS = ('device', 'inode', 'mode', 'links', 'uid', 'gid', 'size', 'mtime_ns', 'ctime_ns') + + +# Captured before any adverse input. Actual startup primitive/source admission +# is still required by the future caller; no module is imported in source work. +_TYPE, _LEN = type, len +_DICT, _LIST, _TUPLE, _STR, _INT, _BOOL, _BYTES = dict, list, tuple, str, int, bool, bytes +MAX_RECORD_KEYS = 256 +MAX_SEQUENCE = 256 +MAX_WIRE_NODES = 8192 +MAX_WIRE_DEPTH = 24 +MAX_WIRE_TEXT = 8192 +MAX_WIRE_TEXT_TOTAL = 512 * 1024 + + +class EpochStop(RuntimeError): + """Literal bounded source error; original foreign failures remain opaque.""" + + +def need(condition: bool, message: str) -> None: + # No truth testing or formatting of an unknown object. + if _TYPE(message) is not _STR or _LEN(message) > 256: + raise EpochStop('invalid internal error literal') + if condition is not True: + raise EpochStop(message) + + +def exact(value: dict, keys: tuple[str, ...]) -> None: + need(_TYPE(value) is _DICT, 'exact record type differs') + need(_LEN(value) <= MAX_RECORD_KEYS, 'record cardinality bound exceeded') + need(_TYPE(keys) is _TUPLE, 'exact expected key tuple differs') + need(_LEN(keys) <= MAX_RECORD_KEYS, 'expected key cardinality bound exceeded') + # Iteration over an exact dict does not hash its keys. Complete this walk + # before membership, set creation, or any value lookup in that dictionary. + for key in value: + need(_TYPE(key) is _STR, 'foreign record key rejected') + need(_LEN(key) <= MAX_WIRE_TEXT, 'record key length bound exceeded') + for key in keys: + need(_TYPE(key) is _STR, 'foreign expected key rejected') + need(_LEN(key) <= MAX_WIRE_TEXT, 'expected key length bound exceeded') + need(_LEN(value) == _LEN(keys), 'exact record keys differ') + seen = set() + for key in keys: + need(key not in seen, 'duplicate expected key') + seen.add(key) + for key in value: + need(key in seen, 'exact record keys differ') + + +def integer(value: int, lower: int, upper: int) -> None: + need(_TYPE(value) is _INT and _TYPE(lower) is _INT and _TYPE(upper) is _INT, + 'exact integer type differs') + need(lower <= value <= upper, 'bounded exact integer differs') + + +def boolean(value: bool) -> None: + need(_TYPE(value) is _BOOL, 'exact boolean type differs') + + +def text(value: str, limit: int = MAX_WIRE_TEXT) -> None: + need(_TYPE(value) is _STR and _TYPE(limit) is _INT, 'exact text/limit type differs') + need(0 <= limit <= MAX_WIRE_TEXT and _LEN(value) <= limit, 'text bound exceeded') + + +def choice(value: str, choices: tuple[str, ...]) -> None: + text(value) + need(_TYPE(choices) is _TUPLE and _LEN(choices) <= MAX_SEQUENCE, 'choice tuple differs') + for item in choices: + text(item) + need(value in choices, 'literal choice differs') + + +def sequence(value: list, count: int) -> None: + need(_TYPE(value) is _LIST and _TYPE(count) is _INT, 'exact sequence type differs') + need(0 <= count <= MAX_SEQUENCE and _LEN(value) == count, 'exact sequence count differs') + + +def digest(value: str) -> None: + text(value, 64) + need(_LEN(value) == 64 and all(c in '0123456789abcdef' for c in value), 'sha256 differs') + + +def label(value: str) -> None: + text(value, 96) + need(1 <= _LEN(value) <= 96 and + all(c in 'abcdefghijklmnopqrstuvwxyz0123456789-' for c in value), 'label differs') + + +def path(value: str) -> None: + text(value, PATH_BYTES) + need(1 < _LEN(value) <= PATH_BYTES and value.isascii() and value.startswith('/'), + 'canonical absolute path differs') + parts = value.split('/')[1:] + need(_LEN(parts) <= MAX_PATH_COMPONENTS and + all(p not in ('', '.', '..') for p in parts) and + all(32 <= ord(c) <= 126 for c in value), 'canonical absolute path differs') + + +def _plain(value, depth: int, budget: list): + # depth and budget are newly created private native values, never inputs. + budget[0] += 1 + need(budget[0] <= MAX_WIRE_NODES and depth <= MAX_WIRE_DEPTH, 'plain record node/depth bound') + kind = _TYPE(value) + if value is None or kind is _BOOL: + return value + if kind is _STR: + need(_LEN(value) <= MAX_WIRE_TEXT, 'plain text bound') + budget[1] += _LEN(value) + need(budget[1] <= MAX_WIRE_TEXT_TOTAL, 'plain total text bound') + return value + if kind is _INT: + need(-(1 << 127) <= value < (1 << 127), 'plain integer bound') + return value + if kind is _DICT: + need(_LEN(value) <= MAX_RECORD_KEYS, 'plain dictionary bound') + for key in value: + need(_TYPE(key) is _STR, 'plain foreign dictionary key') + need(_LEN(key) <= MAX_WIRE_TEXT, 'plain dictionary key bound') + result = {} + for key, item in value.items(): + budget[1] += _LEN(key) + need(budget[1] <= MAX_WIRE_TEXT_TOTAL, 'plain total key text bound') + result[key] = _plain(item, depth + 1, budget) + return result + if kind is _LIST or kind is _TUPLE: + need(_LEN(value) <= MAX_SEQUENCE, 'plain sequence bound') + return [_plain(item, depth + 1, budget) for item in value] + raise EpochStop('foreign plain-record value rejected') + + +def plain_copy(value): + """Bounded callback-free native copy before any codec/equality use.""" + return _plain(value, 0, [0, 0]) + + +def required_roles(group: str) -> tuple[str, ...]: + text(group, 2) + need(group in GROUPS, 'positive/non-native/unknown group cannot import') + return ROLES[:3] + (('pyinit_failure',) if group == '13' else + ('exec_failure',) if group == '14' else ()) + + +def profile(value: dict) -> None: + exact(value, PROFILE_KEYS) + for key in PROFILE_KEYS: + digest(value[key]) + + +def launch(value: dict) -> None: + exact(value, LAUNCH_KEYS) + for key in LAUNCH_KEYS: + digest(value[key]) + + +def blob(value: dict, limit: int = FILE_BYTES) -> None: + integer(limit, 0, FILE_BYTES) + exact(value, ('path', 'sha256', 'bytes', 'identity')) + path(value['path']) + digest(value['sha256']) + integer(value['bytes'], 0, limit) + identity = value['identity'] + exact(identity, IDENTITY_KEYS) + for key in IDENTITY_KEYS: + integer(identity[key], 0, (1 << 127) - 1) + need(identity['inode'] > 0 and identity['size'] == value['bytes'] and + identity['mode'] & 0o170000 == 0o100000 and identity['links'] == 1, + 'regular single-link file custody differs') + + +def inode(value: dict) -> tuple[int, int]: + blob(value) + return value['identity']['device'], value['identity']['inode'] + + +def canonical(value: dict) -> bytes: + need(_TYPE(value) is _DICT, 'canonical top-level exact dictionary required') + safe = plain_copy(value) + raw = json.dumps(safe, sort_keys=True, separators=(',', ':'), ensure_ascii=True, + allow_nan=False).encode('ascii') + b'\n' + need(_LEN(raw) <= RECORD_BYTES, 'record byte bound exceeded') + return raw + + +def sha(raw: bytes) -> str: + need(_TYPE(raw) is _BYTES, 'exact byte buffer required') + return hashlib.sha256(raw).hexdigest() + + +def _pairs(pairs: list) -> dict: + need(_TYPE(pairs) is _LIST and _LEN(pairs) <= MAX_RECORD_KEYS, 'decoded key count differs') + result = {} + for pair in pairs: + need(_TYPE(pair) is _TUPLE and _LEN(pair) == 2, 'decoded pair differs') + key, value = pair + text(key) + need(key not in result, 'duplicate JSON key') + result[key] = value + return result + + +def _reject_constant(value): + raise EpochStop('nonfinite JSON constant rejected') + + +def decode(raw: bytes) -> dict: + need(_TYPE(raw) is _BYTES, 'exact raw bytes required') + need(0 < _LEN(raw) <= RECORD_BYTES, 'raw record bound differs') + result = json.loads(raw.decode('ascii'), object_pairs_hook=_pairs, parse_constant=_reject_constant) + need(_TYPE(result) is _DICT, 'decoded top-level record differs') + safe = plain_copy(result) + need(canonical(safe) == raw, 'noncanonical record bytes') + return safe + + +def build(value: dict) -> None: + exact(value, ('role', 'producer_role', 'producer_generation', 'producer_stage_sha256', + 'command_sha256', 'profile', 'original_output', 'original_receipt', + 'attempt', 'journal', 'stdout', 'stderr')) + choice(value['role'], ROLES) + choice(value['producer_role'], PRODUCERS) + need((value['role'] in ROLES[:3]) == (value['producer_role'] == 'group01'), 'producer role swap') + label(value['producer_generation']) + digest(value['producer_stage_sha256']) + digest(value['command_sha256']) + profile(value['profile']) + blob(value['original_output']) + need(value['original_output']['bytes'] > 0, 'empty compiled artifact') + for key, bound in (('original_receipt', 65536), ('attempt', 65536), + ('journal', JOURNAL_BYTES), ('stdout', LOG_BYTES), ('stderr', LOG_BYTES)): + blob(value[key], bound) + + +def producer(value: dict) -> None: + exact(value, ('role', 'generation', 'stage_sha256', 'command_sha256', 'root_sha256', + 'terminal', 'raw_result', 'raw_groups', 'final_source_custody', + 'parent_observation', 'completion_checker_sha256', 'builds')) + choice(value['role'], PRODUCERS) + label(value['generation']) + for key in ('stage_sha256', 'command_sha256', 'root_sha256', 'completion_checker_sha256'): + digest(value[key]) + for key in ('terminal', 'raw_result', 'raw_groups', 'final_source_custody', 'parent_observation'): + blob(value[key], RAW_RESULT_BYTES) + roles = ROLES[:3] if value['role'] == 'group01' else ROLES[3:] + sequence(value['builds'], len(roles)) + for role, row in zip(roles, value['builds']): + build(row) + need(row['role'] == role and row['producer_role'] == value['role'] and + row['producer_generation'] == value['generation'] and + row['producer_stage_sha256'] == value['stage_sha256'], 'producer build binding differs') + + +def epoch(value: dict) -> None: + exact(value, ('schema', 'epoch_id', 'mode', 'publication_state', 'intent', 'producers', 'exports', + 'not_runtime_authority')) + text(value['schema']) + text(value['publication_state']) + boolean(value['not_runtime_authority']) + need(value['schema'] == SCHEMA and value['publication_state'] == 'COMMITTED' and + value['not_runtime_authority'] is True, 'epoch publication/schema/authority differs') + label(value['epoch_id']) + blob(value['intent'], RECORD_BYTES) + choice(value['mode'], ('normal', 'optimized')) + sequence(value['producers'], 2) + builds = [] + for role, row in zip(PRODUCERS, value['producers']): + producer(row) + need(row['role'] == role, 'producer order differs') + builds.extend(row['builds']) + need(value['producers'][0]['generation'] != value['producers'][1]['generation'], 'producer generation reused') + sequence(value['exports'], MAX_EXPORTS) + seen_paths, seen_inodes = set(), set() + for role, source, row in zip(ROLES, builds, value['exports']): + exact(row, ('role', 'build_sha256', 'file')) + digest(row['build_sha256']) + choice(row['role'], ROLES) + need(row['role'] == role and row['build_sha256'] == sha(canonical(source)), 'export build binding differs') + blob(row['file']) + need((row['file']['sha256'], row['file']['bytes']) == + (source['original_output']['sha256'], source['original_output']['bytes']), 'export bytes differ') + for record in (source['original_output'], row['file']): + need(record['path'] not in seen_paths and inode(record) not in seen_inodes, 'artifact/link alias') + seen_paths.add(record['path']) + seen_inodes.add(inode(record)) + + +def claim(value: dict, manifest: dict, expected_launch: dict, + expected_group: str, expected_generation: str, expected_private_directory: str) -> None: + epoch(manifest) + launch(expected_launch) + label(expected_generation) + path(expected_private_directory) + roles = required_roles(expected_group) + exact(value, ('schema', 'epoch_id', 'mode', 'group', 'generation', 'manifest_sha256', + 'launch', 'copies', 'local_compilations', 'not_runtime_authority', 'admission')) + text(value['schema']) + label(value['epoch_id']) + choice(value['mode'], ('normal', 'optimized')) + text(value['group'], 2) + label(value['generation']) + digest(value['manifest_sha256']) + integer(value['local_compilations'], 0, 0) + boolean(value['not_runtime_authority']) + text(value['admission']) + need(value['schema'] == CLAIM_SCHEMA and value['epoch_id'] == manifest['epoch_id'] and + value['mode'] == manifest['mode'] and value['group'] == expected_group and + value['generation'] == expected_generation and value['manifest_sha256'] == sha(canonical(manifest)), + 'claim independent epoch/mode/group/generation/manifest differs') + launch(value['launch']) + need(value['launch'] == expected_launch and type(value['local_compilations']) is int and + value['local_compilations'] == 0 and value['not_runtime_authority'] is True and + value['admission'] == 'CURRENT_CHILD_CHECKS_REQUIRED', 'claim authority/launch differs') + sequence(value['copies'], len(roles)) + export_by_role = {row['role']: row for row in manifest['exports']} + builds = [row for parent in manifest['producers'] for row in parent['builds']] + occupied_paths = {row['original_output']['path'] for row in builds} + occupied_inodes = {inode(row['original_output']) for row in builds} + occupied_paths.update(row['file']['path'] for row in manifest['exports']) + occupied_inodes.update(inode(row['file']) for row in manifest['exports']) + for role, row in zip(roles, value['copies']): + exact(row, ('role', 'build_sha256', 'source', 'destination')) + choice(row['role'], ROLES) + digest(row['build_sha256']) + blob(row['source']) + blob(row['destination']) + expected = export_by_role[role] + need(row['role'] == role and row['build_sha256'] == expected['build_sha256'] and + row['source'] == expected['file'], 'copy original source provenance differs') + dest = row['destination'] + need(dest['path'] == expected_private_directory + '/' + role + '.artifact', + 'private origin differs from independent launch') + need((dest['sha256'], dest['bytes']) == (row['source']['sha256'], row['source']['bytes']), + 'private copy bytes differ') + need(dest['path'] not in occupied_paths and inode(dest) not in occupied_inodes, 'private copy alias') + occupied_paths.add(dest['path']) + occupied_inodes.add(inode(dest)) + + +def imported_inputs(raw_manifest: bytes, raw_claim: bytes, expected_manifest_sha256: str, + expected_launch: dict, expected_group: str, expected_generation: str, + expected_private_directory: str) -> tuple: + """Validate data binding only. Child must still perform all original checks. + + Expected values must be supplied by independently pinned fresh launch source, + never from either JSON argument. This helper has no runtime admission state. + The negative Root must consume its one-attempt guard BEFORE invoking it. + """ + digest(expected_manifest_sha256) + need(sha(raw_manifest) == expected_manifest_sha256, 'independent parent manifest pin differs') + manifest, receipt = decode(raw_manifest), decode(raw_claim) + claim(receipt, manifest, expected_launch, expected_group, expected_generation, expected_private_directory) + return manifest, receipt + +# Opaque error/result custody. The owner never invokes a foreign object's +# string, equality, hash, attribute, metaclass, or formatting protocol. +ERROR_SLOTS = 64 +CASE_SLOTS = 64 +MAX_ERROR_ARGS = 2 +MAX_ERROR_ARG_CHARS = 256 +MAX_SECONDARY_PROJECTIONS = 6 +_BASE_ARGS_GET = BaseException.args.__get__ +_NATIVE_ERROR_LABELS = ( + (EpochStop, 'EPOCH_STOP'), (RuntimeError, 'RUNTIME_ERROR'), + (ValueError, 'VALUE_ERROR'), (TypeError, 'TYPE_ERROR'), + (OSError, 'OS_ERROR'), (FileNotFoundError, 'FILE_NOT_FOUND'), + (PermissionError, 'PERMISSION_ERROR'), (InterruptedError, 'INTERRUPTED_ERROR'), + (BlockingIOError, 'BLOCKING_IO_ERROR'), (MemoryError, 'MEMORY_ERROR'), + (KeyboardInterrupt, 'KEYBOARD_INTERRUPT'), (SystemExit, 'SYSTEM_EXIT'), + (OverflowError, 'OVERFLOW_ERROR'), (RecursionError, 'RECURSION_ERROR'), + (UnicodeDecodeError, 'UNICODE_DECODE_ERROR')) + + +CUSTODY_SUCCESSORS = tuple(range(1, 257)) +IO_QUARANTINE_ERROR = EpochStop('epoch IO quarantined; parent teardown required') + + +class ErrorOwner: + __slots__ = ('_state',) + + +_OWNER_GET = ErrorOwner._state.__get__ +_OWNER_SET = ErrorOwner._state.__set__ +_OBJECT_NEW = object.__new__ + + +def make_error_owner() -> ErrorOwner: + owner = _OBJECT_NEW(ErrorOwner) + # 0 primary [opaque,phase]; 1 errors; 2 phases; 3 uncertain FD; + # 4 counts [secondary,close_attempts,close_confirmed,cases]; + # 5 overflow [first opaque, incomplete flag]; + # 6 cases [name,opaque,is_error,capture_state,raw_sink_return,validated]. + state = [[None, None, None], [None] * ERROR_SLOTS, [None] * ERROR_SLOTS, + [None] * ERROR_SLOTS, [0, 0, 0, 0], [None, False], + [[None, None, False, 'NOT_RETURNED', None, False, None, None] for _ in range(CASE_SLOTS)], + [False, False, False, None, False, None, False, [0] * 5, [0] * 5, False, False, False, None], + [[None, False, 'NOT_RETURNED', None] for _ in range(CASE_SLOTS)]] + _OWNER_SET(owner, state) + return owner + + +def owner_state(owner: ErrorOwner) -> list: + need(_TYPE(owner) is ErrorOwner, 'exact trusted error owner required') + state = _OWNER_GET(owner, ErrorOwner) + need(_TYPE(state) is _LIST and _LEN(state) == 9, 'trusted owner state shape differs') + for index, count in ((0, 3), (1, ERROR_SLOTS), (2, ERROR_SLOTS), (3, ERROR_SLOTS), + (4, 4), (5, 2), (6, CASE_SLOTS), (7, 13), (8, CASE_SLOTS)): + need(_TYPE(state[index]) is _LIST and _LEN(state[index]) == count, 'trusted owner slot shape differs') + integer(state[4][0], 0, ERROR_SLOTS) + integer(state[4][1], 0, 1 << 32) + integer(state[4][2], 0, state[4][1]) + integer(state[4][3], 0, CASE_SLOTS) + boolean(state[5][1]) + io = state[7] + for index in (0, 1, 2, 4, 6, 9, 10, 11): + boolean(io[index]) + for index in (7, 8): + need(_TYPE(io[index]) is _LIST and _LEN(io[index]) == 5, 'close counter digits differ') + for digit in io[index][:4]: + integer(digit, 0, 255) + integer(io[index][4], 0, 1) + need(io[index][4] == 0 or io[index][:4] == [0, 0, 0, 0], 'close counter exceeds inherited bound') + # Fallible scalar projection occurs only at API entry/snapshot, never in + # the inline cleanup path. The five native digits are authoritative. + attempts = io[7][0] + (io[7][1] << 8) + (io[7][2] << 16) + (io[7][3] << 24) + (io[7][4] << 32) + confirmed = io[8][0] + (io[8][1] << 8) + (io[8][2] << 16) + (io[8][3] << 24) + (io[8][4] << 32) + need(confirmed <= attempts, 'native close confirmation exceeds attempt') + state[4][1], state[4][2] = attempts, confirmed + return state + + +def retain_primary(owner: ErrorOwner, opaque, phase: str, uncertain_fd=None) -> None: + state = owner_state(owner) + text(phase, 96) + if uncertain_fd is not None: + integer(uncertain_fd, 0, (1 << 31) - 1) + if state[0][0] is None: + state[0][0], state[0][1], state[0][2] = opaque, phase, uncertain_fd + elif state[0][0] is not opaque: + retain_secondary(owner, opaque, phase, uncertain_fd) + + +def retain_secondary(owner: ErrorOwner, opaque, phase: str, uncertain_fd) -> None: + state = owner_state(owner) + text(phase, 96) + if uncertain_fd is not None: + integer(uncertain_fd, 0, (1 << 31) - 1) + index = state[4][0] + if index < ERROR_SLOTS: + # Preallocated native slots: no error formatting/attributes, no append. + state[1][index], state[2][index], state[3][index] = opaque, phase, uncertain_fd + state[4][0] = index + 1 + else: + state[5][1] = True + if state[5][0] is None: + state[5][0] = opaque + + +def close_attempt(owner: ErrorOwner) -> None: + state = owner_state(owner) + need(state[4][1] < 1 << 32, 'close attempt counter bound') + digits = state[7][7] + index = 0 + while index < 4 and digits[index] == 255: + digits[index] = 0 + index = CUSTODY_SUCCESSORS[index] + digits[index] = CUSTODY_SUCCESSORS[digits[index]] + + +def close_confirmed(owner: ErrorOwner) -> None: + state = owner_state(owner) + need(state[4][2] < state[4][1], 'close confirmation lacks attempt') + digits = state[7][8] + index = 0 + while index < 4 and digits[index] == 255: + digits[index] = 0 + index = CUSTODY_SUCCESSORS[index] + digits[index] = CUSTODY_SUCCESSORS[digits[index]] + + +def project_error(opaque) -> dict: + kind = _TYPE(opaque) + label_value, admitted = 'FOREIGN_OPAQUE_EXCEPTION', False + for expected_kind, literal_label in _NATIVE_ERROR_LABELS: + if kind is expected_kind: + label_value, admitted = literal_label, True + break + strings, omitted = [], False + if admitted: + # Native BaseException descriptor, only after exact whitelisted type. + # No normal error.args/__dict__/cause/context/name/str access exists. + arguments = _BASE_ARGS_GET(opaque, BaseException) + if _TYPE(arguments) is _TUPLE: + omitted = _LEN(arguments) > MAX_ERROR_ARGS + for argument in arguments[:MAX_ERROR_ARGS]: + if _TYPE(argument) is _STR: + if _LEN(argument) <= MAX_ERROR_ARG_CHARS: + strings.append(argument) + else: + strings.append(argument[:MAX_ERROR_ARG_CHARS]) + omitted = True + else: + omitted = True + else: + omitted = True + return {'literal_type_label': label_value, 'exact_string_args': strings, + 'foreign_or_excess_args_omitted': omitted or not admitted, + 'original_object_retained_opaquely': True} + + +def error_snapshot(owner: ErrorOwner) -> dict: + state = owner_state(owner) + secondary = [] + for index in range(min(state[4][0], MAX_SECONDARY_PROJECTIONS)): + text(state[2][index], 96) + if state[3][index] is not None: + integer(state[3][index], 0, (1 << 31) - 1) + secondary.append({'slot': index, 'phase': state[2][index], + 'uncertain_close_fd': state[3][index], + 'error': project_error(state[1][index])}) + primary = None + if state[0][0] is not None: + text(state[0][1], 96) + if state[0][2] is not None: + integer(state[0][2], 0, (1 << 31) - 1) + primary = {'phase': state[0][1], 'uncertain_close_fd': state[0][2], + 'error': project_error(state[0][0])} + # Projection happens only after operation cleanup. At most six recorder + # errors are projected; a scan of all 64 slots counts omitted projections. + recording_failures = [] + recording_failure_count = 0 + for index, row in enumerate(state[8]): + if row[3] is not None: + recording_failure_count += 1 + if len(recording_failures) < MAX_SECONDARY_PROJECTIONS: + recording_failures.append({'slot': index, 'state': row[2], + 'target_is_error': row[1], 'recording_error': project_error(row[3]), + 'target_retained_opaquely': row[2] != 'NOT_RETURNED'}) + return {'primary': primary, 'secondary': secondary, + 'secondary_capture_incomplete': state[5][1], + 'secondary_projection_omitted': max(0, state[4][0] - MAX_SECONDARY_PROJECTIONS), + 'close_attempts': state[4][1], 'close_confirmed': state[4][2], + 'close_counter_incomplete': state[7][6], + 'io_quarantined': state[7][0], 'native_acquisition_pending': state[7][1], + 'possible_unreturned_native_fd': state[7][2], + 'parent_kernel_teardown_required': state[7][4], + 'uncertain_scandir_owner_retained': state[7][5] is not None, + 'scandir_close_returned_result_unobserved': state[7][9], + # An earlier normal close observation never overrides a later + # delivered failure or retained stream uncertainty. + 'scandir_release_uses_external_premise': (state[7][9] and not state[7][0] + and state[7][5] is None), + 'external_guard_acquisition_pending': state[7][10], + 'external_guard_fd_count_unavailable': state[7][11], + 'native_acquisition_error': None if state[7][3] is None else project_error(state[7][3]), + 'external_guard_error': None if state[7][12] is None else project_error(state[7][12]), + 'recording_failures': recording_failures, + 'recording_projection_omitted': max(0, recording_failure_count - MAX_SECONDARY_PROJECTIONS)} + + + +def record_case(owner: ErrorOwner, name: str, opaque, is_error: bool) -> int: + state = owner_state(owner) + text(name, 16) + boolean(is_error) + count = state[4][3] + need(count < CASE_SLOTS, 'case capacity exceeded') + for index in range(count): + row = state[6][index] + need(_TYPE(row) is _LIST and _LEN(row) == 8, 'case slot shape differs') + text(row[0], 16) + need(row[0] != name, 'case identity replay') + row = state[6][count] + need(_TYPE(row) is _LIST and _LEN(row) == 8, 'case slot shape differs') + text(row[3], 32) + need(row[3] == 'NOT_RETURNED', 'case slot already used') + row[0], row[1], row[2] = name, opaque, is_error + row[3] = 'RETURNED_NOT_CAPTURED' + state[4][3] = count + 1 + return count + + +def case_slot(owner: ErrorOwner, index: int) -> list: + state = owner_state(owner) + integer(index, 0, CASE_SLOTS - 1) + need(index < state[4][3], 'case not recorded') + row = state[6][index] + need(_TYPE(row) is _LIST and _LEN(row) == 8, 'case slot shape differs') + text(row[0], 16) + boolean(row[2]) + choice(row[3], ('NOT_RETURNED', 'RETURNED_NOT_CAPTURED', 'RAW_CAPTURED', 'VALIDATED')) + boolean(row[5]) + return row + +# Original-function record checks use native descriptors only after exact +# FunctionType/CellType gates. Provenance must come from the authenticated Root +# factory call, never a record recaptured after adverse input. +from types import FunctionType as _FUNCTION_TYPE, CellType as _CELL_TYPE +_FUNCTION_GETTERS = tuple(_FUNCTION_TYPE.__dict__[name].__get__ for name in + ('__code__', '__globals__', '__defaults__', '__kwdefaults__', '__closure__', '__annotations__', '__dict__')) +_CELL_GET = _CELL_TYPE.cell_contents.__get__ + + +def capture_original_function(function) -> tuple: + need(_TYPE(function) is _FUNCTION_TYPE, 'exact original function required') + values = tuple(getter(function, _FUNCTION_TYPE) for getter in _FUNCTION_GETTERS) + need(values[2] is None and values[3] is None, 'original callback defaults differ') + closure = values[4] + cells = [] + if closure is not None: + need(_TYPE(closure) is _TUPLE and _LEN(closure) <= 64, 'original closure bound differs') + for cell in closure: + need(_TYPE(cell) is _CELL_TYPE, 'original closure cell differs') + cells.append((cell, _CELL_GET(cell, _CELL_TYPE))) + return function, values, tuple(cells) + + +def check_original_function(function, record) -> None: + need(_TYPE(function) is _FUNCTION_TYPE, 'foreign callable rejected') + need(_TYPE(record) is _TUPLE and _LEN(record) == 3, 'original callback record differs') + need(function is record[0], 'original callback identity differs') + values, cells = record[1], record[2] + need(_TYPE(values) is _TUPLE and _LEN(values) == 7, 'original callback value record differs') + need(_TYPE(cells) is _TUPLE and _LEN(cells) <= 64, 'original callback cell record differs') + for getter, expected in zip(_FUNCTION_GETTERS, values): + need(getter(function, _FUNCTION_TYPE) is expected, 'original callback environment differs') + need(values[2] is None and values[3] is None, 'original callback defaults differ') + closure = values[4] + if closure is None: + need(_LEN(cells) == 0, 'unexpected original closure records') + return + need(_TYPE(closure) is _TUPLE and _LEN(closure) == _LEN(cells), 'original closure record count differs') + for actual_cell, pair in zip(closure, cells): + need(_TYPE(pair) is _TUPLE and _LEN(pair) == 2, 'original cell pair differs') + need(_TYPE(actual_cell) is _CELL_TYPE and actual_cell is pair[0], 'original cell identity differs') + need(_CELL_GET(actual_cell, _CELL_TYPE) is pair[1], 'original closure content identity differs') + + +def prepare_case_shadow(owner: ErrorOwner) -> tuple: + state = owner_state(owner) + count = state[4][3] + need(count < CASE_SLOTS, 'case shadow capacity exceeded') + row = state[8][count] + need(_TYPE(row) is _LIST and _LEN(row) == 4 and row[0] is None and row[3] is None and row[2] == 'NOT_RETURNED', + 'case shadow was already consumed') + return state, count, row diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/field-negative-epoch-v5--SOURCE-READINESS.json.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/field-negative-epoch-v5--SOURCE-READINESS.json.txt new file mode 100644 index 0000000000..b0e631ae9b --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/field-negative-epoch-v5--SOURCE-READINESS.json.txt @@ -0,0 +1,153 @@ +{ + "ParentCompletion_fields_unchanged": true, + "ParentEpoch_API_unchanged": true, + "ParentEpoch_self_attributes": 0, + "activity": { + "controls_fixtures_parser_execution": 0, + "native_compiler_syscall_experiments": 0, + "science_timing": 0, + "stage_ledger_Git_browser_network": 0, + "target_compilation": 0, + "target_imports_calls": 0 + }, + "actual_fault_executor_implemented": false, + "added_controls": { + "bytes": 2875, + "path": "ADDED-CONTROLS.json", + "sha256": "0b97eb3532c5286ee2e693147331f2cc9a1ea13753e6ec30fe55743c8f2bb1ac" + }, + "commands": null, + "complete_cost": "OPEN_UNPRICED_UNFUNDED", + "complete_handler_custody_approved": false, + "complete_schedule": null, + "complete_source_pipeline_accepted": false, + "configuration": null, + "cost_delta": { + "bytes": 1384, + "path": "COST-DELTA.json", + "sha256": "85a4d29de7286d931d5e180629af9576029c1ee9ddab5a148befd9a55dfecb57" + }, + "decision": "AUTHORED_V4_B01_CORRECTIVE_SUCCESSOR_PENDING_INDEPENDENT_REVIEW", + "directory_mode": "0555", + "execution": null, + "file_mode": "0444", + "final_readback_file": "FINAL-READBACK.json", + "finding": "V4-B01", + "full_V4_byte_inverse_pairs": 9, + "funding": null, + "gain_claimed": false, + "gates_None": 20, + "handoff": { + "bytes": 4616, + "path": "README.md", + "sha256": "a0e6646d891ad36ce5d1de0363b554be251284744bc59022215e94c20fb01e64" + }, + "handoff_words": 565, + "input_pins": { + "bytes": 9792, + "path": "INPUT-PINS.json", + "sha256": "a8f64891afcb901c6008c4122c5e14be68c43aff0df8fe0e2802101443f8de57" + }, + "inverse": { + "bytes": 10994, + "path": "SOURCE-INVERSE-v5.json", + "sha256": "0e88ab806783b29a38d213cf648ac2450edb58c43361f32379f72be47d969a78" + }, + "known_raw_records_per_mode": 104, + "known_target_calls_per_mode": 92, + "manifest": { + "bytes": 3931, + "path": "SOURCE-MANIFEST.json", + "sha256": "e3e1f06f3830658f11f1fa2ed6252240f57414a6f6dd1f219c91a1770aacffbf" + }, + "new_unexecuted_control_specs": 5, + "old_expectation_dispositions": { + "bytes": 9282, + "path": "OLD-EXPECTATION-DISPOSITIONS.json", + "sha256": "b2ab3dc9982755f29442c4891b545b928320a0fdb24434020153a12b8efcaa3d" + }, + "open_obligations": [ + "Independent V5 source review of correction and full inverse.", + "Successful first exception delivery, native entry/unwind and protected-state premises.", + "Exact selected-B/runtime/profile/configuration linkage; authentic parent teardown; no actual native-release observation.", + "All old/new controls, complete caller/terminal/parent completion integration, physical schedule and full resource/cost accounting.", + "Separate configuration/stage/command/funding/execution approval." + ], + "original_guards_and_order_preserved": true, + "other_change": "Module import suffix _v4 to _v5; original public data schema tags preserved.", + "owner": "/root/astra_epoch_v4_finish", + "parent_registry_keys": 21, + "passive_checks": 273, + "passive_evidence": { + "bytes": 28293, + "path": "PASSIVE-CHECKS.json", + "sha256": "129cbeb1dfbce1f49cdcdea18411b9c68c85464ff4f0ab9985b4d52167f02afd" + }, + "passive_failed_checks": 0, + "predecessor": { + "all121_images_preserved": true, + "archive_reference_tree_recopied": false, + "directory": "/home/d3lerium/.codex/.chatgpt-projects/g-p-6ad5817fd84881918865926b6fd51453/outputs/h25-data-handling-20261028/areas/field-negative-epoch-v4", + "readiness_sha256": "db6b2aff4cc748fe992900a264768a3f523d95f18c4bd5bccbd2b96bb8c790f6", + "review_sha256": "13862f38f0b8ea5c50a396f7762aede6df90490814608b2eb893d4c96be636b1" + }, + "primitive_contract_sha256": "4927797027f4aa1f8b1204be2a7c321faa9c26b416dc3f43fe4b139df0f8c22a", + "private_state_shape_unchanged": true, + "repair": "Inline exact-primary root, conservative protected-body quarantine and retained iterator uncertainty before cleanup; guard both normal-close premise branches and prevent historical normal-return observation overriding current uncertainty.", + "retained_V4_custody_specs": 12, + "retained_old_fault_specs": 7, + "schema": "h25-negative-epoch-source-readiness-v5", + "selected_B": { + "actual_native_profile_admission": null, + "native_release_proved_or_observed": false, + "parent_adoption_already_recorded": true, + "required_native_premises_sha256": "161bd504c2f3d0e051f0e37c47e28ef287eef8a239456696ebd42ad96a8b7afb", + "semantic_configuration_linkage_admitted": false, + "sha256": "a64b59374b6666884af8000eb38792e97c9960bb21ec78dde8051a8cb2d1125b" + }, + "source_only": true, + "source_review_acceptance": null, + "stage": null, + "substantive_changed_functions": [ + "epoch_copy_v5.require_entries", + "epoch_schema_v5.error_snapshot" + ], + "target_modules": { + "adverse_protocol_controls_v5.py": { + "bytes": 11078, + "sha256": "85534e666301f6a394be6197913477c433299350baa0fe15bd104c034262f424" + }, + "anti_replay_data_controls_v5.py": { + "bytes": 8647, + "sha256": "e831b92d8fe81427d7fed30bcb59dc31e457a5df4cbaa37930a821d760121f1c" + }, + "epoch_copy_v5.py": { + "bytes": 82957, + "sha256": "4f459d0336d59975df787c24373e18dad4044c3a24137392e890115f811b3211" + }, + "epoch_import_claim_v5.py": { + "bytes": 4807, + "sha256": "69a8c1570e6cf521d7a17bda59748578043410a718691e154fc50681e6262095" + }, + "epoch_parent_v5.py": { + "bytes": 26833, + "sha256": "058059912144863a4b2bfe4fc9ffc5233b4ab20ee5a7355bde66f4d3f6f28712" + }, + "epoch_schema_v5.py": { + "bytes": 30668, + "sha256": "b89a789654be87bde40a47300f4d9702dce2b90e6ab3be9a2025f6d8041b3e9a" + }, + "epoch_stop_v5.py": { + "bytes": 8205, + "sha256": "5b10c9d72dd0e646652a73b6ffe9ba870762d6bc2f7432bc6b06571a1b7d2a6f" + }, + "original_build_provenance_v5.py": { + "bytes": 16024, + "sha256": "bd5ffd9a1c221e0945527fc8fa8d0ad4eb36b9a8884503451c1b6b12d00007ea" + }, + "repair_control_sources_v5.py": { + "bytes": 12594, + "sha256": "6dd9569acc6ac50983acd7f86e7346504eef40a545e65be2f0d885efb5cc0270" + } + } +} diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/field-parent-completion-v2--SOURCE-READINESS.json.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/field-parent-completion-v2--SOURCE-READINESS.json.txt new file mode 100644 index 0000000000..8cfb166357 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/field-parent-completion-v2--SOURCE-READINESS.json.txt @@ -0,0 +1,158 @@ +{ + "actual_native_profile_and_semantic_configuration_linkage": null, + "additive_parent_recipe_families": 20, + "all38_parent_recipes_unexecuted": true, + "artifacts": { + "API-AND-GATES.json": { + "bytes": 1729, + "path": "API-AND-GATES.json", + "sha256": "066ecc151356d3253c5cdc0081e339857fef6c0b2f32e8b0d863e2eaace6bebf" + }, + "COMPLETE-COST-BILL.json": { + "bytes": 6223, + "path": "COMPLETE-COST-BILL.json", + "sha256": "8f570c18c286a7d4fc962358f798b83a41fa2f508c40335cdf9277844203a3ea" + }, + "CONDITIONS.json": { + "bytes": 3590, + "path": "CONDITIONS.json", + "sha256": "3333cab0bedefa9f9f78df49fc82c4521ee755cf6c6e3d460a5130b8e511b7ed" + }, + "DEPENDENCY-SELECTION.json": { + "bytes": 1544, + "path": "DEPENDENCY-SELECTION.json", + "sha256": "4cfa1ce08239756fef77bbdde27b18a3c85765e82da7e4e2ad3785e9b7a1a22d" + }, + "INPUT-PINS.json": { + "bytes": 48454, + "path": "INPUT-PINS.json", + "sha256": "c8dc314f3330819c4d9cb8183532f4f5d90f2a1229a4b1202d2ccba6dac0ee33" + }, + "INSPECTOR-ATTEMPTS.json": { + "bytes": 901, + "path": "INSPECTOR-ATTEMPTS.json", + "sha256": "3183dfe1e5b4c21c27e33c64b5c92f79cb8a2f9b399149e393744cd071626b59" + }, + "OLD-EXPECTATION-DISPOSITIONS.json": { + "bytes": 1552, + "path": "OLD-EXPECTATION-DISPOSITIONS.json", + "sha256": "fe7b6f28f2c9f094f9edcda26ee4a852f6a5c54a72767b694a9ef8945816c49e" + }, + "PASSIVE-CHECKS.json": { + "bytes": 42824, + "path": "PASSIVE-CHECKS.json", + "sha256": "753fe95f3121160940d136ec21efeef3679c0249dce82efc43b41e0b46defdc6" + }, + "README.md": { + "bytes": 5269, + "path": "README.md", + "sha256": "398302226937d4e8671a0121f6a6f46d2de8fa513a5da5e0f89220fb4f5e67cd" + }, + "RECEIVER-SOURCE-MAP.json": { + "bytes": 20868, + "path": "RECEIVER-SOURCE-MAP.json", + "sha256": "532733f4d78fc327f00851f33e1db20ae8ef34fd904fc56327d44a4ebea11067" + }, + "REPAIR-CLAIMS.json": { + "bytes": 2260, + "path": "REPAIR-CLAIMS.json", + "sha256": "77846b667bfbba00292e51e327b386b6b960cc94e64e5c9732658caae0ae4729" + }, + "SOURCE-DELTA.json": { + "bytes": 16159, + "path": "SOURCE-DELTA.json", + "sha256": "7c16f7698cb13581dea2156ad3bf6f3e1f73f8fb040df9e9f45990deeb6226c3" + }, + "SOURCE-INVERSE.json": { + "bytes": 39088, + "path": "SOURCE-INVERSE.json", + "sha256": "558ffcc429835537fcb430881226aa7e2bc065d2934ee62b716dde8605e42409" + }, + "SOURCE-TEST-RECIPES.json": { + "bytes": 13798, + "path": "SOURCE-TEST-RECIPES.json", + "sha256": "354a116c8dd252ff39494de020058561aa62cda92731f96cc6e26993192fe54c" + }, + "TYPE-ENVELOPE.json": { + "bytes": 2096, + "path": "TYPE-ENVELOPE.json", + "sha256": "b7fa437cf53e8798eb62e603fbc4f94daf20e9a10c6529dd5bb6a9f2c6f090e1" + } + }, + "command": null, + "complete_V1_byte_inverses": 5, + "complete_cost_fit_gain": "UNMEASURED_UNFUNDED_NO_GAIN", + "configuration": null, + "decision": "AUTHORED_B01_B02_CORRECTIVE_SOURCE_PENDING_INDEPENDENT_REVIEW", + "epoch7old12V4_5V5_and_variant33_specs_unexecuted": true, + "epoch92target104raw_per_mode_retained": true, + "epoch_gates_None": 20, + "execution": null, + "final_passive_checks_before_seal": 360, + "final_readback_sha256": "dabae2bf52d60062c7b7783ff3f99687ce794ca29558206cf5e540027fd60669", + "fixed_receiver_modules": 33, + "funding": null, + "handoff_words": 694, + "old_parent_recipe_families": 18, + "original_predicate_body_byte_identical": true, + "original_public_signatures_unchanged": true, + "own_gates_None": 6, + "owner": "/root/astra_composition_cost", + "passive_checks": 376, + "passive_failures": 0, + "policy_exec_domain_persistent_replay_full_orchestrator": "EXTERNAL_UNIMPLEMENTED", + "predecessor_readiness_sha256": "68ee02d81fffad3b1f5f67c549b91fb48994223a8f858dc3cb1cb97939b74643", + "predecessor_review_sha256": "c05392fcb818bf5af31e7dd6fc2f397e615532bfb8991e52b8c9f621c421c9e8", + "preserved_V1_files": 33, + "raw_before_compare_original_Root_API4_guards_oracles_events_unchanged": true, + "reviewed_source_selection_count": 1, + "runtime_modules": { + "group01_evidence_v1.py": { + "bytes": 15610, + "path": "group01_evidence_v1.py", + "sha256": "05ec6a63c57340ba929aea1fab71b096efc143e099346640f6def41310bd3e25" + }, + "group01_original_predicates_v1.py": { + "bytes": 23224, + "path": "group01_original_predicates_v1.py", + "sha256": "fb9e6e11b39b76ab8652c546fd76c06d662ea4116376abcc2a6267bb4783dbfd" + }, + "parent_closure_v1.py": { + "bytes": 13400, + "path": "parent_closure_v1.py", + "sha256": "2d831cff8bd444de2d6941645d571e07618ede404a1f45692b557f61494b334a" + }, + "parent_completion_v1.py": { + "bytes": 54168, + "path": "parent_completion_v1.py", + "sha256": "d4ee1b7ce4a42b73261984ffb1b9ceb5bb0165223e04a253588f83b99f6981a5" + }, + "parent_domain_v1.py": { + "bytes": 20456, + "path": "parent_domain_v1.py", + "sha256": "9205e14d6661fb5df0597f0ad7b2206006f2d31f01f784805f64c13875663282" + } + }, + "runtime_source_byte_delta": 10961, + "schema": "h25-parent-completion-source-readiness-v2", + "seal_files": [ + "SOURCE-MANIFEST.json", + "SHA256SUMS", + "FINAL-READBACK.json", + "FREEZE-READBACK.json" + ], + "selected_B_parent_adopted": true, + "selected_epoch": "V5 source acceptance only", + "selected_variant": "V2 source acceptance only", + "source_repairs": [ + "B01 own iterator uncertainty, original V5 state propagation, early-constructor and cross-mode quarantine; no fresh acquisition after uncertainty", + "B02 new exact-int scalar envelope plus typed independent pins; original predicate body preserved" + ], + "source_review": null, + "stage": null, + "stage_ledger_Git_browser_network_subagent_activity": 0, + "target_import_call_compile_parser_fixture_control_native_syscall_experiment_science_timing": 0, + "unchanged_input_images": 148, + "variant_gates_None": 12, + "whole_handler_or_native_release_proof": false +} diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/group01_evidence_v1.py.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/group01_evidence_v1.py.txt new file mode 100644 index 0000000000..bde3f97232 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/group01_evidence_v1.py.txt @@ -0,0 +1,256 @@ +"""Parent data replay of the exact unchanged Group01 finite producer route. + +All arguments come from the owning parent registry and independently frozen +prelaunch plan. A parsed status never establishes process ownership, native +correctness or historical source continuity. Those are separate original +source/runtime and owned-domain obligations. No function was executed here. +""" +import json +import math +import epoch_schema_v5 as schema +import epoch_copy_v5 as copying +import original_build_provenance_v5 as original_build +import parent_closure_v1 as closure +import group01_original_predicates_v1 as original_predicates + +_TYPE, _LEN = type, len +GROUP_ORDER = ('native', 'transport', 'collector', 'pure_initial', 'pure_extended', + 'pure_combined', 'root_model', 'sink_close_model', 'projection_model', 'aggregate') +GROUP_KEYS = ('native', 'transport', 'collector', 'elf', 'providers', 'elf_extended') +MAX_JSON_NODES = 200000 +MAX_JSON_BYTES = 4 * 1024 * 1024 +FINITE_KEYS = ('status', 'lanes', 'data_handling', 'data_source_custody', 'optimized', + 'original_controls', 'new_controls', 'new_source_custody', 'driver_sha256', + 'initial_native_tcb', 'initial_native_tcb_restoration', 'native_packet', + 'reference_driver_sha256', 'phases') + + +def _pairs(pairs): + schema.need(_TYPE(pairs) is list and _LEN(pairs) <= 8192, 'receipt JSON object bound') + result = {} + for key, value in pairs: + schema.need(_TYPE(key) is str and _LEN(key) <= 65536 and key not in result, + 'receipt duplicate/foreign/oversize key') + result[key] = value + return result + + +def _reject(value): + raise schema.EpochStop('nonfinite receipt JSON constant') + + +def _plain(value, budget, depth=0): + schema.need(depth <= 40 and budget[0] > 0, 'receipt JSON node/depth bound') + budget[0] -= 1 + kind = _TYPE(value) + if value is None or kind is bool: + return + if kind is int: + schema.need(value.bit_length() <= 4096, 'receipt integer bound') + return + if kind is float: + schema.need(math.isfinite(value), 'nonfinite receipt number') + return + if kind is str: + schema.need(_LEN(value) <= 65536, 'receipt string bound') + budget[1] += _LEN(value) + schema.need(budget[1] <= MAX_JSON_BYTES, 'receipt text budget') + return + schema.need(kind in (list, dict) and _LEN(value) <= 8192, 'receipt exact collection bound') + if kind is dict: + for key, item in value.items(): + schema.need(_TYPE(key) is str, 'receipt exact key required') + _plain(key, budget, depth + 1) + _plain(item, budget, depth + 1) + else: + for item in value: + _plain(item, budget, depth + 1) + + +def decode(raw): + schema.need(_TYPE(raw) is bytes and 0 < _LEN(raw) <= MAX_JSON_BYTES, 'receipt raw byte bound') + value = json.loads(raw.decode('ascii'), object_pairs_hook=_pairs, parse_constant=_reject) + schema.need(_TYPE(value) is dict, 'receipt top-level exact object required') + _plain(value, [MAX_JSON_NODES, 0]) + return value + + +def encode(value): + _plain(value, [MAX_JSON_NODES, 0]) + raw = json.dumps(value, sort_keys=True, separators=(',', ':'), ensure_ascii=True, + allow_nan=False).encode('ascii') + b'\n' + schema.need(_LEN(raw) <= MAX_JSON_BYTES, 'receipt canonical byte bound') + return raw + + +def same_json(left, right): + # Both operands are exact bounded JSON-native data. Canonical bytes retain + # bool/int/float distinctions that Python nested equality otherwise loses. + return encode(left) == encode(right) + + +def _read(path, bound, error_owner): + pin = copying.inspect(path, bound, error_owner=error_owner) + raw = copying.read_verified(pin, bound, error_owner=error_owner) + return pin, raw + + +def _captured_call(receiver_capability, module, name, *args): + # Exact module/function names below are source literals, not caller-selected + # callbacks. Current source/identity checks surround every receiving call. + closure.check_receivers(receiver_capability) + function = closure.receiver(receiver_capability, module, name) + result = function(*args) + closure.check_receivers(receiver_capability) + return result + + +def _legacy_controls(result, expected): + schema.exact(expected, ('original_counts', 'original_fixture_sha256', + 'original_v2_counts', 'original_v2_stream', 'new_controls')) + schema.digest(expected['original_fixture_sha256']) + native = result['original_controls'] + schema.need(_TYPE(native) is dict and native.get('status') == 'FINITE_NATIVE_GF2_CONTROLS_PASS' and + same_json(native.get('counts'), expected['original_counts']) and + native.get('fixture_sha256') == expected['original_fixture_sha256'] and + _TYPE(native.get('micro_repetitions')) is int and native['micro_repetitions'] == 128 and + native.get('independent_oracle') == + 'Dense binary lists, descending pivots, addition modulo 2; no packed/source/native helpers', + 'original native independent outcome projection differs') + schema.need(_TYPE(native.get('micro_fixtures')) is int and native['micro_fixtures'] > 0 and + _TYPE(native.get('native_and_fallback_calls')) is dict and + all(_TYPE(value) is int and value > 0 for value in native['native_and_fallback_calls'].values()), + 'original native and fallback paths not represented') + v2 = native.get('v2_controls') + schema.need(_TYPE(v2) is dict and v2.get('status') == 'V2_RUNTIME_AND_COMPLEMENT_STREAM_PASS' and + same_json(v2.get('counts'), expected['original_v2_counts']) and + same_json(v2.get('complement_fixture_stream'), expected['original_v2_stream']) and + _TYPE(v2.get('modified_helper_invocations')) is int and v2['modified_helper_invocations'] == 0, + 'original runtime/ordered-complement independent projection differs') + # The expected complete new-control tree is an independently approved input + # before launch. It is never learned from this result or an earlier PASS. + schema.need(same_json(result['new_controls'], expected['new_controls']), + 'complete original bookkeeping control return differs') + + +def authenticate_group01(output, expected, process_id, parent_file_limits, + receiver_capability, error_owner, stdout_raw): + """Return actual evidence data; only the owning launcher can mint authority.""" + schema.path(output) + schema.integer(process_id, 1, (1 << 31) - 1) + schema.exact(expected, ('mode', 'generation', 'stage_sha256', 'root_sha256', + 'driver_sha256', 'reference_driver_sha256', 'builds', 'legacy_outcomes', + 'source_receipts', 'tcb_files', 'hashlib_origin')) + schema.choice(expected['mode'], ('normal', 'optimized')) + schema.label(expected['generation']) + for key in ('stage_sha256', 'root_sha256', 'driver_sha256', 'reference_driver_sha256'): + schema.digest(expected[key]) + schema.path(expected['hashlib_origin']) + optimize = 0 if expected['mode'] == 'normal' else 1 + result_pin, result_raw = _read(output + '/receipt.json', MAX_JSON_BYTES, error_owner) + result = decode(result_raw) + schema.exact(result, FINITE_KEYS) + schema.need(result['status'] == 'H25_DATA_HANDLING_FINITE_PASS' and + result['lanes'] == 'all' and _TYPE(result['optimized']) is int and + result['optimized'] == optimize and + result['driver_sha256'] == expected['driver_sha256'] and + result['reference_driver_sha256'] == expected['reference_driver_sha256'], + 'original finite producer route/mode/source differs') + schema.need(same_json(decode(stdout_raw), result), 'original stdout and terminal finite receipt differ') + _legacy_controls(result, expected['legacy_outcomes']) + finite_pin, finite_raw = _read(output + '/finite-controls.json', MAX_JSON_BYTES, error_owner) + schema.need(same_json(decode(finite_raw), result['original_controls']), 'original finite raw result differs') + data, packet = result['data_handling'], result['native_packet'] + schema.need(_TYPE(data) is dict and data.get('schema') == 'h25-data-handling-v2' and + data.get('full_caller_run') is False and data.get('full_candidate_admission') is False and + data.get('cache_teardown_stops') == [] and same_json(data.get('native_packet'), packet), + 'original finite data or cleanup boundary differs') + original_predicates.check_original_control_union( + {'controls': data['controls'], 'native_packet': packet}, optimize, include_late=True) + schema.need(packet['late_started'] is True and packet['late_completed'] is True and + packet['field_service_closed'] is True and packet['direct_close_stop'] is None and + packet['field_group_stop'] is None and packet['field_restoration_receipt_checked'] is True and + packet['field_runtime_qualification'] is False, + 'original late/group/field cleanup or qualification boundary differs') + schema.exact(expected['source_receipts'], ('data_source_custody', 'new_source_custody', + 'compiler_dependencies')) + for key in ('data_source_custody', 'new_source_custody'): + schema.need(same_json(result[key], expected['source_receipts'][key]), 'source-derived receipt custody differs') + schema.need(same_json(packet['compiler_dependencies'], expected['source_receipts']['compiler_dependencies']), + 'original compiler/link/header receipt closure differs') + # Original placement is authenticated by exact launched source. This call + # replays its fixed data contract; it does not rerun initial native checks. + tcb_files = tuple(tuple(row) for row in expected['tcb_files']) + _captured_call(receiver_capability, 'restoration_contract_v1', 'validate_restoration', + result['initial_native_tcb'], data['controls']['native_initial_tcb'], + result['initial_native_tcb_restoration'], tcb_files, expected['hashlib_origin'], + expected['root_sha256'], len(tcb_files)) + schema.integer(result['initial_native_tcb']['pid'], 1, (1 << 31) - 1) + schema.integer(result['initial_native_tcb_restoration']['pid'], 1, (1 << 31) - 1) + schema.need(result['initial_native_tcb']['pid'] == process_id and + result['initial_native_tcb_restoration']['pid'] == process_id, + 'initial/restoration receipt belongs to another process') + initial_pin, initial_raw = _read(output + '/initial-native-tcb.json', MAX_JSON_BYTES, error_owner) + restored_pin, restored_raw = _read(output + '/initial-native-tcb-restoration.json', MAX_JSON_BYTES, error_owner) + schema.need(same_json(decode(initial_raw), result['initial_native_tcb']) and + same_json(decode(restored_raw), result['initial_native_tcb_restoration']), + 'initial/restoration retained raw differs') + controls_pin, controls_raw = _read(output + '/initial-tcb-controls/receipt.json', MAX_JSON_BYTES, error_owner) + schema.need(same_json(decode(controls_raw), data['controls']['native_initial_tcb']), 'original initial five-control raw differs') + delivery = packet['field_group_delivery'] + aggregate = delivery['aggregate'] + schema.need(same_json(data['controls']['native_fields'], aggregate), 'field aggregate projections differ') + # JSON object order is not the original insertion-order observation. Restore + # only this explicit source-fixed mapping order for the existing validator; + # no value/case/sequence/order or unknown-key repair is permitted. + schema.exact(aggregate['groups'], GROUP_KEYS) + aggregate['groups'] = {key: aggregate['groups'][key] for key in GROUP_KEYS} + _captured_call(receiver_capability, 'run_controls_v5', 'validate_all', delivery, expected['mode']) + values = (aggregate['groups']['native'], aggregate['groups']['transport'], + aggregate['groups']['collector'], aggregate['pure_v2']['initial'], + aggregate['pure_v2']['extended'], aggregate['pure_v2'], aggregate['root_model'], + aggregate['sink_close_model'], aggregate['projection_model'], aggregate) + group_rows = [] + for index, (group, value) in enumerate(zip(GROUP_ORDER, values)): + raw_ref = delivery['group_evidence']['raw_pins'][index][1] + validation_ref = delivery['group_evidence']['validation_pins'][index][1] + raw_pin, raw = _read(output + '/' + raw_ref['file'], 1048576, error_owner) + validation_pin, validation_raw = _read(output + '/' + validation_ref['file'], 8192, error_owner) + schema.need(raw_pin['sha256'] == raw_ref['sha256'] and raw_pin['bytes'] == raw_ref['bytes'] and + validation_pin['sha256'] == validation_ref['sha256'] and validation_pin['bytes'] == validation_ref['bytes'], + 'durable group pin differs from actual retained bytes') + schema.need(raw == encode(value), 'complete raw group differs from original aggregate projection') + note = {'schema': 'h25-full-group-evidence-sink-v5', 'mode': expected['mode'], 'group': group, + 'state': 'RETURNED_RAW_OUTER_VALIDATED', 'raw': raw_ref} + schema.need(validation_raw == encode(note), 'complete validation note differs') + group_rows.append({'group': group, 'raw': raw_pin, 'validation': validation_pin}) + builds = [] + schema.sequence(expected['builds'], 3) + for role, build_plan in zip(schema.ROLES[:3], expected['builds']): + schema.exact(build_plan, ('role', 'profile', 'command_sha256', 'original_output_path', 'expected_original')) + schema.need(build_plan['role'] == role, 'original build role order differs') + base = output + '/cold-native-metadata/' + role + original_record_pin, raw_receipt = _read(base + '-build.json', 65536, error_owner) + original_record = decode(raw_receipt) + schema.need(same_json(original_record, packet['builds'][role]), 'original build raw/terminal projection differs') + row = {'role': role, 'producer_role': 'group01', 'producer_generation': expected['generation'], + 'producer_stage_sha256': expected['stage_sha256'], 'command_sha256': build_plan['command_sha256'], + 'profile': build_plan['profile'], + 'original_output': copying.inspect(build_plan['original_output_path'], error_owner=error_owner), + 'original_receipt': original_record_pin, + 'attempt': copying.inspect(base + '.attempt.json', 65536, error_owner=error_owner), + 'journal': copying.inspect(base + '.attempt.jsonl', schema.JOURNAL_BYTES, error_owner=error_owner), + 'stdout': copying.inspect(base + '.stdout.raw', schema.LOG_BYTES, error_owner=error_owner), + 'stderr': copying.inspect(base + '.stderr.raw', schema.LOG_BYTES, error_owner=error_owner)} + independent = schema.plain_copy(build_plan['expected_original']) + independent['producer_process_id'] = process_id + independent['parent_file_limits'] = list(parent_file_limits) + closure.check_receivers(receiver_capability) + original_build.authenticate_original_build(row, independent, error_owner=error_owner) + closure.check_receivers(receiver_capability) + builds.append(row) + return {'raw_result': result_pin, 'group_rows': group_rows, 'builds': builds, + 'additional_raw': [finite_pin, initial_pin, restored_pin, controls_pin], + 'own_group01_source_and_result_contract_checked': True, + 'later_cross_root_aggregate_required_before_export': False, + 'native_runtime_or_full_union_qualified': False} diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/h25_parent_supervisor.py.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/h25_parent_supervisor.py.txt new file mode 100644 index 0000000000..73ed60fe21 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/h25_parent_supervisor.py.txt @@ -0,0 +1,475 @@ +"""Parent-only bounded process supervision; imports no candidate implementation. + +The runtime caller must establish the trusted clean launcher before calling us. +This source was prepared without loading ctypes or running any control. The +closed single-threaded child domain is an explicit premise, not a hostile-fork +sandbox. Numeric process IDs are never used as signal destinations. +""" +import fcntl +import hashlib +import json +import os +from pathlib import Path +import resource +import signal +import stat +import subprocess +import sys +import time + +FLAGS = ('-S', '-s', '-P', '-B') +ENV = {'PATH': '/usr/bin:/bin', 'PYTHONHASHSEED': '0', 'LANG': 'C.UTF-8', + 'LC_ALL': 'C.UTF-8', 'TZ': 'UTC', 'PYTHONDONTWRITEBYTECODE': '1'} +RUNNER_SHA = 'bd882e3dadb1b6aeaa63ee824f1a1c58f8ef2546b6840a2bffa46885a184d3eb' +QUEUE_SHA = '1348a7b4d7cc1f9fef556f5e0abdaf04411a998afdcd574d7812c76ab37dcf68' +TCB_SHA = '610492b3fc06baa0560175edc3ba27057de00d00b8fd3d58dbe55e5a371c042a' +LIBC = '/usr/lib/x86_64-linux-gnu/libc.so.6' +NATIVE_PINS = { + LIBC: '3a15d66867d83762c7f2f1e37359cb8f6c5743edb369c65285cb0b1c4f7498bf', + '/usr/lib/python3.12/lib-dynload/_ctypes.cpython-312-x86_64-linux-gnu.so': 'aad3e24f186e6c0a1c7efa8f16004f951f527db86f6451d30118657384a456c1', + '/usr/lib/x86_64-linux-gnu/libffi.so.8.1.4': '00f593fe192f2851b8ce23b25cec2488d769beb5a8f63e8c9e563071e1075153', + '/usr/lib/python3.12/ctypes/__init__.py': '0782592567ad71097198a3afe985ac3e2ea0b9b5e75452402c9460c89a86318a', + '/usr/lib/python3.12/ctypes/_endian.py': 'c5d692bdce10dfee242752620061bab684633bc72445a3def484961ef1bdbf3a', +} +CHUNK = 65536 +LOG_CAP = 2 * 1024 * 1024 +META_CAP = 256 * 1024 +CLEANUP_SECONDS = 2.0 + + +def need(condition, message): + if not condition: + raise RuntimeError(message) + + +def launch_contract(): + need(sys.executable == '/usr/bin/python3.12', 'Pinned interpreter required') + need(sys.flags.no_site == sys.flags.no_user_site == sys.flags.dont_write_bytecode == 1 and + sys.flags.safe_path and sys.flags.ignore_environment == sys.flags.isolated == + sys.flags.hash_randomization == 0, 'Trusted no-site safe-path fixed-seed flags required') + need(dict(os.environ) == ENV, 'Exact clean environment required') + need(tuple(sys.path) == ('/usr/lib/python312.zip', '/usr/lib/python3.12', + '/usr/lib/python3.12/lib-dynload'), 'Initial system stdlib path changed') + need(list(Path('/proc/self/task').iterdir()) == [Path('/proc/self/task') / str(os.getpid())], + 'Exactly one parent task required') + + +def identity(info): + return (info.st_dev, info.st_ino, info.st_mode, info.st_size, info.st_mtime_ns, info.st_ctime_ns) + + +def stable_file(path, limit, keep=False): + """Complete bounded snapshot; no file read can extend a growing snapshot.""" + path = Path(path) + before = path.stat(follow_symlinks=False) + need(stat.S_ISREG(before.st_mode) and before.st_size <= limit, 'File type/size bound: ' + str(path)) + fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK | os.O_CLOEXEC) + h, count, blocks = hashlib.sha256(), 0, [] + try: + opened = os.fstat(fd) + need(identity(before) == identity(opened), 'File changed while opening') + while count < opened.st_size: + block = os.read(fd, min(CHUNK, opened.st_size - count)) + need(bool(block), 'Short retained-file read') + count += len(block) + h.update(block) + if keep: + blocks.append(block) + after_fd = os.fstat(fd) + finally: + os.close(fd) + after = path.stat(follow_symlinks=False) + need(identity(before) == identity(after_fd) == identity(after), 'File drift during retained snapshot') + row = {'path': str(path), 'sha256': h.hexdigest(), 'bytes': count, + 'identity': list(identity(after)), 'stable': True, 'read_chunk_bytes': CHUNK} + return (row, b''.join(blocks)) if keep else row + + +def read_json(path, limit=META_CAP): + row, raw = stable_file(path, limit, True) + return json.loads(raw), row + + +def write_new(path, row): + raw = json.dumps(row, sort_keys=True, indent=2).encode('ascii') + b'\n' + need(len(raw) <= META_CAP, 'Bounded metadata record exceeded') + fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_CLOEXEC | os.O_NOFOLLOW, 0o600) + try: + view = memoryview(raw) + while view: + written = os.write(fd, view) + need(written > 0, 'Metadata write made no progress') + view = view[written:] + os.fsync(fd) + finally: + os.close(fd) + + +def proc(pid): + try: + with open('/proc/' + str(pid) + '/stat', 'rb') as stream: + raw = stream.read(8193) + need(len(raw) <= 8192, 'Unexpected process-stat size') + end = raw.rfind(b') ') + need(end >= 0, 'Malformed process stat') + fields = raw[end + 2:].split() + return {'pid': int(pid), 'ppid': int(fields[1]), 'pgid': int(fields[2]), + 'sid': int(fields[3]), 'start_ticks': int(fields[19]), + 'state': fields[0].decode('ascii'), + 'rss_bytes': int(fields[21]) * os.sysconf('SC_PAGE_SIZE')} + except (FileNotFoundError, ProcessLookupError, PermissionError): + return None + + +def census(): + found = {} + with os.scandir('/proc') as entries: + for entry in entries: + if entry.name.isdecimal(): + row = proc(int(entry.name)) + if row is not None: + found[row['pid']] = row + return found + + +def generation(row): + return row['pid'], row['start_ticks'] + + +def children_now(): + return [row for row in census().values() if row['ppid'] == os.getpid()] + + +def install_subreaper(root): + """Called only by the future parent, before any controlled root exists.""" + launch_contract() + need(not children_now(), 'Parent must own no preexisting child processes') + tcb, tcb_row = read_json(root / 'control/NATIVE-INITIAL-TCB-v1.json') + need(tcb_row['sha256'] == TCB_SHA, 'Accepted initial TCB changed') + need(any(row['path'] == LIBC and row['sha256'] == NATIVE_PINS[LIBC] + for row in tcb['files']), 'Pinned libc absent from accepted TCB') + evidence = {path: stable_file(path, 16 * 1024 * 1024) for path in NATIVE_PINS} + need(all(evidence[path]['sha256'] == expected for path, expected in NATIVE_PINS.items()), + 'Subreaper native/stdlib source supplement changed') + # This import and native call have NOT been performed during source authoring. + need(Path('/usr/lib/x86_64-linux-gnu/libffi.so.8').resolve() == + Path('/usr/lib/x86_64-linux-gnu/libffi.so.8.1.4'), 'Foreign libffi SONAME resolution') + import ctypes + need(sys.modules['_ctypes'].__file__ == + '/usr/lib/python3.12/lib-dynload/_ctypes.cpython-312-x86_64-linux-gnu.so', 'Foreign _ctypes owner') + need(ctypes.__file__ == '/usr/lib/python3.12/ctypes/__init__.py', 'Foreign ctypes owner') + library = ctypes.CDLL(LIBC, use_errno=True) + call = library.prctl + call.argtypes = [ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong] + call.restype = ctypes.c_int + prior, actual = ctypes.c_int(), ctypes.c_int() + need(call(37, ctypes.addressof(prior), 0, 0, 0) == 0, 'PR_GET_CHILD_SUBREAPER failed') + need(call(36, 1, 0, 0, 0) == 0, 'PR_SET_CHILD_SUBREAPER failed') + need(call(37, ctypes.addressof(actual), 0, 0, 0) == 0 and actual.value == 1, + 'Same-process subreaper readback failed') + for path, expected in NATIVE_PINS.items(): + need(stable_file(path, 16 * 1024 * 1024)['sha256'] == expected, 'TCB bytes changed across load') + # Retain the CDLL and typed function in the owning parent for its whole queue. + return {'pid': os.getpid(), 'prior': prior.value, 'actual': actual.value, + 'tcb_sha256': TCB_SHA, 'native_source_evidence': evidence, + 'trust': 'Trusted OS/loader/initial system stdlib; file pins do not authenticate native memory'}, (library, call) + + +def ledger(root, allow_unclosed=False): + result = {} + runs = root / 'runtime/runs' + for folder in sorted(runs.iterdir()): + need(folder.is_dir() and not folder.is_symlink(), 'Unexpected round run entry') + if allow_unclosed and not (folder / 'receipt.json').exists(): + continue + receipt, _ = read_json(folder / 'receipt.json', 4 * 1024 * 1024) + amount = receipt.get('runner_wall_seconds', receipt.get('wall_seconds')) + need(type(amount) in (int, float) and amount >= 0, 'Invalid ledger amount') + result[folder.name] = float(amount) + return result + + +def budget(root): + phase, _ = read_json(root / 'control/EXECUTION-PHASE.json') + cap = phase['aggregate_cap_seconds'] + need(type(cap) is int and cap in (600, 2400), 'Unrecognized budget phase') + current = ledger(root) + need(sum(current.values()) < cap, 'Round budget consumed') + return cap, current + + +def parent_lock(root): + lock = (root / 'runtime/parent-queue.lock').open('a') + try: + fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB) + except BaseException: + lock.close() + raise + return lock + + +class ExecutionDeadline(RuntimeError): + pass + + +def deadline_handler(signum, frame): + raise ExecutionDeadline('Outer execution deadline reached, including Popen/preexec') + + +class OwnedDomain: + """Only our new children and their observed descendants enter this domain.""" + def __init__(self): + need(not children_now(), 'Owned child domain was not initially empty') + self.rows, self.fds, self.groups, self.reaped = {}, {}, set(), [] + self.root = None + self.parent_group = os.getpgrp() + self.parent_session = os.getsid(0) + + def add(self, row): + key = generation(row) + if key in self.rows: + if row['pgid'] != self.parent_group: + self.groups.add((row['pgid'], row['sid'])) + return + need(len(self.rows) < 128, 'Owned process observation limit exceeded') + need(row['pid'] != os.getpid(), 'Parent cannot enter its own child domain') + try: + fd = os.pidfd_open(row['pid'], 0) + except ProcessLookupError: + return + current = proc(row['pid']) + if current is None or generation(current) != key: + os.close(fd) + return + self.rows[key], self.fds[key] = dict(current), fd + # During interrupted Popen a child can briefly precede setsid. Its + # individual pidfd is owned; the queue parent group never is. + if current['pgid'] != self.parent_group: + self.groups.add((current['pgid'], current['sid'])) + + def observe(self): + all_rows = census() + known = {pid for pid, start in self.rows if pid in all_rows and + all_rows[pid]['start_ticks'] == start} + for pid in known: + self.add(all_rows[pid]) + changed = True + while changed: + changed = False + for pid, row in all_rows.items(): + if pid not in known and (row['ppid'] == os.getpid() or row['ppid'] in known): + self.add(row) + if generation(row) in self.rows: + known.add(pid) + changed = True + return all_rows, [all_rows[pid] for pid in known] + + def kill_owned(self): + self.observe() + for key, fd in self.fds.items(): + current = proc(key[0]) + if current is not None and generation(current) == key and current['state'] != 'Z': + try: + signal.pidfd_send_signal(fd, signal.SIGKILL, None, 0) + except ProcessLookupError: + pass + + def cleanup(self, process): + start = time.monotonic() + seen_after_root = [] + completed = False + while True: + _, current = self.observe() + if process is not None and process.returncode is not None: + seen_after_root.extend(generation(row) for row in current if row['pid'] != process.pid) + self.kill_owned() + if process is not None: + process.poll() + for key in list(self.rows): + row = proc(key[0]) + if row is None or generation(row) != key or row['ppid'] != os.getpid(): + continue + if process is not None and row['pid'] == process.pid: + continue + try: + pid, status = os.waitpid(row['pid'], os.WNOHANG) + except ChildProcessError: + continue + if pid: + self.reaped.append({'pid': pid, 'start_ticks': key[1], 'wait_status': status}) + all_rows, current = self.observe() + occupied = [row for row in all_rows.values() if (row['pgid'], row['sid']) in self.groups] + if not current and not occupied and not children_now(): + completed = True + break + if time.monotonic() - start >= CLEANUP_SECONDS: + break + time.sleep(0.01) + final_rows = census() + remaining = [row for row in final_rows.values() if + generation(row) in self.rows or (row['pgid'], row['sid']) in self.groups or + row['ppid'] == os.getpid()] + for fd in self.fds.values(): + os.close(fd) + self.fds.clear() + return {'complete': completed and not remaining, + 'owned_generations': list(self.rows.values()), + 'groups': [{'pgid': g, 'sid': s} for g, s in sorted(self.groups)], + 'reaped_adopted': self.reaped, + 'observed_after_root_exit': [list(key) for key in sorted(set(seen_after_root))], + 'remaining': remaining, 'cleanup_seconds': time.monotonic() - start, + 'cleanup_tail_limit_seconds': CLEANUP_SECONDS, + 'group_empty_proved': completed and not remaining, + 'signal_method': 'SIGKILL via generation-checked pidfd only; never killpg'} + + +def reconcile_missing_receipt(root, label, began, cause, cleanup): + folder = root / 'runtime/runs' / label + folder.mkdir(exist_ok=True) + if not cleanup['complete'] and not (folder / 'receipt.json').exists(): + # A surviving root must never race a replacement canonical receipt. + # Leave its attempt unclosed, blocking the unchanged runner, and add a + # distinct charged STOP record for the parent to reconcile manually. + folder = root / 'runtime/runs' / (label + '-outer-unclosed-stop') + folder.mkdir() + path = folder / 'receipt.json' + if path.exists(): + return None + start = {} + if (folder / 'START.json').exists(): + start, _ = read_json(folder / 'START.json') + row = dict(start, schema='h25-outer-reconciled-stop-v1', status='STOP', label=label, + kind='outer_reconciled_incomplete_root', termination=cause, attempt_label=label, + wall_seconds=time.monotonic() - began, original_root_receipt_absent=True, + original_root_completion_claimed=False, cleanup_complete=cleanup['complete'], + all_prior_files_preserved=True) + row['label'] = folder.name + row['runner_wall_seconds'] = row['wall_seconds'] + if not (folder / 'START.json').exists(): + write_new(folder / 'START.json', {'kind': row['kind'], 'label': label}) + write_new(path, row) + return row + + +def run_root(root, case, evidence, seconds, shared_deadline, as_bytes=201326592, + rss_bytes=201326592): + """One root. Cleanup and stable custody finish before returning to a queue.""" + launch_contract() + need(stable_file(root / 'run_guarded_v3.py', META_CAP)['sha256'] == RUNNER_SHA, + 'Actual root runner changed') + need(time.monotonic() + CLEANUP_SECONDS < shared_deadline, 'No reserved cleanup tail remains') + command = ['/usr/bin/python3.12', *FLAGS, str(root / 'run_guarded_v3.py'), + case['stage'], case['job'], case['label']] + for value in (case['stage'], case['job'], case['label']): + need(type(value) is str and value and all(c in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_' for c in value), + 'Unsafe case identity') + evidence.mkdir() + need(type(seconds) in (int, float) and 0 < seconds <= 190, 'Unadmitted root deadline') + need(type(as_bytes) is int and 0 < as_bytes <= 1024 ** 3, 'Unadmitted root address-space bound') + need(type(rss_bytes) is int and 0 < rss_bytes <= 1024 ** 3, 'Unadmitted aggregate RSS bound') + began = time.monotonic() + deadline = min(began + seconds, shared_deadline - CLEANUP_SECONDS) + domain = OwnedDomain() + process, failure, cleanup = None, None, None + peak, spawn_entered, captured = 0, False, None + setter, limit_kind, limits = resource.setrlimit, resource.RLIMIT_AS, (as_bytes, as_bytes) + need(list(Path('/proc/self/task').iterdir()) == [Path('/proc/self/task') / str(os.getpid())], + 'Root preexec requires exactly one task') + def child_limit(): + setter(limit_kind, limits) + old_handler = signal.getsignal(signal.SIGALRM) + need(signal.getitimer(signal.ITIMER_REAL) == (0.0, 0.0), 'Parent already has an execution alarm') + write_new(evidence / 'LAUNCH.json', {'command': command, 'parent_pid': os.getpid(), + 'parent_pgid': os.getpgrp(), 'parent_sid': os.getsid(0), + 'root_execution_seconds': seconds, 'address_space_bytes': as_bytes, + 'rss_sum_bytes': rss_bytes, 'new_session': True, 'cleanup_reserved_seconds': CLEANUP_SECONDS}) + try: + with (evidence / 'root.stdout.raw').open('xb') as out, (evidence / 'root.stderr.raw').open('xb') as err: + signal.signal(signal.SIGALRM, deadline_handler) + signal.setitimer(signal.ITIMER_REAL, max(0.000001, deadline - time.monotonic())) + try: + spawn_entered = True + process = subprocess.Popen(command, cwd=root, env=dict(ENV), stdout=out, + stderr=err, start_new_session=True, preexec_fn=child_limit) + # Popen leaves an exited root waitable; capture its generation BEFORE poll. + captured = proc(process.pid) + need(captured is not None and captured['pgid'] == captured['sid'] == process.pid, + 'New root process/session identity missing') + domain.root = generation(captured) + domain.add(captured) + write_new(evidence / 'ROOT-PROCESS.json', captured) + while True: + _, current = domain.observe() + peak = max(peak, sum(row['rss_bytes'] for row in current)) + need(peak <= rss_bytes, 'Owned process RSS sum exceeded') + need(max((evidence / name).stat().st_size for name in + ('root.stdout.raw', 'root.stderr.raw')) <= LOG_CAP, 'Outer raw log cap exceeded') + if process.poll() is not None: + break + time.sleep(0.01) + finally: + signal.setitimer(signal.ITIMER_REAL, 0) + signal.signal(signal.SIGALRM, old_handler) + except BaseException as error: + failure = {'type': type(error).__name__, 'message': str(error)[:2048]} + finally: + signal.setitimer(signal.ITIMER_REAL, 0) + signal.signal(signal.SIGALRM, old_handler) + # This is also required when Popen raised before returning an object. + try: + cleanup = domain.cleanup(process) + except BaseException as cleanup_error: + cleanup = {'complete': False, 'group_empty_proved': False, + 'owned_generations': list(domain.rows.values()), + 'groups': [{'pgid': g, 'sid': sid} for g, sid in sorted(domain.groups)], + 'reaped_adopted': domain.reaped, 'observed_after_root_exit': [], + 'remaining': 'UNKNOWN_AFTER_CLEANUP_ERROR', + 'error': {'type': type(cleanup_error).__name__, 'message': str(cleanup_error)[:2048]}} + for fd in domain.fds.values(): + os.close(fd) + domain.fds.clear() + if not cleanup['complete']: + failure = failure or {'type': 'CleanupIncomplete', 'message': 'Owned descendants/group remain after bounded cleanup tail'} + if time.monotonic() > shared_deadline: + failure = failure or {'type': 'SharedDeadline', 'message': 'Shared cap crossed; necessary cleanup charged'} + reconciled = reconcile_missing_receipt(root, case['label'], began, + failure or {'type': 'MissingRootReceipt', 'message': 'Root exited without receipt'}, cleanup) + if reconciled is not None: + failure = failure or {'type': 'MissingRootReceipt', 'message': 'New reconciled STOP receipt; no retry'} + logs = {} + for name in ('root.stdout.raw', 'root.stderr.raw'): + try: + logs[name] = stable_file(evidence / name, LOG_CAP) + except BaseException as error: + failure = failure or {'type': type(error).__name__, 'message': str(error)[:2048]} + logs[name] = {'path': str(evidence / name), 'complete_hash': None, 'stable': False} + result = {'schema': 'h25-parent-root-supervision-v1', 'label': case['label'], + 'status': 'STOP' if failure else 'ROOT_COMPLETED_AND_OWNED_DOMAIN_EMPTY', + 'failure': failure, 'spawn_entered': spawn_entered, + 'spawn_returned': process is not None, 'captured_root': captured, + 'returncode': None if process is None else process.returncode, + 'cleanup': cleanup, 'outer_logs': logs, 'sampled_owned_rss_bytes': peak, + 'execution_and_cleanup_seconds': time.monotonic() - began, + 'root_receipt_reconciled': reconciled is not None, + 'no_hostile_fork_or_concurrent_children_claim': True} + write_new(evidence / 'SUPERVISION.json', result) + return result + + +def stop_supplement(root, label, reason): + folder = root / 'runtime/runs' / (label + '-supervision-stop') + folder.mkdir() + row = {'status': 'STOP', 'label': folder.name, 'kind': 'supervision_failure_marker', + 'failure': reason, 'wall_seconds': 0.0, 'runner_wall_seconds': 0.0, + 'cost_accounted_by_enclosing_queue_overhead': True, 'original_receipts_preserved': True} + write_new(folder / 'START.json', {'kind': row['kind']}) + write_new(folder / 'receipt.json', row) + + +def packet_unchanged(directory, manifest): + for name, expected in manifest['files'].items(): + row = stable_file(directory / name, META_CAP) + need(row['sha256'] == expected['sha256'] and row['bytes'] == expected['bytes'], + 'Parent source packet changed: ' + name) + need(not (directory / name).stat().st_mode & 0o222, 'Parent source packet became writable') + return True diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/native_tcb_v1.py.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/native_tcb_v1.py.txt new file mode 100644 index 0000000000..55a2f3320b --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/native_tcb_v1.py.txt @@ -0,0 +1,202 @@ +"""Initial native TCB corroboration, before other driver imports or native builds. + +No imports. The parent authenticates this source and the expected native closure +before launch, then calls after its captured sealed root guard. Native hashing, +POSIX, OS/loader integrity and the closed bootstrap interval are explicit trust +premises, not established by this check. The existing217file probe audit remains +separate. This receipt is never a scientific verdict or reusable private-ABI PASS. +""" +_MAX_FILES = 32 +_MAX_FILE_BYTES = 67108864 +_MAX_TOTAL_FILE_BYTES = 268435456 +_MAX_MAP_BYTES = 524288 +_MAX_MAP_LINES = 4096 +_MAX_LINE_BYTES = 8192 +_MAX_EXEC_MAPS = 256 +_CHUNK = 1048576 + + +def _need(condition, message): + if not condition: + raise RuntimeError(message) + + +def _native_ops(root, api): + _need(type(api) is tuple and len(api) == 4, 'Native TCB requires sealed bootstrap API') + root_sha = api[0]() + namespace = root.__dict__ + posix = namespace['posix'] + native_hash_module = namespace['_hashlib'] + function = namespace['_SHA256'] + builtin_type = namespace['BuiltinFunctionType'] + module_type = namespace['ModuleType'] + _need(type(posix) is module_type and type(native_hash_module) is module_type, + 'Native TCB module type differs') + _need(type(function) is builtin_type and function.__self__ is native_hash_module and + function.__name__ == 'openssl_sha256' and + native_hash_module.__dict__.get('openssl_sha256') is function, + 'Native TCB hash function owner differs') + functions = {} + for alias, name in (('open', 'open'), ('read', 'read'), ('fstat', 'fstat'), + ('close', 'close'), ('major', 'major'), ('minor', 'minor'), ('getpid', 'getpid')): + value = posix.__dict__.get(name) + _need(type(value) is builtin_type and value.__self__ is posix and value.__name__ == name, + 'Native TCB POSIX primitive owner differs: ' + name) + functions[alias] = value + _need(functions['open'] is namespace['_OPEN'] and functions['read'] is namespace['_READ'] and + functions['fstat'] is namespace['_FSTAT'] and functions['close'] is namespace['_CLOSE'], + 'Native TCB primitive differs from pristine root') + functions.update({'sha256': function, 'flags': namespace['_FLAGS'], 'posix': posix, + 'hash_module': native_hash_module, 'root_sha256': root_sha}) + return functions + + +def _expected_inventory(expected_files, expected_hashlib_origin): + _need(type(expected_files) is tuple and 1 <= len(expected_files) <= _MAX_FILES, + 'Native TCB expected file inventory type/count differs') + _need(type(expected_hashlib_origin) is str, 'Native TCB expected hashlib origin type differs') + inventory = {} + total = 0 + for row in expected_files: + _need(type(row) is tuple and len(row) == 3, 'Native TCB expected row shape differs') + path, digest, size = row + _need(type(path) is str and path.startswith('/') and len(path) <= 4096 and + all(32 < ord(character) < 127 for character in path) and + path not in inventory and not path.endswith(' (deleted)'), + 'Native TCB expected canonical path differs') + _need(type(digest) is str and len(digest) == 64 and + all(character in '0123456789abcdef' for character in digest), + 'Native TCB expected digest differs') + _need(type(size) is int and 0 < size <= _MAX_FILE_BYTES, + 'Native TCB expected size differs') + total += size + _need(total <= _MAX_TOTAL_FILE_BYTES, 'Native TCB expected total bytes exceed bound') + inventory[path] = (digest, size) + _need(expected_hashlib_origin in inventory, 'Native TCB hashlib origin is undeclared') + return inventory, total + + +def _read_maps(ops): + descriptor = ops['open']('/proc/self/maps', ops['flags']) + try: + info = ops['fstat'](descriptor) + _need((info.st_mode & 0o170000) == 0o100000, 'Native TCB maps pseudo-file type differs') + parts, count = [], 0 + while True: + block = ops['read'](descriptor, min(65536, _MAX_MAP_BYTES + 1 - count)) + if not block: + break + count += len(block) + _need(count <= _MAX_MAP_BYTES, 'Native TCB maps byte bound exceeded') + parts.append(block) + raw = b''.join(parts) + finally: + ops['close'](descriptor) + lines = raw.splitlines() + _need(len(lines) <= _MAX_MAP_LINES, 'Native TCB maps line bound exceeded') + executable = [] + for line in lines: + _need(len(line) <= _MAX_LINE_BYTES, 'Native TCB maps line byte bound exceeded') + fields = line.split(None, 5) + _need(len(fields) >= 5, 'Native TCB maps row shape differs') + address, permissions, offset, device, inode_text = fields[:5] + _need(len(permissions) == 4, 'Native TCB map permissions shape differs') + if permissions[2:3] != b'x': + continue + inode = int(inode_text, 10) + if inode == 0: + continue # anonymous/kernel executable mappings belong to explicit OS TCB + _need(len(fields) == 6 and fields[5].startswith(b'/') and + not fields[5].endswith(b' (deleted)'), 'Native TCB executable map path differs') + path = fields[5].decode('ascii') + span, pair = address.split(b'-'), device.split(b':') + _need(len(span) == 2 and len(pair) == 2, 'Native TCB map address/device shape differs') + start, end = int(span[0], 16), int(span[1], 16) + _need(0 <= start < end < (1 << 64), 'Native TCB map address bounds differ') + row = (path, int(pair[0], 16), int(pair[1], 16), inode, + start, end, int(offset, 16), permissions.decode('ascii')) + executable.append(row) + _need(len(executable) <= _MAX_EXEC_MAPS, 'Native TCB executable map count exceeded') + _need(executable, 'Native TCB no file-backed executable mappings observed') + return tuple(sorted(executable)), len(raw), ops['sha256'](raw).hexdigest() + + +def _fingerprint(info): + return (info.st_dev, info.st_ino, info.st_mode, info.st_size, info.st_mtime_ns, info.st_ctime_ns) + + +def _hash_file(ops, path, expected_digest, expected_size): + """Production uses only freshly captured native ops; controls may separately + instrument this internal reader on an exclusively created temporary file.""" + descriptor = ops['open'](path, ops['flags']) + try: + before = ops['fstat'](descriptor) + _need((before.st_mode & 0o170000) == 0o100000 and before.st_size == expected_size, + 'Native TCB regular-file type/size differs: ' + path) + digest, count = ops['sha256'](), 0 + while True: + block = ops['read'](descriptor, min(_CHUNK, expected_size + 1 - count)) + if not block: + break + count += len(block) + _need(count <= expected_size, 'Native TCB file grew during hashing: ' + path) + digest.update(block) + after = ops['fstat'](descriptor) + _need(_fingerprint(before) == _fingerprint(after) and count == expected_size, + 'Native TCB file changed during hashing: ' + path) + actual = digest.hexdigest() + _need(actual == expected_digest, 'Native TCB file digest differs: ' + path) + return {'path': path, 'expected_sha256': expected_digest, 'observed_sha256': actual, + 'expected_bytes': expected_size, 'observed_bytes': count, + 'device': after.st_dev, 'device_major': ops['major'](after.st_dev), + 'device_minor': ops['minor'](after.st_dev), 'inode': after.st_ino, + 'mode': after.st_mode, 'mtime_ns': after.st_mtime_ns, 'ctime_ns': after.st_ctime_ns} + finally: + ops['close'](descriptor) + + +def verify_native_tcb(bootstrap_root, bootstrap_api, expected_files, expected_hashlib_origin): + """Corroborate the parent's declared initial native file closure, freshly.""" + ops = _native_ops(bootstrap_root, bootstrap_api) + inventory, expected_total = _expected_inventory(expected_files, expected_hashlib_origin) + native_hash_module = ops['hash_module'] + origin = native_hash_module.__dict__.get('__file__') + _need(type(origin) is str and origin == expected_hashlib_origin, + 'Native TCB actual hashlib origin differs') + mappings_before, maps_before_bytes, maps_before_sha = _read_maps(ops) + mapped_paths = {row[0] for row in mappings_before} + _need(mapped_paths == set(inventory), 'Native TCB declared/executable mapped file closure differs') + files = [] + for path, expected_digest, expected_size in expected_files: + observed = _hash_file(ops, path, expected_digest, expected_size) + current = tuple(row for row in mappings_before if row[0] == path) + _need(current and all(row[1] == observed['device_major'] and + row[2] == observed['device_minor'] and row[3] == observed['inode'] + for row in current), 'Native TCB mapped/current file identity differs: ' + path) + observed['executable_mapping_count'] = len(current) + observed['executable_mappings'] = [ + {'start': hex(row[4]), 'end': hex(row[5]), 'offset': row[6], 'permissions': row[7]} + for row in current] + files.append(observed) + mappings_after, maps_after_bytes, maps_after_sha = _read_maps(ops) + _need(mappings_after == mappings_before, 'Native TCB executable mappings changed during audit') + final_ops = _native_ops(bootstrap_root, bootstrap_api) + _need(final_ops['hash_module'] is native_hash_module and final_ops['sha256'] is ops['sha256'] and + native_hash_module.__dict__.get('__file__') == origin and + final_ops['root_sha256'] == ops['root_sha256'], 'Native TCB root/hash provenance changed') + for name in ('open', 'read', 'fstat', 'close', 'major', 'minor', 'getpid'): + _need(final_ops[name] is ops[name], 'Native TCB captured primitive drifted: ' + name) + return {'schema': 'h25-initial-native-tcb-v1', 'status': 'MATCHED_DECLARED_INITIAL_NATIVE_FILES', + 'root_source_sha256': ops['root_sha256'], 'pid': ops['getpid'](), + 'hashlib_origin': origin, 'hashlib_module_id': id(native_hash_module), + 'hash_function_id': id(ops['sha256']), 'hash_function_name': 'openssl_sha256', + 'hash_function_owned_by_root_module': True, 'files': files, + 'declared_file_count': len(files), 'expected_total_file_bytes': expected_total, + 'observed_total_file_bytes': sum(row['observed_bytes'] for row in files), + 'executable_mapping_count': len(mappings_before), + 'maps_before_bytes': maps_before_bytes, 'maps_after_bytes': maps_after_bytes, + 'maps_before_sha256': maps_before_sha, 'maps_after_sha256': maps_after_sha, + 'executable_mappings_stable': True, 'probe_private_abi_access': False, + 'scientific_admission': False, 'reusable_pass': False, + 'trust_boundary': 'Parent-authenticated fresh startup and declared native/OS/loader primitives; corroboration does not self-prove hostile-OS or compromised-hash integrity.', + 'kernel_anonymous_executable_maps': 'Excluded from declared native file closure; remain in explicit OS trust boundary.'} diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/parent_closure_v1.py.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/parent_closure_v1.py.txt new file mode 100644 index 0000000000..ca541e94ca --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/parent_closure_v1.py.txt @@ -0,0 +1,270 @@ +"""Finite concrete receiver admission inside the original trusted parent. + +This verifies pinned source, bytecode derived from those bytes without executing +them, concrete local import edges, and the current captured object graph. It is +not a new Python sandbox or proof of the initial OS/interpreter/native memory. +The original parent must load these exact modules through its admitted bootstrap +before adverse input. No user supplied arbitrary checker is accepted. +""" +import ast +import builtins +import __future__ +import copy +import dataclasses +import fcntl +import gc +import hashlib +import json +import marshal +import math +import os +import pathlib +import posix +import resource +import signal +import struct +import subprocess +import sys +import time +import types +import epoch_schema_v5 as schema +import epoch_copy_v5 as copying + +_TYPE, _LEN, _COMPILE = type, len, compile +_MODULE_DICT = types.ModuleType.__dict__['__dict__'].__get__ +_FUNCTION_GETTERS = tuple(types.FunctionType.__dict__[name].__get__ for name in + ('__code__', '__globals__', '__builtins__', '__defaults__', '__kwdefaults__', '__closure__', '__dict__')) +_CELL_GET = types.CellType.__dict__['cell_contents'].__get__ +_CLASS_DICT = type.__dict__['__dict__'].__get__ +_STATIC_FUNCTION = staticmethod.__dict__['__func__'].__get__ +_CLASS_FUNCTION = classmethod.__dict__['__func__'].__get__ +_SOURCE_RECEIVERS = [] +_STDLIB_MODULES = {name: module for name, module in tuple(sys.modules.items()) + if _TYPE(name) is str and _TYPE(module) is types.ModuleType} +MAX_MODULES = 48 +MAX_GLOBALS = 512 + +# These exact registries are intentionally mutated only by their original +# source. Their object identities are still checked. Private-state sabotage +# by code already running in this trusted parent remains outside the boundary. +_MUTABLE_NAMES = { + 'epoch_parent_v5': ('_RESERVED_EPOCHS', '_PARENT_OWNERS'), + 'epoch_schema_v5': ('_ERROR_OWNERS',), + 'epoch_stop_v5': ('_SINK_REGISTRY',), + 'parent_domain_v1': ('_DOMAINS',), + 'parent_completion_v1': ('_PARENTS', '_PROCESS'), + 'parent_closure_v1': ('_SOURCE_RECEIVERS',), +} +_GATE_SUFFIXES = ('CONFIGURATION', 'SOURCE_REVIEW', 'EXECUTION_APPROVAL', 'FUNDING', + 'STAGE_APPROVAL', 'COMMAND_APPROVAL', 'VALIDATION_EXECUTION') + + +def _namespace(module): + schema.need(_TYPE(module) is types.ModuleType, 'exact original module required') + namespace = _MODULE_DICT(module, types.ModuleType) + schema.need(_TYPE(namespace) is dict and _LEN(namespace) <= MAX_GLOBALS, + 'original module namespace bound differs') + for key in namespace: + schema.text(key, 256) + return namespace + + +def _function_record(function): + schema.need(_TYPE(function) is types.FunctionType, 'exact source function required') + values = tuple(getter(function, types.FunctionType) for getter in _FUNCTION_GETTERS) + closure = values[5] + cells = () if closure is None else tuple((cell, _CELL_GET(cell, types.CellType)) for cell in closure) + schema.need(_LEN(cells) <= 64, 'source function closure bound exceeded') + return function, values, cells + + +def _function_check(record): + function, values, cells = record + schema.need(_TYPE(function) is types.FunctionType, 'source function identity changed') + for getter, expected in zip(_FUNCTION_GETTERS, values): + schema.need(getter(function, types.FunctionType) is expected, + 'source function code/globals/builtins/defaults/closure/dict changed') + for cell, expected in cells: + schema.need(_CELL_GET(cell, types.CellType) is expected, 'source function closure contents changed') + + +def _codes(code, result): + result.setdefault(code.co_qualname, []).append(code) + for child in code.co_consts: + if _TYPE(child) is types.CodeType: + _codes(child, result) + + +def _data(value, depth=0): + """Snapshot literal data only; no foreign repr/hash/eq/iteration protocols.""" + schema.need(depth <= 32, 'literal snapshot depth exceeded') + kind = _TYPE(value) + if value is None or kind in (str, int, bool, bytes, float): + return (kind, value) + if kind in (list, tuple): + schema.need(_LEN(value) <= 65536, 'literal sequence bound exceeded') + return (kind, tuple(_data(item, depth + 1) for item in value)) + if kind is dict: + schema.need(_LEN(value) <= 8192, 'literal mapping bound exceeded') + for key in value: + schema.need(_TYPE(key) in (str, int), 'nonliteral mapping key') + return (kind, tuple((_data(key, depth + 1), _data(item, depth + 1)) + for key, item in value.items())) + if kind in (set, frozenset): + schema.need(_LEN(value) <= 8192 and all(_TYPE(item) in (str, int) for item in value), + 'nonliteral set value') + return (kind, frozenset(value)) + raise schema.EpochStop('not literal data') + + +def _validate_code(function, compiled_codes, namespace): + values = tuple(getter(function, types.FunctionType) for getter in _FUNCTION_GETTERS) + code = values[0] + schema.need(values[1] is namespace and values[2] is builtins.__dict__, + 'source function original namespace/builtins differs') + candidates = compiled_codes.get(code.co_qualname, ()) + encoded = marshal.dumps(code) + schema.need(any(marshal.dumps(expected) == encoded for expected in candidates), + 'receiving function bytecode differs from pinned source') + + +def bind_receivers(modules, source_policy, error_owner): + """Only the source-fixed original parent calls this before child launch. + + source_policy is a separately pinned, prelaunch source inventory, never a + report supplied by a child. The two producer-specific validators have fixed + names; unsupported or absent variant source cannot be substituted by a + callable argument. Every received module must be listed in the policy. + """ + schema.owner_state(error_owner) + schema.need(_TYPE(modules) is dict and 1 <= _LEN(modules) <= MAX_MODULES and + _TYPE(source_policy) is dict, 'finite receiver module map required') + for name in modules: + schema.text(name, 128) + for name in source_policy: + schema.text(name, 128) + schema.need(set(modules) == set(source_policy), 'exact receiver closure differs') + records = [] + for name in sorted(modules): + module = modules[name] + namespace = _namespace(module) + pin = source_policy[name] + schema.blob(pin) + raw = copying.read_verified(pin, schema.FILE_BYTES, error_owner=error_owner) + schema.need(namespace.get('__name__') == name and namespace.get('__file__') == pin['path'], + 'original receiving module origin differs') + tree = ast.parse(raw, filename=pin['path']) + compiled = _COMPILE(raw, pin['path'], 'exec', dont_inherit=True, optimize=sys.flags.optimize) + compiled_codes = {} + _codes(compiled, compiled_codes) + functions, classes, literals, imports = [], [], [], [] + for node in tree.body: + if _TYPE(node) is ast.FunctionDef: + function = namespace[node.name] + _validate_code(function, compiled_codes, namespace) + functions.append(_function_record(function)) + elif _TYPE(node) is ast.ClassDef: + cls = namespace[node.name] + schema.need(_TYPE(cls) is type, 'source class type differs') + class_namespace = _CLASS_DICT(cls, type) + for item in node.body: + if _TYPE(item) is ast.FunctionDef: + method = class_namespace[item.name] + # The currently selected explicit methods have no + # property/classmethod/staticmethod decorators. + schema.need(not item.decorator_list, 'unreviewed decorated receiver method') + # Python implicitly wraps __new__ and two class hooks. + # No arbitrary descriptor protocol is invoked. + if item.name == '__new__' and _TYPE(method) is staticmethod: + method = _STATIC_FUNCTION(method, staticmethod) + elif item.name in ('__init_subclass__', '__class_getitem__') and _TYPE(method) is classmethod: + method = _CLASS_FUNCTION(method, classmethod) + _validate_code(method, compiled_codes, namespace) + functions.append(_function_record(method)) + # Dataclass-generated methods are part of the inherited + # dataclasses/initial-parent trust, not compiled from this + # class body. Their actual original code/environment remains + # captured and checked; they cannot be changed after capture. + for method in class_namespace.values(): + if _TYPE(method) is types.FunctionType and not any(method is r[0] for r in functions): + functions.append(_function_record(method)) + classes.append((cls, tuple(class_namespace.items()))) + elif _TYPE(node) in (ast.Import, ast.ImportFrom): + for alias in node.names: + schema.need(alias.name != '*', 'star receiver import unsupported') + if _TYPE(node) is ast.Import: + source_name = alias.name + local_name = alias.asname or source_name.split('.')[0] + expected = modules.get(source_name, _STDLIB_MODULES.get(source_name)) + else: + source_name = node.module + schema.need(node.level == 0, 'relative receiver import unsupported') + local_name = alias.asname or alias.name + source_module = modules.get(source_name, _STDLIB_MODULES.get(source_name)) + schema.need(source_module is not None, 'receiver import dependency absent') + expected = _namespace(source_module).get(alias.name) + schema.need(expected is not None and namespace.get(local_name) is expected, + 'concrete receiving import identity differs') + imports.append((local_name, expected)) + elif _TYPE(node) is ast.Assign: + if _LEN(node.targets) != 1 or _TYPE(node.targets[0]) is not ast.Name: + continue + key = node.targets[0].id + if key in _MUTABLE_NAMES.get(name, ()) or key.endswith(_GATE_SUFFIXES): + continue + try: + literal = ast.literal_eval(node.value) + except (ValueError, TypeError, SyntaxError): + continue + schema.need(_data(namespace[key]) == _data(literal), 'receiver literal differs from source') + literals.append((key, _data(literal))) + for function in namespace.values(): + if _TYPE(function) is types.FunctionType and not any(function is r[0] for r in functions): + functions.append(_function_record(function)) + records.append((name, module, namespace, pin, tuple(namespace.items()), + tuple(functions), tuple(classes), tuple(literals), tuple(imports))) + capability = object() + packet = (capability, tuple(records), error_owner) + schema.need(_LEN(_SOURCE_RECEIVERS) < 2, 'receiver closure finite parent bound exceeded') + _SOURCE_RECEIVERS.append(packet) + check_receivers(capability) + return capability + + +def _packet(capability): + schema.need(_TYPE(capability) is object, 'exact receiver capability required') + for packet in _SOURCE_RECEIVERS: + if packet[0] is capability: + return packet + raise schema.EpochStop('unknown original receiver closure') + + +def check_receivers(capability): + packet = _packet(capability) + for name, module, namespace, pin, original_items, functions, classes, literals, imports in packet[1]: + schema.need(_namespace(module) is namespace and _LEN(namespace) == _LEN(original_items), + 'receiver namespace identity/census changed') + for key, expected in original_items: + schema.need(namespace.get(key) is expected, 'receiver namespace binding changed') + for record in functions: + _function_check(record) + for cls, items in classes: + current = _CLASS_DICT(cls, type) + schema.need(_LEN(current) == _LEN(items), 'receiver class census changed') + for key, expected in items: + schema.need(current.get(key) is expected, 'receiver class binding changed') + for key, expected in literals: + schema.need(_data(namespace[key]) == expected, 'receiver literal data changed') + copying.verify(pin, error_owner=packet[2]) + return None + + +def receiver(capability, module_name, name): + """Return only a specifically named original from the registered closure.""" + schema.text(module_name, 128) + schema.text(name, 128) + for row in _packet(capability)[1]: + if row[0] == module_name: + schema.need(name in row[2], 'fixed receiving entry missing') + return row[2][name] + raise schema.EpochStop('fixed receiving module missing') diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/parent_completion_v1.py.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/parent_completion_v1.py.txt new file mode 100644 index 0000000000..3191be7570 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/parent_completion_v1.py.txt @@ -0,0 +1,880 @@ +"""Source-only two-producer completion owner for one future guarded parent. + +No configuration or execution gate is installed. The original trusted parent +must authenticate this source, its exact receiver closure and initial OS/runtime +before importing it. Capabilities are process local. This component never +invokes run_guarded, a queue wrapper, a global ledger writer, or a child report +as authority. The enclosing single orchestrator pays this entire component +once, including all child, validation, retention, failure and final-exit costs. +""" +import fcntl +import os +import resource +import signal +import stat +import subprocess +import sys +import time +import epoch_schema_v5 as schema +import epoch_copy_v5 as copying +import epoch_parent_v5 as epoch +import parent_closure_v1 as closure +import parent_domain_v1 as domain +import group01_evidence_v1 as group01 + +CONFIGURATION = None +SOURCE_REVIEW = None +STAGE_APPROVAL = None +COMMAND_APPROVAL = None +FUNDING = None +EXECUTION_APPROVAL = None + +FLAGS = ('-S', '-s', '-P', '-B') +ENV = {'PATH': '/usr/bin:/bin', 'PYTHONHASHSEED': '0', 'LANG': 'C.UTF-8', + 'LC_ALL': 'C.UTF-8', 'TZ': 'UTC', 'PYTHONDONTWRITEBYTECODE': '1'} +_TYPE, _LEN = type, len +_OPEN, _CLOSE, _MKDIR, _STAT, _SCANDIR = os.open, os.close, os.mkdir, os.stat, os.scandir +_POPEN = subprocess.Popen +_CLOCK, _SLEEP = time.monotonic, time.sleep +_SETRLIMIT, _GETRLIMIT = resource.setrlimit, resource.getrlimit +_SETTIMER, _GETTIMER = signal.setitimer, signal.getitimer +_SIGNAL, _GETSIGNAL = signal.signal, signal.getsignal +_PARENTS = [] +_PROCESS = [None] +# Shared before the first constructor read, including failures before a parent +# capability can be published. No mode can replace or reset this owner. +_UNKNOWN_OWNER = {'quarantine': [False], 'pending': [False], + 'iterator_uncertain': [False], 'primary': [None], + 'native_errors': [None] * 4} +_EPOCH_ENTRY = epoch._entry_state +_EPOCH_RESERVE = epoch.ParentEpoch.reserve_producer +_EPOCH_ACCEPT = epoch.ParentEpoch.accept_completed_producer +_EPOCH_COMPLETION = epoch.ParentCompletion +_EPOCH_COMMIT = epoch.ParentEpoch.commit_exports +_EPOCH_CLOSE = epoch.ParentEpoch.close +MAX_SOURCE_FILES = 8192 +MAX_STAGE_ENTRIES = 16384 +MAX_RAW_VARIANT_FILES = 64 +VARIANT_MODULE = 'variant_validation_v1' +VARIANT_FUNCTION = 'validate_variant_producer' +MAX_VARIANT_RAW_BYTES = 32 * 1024 * 1024 +# Source-literal inventory copied from the separately pinned concrete interface. +VARIANT_FILES = ('initial-tcb.raw.json', 'initial-controls.raw.json', 'initial-restoration.raw.json', 'root-before.raw.json', 'preflight-before.raw.json', 'custody-before.raw.json', 'pyinit_failure/control.attempt.json', 'pyinit_failure/control.attempt.jsonl', 'pyinit_failure/control.stdout.raw', 'pyinit_failure/control.stderr.raw', 'pyinit_failure/helper-return.raw.json', 'pyinit_failure/build.json', 'pyinit_failure/_h25_dict_probe.cpython-312-x86_64-linux-gnu.so', 'pyinit_failure/elf.raw.json', 'exec_failure/control.attempt.json', 'exec_failure/control.attempt.jsonl', 'exec_failure/control.stdout.raw', 'exec_failure/control.stderr.raw', 'exec_failure/helper-return.raw.json', 'exec_failure/build.json', 'exec_failure/_h25_dict_probe.cpython-312-x86_64-linux-gnu.so', 'exec_failure/elf.raw.json', 'preflight-after.raw.json', 'custody-after.raw.json', 'root-after.raw.json', 'receipt.json') +VARIANT_GROUPS = ('initial-tcb.raw.json', 'initial-controls.raw.json', 'initial-restoration.raw.json', 'root-before.raw.json', 'preflight-before.raw.json', 'custody-before.raw.json', 'pyinit_failure/helper-return.raw.json', 'pyinit_failure/elf.raw.json', 'exec_failure/helper-return.raw.json', 'exec_failure/elf.raw.json', 'preflight-after.raw.json', 'custody-after.raw.json', 'root-after.raw.json') +REQUIRED_MODULES = ( + 'epoch_schema_v5', 'epoch_copy_v5', 'epoch_parent_v5', 'epoch_stop_v5', + 'original_build_provenance_v5', 'h25_parent_supervisor', 'parent_closure_v1', + 'parent_domain_v1', 'parent_completion_v1', 'group01_evidence_v1', + 'group01_original_predicates_v1', 'receipt_contract_v1', 'native_field_controls_v1', + 'transport_controls_v1', 'collector_controls_v1', 'elf_literal_fixture_v1', + 'elf_controls_v1', 'provider_controls_v1', 'run_pure_controls_v1', + 'elf_literal_fixture_v2', 'elf_extended_controls_v2', 'run_pure_controls_v2', + 'restoration_contract_v1', 'loader_model_controls_v1', 'driver_model_body_sources_v3', + 'root_model_body_sources_v3', 'loader_model_controls_v3', 'group_evidence_v5', + 'close_model_controls_v5', 'projection_model_controls_v5', 'run_controls_v5', + 'variant_validation_v1', 'sealed_elf_profile_v2') + + +class ParentDeadline(RuntimeError): + pass + + +def _alarm(signum, frame): + raise ParentDeadline('owned producer deadline including Popen/preexec') + + +def _gate(): + schema.exact(CONFIGURATION, ('plans', 'receiver_policy', 'checker_source')) + schema.exact(CONFIGURATION['plans'], ('normal', 'optimized')) + for pin in tuple(CONFIGURATION['plans'].values()) + (CONFIGURATION['receiver_policy'], CONFIGURATION['checker_source']): + schema.blob(pin, schema.RECORD_BYTES) + for record, key in ((SOURCE_REVIEW, 'review_sha256'), (STAGE_APPROVAL, 'stage_review_sha256'), + (COMMAND_APPROVAL, 'command_review_sha256'), (FUNDING, 'reservation_sha256'), + (EXECUTION_APPROVAL, 'external_launch_policy_sha256')): + schema.exact(record, (key,)) + schema.digest(record[key]) + + +def _state(capability): + schema.need(_TYPE(capability) is object, 'exact parent capability required') + for token, state in _PARENTS: + if token is capability: + return state + raise schema.EpochStop('unregistered parent completion owner') + + +def _receiver_gate_values(receivers): + # Fail before any producer if the concrete downstream parsers are still + # source-only. These stronger parent envelopes are installed by the + # independently authenticated original bootstrap; hashes alone grant none. + specifications = ( + ('original_build_provenance_v5', 'PARSER_CONFIGURATION', + ('leaf_policy_sha256', 'configuration_sha256', 'original_helper_sha256')), + ('original_build_provenance_v5', 'PARSER_EXECUTION_APPROVAL', ('external_launch_policy_sha256',)), + ('original_build_provenance_v5', 'PARSER_FUNDING', ('reservation_sha256',)), + ('variant_validation_v1', 'VALIDATION_CONFIGURATION', ('leaf_policy_sha256', 'configuration_sha256')), + ('variant_validation_v1', 'VALIDATION_SOURCE_REVIEW', ('review_sha256',)), + ('variant_validation_v1', 'VALIDATION_EXECUTION', ('external_launch_policy_sha256',)), + ('variant_validation_v1', 'VALIDATION_FUNDING', ('reservation_sha256',))) + result = {} + for module, name, keys in specifications: + value = closure.receiver(receivers, module, name) + schema.exact(value, keys) + for item in value.values(): + schema.digest(item) + result[module + '.' + name] = schema.plain_copy(value) + schema.need(result['original_build_provenance_v5.PARSER_CONFIGURATION']['original_helper_sha256'] == + 'aa0a315110e031e19291970c9611fe5e0f91465fa20eaec51e81186099563f78', + 'original helper source protocol differs before producer launch') + return result + + +def _guard(state): + _gate() + schema.need(state['phase'] not in ('STOP', 'CLOSED'), 'parent completion owner is terminal') + domain.refresh_unknown_owner(state['unknown_owner']) + schema.need(state['io_quarantine'][0] is False and state['unknown_owner']['pending'][0] is False and + state['unknown_owner']['iterator_uncertain'][0] is False and + state['unknown_owner']['primary'][0] is None, + 'parent I/O ownership requires kernel teardown') + schema.need(os.getpid() == state['pid'], 'parent capability cannot cross exec/process') + schema.need(_POPEN is subprocess.Popen and _OPEN is os.open and _CLOSE is os.close and + _SETRLIMIT is resource.setrlimit and _GETRLIMIT is resource.getrlimit and + _CLOCK is time.monotonic and _SETTIMER is signal.setitimer and + _GETTIMER is signal.getitimer and _SIGNAL is signal.signal and + _GETSIGNAL is signal.getsignal, + 'original parent runtime primitive binding changed') + schema.need(epoch._entry_state is _EPOCH_ENTRY and epoch.ParentEpoch.reserve_producer is _EPOCH_RESERVE and + epoch.ParentEpoch.accept_completed_producer is _EPOCH_ACCEPT and + epoch.ParentCompletion is _EPOCH_COMPLETION and epoch.ParentEpoch.commit_exports is _EPOCH_COMMIT and + epoch.ParentEpoch.close is _EPOCH_CLOSE, 'original epoch receiving entry changed') + closure.check_receivers(state['receivers']) + schema.need(_receiver_gate_values(state['receivers']) == state['receiver_gate_snapshot'], + 'independently installed receiver gates changed') + for key in ('plan', 'receiver_policy', 'checker_source'): + current = CONFIGURATION['plans'][state['plan']['mode']] if key == 'plan' else CONFIGURATION[key] + schema.need(current == state['configuration'][key], 'configured source binding changed') + copying.verify(state['configuration'][key], error_owner=state['errors']) + schema.need(_CLOCK() <= state['shared_deadline'], 'complete parent reservation deadline exceeded') + + +def _stop(state, operation, primary): + # No formatting or instance dispatch on an exception. Capture failure is + # separate, never a reason to replace the already delivered primary. + state['phase'] = 'STOP' + # The shared slot was stored inline at the first delivered local/domain + # failure, before any optional retention helper or cleanup call. + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = primary + elif state['unknown_owner']['primary'][0] is not primary: + if state['fallback'][4] is None: + state['fallback'][4] = primary + primary = state['unknown_owner']['primary'][0] + if state['stop'][0] is None: + state['stop'][0] = primary + state['stop'][1] = operation + try: + domain.refresh_unknown_owner(state['unknown_owner']) + except BaseException as error: + # Failure even to inspect retained ownership cannot permit a writer. + state['io_quarantine'][0] = True + if state['fallback'][5] is None: + state['fallback'][5] = error + try: + schema.retain_primary(state['errors'], primary, operation) + except BaseException as error: + state['fallback'][0] = error + # An uncertain native acquisition prevents further diagnostic I/O. The + # outer guard must retain memory state and observe kernel parent teardown. + if (state['directory_created'] and not state['stop_write_attempted'] and not state['io_quarantine'][0] and + not state['unknown_owner']['pending'][0] and not state['unknown_owner']['iterator_uncertain'][0] and + not (_PROCESS[0] is not None and _PROCESS[0]['acquisition_in_flight'])): + try: + state['stop_write_attempted'] = True + record = {'schema': 'h25-parent-completion-stop-v1', 'operation': operation, + 'epoch_id': state['plan']['epoch_id'], 'mode': state['plan']['mode'], + 'status': 'STOP', 'retry_or_restore_allowed': False, + 'error': schema.error_snapshot(state['errors']), + 'domain_obligations_may_be_incomplete': True, + 'enclosing_guard_must_observe_parent_exit': True} + state['stop_file'] = copying.write_once(state['plan']['session_directory'] + '/STOP.json', + schema.canonical(record), error_owner=state['errors']) + except BaseException as error: + state['fallback'][1] = error + + +def _snapshot_sources(plan, error_owner): + schema.need(_TYPE(plan['source_files']) is list and 1 <= _LEN(plan['source_files']) <= MAX_SOURCE_FILES, + 'complete prelaunch source inventory bound differs') + rows, paths, categories = [], set(), set() + for expected in plan['source_files']: + schema.exact(expected, ('category', 'path', 'sha256', 'bytes', 'mode')) + schema.choice(expected['category'], ('parent', 'root', 'provider', 'driver', 'project', + 'system_headers', 'compiler_link', 'oracle', 'stage')) + schema.path(expected['path']) + schema.digest(expected['sha256']) + schema.integer(expected['bytes'], 1, schema.FILE_BYTES) + schema.integer(expected['mode'], 0, 0o7777) + schema.need(expected['path'] not in paths, 'duplicate prelaunch source path') + paths.add(expected['path']) + categories.add(expected['category']) + actual = copying.inspect(expected['path'], schema.FILE_BYTES, error_owner=error_owner) + schema.need(actual['sha256'] == expected['sha256'] and actual['bytes'] == expected['bytes'] and + actual['identity']['mode'] & 0o7777 == expected['mode'], 'source/profile/closure changed') + rows.append(actual) + schema.need(categories == {'parent', 'root', 'provider', 'driver', 'project', 'system_headers', + 'compiler_link', 'oracle', 'stage'}, 'a mandatory source category is absent') + return rows + + +def _tree(root, state): + """Bounded exact stage census; all actual file contents are separately read.""" + schema.path(root) + pending, files, directories = [('', root)], [], [] + count = 0 + while pending: + schema.need(state['io_quarantine'][0] is False and state['unknown_owner']['pending'][0] is False and + state['unknown_owner']['iterator_uncertain'][0] is False, + 'stage census cannot acquire after uncertain ownership') + relative, current = pending.pop() + before = _STAT(current, follow_symlinks=False) + schema.need(stat.S_ISDIR(before.st_mode) and not before.st_mode & 0o222, + 'immutable stage directory kind/mode differs') + entries, primary = None, None + state['unknown_owner']['pending'][0] = True + try: + entries = _SCANDIR(current) + state['unknown_owner']['pending'][0] = False + for entry in entries: + count += 1 + schema.need(count <= MAX_STAGE_ENTRIES, 'stage census bound exceeded') + name = entry.name + schema.need(_TYPE(name) is str and name not in ('.', '..') and '/' not in name, + 'stage entry name differs') + child = name if not relative else relative + '/' + name + info = entry.stat(follow_symlinks=False) + if stat.S_ISREG(info.st_mode): + files.append(child) + elif stat.S_ISDIR(info.st_mode): + directories.append(child) + pending.append((child, current + '/' + name)) + else: + raise schema.EpochStop('stage has symlink or special file') + except BaseException as error: + primary = error + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = error + state['io_quarantine'][0] = True + state['unknown_owner']['iterator_uncertain'][0] = True + state['fallback'][2] = error + raise + finally: + if entries is not None: + owned = entries + entries = None + try: + owned.close() + except BaseException as error: + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = error + state['io_quarantine'][0] = True + state['unknown_owner']['iterator_uncertain'][0] = True + state['fallback'][3] = error + if primary is None: + raise + after = _STAT(current, follow_symlinks=False) + schema.need((before.st_dev, before.st_ino, before.st_mode, before.st_mtime_ns, before.st_ctime_ns) == + (after.st_dev, after.st_ino, after.st_mode, after.st_mtime_ns, after.st_ctime_ns), + 'stage directory changed during census') + return sorted(files), sorted(directories) + + +def _stage(plan, error_owner, state): + copying.verify(plan['stage_manifest'], error_owner=error_owner) + raw = copying.read_verified(plan['stage_manifest'], schema.RECORD_BYTES, error_owner=error_owner) + declared = group01.decode(raw) + schema.need(_TYPE(declared.get('files')) is dict and + plan['stage_manifest']['path'] == plan['stage_directory'] + '/STAGE.json', + 'independent stage manifest origin differs') + files, directories = _tree(plan['stage_directory'], state) + schema.need(files == sorted(list(declared['files']) + ['STAGE.json']) and + directories == plan['stage_directories'], 'complete immutable stage census differs') + source_by_path = {row['path']: row for row in plan['source_files']} + for relative, expected in declared['files'].items(): + schema.need(_TYPE(relative) is str and not relative.startswith('/') and + all(part not in ('', '.', '..') for part in relative.split('/')), + 'stage relative path differs') + path = plan['stage_directory'] + '/' + relative + schema.need(path in source_by_path and expected == + {'sha256': source_by_path[path]['sha256'], 'mode': source_by_path[path]['mode']}, + 'stage file absent from independently fixed current source closure') + return {'manifest': plan['stage_manifest'], 'file_count': len(files), 'directories': directories} + + +def _validate_plan(plan): + schema.exact(plan, ('schema', 'epoch_id', 'mode', 'round_root', 'session_directory', + 'session_seconds', 'source_closure_admission_sha256', 'source_files', 'producers')) + schema.need(plan['schema'] == 'h25-parent-completion-plan-v1', 'parent plan schema differs') + schema.label(plan['epoch_id']) + schema.choice(plan['mode'], ('normal', 'optimized')) + schema.path(plan['round_root']) + schema.path(plan['session_directory']) + schema.integer(plan['session_seconds'], 1, 600) + schema.digest(plan['source_closure_admission_sha256']) + schema.exact(plan['producers'], ('group01', 'failure_variants')) + for role in schema.PRODUCERS: + row = plan['producers'][role] + schema.exact(row, ('epoch_plan', 'command', 'cwd', 'output', 'evidence_directory', + 'stage_directory', 'stage_manifest', 'stage_directories', 'launch_binding', 'launch_nonce', + 'root_seconds', 'address_space_bytes', 'rss_bytes', 'evidence_plan', 'launch_artifacts')) + epoch._plan(row['epoch_plan'], role) + schema.launch(row['launch_binding']) + schema.text(row['launch_nonce'], 64) + schema.need(_LEN(row['launch_nonce']) == 64 and + all(c in '0123456789abcdef' for c in row['launch_nonce']), 'one-use launch nonce differs') + for key in ('cwd', 'output', 'evidence_directory', 'stage_directory'): + schema.path(row[key]) + schema.blob(row['stage_manifest'], schema.RECORD_BYTES) + schema.need(row['stage_manifest']['sha256'] == row['epoch_plan']['stage_sha256'] == + row['launch_binding']['stage_sha256'], 'independent producer stage pins differ') + schema.need(row['launch_binding']['root_sha256'] == row['epoch_plan']['root_sha256'], + 'independent producer root pins differ') + schema.integer(row['root_seconds'], 1, 180) + schema.integer(row['address_space_bytes'], 1, 1024 ** 3) + schema.integer(row['rss_bytes'], 1, 1024 ** 3) + command = row['command'] + schema.need(_TYPE(command) is list and 6 <= _LEN(command) <= 128, 'bounded original root argv required') + for argument in command: + schema.text(argument, 8192) + schema.need(bool(argument), 'empty root argument') + prefix = ['/usr/bin/python3.12', *FLAGS] + (['-O'] if plan['mode'] == 'optimized' else []) + schema.need(command[:len(prefix)] == prefix, 'original root interpreter/flags/mode differs') + entry = command[len(prefix)] + schema.path(entry) + schema.need(entry.startswith(row['stage_directory'] + '/') and + entry == row['stage_directory'] + '/integration/full_driver.py', + 'source-fixed genuine root entry differs') + schema.need(command.count('--output') == 1 and + command[command.index('--output') + 1] == row['output'], 'independent root output differs') + args = command[len(prefix) + 1:] + schema.need(len(args) >= 11 and args[0] == '--root-sha256' and args[2] == '--provider' and + args[5] == '--driver' and args[8] == '--integration' and args[10] == '--', + 'original bootstrap argv positions differ') + by_path = {item['path']: item for item in plan['source_files']} + integration = row['stage_directory'] + '/integration' + schema.need(args[1] == row['epoch_plan']['root_sha256'] and args[9] == integration and + args[3].rsplit('/', 1)[0] == args[6].rsplit('/', 1)[0] == integration, + 'actual root/provider/driver source origins differ') + for path, digest, category in ((entry, args[1], 'root'), (args[3], args[4], 'provider'), + (args[6], args[7], 'driver')): + schema.need(path in by_path and by_path[path]['sha256'] == digest and + by_path[path]['category'] == category, 'bootstrap hash not in independent source closure') + schema.exact(row['launch_artifacts'], ('configuration_sha256', 'startup_tcb_sha256', 'expected_history_sha256')) + for key, pin in row['launch_artifacts'].items(): + schema.blob(pin, schema.RECORD_BYTES) + schema.need(pin['sha256'] == row['launch_binding'][key] and pin['path'] in by_path and + by_path[pin['path']]['sha256'] == pin['sha256'] and + by_path[pin['path']]['bytes'] == pin['bytes'], 'launch data binding lacks actual source pin') + evidence = row['evidence_plan'] + if role == 'group01': + schema.need(command.count('--finite-only') == 1 and command.count('--lanes') == 1 and + command[command.index('--lanes') + 1] == 'candidate', 'Group01 must use original finite candidate route') + schema.need(evidence['mode'] == plan['mode'] and evidence['generation'] == row['epoch_plan']['generation'] and + evidence['stage_sha256'] == row['epoch_plan']['stage_sha256'] and + evidence['root_sha256'] == args[1] and evidence['driver_sha256'] == args[7], + 'Group01 evidence expectation not bound to actual independent launch') + else: + schema.need(args[11:] == ['--output', row['output'], '--generation', row['epoch_plan']['generation'], + '--launch-nonce', row['launch_nonce']], 'variant exact tail argv differs') + schema.need(args[1] == 'f5a2d33f2b4d3651f214156a0e7094c2bb516ce2d5ab7698d18c11f98f35dee0' and + args[3] == integration + '/probe_binding_v3.py' and + args[4] == '9cbb7368f89e71d1e6cc46db5dc77efed3e03ed2a801c98c88fe316e4d9f3ef2' and + args[6] == integration + '/variant_driver_v1.py', 'variant genuine original bootstrap differs') + schema.need(evidence['binding'] == {'mode': plan['mode'], 'generation': row['epoch_plan']['generation'], + 'launch_nonce': row['launch_nonce']} and evidence['output'] == row['output'] and + evidence['stage_root'] == row['stage_directory'] and evidence['raw_file_names'] == list(VARIANT_FILES), + 'variant expectation not bound to actual independent launch') + schema.need(schema.sha(schema.canonical({'argv': command})) == row['epoch_plan']['command_sha256'] == + row['launch_binding']['command_sha256'], 'independent exact root command digest differs') + schema.need(row['evidence_directory'] == plan['session_directory'] + '/' + role and + row['output'] == row['evidence_directory'] + '/producer-output', + 'source-fixed private producer origins differ') + schema.need(plan['producers']['group01']['launch_nonce'] != plan['producers']['failure_variants']['launch_nonce'], + 'producer exec launch nonce reused') + + +def make_parent(original_epoch, original_authority, original_receivers): + _gate() + schema.need(_LEN(_PARENTS) < 2, 'finite two-mode parent owner bound exceeded') + # A second mode shares the same process and therefore the same unknown + # resources. Check before the first configuration read can acquire an FD. + for unused, prior in _PARENTS: + owner = prior['unknown_owner'] + domain.refresh_unknown_owner(owner) + schema.need(prior['phase'] != 'STOP' and owner['primary'][0] is None and + owner['quarantine'][0] is False and owner['pending'][0] is False and + owner['iterator_uncertain'][0] is False, + 'prior parent failure forbids a new mode or configuration read') + schema.need(_PROCESS[0] is None or _PROCESS[0]['acquisition_in_flight'] is False, + 'uncertain process-owned lock acquisition requires kernel teardown') + owner = _UNKNOWN_OWNER + domain.refresh_unknown_owner(owner) + schema.need(owner['primary'][0] is None and owner['quarantine'][0] is False and + owner['pending'][0] is False and owner['iterator_uncertain'][0] is False, + 'earlier constructor failure prohibits configuration reads') + try: + errors = schema.make_error_owner() + native_index = 2 * len(_PARENTS) + owner['native_errors'][native_index] = schema.owner_state(errors) + original_state = _EPOCH_ENTRY(original_epoch, original_authority) + owner['native_errors'][native_index + 1] = schema.owner_state(original_state['_error_owner']) + domain.refresh_unknown_owner(owner) + schema.need(owner['quarantine'][0] is False, 'original V5 owner already requires teardown') + mode = original_state['_mode'] + schema.choice(mode, ('normal', 'optimized')) + schema.need(not any(item[1]['plan']['mode'] == mode for item in _PARENTS), 'mode parent already consumed') + configuration = schema.plain_copy({'plan': CONFIGURATION['plans'][mode], + 'receiver_policy': CONFIGURATION['receiver_policy'], 'checker_source': CONFIGURATION['checker_source']}) + plan = group01.decode(copying.read_verified(configuration['plan'], schema.RECORD_BYTES, error_owner=errors)) + _validate_plan(plan) + policy = group01.decode(copying.read_verified(configuration['receiver_policy'], schema.RECORD_BYTES, error_owner=errors)) + schema.need(set(policy) == set(REQUIRED_MODULES), 'exact fixed parent/producer receiving closure differs') + schema.need(policy['parent_completion_v1'] == configuration['checker_source'], + 'actual completion source differs from configured checker') + receivers = closure.bind_receivers(original_receivers, policy, errors) + receiver_gate_snapshot = _receiver_gate_values(receivers) + schema.need(closure.receiver(receivers, 'epoch_parent_v5', 'ParentEpoch') is epoch.ParentEpoch and + closure.receiver(receivers, 'epoch_schema_v5', 'need') is schema.need and + closure.receiver(receivers, 'epoch_copy_v5', 'inspect') is copying.inspect, + 'parent/checker epoch module identities differ') + source_guard = closure.receiver(receivers, 'h25_parent_supervisor', 'launch_contract') + source_guard() + closure.check_receivers(receivers) + original_state = _EPOCH_ENTRY(original_epoch, original_authority) + schema.need(original_state['_epoch_id'] == plan['epoch_id'] and original_state['_mode'] == plan['mode'] and + original_state['_state'] == 'PRODUCERS_PENDING' and + original_state['_plans'] == {role: row['epoch_plan'] for role, row in plan['producers'].items()} and + epoch.CONFIGURATION['parent_checker_sha256'] == configuration['checker_source']['sha256'], + 'original constructor registry is not this prelaunch epoch/plan/checker') + token = object() + state = {'pid': os.getpid(), 'phase': 'CONSTRUCTING', 'epoch': original_epoch, + 'authority': original_authority, 'errors': errors, 'plan': plan, 'configuration': configuration, + 'receivers': receivers, 'receiver_gate_snapshot': receiver_gate_snapshot, + 'runs': {}, 'next': 0, 'directory_created': False, + 'stop': [None, None], 'fallback': [None] * 8, 'stop_file': None, + 'stop_write_attempted': False, 'io_quarantine': owner['quarantine'], + 'unknown_owner': owner, + 'began': _CLOCK(), 'shared_deadline': _CLOCK() + plan['session_seconds'], + 'subreaper': None, 'native_keeper': None, 'lock_fds': [None, None], + 'lock_attempted': [False, False], 'initial_sources': None} + _PARENTS.append((token, state)) + except BaseException as error: + # Reserve the original error before another call or native cleanup. + # This also covers failures before _PARENTS receives a capability. + if owner['primary'][0] is None: + owner['primary'][0] = error + owner['quarantine'][0] = True + raise + try: + # Exclusive creation is the persistent no-restore marker. It is never + # deleted by this source; a crashed/partial same-plan session cannot run. + _MKDIR(plan['session_directory'], 0o700) + state['directory_created'] = True + if _PROCESS[0] is None: + process_record = {'pid': state['pid'], 'locks': [None, None], 'keeper': None, + 'subreaper': None, 'acquisition_in_flight': False} + _PROCESS[0] = process_record + for index, name in enumerate(('parent-queue.lock', 'science.lock')): + process_record['acquisition_in_flight'] = True + process_record['locks'][index] = _OPEN(plan['round_root'] + '/runtime/' + name, + os.O_RDWR | os.O_CREAT | os.O_CLOEXEC | os.O_NOFOLLOW, 0o600) + process_record['acquisition_in_flight'] = False + fcntl.flock(process_record['locks'][index], fcntl.LOCK_EX | fcntl.LOCK_NB) + installer = closure.receiver(receivers, 'h25_parent_supervisor', 'install_subreaper') + # Original installer has a concrete pinned source/TCB/native closure. + # Its path interface is the original pathlib.Path contract. + from pathlib import Path + subreaper, keeper = installer(Path(plan['round_root'])) + process_record['subreaper'], process_record['keeper'] = subreaper, keeper + process_record = _PROCESS[0] + schema.need(process_record['pid'] == state['pid'] and process_record['keeper'] is not None, + 'original same-process subreaper ownership missing') + state['subreaper'], state['native_keeper'] = process_record['subreaper'], process_record['keeper'] + closure.check_receivers(receivers) + state['initial_sources'] = _snapshot_sources(plan, errors) + copying.verify(configuration['checker_source'], error_owner=errors) + copying.write_once(plan['session_directory'] + '/PARENT-INTENT.json', + schema.canonical({'schema': 'h25-parent-completion-intent-v1', 'epoch_id': plan['epoch_id'], + 'mode': plan['mode'], 'configuration': configuration, 'parent_pid': state['pid'], + 'source_closure_admission_sha256': plan['source_closure_admission_sha256'], + 'retry_or_restore_allowed': False, 'accounting': 'nested non-additive; paid by one outer orchestrator'}), + error_owner=errors) + state['phase'] = 'READY' + _guard(state) + return token + except BaseException as primary: + _stop(state, 'make_parent', primary) + raise + + +def _close_logs(run, primary): + first = None + for index in range(2): + descriptor = run['log_fds'][index] + if descriptor is None or run['log_close_attempted'][index]: + continue + run['log_close_attempted'][index] = True + try: + _CLOSE(descriptor) + run['log_close_confirmed'][index] = True + except BaseException as error: + if run['unknown_owner']['primary'][0] is None: + run['unknown_owner']['primary'][0] = primary if primary is not None else error + run['unknown_owner']['quarantine'][0] = True + run['errors'][index] = error + if first is None: + first = error + if primary is None and first is not None: + raise first + + +def run_producer(owner_capability, producer_role): + state = _state(owner_capability) + try: + _guard(state) + schema.choice(producer_role, schema.PRODUCERS) + schema.need(state['phase'] == 'READY' and state['next'] < 2 and + producer_role == schema.PRODUCERS[state['next']] and producer_role not in state['runs'], + 'producer order, replay or prior completion differs') + except BaseException as primary: + _stop(state, 'run_producer_entry', primary) + raise + row = state['plan']['producers'][producer_role] + # Burn the actual epoch ticket before any later preparation or launch. + try: + ticket = _EPOCH_RESERVE(state['epoch'], state['authority'], producer_role) + run_token = object() + run = {'token': run_token, 'ticket': ticket, 'role': producer_role, 'phase': 'RESERVED', + 'unknown_owner': state['unknown_owner'], + 'plan': row, 'domain': None, 'process': None, 'root': None, 'terminal': None, + 'log_fds': [None, None], 'log_close_attempted': [False, False], + 'log_close_confirmed': [False, False], 'errors': [None] * 8, + 'primary': [None], 'acquisition_in_flight': False, 'spawn_entered': False, + 'spawn_returned': False, 'source_before': None, 'stage_before': None, + 'began': _CLOCK(), 'peak_rss': 0, 'file_limits': tuple(_GETRLIMIT(resource.RLIMIT_FSIZE))} + state['runs'][producer_role] = run + state['phase'] = 'PRODUCER_IN_FLIGHT' + except BaseException as primary: + _stop(state, 'run_producer_reservation', primary) + raise + primary = None + old_handler = None + alarm_installed = False + try: + _guard(state) + _MKDIR(row['evidence_directory'], 0o700) + # output remains absent; the genuine original Root creates it exclusively. + try: + _STAT(row['output'], follow_symlinks=False) + except FileNotFoundError: + pass + else: + raise schema.EpochStop('producer output already exists') + local_plan = dict(state['plan'], **row) + run['source_before'] = _snapshot_sources(state['plan'], state['errors']) + run['stage_before'] = _stage(local_plan, state['errors'], state) + # Reject oversized complete-custody records BEFORE any child launch. + run['source_bytes_before'] = _source_custody_bytes(state, run['source_before'], run['stage_before']) + for pin in row['launch_artifacts'].values(): + copying.verify(pin, schema.RECORD_BYTES, error_owner=state['errors']) + run['domain'] = domain.create_domain(state['unknown_owner']) + launch = {'schema': 'h25-owned-producer-launch-v1', 'epoch_id': state['plan']['epoch_id'], + 'mode': state['plan']['mode'], 'role': producer_role, + 'generation': row['epoch_plan']['generation'], 'launch_nonce': row['launch_nonce'], + 'parent_pid': state['pid'], 'command': row['command'], 'environment': ENV, 'cwd': row['cwd'], + 'launch_binding': row['launch_binding'], 'parent_file_limits': list(run['file_limits']), + 'new_session': True, 'close_fds': True, 'pass_fds': [], + 'root_seconds': row['root_seconds'], 'rss_bytes': row['rss_bytes'], + 'address_space_bytes': row['address_space_bytes']} + run['launch'] = copying.write_once(row['evidence_directory'] + '/LAUNCH.json', + schema.canonical(launch), error_owner=state['errors']) + for index, name in enumerate(('stdout.raw', 'stderr.raw')): + schema.need(state['io_quarantine'][0] is False and state['unknown_owner']['pending'][0] is False and + state['unknown_owner']['iterator_uncertain'][0] is False, + 'raw stream cannot acquire after uncertain ownership') + run['acquisition_in_flight'] = True + state['unknown_owner']['pending'][0] = True + run['log_fds'][index] = _OPEN(row['evidence_directory'] + '/' + name, + os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_CLOEXEC | os.O_NOFOLLOW, 0o600) + run['acquisition_in_flight'] = False + state['unknown_owner']['pending'][0] = False + setter, kind, limits = _SETRLIMIT, resource.RLIMIT_AS, (row['address_space_bytes'], row['address_space_bytes']) + def child_limit(): + setter(kind, limits) + schema.need(_GETTIMER(signal.ITIMER_REAL) == (0.0, 0.0), 'existing parent timer cannot be replaced') + old_handler = _GETSIGNAL(signal.SIGALRM) + _SIGNAL(signal.SIGALRM, _alarm) + alarm_installed = True + deadline = min(run['began'] + row['root_seconds'], state['shared_deadline'] - domain.CLEANUP_SECONDS) + schema.need(_CLOCK() < deadline, 'no funded root/cleanup interval remains') + _SETTIMER(signal.ITIMER_REAL, max(0.000001, deadline - _CLOCK())) + run['spawn_entered'] = True + run['process'] = _POPEN(row['command'], cwd=row['cwd'], env=dict(ENV), + stdout=run['log_fds'][0], stderr=run['log_fds'][1], stdin=subprocess.DEVNULL, + close_fds=True, pass_fds=(), start_new_session=True, preexec_fn=child_limit) + run['spawn_returned'] = True + run['root'] = domain.adopt_popen(run['domain'], run['process']) + while True: + unused, current = domain.observe(run['domain']) + run['peak_rss'] = max(run['peak_rss'], sum(item[6] for item in current)) + schema.need(run['peak_rss'] <= row['rss_bytes'], 'owned process RSS sum exceeded') + schema.need(max(_STAT(row['evidence_directory'] + '/' + name, follow_symlinks=False).st_size + for name in ('stdout.raw', 'stderr.raw')) <= schema.LOG_BYTES, 'root output bound exceeded') + if domain.poll_owned(run['domain']) is not None: + break + _SLEEP(0.01) + except BaseException as error: + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = error + primary = state['unknown_owner']['primary'][0] + run['primary'][0] = primary + if primary is not error: + run['errors'][4] = error + if (run['acquisition_in_flight'] or state['unknown_owner']['pending'][0] or + state['unknown_owner']['iterator_uncertain'][0] or _TYPE(error) is MemoryError): + state['io_quarantine'][0] = True + raise primary + finally: + # Preserve the first locally delivered primary through all cleanup. + first_cleanup = None + if alarm_installed: + try: + _SETTIMER(signal.ITIMER_REAL, 0) + _SIGNAL(signal.SIGALRM, old_handler) + except BaseException as error: + run['errors'][2] = error + first_cleanup = error + if run['domain'] is not None: + try: + domain.finish_domain(run['domain']) + except BaseException as error: + run['errors'][3] = error + state['io_quarantine'][0] = True + if first_cleanup is None: + first_cleanup = error + try: + _close_logs(run, primary if primary is not None else first_cleanup) + except BaseException as error: + if first_cleanup is None: + first_cleanup = error + for index in range(2): + if run['log_close_attempted'][index] and not run['log_close_confirmed'][index]: + state['io_quarantine'][0] = True + if primary is not None: + _stop(state, 'run_producer', primary) + elif first_cleanup is not None: + _stop(state, 'run_producer_cleanup', first_cleanup) + raise first_cleanup + try: + schema.need(run['spawn_entered'] is True and run['spawn_returned'] is True and + run['acquisition_in_flight'] is False and all(run['log_close_confirmed']), + 'root spawn or raw stream ownership incomplete') + run['terminal'] = domain.terminal_facts(run['domain']) + schema.need(tuple(_GETRLIMIT(resource.RLIMIT_FSIZE)) == run['file_limits'], 'parent file limit drift') + run['phase'] = 'JOINED' + state['phase'] = 'PRODUCER_JOINED' + _guard(state) + return run_token + except BaseException as primary: + _stop(state, 'postcleanup_terminal', primary) + raise + + +def _source_custody_bytes(state, files, stage): + raw = group01.encode({'schema': 'h25-parent-current-source-custody-v1', 'files': files, + 'stage': stage, 'source_closure_admission_sha256': state['plan']['source_closure_admission_sha256'], + 'historical_compiler_interval_proof_claimed_by_this_record': False}) + schema.need(len(raw) <= schema.RECORD_BYTES, 'complete source custody record exceeds admitted writer bound') + return raw + + +def _variant(state, run, stdout_raw): + """Dedicated concrete typed receiver; source remains external until frozen.""" + expected = group01.decode(group01.encode(run['plan']['evidence_plan'])) + expected['producer_process_id'] = run['root'][0] + expected['parent_file_limits'] = list(run['file_limits']) + files = expected['raw_file_names'] + schema.need(_TYPE(files) is list and files == list(VARIANT_FILES), + 'fixed variant raw file inventory missing') + raw_files, pins, total = {}, [], 0 + for relative in files: + schema.text(relative, 256) + schema.need(not relative.startswith('/') and all(part not in ('', '.', '..') for part in relative.split('/')), + 'variant raw origin differs') + path = run['plan']['output'] + '/' + relative + limit = 8388608 if relative.endswith('.so') else schema.LOG_BYTES if relative.endswith('.raw') else schema.RECORD_BYTES + pin = copying.inspect(path, limit, error_owner=state['errors']) + total += pin['bytes'] + schema.need(total <= MAX_VARIANT_RAW_BYTES, 'variant aggregate byte bound exceeded before allocation') + raw_files[relative] = copying.read_verified(pin, limit, error_owner=state['errors']) + pins.append(pin) + closure.check_receivers(state['receivers']) + validator = closure.receiver(state['receivers'], VARIANT_MODULE, VARIANT_FUNCTION) + result = validator(raw_files, expected) + closure.check_receivers(state['receivers']) + # Exact result schema is fixed with the separately frozen variant source. + # This branch cannot run before that complete source/interface is admitted. + schema.exact(result, ('schema', 'raw_result_relative', 'raw_group_relatives', 'builds', + 'zero_candidate_loads', 'not_runtime_authority')) + schema.need(result['schema'] == 'h25-negative-variant-data-authentication-v1' and + result['zero_candidate_loads'] is True and result['not_runtime_authority'] is True, + 'variant data-validation scope differs') + pin_by_relative = dict(zip(files, pins)) + schema.need(result['raw_result_relative'] == 'receipt.json' and + group01.same_json(group01.decode(stdout_raw), group01.decode(raw_files['receipt.json'])), + 'variant original stdout/final raw result differs') + builds = [] + schema.sequence(result['builds'], 2) + for role, row in zip(schema.ROLES[3:], result['builds']): + schema.exact(row, ('role', 'command_sha256', 'profile', 'files')) + schema.need(row['role'] == role, 'variant build role order differs') + schema.exact(row['files'], ('original_output', 'original_receipt', 'attempt', 'journal', 'stdout', 'stderr')) + build = {'role': role, 'producer_role': 'failure_variants', + 'producer_generation': run['plan']['epoch_plan']['generation'], + 'producer_stage_sha256': run['plan']['epoch_plan']['stage_sha256'], + 'command_sha256': row['command_sha256'], 'profile': row['profile']} + for key, relative in row['files'].items(): + schema.text(relative, 256) + schema.need(relative in pin_by_relative, 'variant validator returned unowned file') + build[key] = pin_by_relative[relative] + schema.build(build) + builds.append(build) + schema.need(result['raw_group_relatives'] == list(VARIANT_GROUPS), 'variant exact raw group census differs') + raw_groups = [] + for relative in result['raw_group_relatives']: + schema.text(relative, 256) + schema.need(relative in pin_by_relative, 'variant validator returned unowned raw group') + raw_groups.append({'file': relative, 'raw': pin_by_relative[relative]}) + return {'raw_result': pin_by_relative['receipt.json'], 'group_rows': raw_groups, + 'builds': builds, 'additional_raw': pins, + 'native_runtime_or_full_union_qualified': False} + + +def accept_producer(owner_capability, completed_run_capability): + state = _state(owner_capability) + try: + _guard(state) + schema.need(_TYPE(completed_run_capability) is object and state['phase'] == 'PRODUCER_JOINED', + 'joined original producer capability required') + matches = [run for run in state['runs'].values() if run['token'] is completed_run_capability] + schema.need(_LEN(matches) == 1 and matches[0]['phase'] == 'JOINED', 'unknown or replayed producer completion') + run = matches[0] + run['phase'] = 'COMPLETION_CONSUMED' + terminal = domain.terminal_facts(run['domain']) + schema.need(terminal == run['terminal'], 'owned terminal facts changed') + row, errors = run['plan'], state['errors'] + stdout = copying.inspect(row['evidence_directory'] + '/stdout.raw', schema.LOG_BYTES, error_owner=errors) + stderr = copying.inspect(row['evidence_directory'] + '/stderr.raw', schema.LOG_BYTES, error_owner=errors) + schema.need(stderr['bytes'] == 0, 'original producer stderr is not empty') + stdout_raw = copying.read_verified(stdout, schema.LOG_BYTES, error_owner=errors) + if run['role'] == 'group01': + actual = group01.authenticate_group01(row['output'], row['evidence_plan'], run['root'][0], + run['file_limits'], state['receivers'], errors, stdout_raw) + else: + actual = _variant(state, run, stdout_raw) + # These facts are parent-derived from current bytes and real owned + # cleanup, never child status flags or an imported ParentCompletion. + source_after = _snapshot_sources(state['plan'], errors) + schema.need(source_after == run['source_before'] == state['initial_sources'], 'complete current source identity changed') + stage_after = _stage(dict(state['plan'], **row), errors, state) + schema.need(stage_after == run['stage_before'], 'late complete stage custody changed') + closure.check_receivers(state['receivers']) + schema.need(domain.terminal_facts(run['domain']) == terminal, 'late parent-domain cleanup changed') + copying.verify(stdout, schema.LOG_BYTES, error_owner=errors) + copying.verify(stderr, schema.LOG_BYTES, error_owner=errors) + for build in actual['builds']: + for key, limit in (('original_output', schema.FILE_BYTES), ('original_receipt', 65536), + ('attempt', 65536), ('journal', schema.JOURNAL_BYTES), ('stdout', schema.LOG_BYTES), ('stderr', schema.LOG_BYTES)): + copying.verify(build[key], limit, error_owner=errors) + for pin in actual['additional_raw']: + copying.verify(pin, schema.FILE_BYTES, error_owner=errors) + copying.verify(actual['raw_result'], schema.RAW_RESULT_BYTES, error_owner=errors) + for pin in row['launch_artifacts'].values(): + copying.verify(pin, schema.RECORD_BYTES, error_owner=errors) + for group in actual['group_rows']: + copying.verify(group['raw'], schema.RECORD_BYTES, error_owner=errors) + if run['role'] == 'group01': + copying.verify(group['validation'], 8192, error_owner=errors) + directory = row['evidence_directory'] + terminal_pin = copying.write_once(directory + '/TERMINAL.json', schema.canonical({ + 'schema': 'h25-owned-producer-terminal-v1', 'launch': run['launch'], + 'generation': row['epoch_plan']['generation'], 'launch_nonce': row['launch_nonce'], + 'actual': terminal, 'stdout': stdout, 'stderr': stderr, + 'root_wall_before_completion_diagnostic_nanoseconds': int((_CLOCK() - run['began']) * 1000000000), + 'diagnostic_is_nested_not_additive': True}), error_owner=errors) + raw_groups = copying.write_once(directory + '/RAW-GROUPS.json', + group01.encode({'schema': 'h25-parent-retained-raw-groups-v1', 'rows': actual['group_rows'], + 'additional_raw': actual['additional_raw'], 'returned_groups_checked_before_mint': True}), error_owner=errors) + source_bytes_after = _source_custody_bytes(state, source_after, stage_after) + schema.need(source_bytes_after == run['source_bytes_before'], 'source custody changed after prelaunch size gate') + source_pin = copying.write_once(directory + '/FINAL-SOURCE-CUSTODY.json', source_bytes_after, error_owner=errors) + _guard(state) + schema.need(_CLOCK() - run['began'] <= row['root_seconds'], 'complete root including validation/custody exceeded bound') + observation = {'schema': 'h25-owned-parent-observation-v1', 'epoch_id': state['plan']['epoch_id'], + 'mode': state['plan']['mode'], 'producer_role': run['role'], 'generation': row['epoch_plan']['generation'], + 'launch_nonce': row['launch_nonce'], 'launch': run['launch'], 'terminal': terminal_pin, + 'raw_result': actual['raw_result'], 'raw_groups': raw_groups, 'final_source_custody': source_pin, + 'root_pid': run['root'][0], 'root_start_ticks': run['root'][4], + 'later_cross_root_aggregate_required_before_export': False, + 'native_full_or_gain_qualification': False} + observed_pin = copying.write_once(directory + '/PARENT-OBSERVATION.json', schema.canonical(observation), error_owner=errors) + record = {key: row['epoch_plan'][key] for key in ('role', 'generation', 'stage_sha256', 'command_sha256', 'root_sha256')} + record.update(terminal=terminal_pin, raw_result=actual['raw_result'], raw_groups=raw_groups, + final_source_custody=source_pin, parent_observation=observed_pin, + completion_checker_sha256=state['configuration']['checker_source']['sha256'], builds=actual['builds']) + schema.producer(record) + # The only mint site is below every actual launch/domain/raw/source + # check. Neither ticket nor completion is ever returned to a caller. + _guard(state) + completion = _EPOCH_COMPLETION(run['ticket'], state['configuration']['checker_source']['sha256'], + observed_pin['sha256'], row['epoch_plan']['generation'], state['plan']['mode'], run['role'], + run['root'][0], run['root'][4], True, True, True, True, True, True) + _EPOCH_ACCEPT(state['epoch'], state['authority'], run['ticket'], completion, record) + _guard(state) + schema.need(_CLOCK() - run['began'] <= row['root_seconds'], + 'complete root plus acceptance tail exceeded bound') + run['phase'], run['record'] = 'ACCEPTED', record + state['next'] += 1 + state['phase'] = 'READY' if state['next'] < 2 else 'PRODUCERS_ACCEPTED' + return schema.plain_copy(record) + except BaseException as primary: + _stop(state, 'accept_producer', primary) + raise + + +def commit_exports(owner_capability): + state = _state(owner_capability) + try: + _guard(state) + schema.need(state['phase'] == 'PRODUCERS_ACCEPTED' and state['next'] == 2 and + all(run['phase'] == 'ACCEPTED' for run in state['runs'].values()), + 'only two genuinely accepted producer records may export') + result = _EPOCH_COMMIT(state['epoch'], state['authority']) + _guard(state) + state['phase'] = 'EXPORTED' + return result + except BaseException as primary: + _stop(state, 'commit_exports', primary) + raise + + +def stop_evidence(owner_capability): + state = _state(owner_capability) + summaries = [{'role': run['role'], 'phase': run['phase'], + 'spawn_entered': run['spawn_entered'], 'spawn_returned': run['spawn_returned'], + 'log_close_attempted': list(run['log_close_attempted']), + 'log_close_confirmed': list(run['log_close_confirmed'])} + for run in state['runs'].values()] + # Never expose the epoch ticket, Popen object, domain capability or private + # run sidecar through diagnostic return values. + return state['stop'], state['errors'], state['fallback'], summaries diff --git a/research/h25-c05-v03-parent-interface-audit/snapshot/parent_domain_v1.py.txt b/research/h25-c05-v03-parent-interface-audit/snapshot/parent_domain_v1.py.txt new file mode 100644 index 0000000000..55f0103208 --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/snapshot/parent_domain_v1.py.txt @@ -0,0 +1,450 @@ +"""Owned Linux child domains for one trusted, single-threaded parent process. + +Source proposal only. No target was imported or run during authoring. The +external launcher must authenticate the OS, interpreter, system modules and +original subreaper installer before importing this module. This is the original +closed child-domain premise, not a sandbox against hostile forking or a hostile +host. Acquisition/unwind ambiguity quarantines the parent; it never authorizes +another launch or a completion. The enclosing guard must observe parent exit. +""" +import os +import signal +import subprocess +import time +import epoch_schema_v5 as schema + +_TYPE, _LEN = type, len +_OPEN, _READ, _CLOSE = os.open, os.read, os.close +_STAT = os.stat +_SCANDIR, _GETPID, _GETPGRP, _GETSID = os.scandir, os.getpid, os.getpgrp, os.getsid +_PIDFD_OPEN, _PIDFD_SIGNAL = os.pidfd_open, signal.pidfd_send_signal +_WAITPID, _CLOCK, _SLEEP = os.waitpid, time.monotonic, time.sleep +_POPEN, _POLL = subprocess.Popen, subprocess.Popen.poll +_PAGE_BYTES = os.sysconf('SC_PAGE_SIZE') +_DOMAINS = [] +MAX_GENERATIONS = 128 +MAX_PROC_ENTRIES = 131072 +MAX_PROC_BYTES = 8192 +CLEANUP_SECONDS = 2.0 + + +def _state(capability): + schema.need(_TYPE(capability) is object, 'exact owned domain capability required') + for token, state in _DOMAINS: + if token is capability: + return state + raise schema.EpochStop('unregistered owned domain') + + +def refresh_unknown_owner(owner): + # These are exact V5 ErrorOwner state references captured by the original + # parent before use. Read only the pinned private shape; no projection, + # callback, native I/O or interpretation of historical release slot9. + for native in owner['native_errors']: + if native is None: + continue + io = native[7] + if (io[0] or io[1] or io[2] or io[4] or io[6] or io[10] or io[11] or + io[5] is not None or native[5][1] or io[7][4] == 1): + owner['quarantine'][0] = True + if io[5] is not None: + owner['iterator_uncertain'][0] = True + + +def _fresh_acquisition(state): + # This shares the original parent's preallocated unknown-resource owner. + # Pending acquisition and delivered census failure are independent of a + # later Python close return. Neither flag is cleared by cleanup. + owner = state['unknown_owner'] + refresh_unknown_owner(owner) + schema.need(state['quarantine'] is False and state['acquisition_in_flight'] is False and + state['io_uncertain'] is False and owner['quarantine'][0] is False and + owner['pending'][0] is False and owner['iterator_uncertain'][0] is False, + 'uncertain ownership prohibits a fresh native acquisition') + + +def _opaque(state, error, slot): + # Preallocated slots retain the actual delivered object, without formatting. + # A secondary never replaces the first primary. Slots are finite and an + # overflow means quarantine, not a successful evidence projection. + state['quarantine'] = True + if state['primary'][0] is None: + state['primary'][0] = error + elif state['secondary'][slot] is None: + state['secondary'][slot] = error + else: + state['overflow'][0] = error + + +def _proc(pid, state): + schema.integer(pid, 1, (1 << 31) - 1) + descriptor = None + primary = None + _fresh_acquisition(state) + # The uncertain acquisition flag is set before the native entry. If open + # raises after an undisclosed descriptor acquisition, parent exit is needed. + try: + try: + _STAT('/proc/' + str(pid) + '/stat', dir_fd=None, follow_symlinks=False) + except (FileNotFoundError, ProcessLookupError): + # Only the pinned metadata-only primitive establishes absence. + # An exception from a later acquisition never proves no FD existed. + return None + state['acquisition_in_flight'] = True + state['unknown_owner']['pending'][0] = True + descriptor = _OPEN('/proc/' + str(pid) + '/stat', + os.O_RDONLY | os.O_CLOEXEC | os.O_NOFOLLOW | os.O_NONBLOCK) + state['acquisition_in_flight'] = False + state['unknown_owner']['pending'][0] = False + raw = _READ(descriptor, MAX_PROC_BYTES + 1) + schema.need(_TYPE(raw) is bytes and _LEN(raw) <= MAX_PROC_BYTES, + 'bounded proc stat read differs') + end = raw.rfind(b') ') + schema.need(end >= 0, 'malformed proc stat') + fields = raw[end + 2:].split() + schema.need(_LEN(fields) >= 22 and raw[:raw.find(b' ')] == str(pid).encode('ascii'), + 'proc stat identity or shape differs') + row = (pid, int(fields[1]), int(fields[2]), int(fields[3]), + int(fields[19]), fields[0].decode('ascii'), int(fields[21]) * _PAGE_BYTES) + schema.need(row[4] > 0 and row[6] >= 0, 'proc generation or RSS differs') + return row + except BaseException as error: + primary = error + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = error + state['quarantine'] = True + state['unknown_owner']['quarantine'][0] = True + _opaque(state, error, 0) + raise + finally: + if descriptor is not None: + # Burn before entry; a failed native close is not retried. + owned = descriptor + descriptor = None + try: + _CLOSE(owned) + except BaseException as close_error: + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = close_error + state['quarantine'] = True + state['unknown_owner']['quarantine'][0] = True + state['io_uncertain'] = True + _opaque(state, close_error, 1) + if primary is None: + raise + + +def _census(state): + iterator = None + primary = None + rows = {} + _fresh_acquisition(state) + state['acquisition_in_flight'] = True + state['unknown_owner']['pending'][0] = True + try: + iterator = _SCANDIR('/proc') + state['acquisition_in_flight'] = False + state['unknown_owner']['pending'][0] = False + count = 0 + for entry in iterator: + count += 1 + schema.need(count <= MAX_PROC_ENTRIES, 'proc census entry bound exceeded') + name = entry.name + if name.isdecimal(): + row = _proc(int(name), state) + if row is not None: + rows[row[0]] = row + return rows + except BaseException as error: + primary = error + # All delivered iteration/body failures latch before optional helper + # entry. A no-op/successful close cannot establish release afterward. + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = error + state['quarantine'] = True + state['io_uncertain'] = True + state['unknown_owner']['quarantine'][0] = True + state['unknown_owner']['iterator_uncertain'][0] = True + _opaque(state, error, 2) + raise + finally: + if iterator is not None: + owned = iterator + iterator = None + try: + owned.close() + except BaseException as close_error: + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = close_error + state['quarantine'] = True + state['unknown_owner']['quarantine'][0] = True + state['unknown_owner']['iterator_uncertain'][0] = True + state['io_uncertain'] = True + _opaque(state, close_error, 3) + if primary is None: + raise + + +def create_domain(unknown_owner): + """Called only after the original same-process subreaper was installed.""" + schema.need(_LEN(_DOMAINS) < 4, 'two modes by two producers domain bound exceeded') + schema.exact(unknown_owner, ('quarantine', 'pending', 'iterator_uncertain', 'primary', 'native_errors')) + for key in ('quarantine', 'pending', 'iterator_uncertain', 'primary'): + schema.need(_TYPE(unknown_owner[key]) is list and _LEN(unknown_owner[key]) == 1, + 'original parent unknown-resource slot differs') + schema.need(_TYPE(unknown_owner['native_errors']) is list and _LEN(unknown_owner['native_errors']) == 4, + 'exact two-mode V5 error-owner registry required') + for native in unknown_owner['native_errors']: + schema.need(native is None or (_TYPE(native) is list and _LEN(native) == 9 and + _TYPE(native[7]) is list and _LEN(native[7]) == 13), + 'original captured V5 error-owner shape differs') + refresh_unknown_owner(unknown_owner) + schema.need(all(unknown_owner[key][0] is False for key in + ('quarantine', 'pending', 'iterator_uncertain')) and unknown_owner['primary'][0] is None, + 'unknown-resource parent already requires teardown') + token = object() + state = {'rows': [None] * MAX_GENERATIONS, 'fds': [None] * MAX_GENERATIONS, + 'fd_attempted': [False] * MAX_GENERATIONS, + 'fd_closed': [False] * MAX_GENERATIONS, 'count': 0, + 'groups': set(), 'reaped': [], 'after_root': set(), + 'process': None, 'root': None, 'returncode': None, + 'parent_pid': _GETPID(), 'parent_group': _GETPGRP(), 'parent_session': _GETSID(0), + 'phase': 'CONSTRUCTING', 'quarantine': False, + 'acquisition_in_flight': False, 'io_uncertain': False, 'primary': [None], + 'unknown_owner': unknown_owner, + 'secondary': [None] * 16, 'overflow': [None], + 'final_rows': None, 'closure_confirmed': False} + _DOMAINS.append((token, state)) + try: + rows = _census(state) + schema.need(not any(row[1] == state['parent_pid'] for row in rows.values()), + 'parent has preexisting child processes') + state['phase'] = 'RESERVED' + return token + except BaseException as error: + if unknown_owner['primary'][0] is None: + unknown_owner['primary'][0] = error + unknown_owner['quarantine'][0] = True + state['quarantine'] = True + _opaque(state, error, 4) + state['phase'] = 'STOP' + raise + + +def _add(state, row): + _fresh_acquisition(state) + key = row[0], row[4] + schema.need(row[0] != state['parent_pid'], 'parent cannot enter own child domain') + for index in range(state['count']): + prior = state['rows'][index] + if prior is not None and (prior[0], prior[4]) == key: + if row[2] != state['parent_group']: + state['groups'].add((row[2], row[3])) + return True + index = state['count'] + schema.need(index < MAX_GENERATIONS, 'owned process generation bound exceeded') + # Reserve the slot before native acquisition. No role/generation slot is + # recycled after a failed or disappeared acquisition. + state['count'] = index + 1 + state['rows'][index] = row + state['acquisition_in_flight'] = True + state['unknown_owner']['pending'][0] = True + try: + state['fds'][index] = _PIDFD_OPEN(row[0], 0) + state['acquisition_in_flight'] = False + state['unknown_owner']['pending'][0] = False + current = _proc(row[0], state) + if current is None or (current[0], current[4]) != key: + return False # The actual FD stays owned for one terminal close. + if current[2] != state['parent_group']: + state['groups'].add((current[2], current[3])) + return True + except BaseException as error: + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = error + state['quarantine'] = True + state['unknown_owner']['quarantine'][0] = True + _opaque(state, error, 5) + raise + + +def observe(capability): + state = _state(capability) + all_rows = _census(state) + known = set() + for index in range(state['count']): + prior = state['rows'][index] + current = None if prior is None else all_rows.get(prior[0]) + if current is not None and current[4] == prior[4]: + known.add(current[0]) + _add(state, current) + for unused in range(MAX_GENERATIONS + 1): + changed = False + for pid, row in all_rows.items(): + if pid not in known and (row[1] == state['parent_pid'] or row[1] in known): + if _add(state, row): + known.add(pid) + changed = True + if not changed: + break + else: + raise schema.EpochStop('child-domain closure iteration bound exceeded') + return all_rows, tuple(all_rows[pid] for pid in sorted(known)) + + +def adopt_popen(capability, process): + state = _state(capability) + schema.need(state['phase'] == 'RESERVED' and state['process'] is None and + _TYPE(process) is _POPEN, 'Popen ownership or one-attempt state differs') + state['process'] = process # Exact original return, never a supplied proxy. + row = _proc(process.pid, state) + schema.need(row is not None and row[1] == state['parent_pid'] and + row[2] == row[3] == process.pid, + 'new child PID/session/generation missing before first poll') + state['root'] = row + schema.need(_add(state, row) is True, 'original child pidfd generation not owned') + state['phase'] = 'RUNNING' + return row + + +def poll_owned(capability): + state = _state(capability) + schema.need(state['phase'] == 'RUNNING' and _TYPE(state['process']) is _POPEN, + 'original running Popen required') + result = _POLL(state['process']) + if result is not None: + schema.integer(result, -128, 255) + state['returncode'] = result + return result + + +def _kill(state): + for index in range(state['count']): + fd, prior = state['fds'][index], state['rows'][index] + if fd is None or state['fd_attempted'][index]: + continue + current = _proc(prior[0], state) + if current is not None and current[4] == prior[4] and current[5] != 'Z': + try: + _PIDFD_SIGNAL(fd, signal.SIGKILL, None, 0) + except ProcessLookupError: + pass + + +def finish_domain(capability): + """Always attempted, including Popen exceptions; no caller closure claims.""" + state = _state(capability) + schema.need(state['phase'] in ('RESERVED', 'RUNNING'), 'domain cleanup replay') + state['phase'] = 'CLEANUP_CONSUMED' + started = _CLOCK() + primary = None + try: + _fresh_acquisition(state) + while True: + all_rows, current = observe(capability) + process = state['process'] + if process is not None and process.returncode is not None: + for row in current: + if row[0] != process.pid: + state['after_root'].add((row[0], row[4])) + _kill(state) + if process is not None: + result = _POLL(process) + if result is not None: + state['returncode'] = result + for index in range(state['count']): + prior = state['rows'][index] + row = _proc(prior[0], state) + if (row is None or row[4] != prior[4] or row[1] != state['parent_pid'] or + (process is not None and row[0] == process.pid)): + continue + try: + pid, status = _WAITPID(row[0], os.WNOHANG) + except ChildProcessError: + continue + if pid: + state['reaped'].append((pid, prior[4], status)) + all_rows, current = observe(capability) + remaining = tuple(row for row in all_rows.values() + if row[1] == state['parent_pid'] or (row[2], row[3]) in state['groups'] or + any(prior is not None and (row[0], row[4]) == (prior[0], prior[4]) + for prior in state['rows'][:state['count']])) + state['final_rows'] = remaining + if not current and not remaining: + state['closure_confirmed'] = True + break + if _CLOCK() - started >= CLEANUP_SECONDS: + break + _SLEEP(0.01) + except BaseException as error: + primary = error + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = error + state['quarantine'] = True + state['unknown_owner']['quarantine'][0] = True + _opaque(state, error, 6) + raise + finally: + # Every known FD gets one attempt even if a prior close failed. Native + # return/boxing, Python call-entry and final unwind still have no total + # recovery theorem; any such failure forbids minting and parent reuse. + first_close = None + for index in range(state['count']): + descriptor = state['fds'][index] + if descriptor is None or state['fd_attempted'][index]: + continue + state['fd_attempted'][index] = True + try: + _CLOSE(descriptor) + state['fd_closed'][index] = True + except BaseException as error: + if state['unknown_owner']['primary'][0] is None: + state['unknown_owner']['primary'][0] = error + state['quarantine'] = True + state['unknown_owner']['quarantine'][0] = True + state['io_uncertain'] = True + _opaque(state, error, 7) + if first_close is None: + first_close = error + state['phase'] = 'CLOSED' if primary is None and first_close is None else 'STOP' + if primary is None and first_close is not None: + raise first_close + + +def terminal_facts(capability): + state = _state(capability) + _fresh_acquisition(state) + schema.need(state['phase'] == 'CLOSED' and state['quarantine'] is False and + state['acquisition_in_flight'] is False and state['io_uncertain'] is False and state['root'] is not None and + state['returncode'] == 0 and state['closure_confirmed'] is True and + state['final_rows'] == () and not state['after_root'] and not state['reaped'] and + all(fd is None or (state['fd_attempted'][index] and state['fd_closed'][index]) + for index, fd in enumerate(state['fds'])), + 'owned terminal domain is incomplete, failed, orphaned or quarantined') + # Fresh census after FD cleanup. This is independent of receipt booleans. + rows = _census(state) + schema.need(not any(row[1] == state['parent_pid'] or + (row[2], row[3]) in state['groups'] for row in rows.values()), + 'postcleanup owned child/group still present') + return {'root': list(state['root']), 'returncode': state['returncode'], + 'owned_generations': [list(row) for row in state['rows'][:state['count']]], + 'groups': [list(pair) for pair in sorted(state['groups'])], + 'remaining': [], 'adopted_reaps': [], 'observed_after_root_exit': [], + 'pidfd_close_attempted': list(state['fd_attempted'][:state['count']]), + 'pidfd_close_confirmed': list(state['fd_closed'][:state['count']]), + 'source': 'original in-process Popen and owned generation registry', + 'hostile_fork_or_privileged_host_resistance_claimed': False} + + +def stop_slots(capability): + state = _state(capability) + return state['primary'], state['secondary'], state['overflow'], { + 'phase': state['phase'], 'quarantine': state['quarantine'], + 'acquisition_in_flight': state['acquisition_in_flight'], + 'io_uncertain': state['io_uncertain'], + 'shared_pending': state['unknown_owner']['pending'][0], + 'shared_iterator_uncertain': state['unknown_owner']['iterator_uncertain'][0], + 'shared_quarantine': state['unknown_owner']['quarantine'][0], + 'closure_confirmed': state['closure_confirmed'], + 'pidfd_close_attempted': list(state['fd_attempted'][:state['count']]), + 'pidfd_close_confirmed': list(state['fd_closed'][:state['count']])} diff --git a/research/h25-c05-v03-parent-interface-audit/verify.py b/research/h25-c05-v03-parent-interface-audit/verify.py new file mode 100644 index 0000000000..32d409b35c --- /dev/null +++ b/research/h25-c05-v03-parent-interface-audit/verify.py @@ -0,0 +1,47 @@ +"""Archive identity and source-anchor check. Never imports archived code.""" +from pathlib import Path +import ast +import hashlib +import json + +ROOT = Path(__file__).resolve().parent + +def need(condition, message): + if condition is not True: + raise RuntimeError(message) + +def main(): + manifest = json.loads((ROOT / "ARTIFACTS.json").read_text()) + actual = sorted(p.relative_to(ROOT).as_posix() for p in ROOT.rglob("*") if p.is_file() and p.name != "ARTIFACTS.json") + need(actual == sorted(row["path"] for row in manifest["files"]), "archive file set changed") + for row in manifest["files"]: + raw = (ROOT / row["path"]).read_bytes() + need(len(raw) == row["bytes"] and hashlib.sha256(raw).hexdigest() == row["sha256"], "archive byte identity changed: " + row["path"]) + findings = json.loads((ROOT / "SOURCE-FINDINGS.json").read_text()) + for row in findings["anchors"]: + raw = (ROOT / row["path"]).read_text() + tree = ast.parse(raw) + nodes = [n for n in tree.body if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)) and n.name == row["function"]] + need(len(nodes) == 1, "source function missing or ambiguous") + node = nodes[0] + segment = "\n".join(raw.split("\n")[node.lineno-1:node.end_lineno]) + need(row["literal"] in segment, "pinned source anchor changed: " + row["id"]) + for row in findings["constants"]: + tree = ast.parse((ROOT / row["path"]).read_text()) + assignments = [n.value for n in tree.body if isinstance(n, ast.Assign) and any(isinstance(t, ast.Name) and t.id == row["name"] for t in n.targets)] + need(len(assignments) == 1, "literal binding missing or ambiguous") + value = ast.literal_eval(assignments[0]) + if "expected_length" in row: + need(type(value) is tuple and len(value) == row["expected_length"], "literal inventory cardinality changed") + else: + if type(value) is tuple: + value = list(value) + need(type(value) is type(row["expected"]) and value == row["expected"], "literal value changed") + # These are structural readings of authenticated text, not original execution. + parent = ast.parse((ROOT / "snapshot/parent_completion_v1.py.txt").read_text()) + need(not any(isinstance(n, ast.If) and "__name__" in ast.unparse(n.test) and "__main__" in ast.unparse(n.test) for n in parent.body), "unexpected executable parent main guard") + need(findings["full_C05"] is False and findings["full_V03"] is False and findings["original_execution"] is False, "scope changed") + print("PASS_SOURCE_IDENTITIES_AND_PINNED_ANCHORS", len(manifest["files"]), len(findings["anchors"])) + +if __name__ == "__main__": + main()