diff --git a/docs/plans/original-completion-2026-10-02/execution/p08-03/CONDITION_MATRIX.md b/docs/plans/original-completion-2026-10-02/execution/p08-03/CONDITION_MATRIX.md index d435c8d..769de07 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p08-03/CONDITION_MATRIX.md +++ b/docs/plans/original-completion-2026-10-02/execution/p08-03/CONDITION_MATRIX.md @@ -1,6 +1,41 @@ # P08-03 condition matrix — implementation submission, not acceptance -## Repair14 current submission +## Repair16 current submission + +Root finalized deletion of the repair13 fixture omitted by the Runner submission. +No repair13 fixture remains in the net final diff. Repair14 observations below +are historical and superseded; they do not require a native re-run now. + +Environment provenance: the P08_/THE_TREE_ subset is reconstructable and checked +by direct equality across started, process-started, ended and the pinned receipt. +The full-env environment_sha256 is opaque and checked only by cross-receipt and +pin equality; the original os.environ cannot be reconstructed. Receipt bytes and +SHA are pinned through the original index and ended receipt. Driver bytes at HEAD +and in the working tree must equal R09_COMMIT. Other applicability gates remain. + +Net diff command (executed read-only): +`git diff --name-status --no-renames 31aa7706d28a92e313c432d5a62e35d19503dcc3 HEAD` +HEAD: **to be bound by Runner**. Output: +```text +M docs/plans/original-completion-2026-10-02/execution/p08-03/CONDITION_MATRIX.md +A docs/plans/original-completion-2026-10-02/execution/p08-03/REPAIR12_CONTEXT_GAP.md +A docs/plans/original-completion-2026-10-02/execution/p08-03/ROOT_NATIVE_R09_COLLECTION_PINS.json +A docs/plans/original-completion-2026-10-02/execution/p08-03/ROOT_R09_COLLECTION_AND_PUBLICATION_DIAGNOSIS.json +A docs/plans/original-completion-2026-10-02/execution/p08-03/ROOT_R09_READONLY_IMAGE_DIMENSIONS.json +M docs/plans/original-completion-2026-10-02/execution/p08-03/implementation.json +A docs/plans/original-completion-2026-10-02/execution/p08-03/repair13-local-source-manifest.json +A docs/plans/original-completion-2026-10-02/execution/p08-03/repair13-local-validation.json +M tools/check_p08_normal_placement_evidence.py +M tools/test_p08_normal_placement_evidence.py +``` +Only the two validators and scoped docs; no fixture, Godot, controller, recorder +or input changes. Repair16 retains the 107 existing tests and adds eight specific +negative controls and one driver-rule positive. +Repair16 local validation: `python3 tools/test_p08_normal_placement_evidence.py` +ran 116 tests in 80.606s: OK, exit0, no failures or skips. No native/OS/full run. +Current validator SHA-256: +- checker: 3b2aeb4f064e08e774997b4548dd966d994dc6a07a2ffb2e233b4c9d7aab24a4 +- tests: 7814ee7a45934ef6929748423c18424478f2634d63dc4979fa056aef3798af4a Executed native source commit: 31aa7706d28a92e313c432d5a62e35d19503dcc3. Current candidate commit: **to be bound by Runner**. @@ -15,8 +50,8 @@ integration pending**. No acceptance or earlier PASS is inherited. Strict reuse checks require the R09 ancestor, complete committed and working-tree whitelists, exact inputs and non-whitelisted sources, R09 validator blobs and SHA-pinned runner/OS receipts and engine bytes. The committed R09..HEAD diff -contains A tests/fixtures/p08-03/repair13_images.py. Deleting the fixture does -not erase that history: applicability fails and a Root re-run is required. +contains only validator and scoped documentation changes after Root finalized +the fixture deletion. The prior Repair14 fixture-addition finding is superseded. No fixture inputs are excluded. JPEG positives use only actual R09 capture bytes, compared to the SHA-pinned @@ -27,20 +62,20 @@ inside the Python test module. Open semantic findings: preview/runtime stair difference; coordinator runtime acceptance=false; Windows same-distribution/device. Required remaining work: -Root R09 positive hash re-check; Root re-run for failed reuse applicability; +Root R09 positive hash re-check; Root final full175; independent Opus review of all five conditions; integration/current final verification/ledger; Windows same-distribution/device (no Mac substitution). The denominator30/88 and immutable spec are unchanged. Repair counter14 is historical; repair/inference/material limits remain null. -Final local validation: python3 tools/test_p08_normal_placement_evidence.py: +Historical Repair14 local validation: python3 tools/test_p08_normal_placement_evidence.py: 107 tests in 84.026 seconds, exit0, no failures or skips. Two Python AST checks and git diff --check passed. Earlier failed helper-renaming attempts were corrected; no native, Godot, full regression or verify-only run occurred. Focused final controls: 18 tests passed, including actual original capture hashes. Root positive re-check remains required. -Validator-only SHA-256: +Historical Repair14 validator-only SHA-256: - tools/check_p08_normal_placement_evidence.py: 301098ced37bf83bd580af8b0a73e32f776157737ec6a55513c8cb5f63cd10f6 - tools/test_p08_normal_placement_evidence.py: 24a6894d7e944f5819641adc1bf2ce7a2fba5b367f1005bbae83775060498283 diff --git a/docs/plans/original-completion-2026-10-02/execution/p08-03/implementation.json b/docs/plans/original-completion-2026-10-02/execution/p08-03/implementation.json index 6ac3d17..882477b 100644 --- a/docs/plans/original-completion-2026-10-02/execution/p08-03/implementation.json +++ b/docs/plans/original-completion-2026-10-02/execution/p08-03/implementation.json @@ -5,7 +5,7 @@ "P08-03" ], "base_commit": "12430ba89970bda349781e51157e72e48a4ac06f", - "actual_worktree_HEAD": "7dde98ccb749cbd1c1b82e066b59350e73191400", + "actual_worktree_HEAD": "to be bound by Runner", "worker_committed": false, "final_commit": null, "final_commit_note": "Root must freeze and record the submitted candidate; worker git writes are prohibited.", @@ -31,10 +31,10 @@ "tests/fixtures/p08-03/placement.gd.uid": "5caca08c1e627e0ca07e2ab7b13bd82b24a22f77513fe87e30b79023568e1987", "tests/ui/test_p08_normal_placement_ops.gd": "d3c246d34f8fd66f6ed237e42a86df89ebaf481bc9dee143b4de8d654ce0eb2e", "tests/ui/test_p08_normal_placement_ops.gd.uid": "7d168ac50ca82ae1979da31c467f9a5020ca5ec7616b5bf99294413d85b3b299", - "tools/check_p08_normal_placement_evidence.py": "301098ced37bf83bd580af8b0a73e32f776157737ec6a55513c8cb5f63cd10f6", + "tools/check_p08_normal_placement_evidence.py": "3b2aeb4f064e08e774997b4548dd966d994dc6a07a2ffb2e233b4c9d7aab24a4", "tools/regression/suite-policy.json": "a74dc701155b6207bc23095296d723928f62719fce14fda392b12f9947007fb1", "tools/run_p08_normal_placement.py": "5cb1f58664a0bec71c8b5e853749d1c3656e0a2a027201e33fbaa6b0c0291fc6", - "tools/test_p08_normal_placement_evidence.py": "24a6894d7e944f5819641adc1bf2ce7a2fba5b367f1005bbae83775060498283", + "tools/test_p08_normal_placement_evidence.py": "7814ee7a45934ef6929748423c18424478f2634d63dc4979fa056aef3798af4a", "docs/plans/original-completion-2026-10-02/execution/p08-03/NATIVE_R02_READER_OPERATION_DELTA.json": "60463e735d4f473bdad7b0925c37b9ca71ee34d6f0eb74ea6c07b508b5153e41", "docs/plans/original-completion-2026-10-02/execution/p08-03/native-r02-reader-stderr.log": "8079b3dc2ba7b9a9c37fcd9a5a8df0971354027c60def4b95fb15c7310832040", "docs/plans/original-completion-2026-10-02/execution/p08-03/OS_R04_INITIAL_LOAD_ORACLE_FINDING.json": "6a796bd63f5a16bd0bf0fcf07cec3f4414a5e6704409a79522a2677eae53b417", @@ -65,8 +65,8 @@ }, "actual_local_validation": { "command": "python3 tools/test_p08_normal_placement_evidence.py", - "tests": 107, - "duration_seconds": 84.026, + "tests": 116, + "duration_seconds": 80.606, "exit_code": 0, "failures": 0, "errors": 0, @@ -89,7 +89,7 @@ "conditions": { "support_connection": { "implementation": "prepared", - "local_checker_controls": "107 pure Python checker tests, exit0; no gameplay acceptance", + "local_checker_controls": "116 pure Python checker tests, exit0; no gameplay acceptance", "actual_Godot_handler": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "actual_native_OS": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "independent_review": "pending", @@ -98,7 +98,7 @@ }, "invalid_position_reason": { "implementation": "prepared", - "local_checker_controls": "107 pure Python checker tests, exit0; no gameplay acceptance", + "local_checker_controls": "116 pure Python checker tests, exit0; no gameplay acceptance", "actual_Godot_handler": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "actual_native_OS": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "independent_review": "pending", @@ -107,7 +107,7 @@ }, "demolish_rebuild": { "implementation": "prepared", - "local_checker_controls": "107 pure Python checker tests, exit0; no gameplay acceptance", + "local_checker_controls": "116 pure Python checker tests, exit0; no gameplay acceptance", "actual_Godot_handler": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "actual_native_OS": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "independent_review": "pending", @@ -116,7 +116,7 @@ }, "pan_zoom_world_identity": { "implementation": "prepared", - "local_checker_controls": "107 pure Python checker tests, exit0; no gameplay acceptance", + "local_checker_controls": "116 pure Python checker tests, exit0; no gameplay acceptance", "actual_Godot_handler": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "actual_native_OS": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "independent_review": "pending", @@ -125,7 +125,7 @@ }, "separate_pid_resume": { "implementation": "prepared", - "local_checker_controls": "107 pure Python checker tests, exit0; no gameplay acceptance", + "local_checker_controls": "116 pure Python checker tests, exit0; no gameplay acceptance", "actual_Godot_handler": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "actual_native_OS": "Root native evidence collected at 31aa; independent semantic acceptance pending; Root final full175 regression pending; integration pending", "independent_review": "pending", @@ -135,7 +135,6 @@ }, "pending": [ "Root R09 positive hash re-check", - "Root re-run required: R09..HEAD committed fixture addition violates reuse whitelist", "Root final full175", "Independent Opus review of all 5 conditions", "Integration/current final verification/ledger", @@ -164,6 +163,26 @@ "P08_01_all30_claimed": false, "formal_acceptance": false, "repair": { + "repair16": { + "status": "submitted", + "target": "Subset-vs-full-env recomputation defect in R09 applicability", + "fixture_deletion": "Root finalized deletion of repair13 fixture omitted by Runner submission; absent from net final diff", + "environment_provenance": "P08_/THE_TREE_ subset is reconstructable and checked by direct equality; full-env environment_sha256 is opaque and checked only by cross-receipt and pin equality, without original os.environ", + "checks": "Pinned bytes/SHA of started, process-started and ended via original index and receipt pins; role/pair/proof paths; retained other equality gates; HEAD and working driver byte-identical to R09_COMMIT", + "net_diff_command": "git diff --name-status --no-renames 31aa7706d28a92e313c432d5a62e35d19503dcc3 HEAD", + "HEAD": "to be bound by Runner", + "net_diff": "Only tools/check_p08_normal_placement_evidence.py, tools/test_p08_normal_placement_evidence.py and scoped p08-03 docs; exact output in CONDITION_MATRIX.md; no fixture, Godot, controller, recorder or input changes", + "test_command": "python3 tools/test_p08_normal_placement_evidence.py", + "test_result": "116 tests in 80.606s, OK, exit0; existing107 unchanged plus8 negatives and1 positive", + "existing_tests_unchanged": 107, + "added_negatives": 8, + "added_driver_rule_positive": 1, + "native_OS_full_runs": false, + "formal_acceptance": false, + "pending": "Root R09 positive hash re-check; Root final full175; independent Opus review all 5 conditions; integration/current final verification/ledger; Windows same-distribution/device (no Mac substitution)", + "open_semantics": "preview/runtime stair difference; coordinator runtime acceptance=false", + "repair_inference_material_limits": null + }, "prior_submitted_commit": "c2b59f04f94dda0a61991ec3bb7f0e946196f995", "failure_authorities": [ "NATIVE_R02_READER_OPERATION_DELTA.json", @@ -363,13 +382,12 @@ "Synthetic JPEG negatives generated inside test module; repair13 fixture removed", "Executed native bindings remain separate from candidate validator hashes" ], - "reuse_applicability": "fails: committed A tests/fixtures/p08-03/repair13_images.py in R09..HEAD", - "root_rerun_needed": true, + "reuse_applicability": "Historical Repair14 finding, superseded by Root-finalized fixture deletion and Repair16; fixture absent from net final diff", + "root_rerun_needed": false, "positive_capture_recheck": "Root pending; local pure Python original-capture check only", "worker_git_writes": false, "pending": [ "Root R09 positive hash re-check", - "Root re-run required: R09..HEAD committed fixture addition violates reuse whitelist", "Root final full175", "Independent Opus review of all 5 conditions", "Integration/current final verification/ledger", @@ -1787,8 +1805,8 @@ }, "current_candidate_commit": "to be bound by Runner", "validator_only_changes": { - "tools/check_p08_normal_placement_evidence.py": "301098ced37bf83bd580af8b0a73e32f776157737ec6a55513c8cb5f63cd10f6", - "tools/test_p08_normal_placement_evidence.py": "24a6894d7e944f5819641adc1bf2ce7a2fba5b367f1005bbae83775060498283" + "tools/check_p08_normal_placement_evidence.py": "3b2aeb4f064e08e774997b4548dd966d994dc6a07a2ffb2e233b4c9d7aab24a4", + "tools/test_p08_normal_placement_evidence.py": "7814ee7a45934ef6929748423c18424478f2634d63dc4979fa056aef3798af4a" }, "semantic_acceptance_findings": { "preview/runtime stair difference": "open", diff --git a/tools/check_p08_normal_placement_evidence.py b/tools/check_p08_normal_placement_evidence.py index 7897e90..aa07e4e 100644 --- a/tools/check_p08_normal_placement_evidence.py +++ b/tools/check_p08_normal_placement_evidence.py @@ -146,6 +146,9 @@ def input_map(root): R09_COMMIT = '31aa7706d28a92e313c432d5a62e35d19503dcc3' R09_DOCS = 'docs/plans/original-completion-2026-10-02/execution/p08-03' +ENVIRONMENT_PROVENANCE = ('The P08_/THE_TREE_ subset is reconstructable and checked by direct equality; ' + 'the full-env environment_sha256 is opaque and checked only by ' + 'cross-receipt and pin equality, without the original os.environ.') VALIDATORS = {'tools/check_p08_normal_placement_evidence.py', 'tools/test_p08_normal_placement_evidence.py'} @@ -202,14 +205,50 @@ def r09_applicability(root, index): require(pinned['commit'] == index['commit'] and pinned['inputs'] == index['inputs'], 'R09 runner binding drift') require(sha(pinned['engine']) == pinned['engine_sha256'], 'R09 engine hash drift') + driver = 'tools/run_p08_normal_placement.py' + baseline = subprocess.check_output(['git', '-C', str(root), 'show', R09_COMMIT+':'+driver]) + head_driver = subprocess.check_output(['git', '-C', str(root), 'show', head+':'+driver]) + r09_driver_bytes(baseline, head_driver, (root/driver).read_bytes()) + original_index = pinned_document(pins['index']) for role in ('writer', 'reader'): receipt = pinned_document(pins['OS'][role]['receipt']) require(receipt['engine_sha256'] == pinned['engine_sha256'], 'R09 engine hash/version drift') - require(receipt['environment_sha256'] == hashlib.sha256( - json.dumps(receipt['environment'], sort_keys=True).encode()).hexdigest(), - 'R09 settings/environment drift') + require(receipt['controller_sha256'] == hashlib.sha256(baseline).hexdigest(), 'R09 controller hash drift') + receipts = [] + for phase in ('started', 'process-started', 'ended'): + name = 'os-runs/'+role+'/'+phase+'.json' + path = original/name + pin = original_index['artifacts'][name] + r09_receipt_bytes(path.read_bytes(), pin) + receipts.append(load(path)) + r09_environment(receipts, receipt, role, original) return {name:sha(root/name) for name in sorted(VALIDATORS)} +def r09_driver_bytes(baseline, head, working): + require(head == baseline == working, 'R09 driver bytes drift') + +def r09_receipt_bytes(data, pin): + require(len(data) == pin['bytes'] and hashlib.sha256(data).hexdigest() == pin['sha256'], + 'R09 receipt bytes drift') + +def r09_environment(receipts, pinned, role, original): + require(all(r['environment'] == receipts[0]['environment'] for r in receipts), + 'R09 environment subset cross-receipt drift') + require(receipts[0]['environment'] == pinned['environment'], 'R09 environment subset pin drift') + require(all(r['environment_sha256'] == receipts[0]['environment_sha256'] for r in receipts), + 'R09 environment hash cross-receipt drift') + require(receipts[0]['environment_sha256'] == pinned['environment_sha256'], 'R09 environment hash pin drift') + for r in receipts: + env = r['environment'] + require(env['P08_PLACEMENT_ROLE'] == r['role'] == role, 'R09 environment role mismatch') + require(env['P08_PLACEMENT_ROOT'] == str(original/'os-pair'), 'R09 environment pair path mismatch') + proof = original/'os-runs'/role/'teardown' + require(env['THE_TREE_AUDIO_TEARDOWN_PROOF_DIR'] == str(proof/'owned-audio') and + env['THE_TREE_AUDIO_FIXTURE_CONTROL_PROOF'] == str(proof/'control.json'), + 'R09 environment proof path mismatch') + for field in ('controller_sha256', 'recorder_sha256', 'engine_sha256', 'command', 'source_map'): + require(r[field] == pinned[field], 'R09 receipt '+field+' drift') + def jpeg_dimensions(data): """Structural validation only; positive validity requires original capture hashes.""" require(data[:2] == b'\xff\xd8' and data[-2:] == b'\xff\xd9', 'invalid JPEG SOI/EOI') @@ -923,7 +962,8 @@ def main(argv=None): return 2 deficits = check(args.project_root, Path(build)/'p08-normal-placement-evidence') print(json.dumps({'task_id': 'P08-03', 'integrity': 'fail' if deficits else 'pass', - 'deficits': deficits, 'acceptance': 'pending'}, ensure_ascii=False)) + 'deficits': deficits, 'acceptance': 'pending', + 'environment_provenance': ENVIRONMENT_PROVENANCE}, ensure_ascii=False)) return 1 if deficits else 0 if __name__ == '__main__': diff --git a/tools/test_p08_normal_placement_evidence.py b/tools/test_p08_normal_placement_evidence.py index 9b8dc20..1d001e0 100644 --- a/tools/test_p08_normal_placement_evidence.py +++ b/tools/test_p08_normal_placement_evidence.py @@ -739,6 +739,67 @@ class R09ApplicabilityTests(unittest.TestCase): C.r09_applicability(ROOT, {'commit':C.R09_COMMIT, 'inputs':{'fixture':'original'}}) +class R16EnvironmentTests(unittest.TestCase): + def setUp(self): + self.original = Path('/recorded/r09') + env = {'PATH':'/opaque/original', 'P08_PLACEMENT_ROLE':'writer', + 'P08_PLACEMENT_ROOT':str(self.original/'os-pair'), + 'THE_TREE_AUDIO_TEARDOWN_PROOF_DIR':str(self.original/'os-runs/writer/teardown/owned-audio'), + 'THE_TREE_AUDIO_FIXTURE_CONTROL_PROOF':str(self.original/'os-runs/writer/teardown/control.json')} + self.pin = {'role':'writer', 'environment':{k:v for k,v in env.items() if k.startswith(('P08_', 'THE_TREE_'))}, + 'environment_sha256':hashlib.sha256(json.dumps(env, sort_keys=True).encode()).hexdigest(), + 'controller_sha256':'driver', 'recorder_sha256':'recorder', 'engine_sha256':'engine', + 'command':['engine', '--script', 'recorder'], 'source_map':{'source':'hash'}} + self.receipts = [copy.deepcopy(self.pin) for _ in range(3)] + + def verify(self): + C.r09_environment(self.receipts, self.pin, 'writer', self.original) + + def test_driver_recording_positive(self): + self.assertNotEqual(self.pin['environment_sha256'], hashlib.sha256( + json.dumps(self.pin['environment'], sort_keys=True).encode()).hexdigest()) + self.verify() + + def test_subset_one_receipt(self): + self.receipts[0]['environment']['P08_PLACEMENT_ROOT'] = '/changed' + with self.assertRaisesRegex(ValueError, 'R09 environment subset cross-receipt drift'): self.verify() + + def test_subset_all_receipts_not_pin(self): + for r in self.receipts: r['environment']['P08_PLACEMENT_ROOT'] = '/changed' + with self.assertRaisesRegex(ValueError, 'R09 environment subset pin drift'): self.verify() + + def test_hash_started_ended_difference(self): + self.receipts[0]['environment_sha256'] = '0'*64 + with self.assertRaisesRegex(ValueError, 'R09 environment hash cross-receipt drift'): self.verify() + + def test_hash_all_receipts_not_pin(self): + for r in self.receipts: r['environment_sha256'] = '0'*64 + with self.assertRaisesRegex(ValueError, 'R09 environment hash pin drift'): self.verify() + + def test_receipt_bytes_not_pin(self): + data = json.dumps(self.pin).encode() + pin = {'bytes':len(data), 'sha256':hashlib.sha256(data).hexdigest()} + C.r09_receipt_bytes(data, pin) + with self.assertRaisesRegex(ValueError, 'R09 receipt bytes drift'): + C.r09_receipt_bytes(data.replace(b'writer', b'reader'), pin) + + def test_role_mismatch(self): + for r in [self.pin]+self.receipts: r['environment']['P08_PLACEMENT_ROLE'] = 'reader' + with self.assertRaisesRegex(ValueError, 'R09 environment role mismatch'): self.verify() + + def test_proof_path_mismatch(self): + for field in ('THE_TREE_AUDIO_TEARDOWN_PROOF_DIR', 'THE_TREE_AUDIO_FIXTURE_CONTROL_PROOF'): + with self.subTest(field=field): + self.setUp() + for r in [self.pin]+self.receipts: r['environment'][field] = '/wrong' + with self.assertRaisesRegex(ValueError, 'R09 environment proof path mismatch'): self.verify() + + def test_driver_changed_at_head(self): + C.r09_driver_bytes(b'original', b'original', b'original') + with self.assertRaisesRegex(ValueError, 'R09 driver bytes drift'): + C.r09_driver_bytes(b'original', b'changed', b'original') + + class RealR05InfrastructureTests(unittest.TestCase): """Actual native snapshot, never a fabricated acceptance specimen.""" def setUp(self):