diff --git a/notes/agent-45-task-card.md b/notes/agent-45-task-card.md new file mode 100644 index 0000000000..ad148123eb --- /dev/null +++ b/notes/agent-45-task-card.md @@ -0,0 +1,70 @@ +# Local task card — agent-45 (written before substantial computation) + +Task ID / proposed scope key: `uniform-transfer-audit` (chooser scope key `603f341b99f590f17a76`), +refined to the hosted-template post-emit field-contract read-set audit. +Track: adversarial-audit. Chooser nonce: `2bb90ec128a184bdec47e263785b9c5d` (OS-random draw, +priority revision 4, catalogue SHA-256 `d46eb6d5b3e279428753d770653663fbdf1063e55c255ea073d768f344927ef7`). + +Base commit; exact predecessor and dependency heads: +- Base main `0fdd7d82de03e43c9e5a1000dfbcd380d1b687d2`; selected-record SHA-256 `10b9e340fd8e354a37a0c4813c90e5de1dd42044b5f6aca4a3fc5a42b685fa32`. +- Predecessor: Josie Elliston's PR1959 `research/t16-audit-mutant-coverage` (on main at base), + whose README records the exact claim audited here and labels it "a text search, not a proof". +- Adjacent concurrent work: PR2158 `research/invoice-mutant-coverage` (invoice `run()` mutation + testing; different object and method — dynamic mutation of invoice predicates vs static + read-set/whole-object channel audit across all pinned post-emit consumers). + +Concrete object and question: +The frozen PR1087 `code/audit_allcold.py` acceptance audit does not read 15 hosted-template +fields (`cover`, `m`, `version`, `port_restriction`, `provider_dispatch`, `replica_lift`, +`route_semantics`, `supplier_substitution`, `expanded_scalar_interface`, +`hosting.{rule, scope, idle_remainder_semantics, owner_map_sha256}`, +`async_schedule.{scope, source_plan_sha256}`). PR1959 asserts by text search that no stage +after `emit_allcold.py` reads any of them. Question: is that claim machine-checkable over the +pinned consumer universe (frozen PR1087 archive `code/` + maintainer frontier1094 scripts), +and through which whole-object channels (hash binding, serialization, iteration, equality) +could a change to those 15 fields still reach a post-emit acceptance decision? + +Scope status: refined; reason: the card asks for one exact hosting/transfer implication with +explicit quantified hypotheses; the refined object is one named claim ("no post-emit reader of +the 15 audit-unread fields") whose downstream consequence is the template acceptance boundary. + +Existing restriction being changed (or exact claim being audited): +Exact claim audited: research/t16-audit-mutant-coverage/README.md, "Accepted: 19 path mutations" +bullet ("A text search of the PR1087 archive and the maintainer frontier1094 scripts finds no +reader of the 15 unread fields in the hosted template after `emit`. This is a text search, not +a proof."). No restriction is changed; the audit upgrades the evidence class. + +Method; explicit parameter ranges/candidate alphabet: +stdlib-only AST read-set analysis (Python `ast`): every constant string equal to one of the 15 +names in every pinned file is classified by syntactic context (subscript key, attribute, call +argument of `get`/`pop`/`setdefault`, plain string, other); every dynamic-access site +(`x[name]`, `getattr(x, name)`, `**` unpacking, whole-object iteration/serialization/hash/ +comparison) is enumerated per file. Universe: all `.py` members of +`research/complex-t16-rare-pattern-exchanges/upstream1087.tar.gz` (SHA-256 pinned) plus +`scripts/verify_frontier1094*.py` and `research/community-batch1099-audit/check_frontier1094.py` +and the selected stage wrapper `research/complex-t16-rare-pattern-exchanges/verify.py`. +Falsification first: any name-directed post-emit read or unresolvable dynamic access falsifies +the claim at the smallest instance (the exact file/line). + +Nearest overlapping PRs and why this adds something: +- PR1959 (merged): raised the gap and left it as a text search; open question 2 is a different + (driver-binding) item blocked on a maintainer decision. This adds the missing machine check. +- PR2158 (open): dynamic mutation of `invoice_allcold.py` predicates; mine is a static, + universe-complete channel map over all post-emit consumers, and states exactly which channels + mutation testing can and cannot reach. + +Optimistic full cost budget; required observable improvement: +No kappa/supplier claim. Deliverable is a checked statement + channel map with pinned hashes; +cost is bounded by universe size (a few dozen source files); runtime target well under 60 s. + +Success evidence; falsification test; time/compute cap: +Success: `verify.py` prints PASS with EXPECTED.json equality over the pinned universe; a +corruption control (a name-directed read injected into a scratch copy) flips the result. +Falsification: a single name-directed post-emit read of any of the 15 names, or a dynamic access +that cannot be resolved from constants. Compute cap: seconds per run; one bounded pivot maximum. + +Predecessor authors; intended artifact and reproduction command: +Josie Elliston (PR1959); Jeremy Kothe (PR1087/PR870 frozen code); Rohan Arun (PR1094 selected +run); agent-43/Aaron Wang (PR2158, adjacent). Intended artifact: `research/hosted-template-postemit-fields/` +(README, TASK.json, SOURCES.json, VERIFY.json, verify.py, EXPECTED.json). Reproduce: +`python3 -B research/hosted-template-postemit-fields/verify.py`. diff --git a/research/hosted-template-postemit-fields/EXPECTED.json b/research/hosted-template-postemit-fields/EXPECTED.json new file mode 100644 index 0000000000..2cc661f078 --- /dev/null +++ b/research/hosted-template-postemit-fields/EXPECTED.json @@ -0,0 +1,1064 @@ +{ + "archive_sha256": "d4acf04daef85d4514f80ec5fcd2492d0c60e5d6c49fa71b3e6523f8db2dea86", + "channel_pins": [ + [ + "archive:code/audit_allcold.py", + "assert hashlib.sha256(raw).hexdigest()==summary['template_sha256']" + ], + [ + "archive:code/invoice_allcold.py", + "assert template_hash==control['complex_template_sha256']==owners['template_sha256']==summary['template_sha256']" + ], + [ + "archive:code/invoice_allcold.py", + "template_hash=contenthash(template_path)" + ] + ], + "post_emit_closure": { + "code/assemble.py": "15f6986a476bac76bcdc0bfcf51da115389b46f1950d2766b6822f757888b13a", + "code/assembly_controls.py": "da7e981ae1b9f099d4e1524cb4f3ba1116011936ebe378692889b5dbfa99029d", + "code/audit_allcold.py": "1467a2acb654e62552c69fb9a7c4c85f70a02120881d222313865058ab71a6cc", + "code/bit_supplier_controls.py": "e6d33fb61a570c3f50669412acc467a3fd06ef0b806da6a75bc296c6ba2142a5", + "code/generated_identity.py": "c8af22719c0f3097a991a3f6ccac8f090afd2faba554745733d9ea88f2c25708", + "code/invoice_allcold.py": "71eb57514e28ced97251e0507105f654f59885ec4d40486a780bf166098858a8", + "code/witness.py": "779c5172894b992131e85be1e592ed2a1aec8c287b872ff42007d36a7291e444" + }, + "post_emit_dynamic_sites": { + "code/assemble.py": [], + "code/assembly_controls.py": [], + "code/audit_allcold.py": [ + { + "code": "assert t['local_providers']==registry and t['recipe']==parent['recipe']and 'each local invocation completes before the next' in t['loop_order'].lower()", + "keys": null, + "kind": "compare-operand", + "line": 94, + "on": "t.local_providers" + }, + { + "code": "assert t['local_providers']==registry and t['recipe']==parent['recipe']and 'each local invocation completes before the next' in t['loop_order'].lower()", + "keys": null, + "kind": "compare-operand", + "line": 94, + "on": "t.recipe" + }, + { + "code": "assert not any(k in t for k in('local_programs','exact_local_clifford_recipe_sha256','residual_adapter_sha256'))", + "keys": null, + "kind": "compare-operand", + "line": 95, + "on": "t" + }, + { + "code": "assert len(t['calls'])==144 and t['hosting']['max_helpers_per_physical_family_per_call']==1 and t['hosting']['banks']==[0]*9", + "keys": null, + "kind": "compare-operand", + "line": 96, + "on": "t.hosting.banks" + }, + { + "code": "assert len(t['calls'])==144 and t['hosting']['max_helpers_per_physical_family_per_call']==1 and t['hosting']['banks']==[0]*9", + "keys": null, + "kind": "compare-operand", + "line": 96, + "on": "t.hosting.max_helpers_per_physical_family_per_call" + }, + { + "code": "assert len(t['calls'])==144 and t['hosting']['max_helpers_per_physical_family_per_call']==1 and t['hosting']['banks']==[0]*9", + "keys": null, + "kind": "convert-of-arg", + "line": 96, + "on": "t.calls" + }, + { + "code": "for key in('exact_data_phase_recipe_sha256','adapter_policy'):assert t[key]==parent[key]", + "keys": [ + "adapter_policy", + "exact_data_phase_recipe_sha256" + ], + "kind": "subscript-bounded-top", + "line": 97, + "on": "t keys=adapter_policy,exact_data_phase_recipe_sha256" + }, + { + "code": "assert t['exact_data_phase_recipe_sha256']==sha(BASE/'work/complex-nine-native/DATA-PHASES.json')", + "keys": null, + "kind": "compare-operand", + "line": 98, + "on": "t.exact_data_phase_recipe_sha256" + }, + { + "code": "src=parent['execution_schedule'];assert t['async_schedule']['source_schedule']==src", + "keys": null, + "kind": "compare-operand", + "line": 100, + "on": "t.async_schedule.source_schedule" + }, + { + "code": "assert t['async_schedule']['source_call_order']==[[c['stage'],c['replica']]for c in parent['calls']]", + "keys": null, + "kind": "compare-operand", + "line": 101, + "on": "t.async_schedule.source_call_order" + }, + { + "code": "order=[(c['stage'],c['replica'])for c in t['calls']]", + "keys": null, + "kind": "iter-path", + "line": 102, + "on": "t.calls" + }, + { + "code": "assert [list(x)for x in order]==t['async_schedule']['order'] and len(set(order))==144", + "keys": null, + "kind": "compare-operand", + "line": 103, + "on": "t.async_schedule.order" + }, + { + "code": "for e in t['execution_schedule']:", + "keys": null, + "kind": "iter-path", + "line": 105, + "on": "t.execution_schedule" + }, + { + "code": "assert all('replica'in e for e in t['execution_schedule'][:-2])", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 122, + "on": "t.execution_schedule" + }, + { + "code": "assert [e['source_event']for e in t['execution_schedule'][-2:]]==[30,31]", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 123, + "on": "t.execution_schedule" + }, + { + "code": "for e in t['execution_schedule'][:-2]:", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 127, + "on": "t.execution_schedule" + }, + { + "code": "assert t['bank_padding']==dict(parent['bank_padding'],families=[],children=[])", + "keys": null, + "kind": "compare-operand", + "line": 130, + "on": "t.bank_padding" + }, + { + "code": "assert t['cover_final_correction']==dict(parent['cover_final_correction'],families=[0,DATA],charged_calls_per_cover=DATA)", + "keys": null, + "kind": "compare-operand", + "line": 131, + "on": "t.cover_final_correction" + }, + { + "code": "assert t['private_namespace']=={'centers':[DATA,DATA+CENTRES],'reserved_tableau':[DATA+CENTRES,DATA+CENTRES+R],'coefficient':[DATA+CENTRES+R,PHYSICAL]}", + "keys": null, + "kind": "compare-operand", + "line": 132, + "on": "t.private_namespace" + }, + { + "code": "for call in t['calls']:", + "keys": null, + "kind": "iter-path", + "line": 146, + "on": "t.calls" + }, + { + "code": "assert len(t['hosting']['pooled_slots'])==HOSTED", + "keys": null, + "kind": "convert-of-arg", + "line": 169, + "on": "t.hosting.pooled_slots" + }, + { + "code": "for z in t['hosting']['pooled_slots']:", + "keys": null, + "kind": "iter-path", + "line": 170, + "on": "t.hosting.pooled_slots" + }, + { + "code": "assert len({(z['stage'],z['replica'],z['helper'])for z in t['hosting']['pooled_slots']})==HOSTED", + "keys": null, + "kind": "iter-path", + "line": 173, + "on": "t.hosting.pooled_slots" + }, + { + "code": "assert t['idle_children']==wanted", + "keys": null, + "kind": "compare-operand", + "line": 181, + "on": "t.idle_children" + }, + { + "code": "q=copy.deepcopy(ct);mut(q)", + "keys": null, + "kind": "deepcopy-of-arg", + "line": 190, + "on": "ct" + }, + { + "code": "enter=lambda q:next(o for c in q['calls']for o in c['owners'][(2*V):]if o[1][0]==4)", + "keys": null, + "kind": "iter-path", + "line": 194, + "on": "q.calls" + }, + { + "code": "reject('alias two whole owners',lambda q:q['calls'][0]['owners'].__setitem__((2*V+1),q['calls'][0]['owners'][(2*V)]))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 195, + "on": "q.calls" + }, + { + "code": "reject('alias two whole owners',lambda q:q['calls'][0]['owners'].__setitem__((2*V+1),q['calls'][0]['owners'][(2*V)]))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 195, + "on": "q.calls" + }, + { + "code": "reject('helper on active data family',lambda q:q['calls'][0]['owners'][(2*V)].__setitem__(0,q['calls'][0]['owners'][0][0]))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 196, + "on": "q.calls" + }, + { + "code": "reject('helper on active data family',lambda q:q['calls'][0]['owners'][(2*V)].__setitem__(0,q['calls'][0]['owners'][0][0]))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 196, + "on": "q.calls" + }, + { + "code": "reject('owner in private namespace',lambda q:q['calls'][0]['owners'][(2*V)].__setitem__(0,DATA))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 197, + "on": "q.calls" + }, + { + "code": "at_p=lambda q:next(c for c in q['calls']if c['provider_id']==P)", + "keys": null, + "kind": "iter-path", + "line": 205, + "on": "q.calls" + }, + { + "code": "reject(P+': stale serialized provider program',lambda q:q['local_providers'][P]['local_programs']['forward'].pop())", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 209, + "on": "q.local_providers" + }, + { + "code": "reject(P+': unbound residual adapter hash',lambda q:q['local_providers'][P].__setitem__('residual_adapter_sha256','0'*64))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 210, + "on": "q.local_providers" + }, + { + "code": "reject(P+': wrong provider width registry',lambda q:q['local_providers'][P]['widths'].__setitem__(narrow,providers[P]['widths'][narrow]-1))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 211, + "on": "q.local_providers" + }, + { + "code": "reject(P+': wrong sweep provider',lambda q:next(e for e in q['execution_schedule']if e['kind']=='local_cover_sweep').__setitem__('provider_id','__unregistered__", + "keys": null, + "kind": "iter-path", + "line": 213, + "on": "q.execution_schedule" + }, + { + "code": "reject(P+': entering helper width silently restored to nine',lambda q:q['local_providers'][P]['widths'].__setitem__(narrow,9))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 214, + "on": "q.local_providers" + }, + { + "code": "at_p=lambda q,P=P:next(c for c in q['calls']if c['provider_id']==P)", + "keys": null, + "kind": "iter-path", + "line": 219, + "on": "q.calls" + }, + { + "code": "reject(P+': stale serialized provider program',lambda q,P=P,Qp=Qp:q['local_providers'][P].__setitem__('local_programs',registry[Qp]['local_programs']))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 224, + "on": "q.local_providers" + }, + { + "code": "reject(P+': unbound residual adapter hash',lambda q,P=P:q['local_providers'][P].__setitem__('residual_adapter_sha256','0'*64))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 225, + "on": "q.local_providers" + }, + { + "code": "if diff:reject(P+': partner width in provider width registry',lambda q,P=P,Qp=Qp,h=diff[0]:q['local_providers'][P]['widths'].__setitem__(h,providers[Qp]['widths", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 226, + "on": "q.local_providers" + }, + { + "code": "reject(P+': wrong sweep provider',lambda q,P=P,Qp=Qp:next(e for e in q['execution_schedule']if e['kind']=='local_cover_sweep'and DISPATCH[e['stage'],e['replica'", + "keys": null, + "kind": "iter-path", + "line": 228, + "on": "q.execution_schedule" + }, + { + "code": "reject(P+': entering helper width silently restored to nine',lambda q,P=P,h=narrow:q['local_providers'][P]['widths'].__setitem__(h,9))", + "keys": null, + "kind": "subscript-dynamic-path", + "line": 229, + "on": "q.local_providers" + }, + { + "code": "report=dict(status='PASS_INDEPENDENT_ASYNC_WHOLE_OWNER_CONTROLLER_PHASES_AND_SPECTATORS',template_sha256=summary['template_sha256'],complex_template_sha256=summ", + "keys": null, + "kind": "iter-path", + "line": 231, + "on": "ct.calls" + }, + { + "code": "for z in ct['idle_children']:", + "keys": null, + "kind": "iter-path", + "line": 241, + "on": "ct.idle_children" + } + ], + "code/bit_supplier_controls.py": [], + "code/generated_identity.py": [], + "code/invoice_allcold.py": [ + { + "code": "assert template['recipe']==parent['recipe']", + "keys": null, + "kind": "compare-operand", + "line": 177, + "on": "template.recipe" + }, + { + "code": "assert 'local_programs' not in template", + "keys": null, + "kind": "compare-operand", + "line": 178, + "on": "template" + }, + { + "code": "assert set(template['local_providers'])==set(PIDS)", + "keys": null, + "kind": "convert-of-arg", + "line": 179, + "on": "template.local_providers" + }, + { + "code": "call_count=len(template['calls'])", + "keys": null, + "kind": "convert-of-arg", + "line": 199, + "on": "template.calls" + }, + { + "code": "assert len({(c['stage'],c['replica']) for c in template['calls']})==call_count", + "keys": null, + "kind": "iter-path", + "line": 202, + "on": "template.calls" + }, + { + "code": "sweeps=[e for e in template['execution_schedule'] if e['kind']=='local_cover_sweep']", + "keys": null, + "kind": "iter-path", + "line": 204, + "on": "template.execution_schedule" + }, + { + "code": "for c in template['calls']:", + "keys": null, + "kind": "iter-path", + "line": 209, + "on": "template.calls" + }, + { + "code": "by_call={(c['stage'],c['replica']):c for c in template['calls']}", + "keys": null, + "kind": "iter-path", + "line": 227, + "on": "template.calls" + }, + { + "code": "bridge_sweeps=sum(event['kind']=='bridge' for event in template['execution_schedule'])", + "keys": null, + "kind": "iter-path", + "line": 236, + "on": "template.execution_schedule" + } + ], + "code/witness.py": [] + }, + "post_emit_name_sites": { + "code/assemble.py": [ + { + "access": "construct", + "code": "return dict(status='PASS_GAUGE44_NATIVE_EXACT_GLOBAL_ASSEMBLY',kappa=str(k),kappa_decimal=dec(k),complex_lower=str(b),complex_decimal=dec(b),bit_lower=str(c),bi", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 234, + "name": "scope" + } + ], + "code/assembly_controls.py": [ + { + "access": "construct", + "code": "scope='Complete receipt schema; ordered widths and both reflected providers; exact program, work and paid-profile binding; independently recounted compiler, con", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 246, + "name": "scope" + } + ], + "code/audit_allcold.py": [ + { + "access": "construct", + "code": "report=dict(status='PASS_INDEPENDENT_ASYNC_WHOLE_OWNER_CONTROLLER_PHASES_AND_SPECTATORS',template_sha256=summary['template_sha256'],complex_template_sha256=summ", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 231, + "name": "scope" + }, + { + "access": "construct", + "code": "scope='Actual orthogonal axes after the independently checked whole-owner prefix in each inherited pending child.')", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 253, + "name": "scope" + } + ], + "code/bit_supplier_controls.py": [], + "code/generated_identity.py": [], + "code/invoice_allcold.py": [ + { + "access": "construct", + "code": "scope='Actual call-specific mixed scalar, Horner, wrappers and paid children recounted. All three providers use fresh hash-bound independent all-column/frame/ph", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 310, + "name": "scope" + } + ], + "code/witness.py": [] + }, + "template_vars": { + "code/assemble.py": [], + "code/assembly_controls.py": [], + "code/audit_allcold.py": [ + "ct", + "t", + "q" + ], + "code/bit_supplier_controls.py": [], + "code/generated_identity.py": [], + "code/invoice_allcold.py": [ + "template" + ], + "code/witness.py": [] + }, + "universe_name_sites": { + "archive:code/assemble.py": [ + { + "access": "construct", + "code": "return dict(status='PASS_GAUGE44_NATIVE_EXACT_GLOBAL_ASSEMBLY',kappa=str(k),kappa_decimal=dec(k),complex_lower=str(b),complex_decimal=dec(b),bit_lower=str(c),bi", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 234, + "name": "scope" + } + ], + "archive:code/assembly_controls.py": [ + { + "access": "construct", + "code": "scope='Complete receipt schema; ordered widths and both reflected providers; exact program, work and paid-profile binding; independently recounted compiler, con", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 246, + "name": "scope" + } + ], + "archive:code/audit_allcold.py": [ + { + "access": "construct", + "code": "report=dict(status='PASS_INDEPENDENT_ASYNC_WHOLE_OWNER_CONTROLLER_PHASES_AND_SPECTATORS',template_sha256=summary['template_sha256'],complex_template_sha256=summ", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 231, + "name": "scope" + }, + { + "access": "construct", + "code": "scope='Actual orthogonal axes after the independently checked whole-owner prefix in each inherited pending child.')", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 253, + "name": "scope" + } + ], + "archive:code/bind_providers_portable.py": [ + { + "access": "construct", + "code": "receipt=dict(status='PASS_FROZEN_048_ALLCOLD_DISPATCH_FRESH_PROVIDER_BINDING',source_plan_sha256=sha(a.plan),runtime_plan_sha256=sha(a.out/'PLAN.json'),provider", + "context": "dict-or-call-keyword", + "field": "async_schedule.source_plan_sha256", + "line": 65, + "name": "source_plan_sha256" + } + ], + "archive:code/emit_allcold.py": [ + { + "access": "construct", + "code": "t.update(version='round20-R%d-asynchronous-whole-owner-v1'%R,live=DATA,physical=physical,idle_children=newidle,private_namespace={'centers':[DATA,DATA+C],'reser", + "context": "dict-or-call-keyword", + "field": "version", + "line": 100, + "name": "version" + }, + { + "access": "construct", + "code": "t['hosting']=dict(rule='one-helper-per-physical-family-per-complete-invocation',max_helpers_per_physical_family_per_call=1,scope='asynchronously interleaved dat", + "context": "dict-or-call-keyword", + "field": "hosting.idle_remainder_semantics", + "line": 101, + "name": "idle_remainder_semantics" + }, + { + "access": "construct", + "code": "t['hosting']=dict(rule='one-helper-per-physical-family-per-complete-invocation',max_helpers_per_physical_family_per_call=1,scope='asynchronously interleaved dat", + "context": "dict-or-call-keyword", + "field": "hosting.owner_map_sha256", + "line": 101, + "name": "owner_map_sha256" + }, + { + "access": "construct", + "code": "t['hosting']=dict(rule='one-helper-per-physical-family-per-complete-invocation',max_helpers_per_physical_family_per_call=1,scope='asynchronously interleaved dat", + "context": "dict-or-call-keyword", + "field": "hosting.rule", + "line": 101, + "name": "rule" + }, + { + "access": "construct", + "code": "t['hosting']=dict(rule='one-helper-per-physical-family-per-complete-invocation',max_helpers_per_physical_family_per_call=1,scope='asynchronously interleaved dat", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 101, + "name": "scope" + }, + { + "access": "read", + "code": "t['route_semantics']['helper']='Whole physical family may belong to another replica; actual orthogonal port basis followed by residual/spectator coordinate perm", + "context": "subscript-key", + "field": "route_semantics", + "line": 102, + "name": "route_semantics" + }, + { + "access": "construct", + "code": "t['async_schedule']=dict(order=[list(x)for x in call_order],source_plan_sha256=hashlib.sha256(PLAN.read_bytes().replace(b'\\r\\n',b'\\n')).hexdigest(),source_sched", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 132, + "name": "scope" + }, + { + "access": "construct", + "code": "t['async_schedule']=dict(order=[list(x)for x in call_order],source_plan_sha256=hashlib.sha256(PLAN.read_bytes().replace(b'\\r\\n',b'\\n')).hexdigest(),source_sched", + "context": "dict-or-call-keyword", + "field": "async_schedule.source_plan_sha256", + "line": 132, + "name": "source_plan_sha256" + }, + { + "access": "write", + "code": "t['provider_dispatch']='For each indivisible local_cover_sweep, execute local_providers[call.provider_id].local_programs[call.orientation] with that provider re", + "context": "subscript-key", + "field": "provider_dispatch", + "line": 137, + "name": "provider_dispatch" + }, + { + "access": "construct", + "code": "scope='Two actual verified plain/width-seven providers dispatched per complete invocation; independent controller/spectator/normalization and complete finite in", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 149, + "name": "scope" + } + ], + "archive:code/invoice_allcold.py": [ + { + "access": "construct", + "code": "scope='Actual call-specific mixed scalar, Horner, wrappers and paid children recounted. All three providers use fresh hash-bound independent all-column/frame/ph", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 310, + "name": "scope" + } + ], + "archive:code/prepare_global.py": [ + { + "access": "construct", + "code": "source_plan_sha256=sha(parent_path),", + "context": "dict-or-call-keyword", + "field": "async_schedule.source_plan_sha256", + "line": 105, + "name": "source_plan_sha256" + } + ], + "archive:code/restore_parent.py": [ + { + "access": "construct", + "code": "word.update(version='round20-new-supplier-dedicated-bank-parent-v1',live=live,physical=physical,local_programs=programs)", + "context": "dict-or-call-keyword", + "field": "version", + "line": 36, + "name": "version" + }, + { + "access": "write", + "code": "word['supplier_substitution']={'parent_template_sha256':sha(parent),", + "context": "subscript-key", + "field": "supplier_substitution", + "line": 58, + "name": "supplier_substitution" + }, + { + "access": "read", + "code": "word['route_semantics']['helper']='Dedicated family DATA+stage*R+helper; one helper per bank per complete invocation. Width-nine route[2,replica] uses axes9*rep", + "context": "subscript-key", + "field": "route_semantics", + "line": 62, + "name": "route_semantics" + } + ], + "archive:construction/construct_gauge_xcentre.py": [ + { + "access": "construct", + "code": "'h':9,'v':112,'R':NH,'cst':64,'m':73,'local_profile':dict(sorted(H.items())),", + "context": "dict-literal-key", + "field": "m", + "line": 368, + "name": "m" + }, + { + "access": "construct", + "code": "'local_rank_mass':sum(r*n for r,n in H.items()),'scope':'Clean scalar identity and all literal monotone local frames only; arbitrary-dirt compensation, entrance", + "context": "dict-literal-key", + "field": "hosting.scope", + "line": 371, + "name": "scope" + } + ], + "archive:construction/layers/build_pivot_swap.py": [ + { + "access": "construct", + "code": "scope='Exact family rewrite, exact zero dirty response of every new pivot, identical paid profile and widths, '", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 158, + "name": "scope" + } + ], + "archive:construction/leaver/cgx_leaver.py": [ + { + "access": "opaque", + "code": "done.add((t,blk));items.append(('m',t,maps[blk][ev[0]],q,blk,True))", + "context": "type:Tuple", + "field": "m", + "line": 279, + "name": "m" + }, + { + "access": "opaque", + "code": "items.append(('m',t,evinfo(blk)[0],q,blk,True))", + "context": "type:Tuple", + "field": "m", + "line": 295, + "name": "m" + }, + { + "access": "test", + "code": "k0=min(i for i,x in enumerate(items) if x[0]=='m' and x[4]==blk)", + "context": "membership-or-compare", + "field": "m", + "line": 298, + "name": "m" + }, + { + "access": "test", + "code": "if k=='m':return evi[0] in used", + "context": "membership-or-compare", + "field": "m", + "line": 314, + "name": "m" + }, + { + "access": "construct", + "code": "'h':9,'v':112,'R':NH,'cst':64,'m':73,'local_profile':dict(sorted(H.items())),", + "context": "dict-literal-key", + "field": "m", + "line": 478, + "name": "m" + }, + { + "access": "construct", + "code": "'local_rank_mass':sum(r*n for r,n in H.items()),'scope':'Clean scalar identity and all literal monotone local frames only; arbitrary-dirt compensation, entrance", + "context": "dict-literal-key", + "field": "hosting.scope", + "line": 481, + "name": "scope" + } + ], + "archive:construction/notri/cgx.py": [ + { + "access": "opaque", + "code": "done.add((t,blk));items.append(('m',t,maps[blk][ev[0]],q,blk,True))", + "context": "type:Tuple", + "field": "m", + "line": 260, + "name": "m" + }, + { + "access": "opaque", + "code": "items.append(('m',t,evinfo(blk)[0],q,blk,True))", + "context": "type:Tuple", + "field": "m", + "line": 276, + "name": "m" + }, + { + "access": "test", + "code": "k0=min(i for i,x in enumerate(items) if x[0]=='m' and x[4]==blk)", + "context": "membership-or-compare", + "field": "m", + "line": 279, + "name": "m" + }, + { + "access": "test", + "code": "if k=='m':return evi[0] in used", + "context": "membership-or-compare", + "field": "m", + "line": 295, + "name": "m" + }, + { + "access": "construct", + "code": "'h':9,'v':112,'R':NH,'cst':64,'m':73,'local_profile':dict(sorted(H.items())),", + "context": "dict-literal-key", + "field": "m", + "line": 456, + "name": "m" + }, + { + "access": "construct", + "code": "'local_rank_mass':sum(r*n for r,n in H.items()),'scope':'Clean scalar identity and all literal monotone local frames only; arbitrary-dirt compensation, entrance", + "context": "dict-literal-key", + "field": "hosting.scope", + "line": 459, + "name": "scope" + } + ], + "archive:construction/notri/port_stage_x.py": [ + { + "access": "construct", + "code": "scope='Transfer construction only; exactness, frame chains and profile are certified by the native audit run on the output.')", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 121, + "name": "scope" + } + ], + "archive:hosting/expand_owners.py": [ + { + "access": "construct", + "code": "'source_plan':str(a.plan),'source_plan_sha256':sha(a.plan),'source_owners':str(a.owners),'source_owners_sha256':sha(a.owners),", + "context": "dict-literal-key", + "field": "async_schedule.source_plan_sha256", + "line": 172, + "name": "source_plan_sha256" + } + ], + "archive:hosting/reproduce.py": [ + { + "access": "construct", + "code": "'scope': 'Exact hosting nomination and callwise fixed-point replay; full supplier admission is separate.',", + "context": "dict-literal-key", + "field": "hosting.scope", + "line": 93, + "name": "scope" + } + ], + "archive:hosting/reuse_owners.py": [ + { + "access": "construct", + "code": "'source_plan':str(a.plan),'source_plan_sha256':sha(a.plan),'source_owners_sha256':sha(a.owners),", + "context": "dict-literal-key", + "field": "async_schedule.source_plan_sha256", + "line": 216, + "name": "source_plan_sha256" + } + ], + "archive:independent/audit_local.py": [ + { + "access": "construct", + "code": "scope='Exact rational full scalar map in both orientations; all literal native frame chains, center levels, dyadic units, entrance-zero response, wrapper exclus", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 162, + "name": "scope" + } + ], + "archive:independent/price_profile.py": [ + { + "access": "construct", + "code": "global_profile=H, live=7168, m=73, rank_mass=sum(r*n for r, n in H.items()), deficit=2560,", + "context": "dict-or-call-keyword", + "field": "m", + "line": 151, + "name": "m" + }, + { + "access": "construct", + "code": "scope='Independent arithmetic for the exact nominated all72 profile. Complete local, controller and finite invoice admission are separately replayed by the pack", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 155, + "name": "scope" + } + ], + "archive:independent/review_guards.py": [ + { + "access": "construct", + "code": "scope='Exact syntax preservation for all admission assertions in these five files. The changed emitter/controller centre boundary and single-provider controls r", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 40, + "name": "scope" + } + ], + "archive:t16/build_parent.py": [ + { + "access": "read", + "code": "require(source['m'] == 73, 'source dimension')", + "context": "subscript-key", + "field": "m", + "line": 63, + "name": "m" + }, + { + "access": "construct", + "code": "version='t16-direct-sum-two-bank-groups-parent-v1')", + "context": "dict-or-call-keyword", + "field": "version", + "line": 116, + "name": "version" + }, + { + "access": "read", + "code": "t['route_semantics']['helper'] = (", + "context": "subscript-key", + "field": "route_semantics", + "line": 117, + "name": "route_semantics" + }, + { + "access": "write", + "code": "t['replica_lift'] = dict(", + "context": "subscript-key", + "field": "replica_lift", + "line": 126, + "name": "replica_lift" + }, + { + "access": "construct", + "code": "source_plan_sha256=source_plan_sha, source_owners_sha256=source_owners_sha,", + "context": "dict-or-call-keyword", + "field": "async_schedule.source_plan_sha256", + "line": 212, + "name": "source_plan_sha256" + }, + { + "access": "write", + "code": "p['replica_lift'] = dict(groups=2, source_replicas=8, replicas=16,", + "context": "subscript-key", + "field": "replica_lift", + "line": 226, + "name": "replica_lift" + }, + { + "access": "construct", + "code": "source_plan_sha256=sha(args.source_plan), source_owners_sha256=sha(args.source_owners),", + "context": "dict-or-call-keyword", + "field": "async_schedule.source_plan_sha256", + "line": 264, + "name": "source_plan_sha256" + }, + { + "access": "construct", + "code": "scope='Legal direct-sum parent namespace and actual source-event windows; full global emitter, geometry, finite invoice, and recurrence admission remain separat", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 275, + "name": "scope" + } + ], + "archive:t16/indep16.py": [ + { + "access": "construct", + "code": "scope='Finite role/window/chart and inherited prefix/row obligations. Requires separately admitted local supplier and emitted controller, complete finite invoic", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 239, + "name": "scope" + } + ], + "archive:t16/lift16.py": [ + { + "access": "construct", + "code": "source_plan_sha256=plan_sha, source_owners_sha256=owners8_sha,", + "context": "dict-or-call-keyword", + "field": "async_schedule.source_plan_sha256", + "line": 52, + "name": "source_plan_sha256" + }, + { + "access": "write", + "code": "p['replica_lift'] = dict(groups=2, source_replicas=8, replicas=16,", + "context": "subscript-key", + "field": "replica_lift", + "line": 66, + "name": "replica_lift" + } + ], + "archive:verify_t16.py": [ + { + "access": "construct", + "code": "t8_kappa=rd(SPEC8)['expected']['kappa'], spec_sha256=sha(SPEC16), stages=stages, scope=asm['scope'])", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 120, + "name": "scope" + }, + { + "access": "read", + "code": "t8_kappa=rd(SPEC8)['expected']['kappa'], spec_sha256=sha(SPEC16), stages=stages, scope=asm['scope'])", + "context": "subscript-key", + "field": "hosting.scope", + "line": 120, + "name": "scope" + } + ], + "main:scripts/verify_frontier1094.py": [ + { + "access": "construct", + "code": "scope=receipt['scope'])", + "context": "dict-or-call-keyword", + "field": "hosting.scope", + "line": 101, + "name": "scope" + }, + { + "access": "read", + "code": "scope=receipt['scope'])", + "context": "subscript-key", + "field": "hosting.scope", + "line": 101, + "name": "scope" + } + ] + }, + "universe_sha256": { + "archive:code/assemble.py": "15f6986a476bac76bcdc0bfcf51da115389b46f1950d2766b6822f757888b13a", + "archive:code/assembly_controls.py": "da7e981ae1b9f099d4e1524cb4f3ba1116011936ebe378692889b5dbfa99029d", + "archive:code/audit_allcold.py": "1467a2acb654e62552c69fb9a7c4c85f70a02120881d222313865058ab71a6cc", + "archive:code/bind_providers_portable.py": "1d39bcc7b63ac158e021454beaae897d123e174360573762aecade3cd43193f6", + "archive:code/bit_supplier_controls.py": "e6d33fb61a570c3f50669412acc467a3fd06ef0b806da6a75bc296c6ba2142a5", + "archive:code/emit_allcold.py": "354367e1fd6185a67b04f4268bcae4d502e47b18cb2131e247f5bcab5b3a769e", + "archive:code/freeze_spec.py": "5971eecac6d6fbcb53244b80f1b9d7232012dc32876fab511214a5addebbe6c2", + "archive:code/generated_identity.py": "c8af22719c0f3097a991a3f6ccac8f090afd2faba554745733d9ea88f2c25708", + "archive:code/invoice_allcold.py": "71eb57514e28ced97251e0507105f654f59885ec4d40486a780bf166098858a8", + "archive:code/prepare_global.py": "8c0dae301a8f34b77a5a462f840952d08ed120576212adf5051bc09bcad874dc", + "archive:code/restore_parent.py": "69b7b25ff85e9b8160e233c1d415cc6a0272019e5c486dcec14cb6c349e7024d", + "archive:code/witness.py": "779c5172894b992131e85be1e592ed2a1aec8c287b872ff42007d36a7291e444", + "archive:construction/barch/build_tri.py": "0fba65b31c2fd71864c291358bb0ad8d5f7e1be07e21df23f0ae73d7b966002e", + "archive:construction/barch/reproduce_barch.py": "19bc970aa6af25ab0e7fa96fb65c64dd0c5243976d8f2cb733cba839155482c1", + "archive:construction/barch/run_controls.py": "42639bf62bf57795e3ea615c1944c67efed00f28591333daeb3139bf63d04476", + "archive:construction/build_gauge_cold44.py": "ec730a4d3ff12fb058780718b1d5a7afe61243c532679ef347a5a48e2af0a3bb", + "archive:construction/construct_gauge_xcentre.py": "d8d295566ef2399af2da0707a4adc83e07aa26d2344c01a66bd0ca7684cf9217", + "archive:construction/frames/build_frames.py": "200847a7e8b3125cbeea0765dad67650e0bf83d32b66d72ba4977e99b8ee8eeb", + "archive:construction/frames/frame_controls.py": "477de854ec9184a2c73d6ac3857a9d0cbd6bc04b71d10a105e7344434b492a77", + "archive:construction/frames/reproduce_frames.py": "dc39ada9a2eb387310be181f3cea5dbd4b538632a888cd7372ece5e38a771832", + "archive:construction/jx/build_jx.py": "3cc7550b0c24bb54e245c6f7f16de489fd7844721fbb64aac628f38f43887916", + "archive:construction/jx/reproduce_jx.py": "5c7afebb4eb7fcdeb7e971cfbc457cf071850e2da21c3c71295efdd453c2399c", + "archive:construction/layers/build_pivot_swap.py": "8e8bced88be2e592ded40929499bac385ca92fcc1fa59183c22229dbf34093b8", + "archive:construction/layers/layer_end_controls.py": "7829187bfc8f909948d5250e0ec00f02c89f5fe98306a3ed88daee36cb3c92ef", + "archive:construction/layers/reproduce_layers.py": "435699f6f79c6c7fb8d6cc5a8382576d6ac88747583a975ff671e45440b93c4e", + "archive:construction/layers_np/reproduce_np.py": "1a304144a250d00d14154692ba522365b036777cf2b6fac466095e8ba733c16c", + "archive:construction/layers_p6n/layer_end_controls.py": "fc58c5699ba6191c1163a3041241f6f0b619626c4462cd99bcf88210bac9e81e", + "archive:construction/layers_p6n/reproduce_p6n.py": "aa7d6bcbed05aa1c689437c07a26e5c95be3c700c0c1fb7bcf91c432a88436ca", + "archive:construction/leaver/build_frames_lv.py": "2eb80d612aa59a7bd8b04a122045e3bd2b83a21954e3164943cd20cf6050a21b", + "archive:construction/leaver/cgx_leaver.py": "3af491c63dd96204a7c36006c7e419c2e5ce77e5bc453ccd2495c1e41f83f87c", + "archive:construction/leaver/layer_end_controls_leaver.py": "4ba676f1ea326b739a64c3477f64eeb295f8151514f78fa7e62b71e4373a6206", + "archive:construction/leaver/reproduce_leaver.py": "831bfdf2247b5d864b74c3b2b6a475718053d48570851d48bd1c5471d410ee30", + "archive:construction/leaver/reproduce_leaver_chain.py": "2bc3fc3f32e0f957a0731b79254c553ca48fc6d4d47c4f99d6cd31e1901d85b5", + "archive:construction/notri/cgx.py": "3da039d4184097c14802f9dbf972520d5b807671196f5e47a2247bc9f29bb418", + "archive:construction/notri/cold44x.py": "f0bc3500efb2c839a0f8cb03dbb9ea0a54f1dfc71ef81e5373b3d638ac5b8296", + "archive:construction/notri/port_stage_x.py": "38310744d054e393ea35e996047cddeb2d212141aaaaa4b07f7a4663b11db8e7", + "archive:construction/notri/reproduce_notri.py": "90148c2a0422b4f92164298a283de73d413ab3d4cb7151a0e6b643a37ea025a8", + "archive:construction/promo/build_promotion.py": "9c9e2001b8d68bbe934d136026276fe97bd9bf6f94d4d78441fc28e14aca4daf", + "archive:construction/promo/make_recipe.py": "ba9e4fdc0c1be7f6a150a5a50909911257a1a8c7cc5d03d61f541178fc07c122", + "archive:construction/promo/promo_controls.py": "786c51f84b53698c2c833083506c4432c30eb0ed3b71e7dbe458a70c7413c372", + "archive:construction/promo/reproduce_promo.py": "f979be666c3f5cf57e342a8427863c0b35b67ca4d3be495ac386f6870deb2026", + "archive:construction/reproduce.py": "047bb9b3536b0b16bb08a21cd9fd80404ca9d022345f1aeab34b21dffc281c92", + "archive:construction/slots/verify_slots.py": "bc1c0e3e3d7c81dc1649f5be82cdd2399e543d46c24879cb975877bf9b7957be", + "archive:construction/sw4/build_sw4.py": "9a295f3d534594a6b1326d8a6647e947670d1c6fbc92f37f5169661fde4c8f66", + "archive:construction/sw4/reproduce_sw4.py": "3d082e0cc576fb1b4fb9e5dd11d63bab697c8a8626e2837813cd00d100b1aeac", + "archive:hosting/audit_frozen.py": "a8d9c7c894cb44453aea93b33141559824f6c3ff81a85a6d066f4a10a2757659", + "archive:hosting/expand_owners.py": "0f826377881d0c9405f90d9f5feac857c7c7cf8aef5bcf22d326bc274f038a70", + "archive:hosting/reproduce.py": "7551004d8d15cebcecc6793ebd17385830390935ccd1a8957f1c5472bce6ec82", + "archive:hosting/reuse_owners.py": "2106fe79bd89071e62a3a25c1e444531e14fb89f88b4bdeb72d7b40c91266402", + "archive:independent/audit_local.py": "03afcfc9da428b3f6edac81c1fee7f277ab81b64998efae78380b63498dec6cd", + "archive:independent/price_profile.py": "d2f548ad6b99f64a8ca5fbaf822a89560bb99359957ce3420b497f6a46fc0acf", + "archive:independent/review_guards.py": "b83164d6c0122a055b3281f3381b305683a875760a2d727dd0188bb2aa59d67d", + "archive:t16/build_parent.py": "82e274d0c7a94f9bf0468dd37f0505d0c42017559ebb4ba8c079a1f4e403d91e", + "archive:t16/indep16.py": "1beb512a1d072f81d3e8e492c8827636029686897093bd433e4d4c92d0c830c7", + "archive:t16/lift16.py": "072fe6ac032543d5106631f9b4aa36103269b64ab72061d97ec604f648830689", + "archive:verify_manifest.py": "723d726dbbe5b65a49caecae0f1aab664a1413fb639abfd3e826a5a538e14e5b", + "archive:verify_t16.py": "050e2dfba59911b8f29fd94422833d421367a0ad01c5e4ae916a75a235ee5e46", + "main:research/community-batch1099-audit/check_frontier1094.py": "2608ef213260a43d09a40b3429742f7a5f280861b54acae66400a7c29a123f51", + "main:research/complex-t16-rare-pattern-exchanges/verify.py": "b8c2f76b305c5c9ceb42df203deef564857d17f1f8182d0745dda9ab96e3d4de", + "main:research/pending-claims-independent-pricing/sweep.py": "aeafc6a5e39817a893fa8392f4f7e767b23437e3317067075bb9d5552e3df23f", + "main:research/t16-owner-audit-seed67/verify.py": "f6e27f76c9ccb87b3ce6c5e673588338a09847d22771da7b3f28579661c9404b", + "main:scripts/verify_frontier1094.py": "c7e20f59968ed5736fb859735de4de207de3418083e37012310ebcded946b949" + } +} diff --git a/research/hosted-template-postemit-fields/README.md b/research/hosted-template-postemit-fields/README.md new file mode 100644 index 0000000000..8d391729da --- /dev/null +++ b/research/hosted-template-postemit-fields/README.md @@ -0,0 +1,133 @@ +# Post-emit read-set of the 15 audit-unread hosted-template fields + +**Scope.** This package machine-checks one hosting transfer claim of the selected #1094 chain. +The frozen PR1087 `code/audit_allcold.py` acceptance audit does not read 15 fields of the hosted +template it checks (`cover`, `m`, `version`, `port_restriction`, `provider_dispatch`, +`replica_lift`, `route_semantics`, `supplier_substitution`, `expanded_scalar_interface`, +`hosting.rule`, `hosting.scope`, `hosting.idle_remainder_semantics`, `hosting.owner_map_sha256`, +`async_schedule.scope`, `async_schedule.source_plan_sha256`). Josie Elliston's +[`research/t16-audit-mutant-coverage`](../t16-audit-mutant-coverage/README.md) +([PR #1959](https://github.com/CrocSwap/integer-mult-bounds/pull/1959)) asserts "a text search of +the PR1087 archive and the maintainer frontier1094 scripts finds no reader of the 15 unread fields +in the hosted template after `emit`", and labels it "a text search, not a proof". This package +replaces the text search with a pinned AST inventory of the whole consumer universe and maps the +whole-object channels through which those fields could still reach a post-emit acceptance +decision. It makes no kappa, certificate, supplier or frontier change, and it is not a cold +replay or a mutation audit. + +## Result + +Universe: all 57 `*.py` members of the pinned +`research/complex-t16-rare-pattern-exchanges/upstream1087.tar.gz` (SHA-256 +`d4acf04daef85d4514f80ec5fcd2492d0c60e5d6c49fa71b3e6523f8db2dea86`) plus five main-tree files +(`scripts/verify_frontier1094.py`, `research/community-batch1099-audit/check_frontier1094.py`, +the selected stage driver `research/complex-t16-rare-pattern-exchanges/verify.py`, and the +in-process import closure of `check_frontier1094.py`: +`research/t16-owner-audit-seed67/verify.py` and +`research/pending-claims-independent-pricing/sweep.py`). Every file is SHA-256 pinned in +`EXPECTED.json`; the post-emit consumer closure is `code/audit_allcold.py`, +`code/invoice_allcold.py`, `code/assemble.py`, `code/assembly_controls.py`, +`code/bit_supplier_controls.py` and the audit's in-process helpers `code/witness.py`, +`code/generated_identity.py`. + +**S1 — no post-emit name-directed read.** Of the 58 name-directed occurrences of the 15 field +names in the universe, exactly five are in the post-emit closure, and all five are output-receipt +construction keys (`scope=` in the `dict(...)` builders at `assemble.py:234`, +`assembly_controls.py:246`, `audit_allcold.py:231`, `audit_allcold.py:253`, +`invoice_allcold.py:310`). A dict()/dict-literal key writes another dict; it cannot read the +template. Zero post-emit occurrences are reads, writes, presence tests or opaque calls of any of +the 15 names. This is the machine-checked replacement for PR1959's text search. + +**S2 — complete occurrence inventory.** All 58 occurrences are pinned with file, line, syntactic +context and access class in `EXPECTED.json`, so source drift invalidates the receipt. The only +semantic reads of any of the 15 names in the entire universe are three pre-emit read-modify-writes +of `route_semantics` (each overwrites its `helper` subfield during construction: +`restore_parent.py:62`, `t16/build_parent.py:117`, `code/emit_allcold.py:102`) and two reads of +*other* objects that happen to share a field name (`t16/build_parent.py:63` reads the source +SPEC's dimension `source['m']`; `verify_t16.py:120` and `scripts/verify_frontier1094.py:101` read +an assembly receipt's `scope`). Nothing in the pinned universe reads the hosted template's 15 +fields. + +**S3 — dynamic and whole-object channels.** The 54 dynamic-access sites of the template variables +(`ct`, `t`, `q` in the audit; `template` in the invoice) are pinned with excerpts. There is no +unbounded top-level dynamic read: the single top-level dynamic subscript is +`audit_allcold.py:97`, `for key in ('exact_data_phase_recipe_sha256','adapter_policy'): assert +t[key]==parent[key]`, whose key set is finite and disjoint from the 15 fields. The two top-level +presence tests (`audit_allcold.py:95`, `invoice_allcold.py:178`) probe retired field names +(`local_programs`, `exact_local_clifford_recipe_sha256`, `residual_adapter_sha256`), not the 15. +No post-emit code iterates, serializes, hashes or compares the template object itself in-process; +the one `copy.deepcopy(ct)` (`audit_allcold.py:190`) is the audit's own mutation harness. + +**Channel map — how the 15 fields can still reach acceptance.** Through whole-object byte +equality only, against receipts produced by the same emit run: + +| Channel | Pinned statement | Effect on a changed field | +| --- | --- | --- | +| audit stage | `audit_allcold.py:185` recomputes `sha256` of the template file bytes and requires `== summary['template_sha256']` (`HOSTED.json`, written by `emit_allcold.py`) | detected unless `HOSTED.json` is re-emitted consistently | +| invoice stage | `invoice_allcold.py` `run()`: `template_hash=contenthash(template_path)` must equal `control['complex_template_sha256']` (ASYNC-AUDIT.json), `owners['template_sha256']` (OWNERS-AND-PROFILE.json) and `summary['template_sha256']` (HOSTED.json) — the four-way binding | detected unless all four values are consistent with the changed bytes | +| maintainer check | `check_frontier1094.py:18` binds `a.TEMPLATE` (the **ROUND20 parent** template, a pre-emit artifact) by file hash to `research/t16-owner-audit-seed67/SOURCES.json`, and `geometry()` reads only `execution_schedule` and `recipe` from it | does not touch the hosted emit output | + +Consequence (what would change downstream): with the emit-produced receipts kept consistent, no +post-emit acceptance predicate in the pinned universe distinguishes any values of the 15 fields. +Their presence in the hosted template is provenance/documentation; the chain's protection of them +is the emit-stage byte-hash provenance binding, not semantic validation. PR1959's prose ("the +audit alone accepts changed pooled-slot times and the 15 unread fields") therefore extends from +`audit()` alone to the whole pinned post-emit chain, modulo the file-hash bindings above. + +**S4 — detector self-test (corruption control).** `verify.py` parses ten synthetic probe forms +(subscript read, attribute read, dict() keyword, dict-literal key, `get()` argument, subscript +write, membership test, unbounded dynamic subscript, bounded dynamic subscript, top-level +iteration, top-level hash) and fails unless every one is classified as intended. A single +injected `ct['cover']` in any pinned file would trip S1 and the EXPECTED inventory comparison. + +## What this does not establish + +- This is static analysis of pinned bytes. Receiver binding for the dynamic sites uses the + declared template variables (`TEMPLATE_VARS` in `verify.py`); renamed receivers would need a + re-derivation, though any byte drift already fails the pins. +- It certifies the pinned universe, not arbitrary future code, and it is not a proof of semantic + non-interference. The `engines/moment.py`, `engines/base_two_moment.py` and `engines/outer.py` + modules that `assemble.py` loads from its own package directory are outside the frozen archive + and were not scanned; `assemble.py` passes them profile dictionaries, not the template (visible + in the pinned site inventory). +- It does not replay the selected chain, does not mutation-test any stage, and does not discharge + the all-size/compiler, precision, hosting or restoration obligations themselves. The template + owner-map binding left open by PR1959's open question 2 is untouched. + +## Reproduce + +```sh +python3 -B research/hosted-template-postemit-fields/verify.py +python3.12 scripts/research_package.py --package research/hosted-template-postemit-fields +``` + +Stdlib only, CPython 3.10+. `verify.py --write` regenerates `EXPECTED.json` after a deliberate +source change. Checked on CPython 3.13 and 3.12 on Windows, identical output. + +## Open next questions + +1. **Read-set receipt for the other `audit_allcold.py` versions.** PR1959's open question 1 lists + nine other hashes of that file in the repository. First step: parametrize `verify.py` by + archive member and re-run the inventory on the #1042 audit archive. Blocked by: locating each + version's hosted template in the retained receipts (PR1959's own blocker). +2. **Consumers of the emitted `scope` receipts.** Five post-emit receipts carry a `scope=` string; + which downstream readers (human or script) consume them? First step: a name-directed scan of + `report['scope']` consumers in the replay drivers and ledger tooling. Blocked by: nothing. +3. **Bind the parent/hosted template distinction.** `check_frontier1094.py` pins the parent + template bytes; no stage pins the hosted template bytes against a pre-emit value. First step: + a two-line pin of the hosted template in the frontier1094 driver, as PR1959's open question 2 + proposes for the owner map. Blocked by: a maintainer decision on wrapping the frozen driver. + +## Credit + +The audited claim and the 15-field census are Josie Elliston's (PR #1959, +`research/t16-audit-mutant-coverage`), prepared with Claude Code assistance. The frozen chain code +is Jeremy Kothe's PR1087/#870 lineage with T16 edits from Hao Yan (@FanPUYen) #858; the selected +run is Rohan Arun's PR1094; the frontier1094 composition is Douglas Colkitt's; the owner audit is +Josie Elliston's `research/t16-owner-audit-seed67`; the pricing sweep is Sagar Thakrar's +`research/pending-claims-independent-pricing`. Adjacent concurrent work: +[PR #2158](https://github.com/CrocSwap/integer-mult-bounds/pull/2158) (Aaron Wang, agent-43) +mutation-tests `invoice_allcold.py`'s predicates — a dynamic method on one stage; this package's +static, universe-complete inventory complements it and neither supersedes the other. + +Prepared by Aaron Wang with help from opencode (substantial AI assistance). Apache-2.0. diff --git a/research/hosted-template-postemit-fields/SOURCES.json b/research/hosted-template-postemit-fields/SOURCES.json new file mode 100644 index 0000000000..c0b7a2f427 --- /dev/null +++ b/research/hosted-template-postemit-fields/SOURCES.json @@ -0,0 +1,54 @@ +{ + "schema_version": 1, + "base_commit": "0fdd7d82de03e43c9e5a1000dfbcd380d1b687d2", + "files": [ + { + "path": "certificates/selected-result.json", + "usage": "provenance", + "git_blob": "ae6a99f28aa468649eb66a361e764d769363bf11", + "sha256": "10b9e340fd8e354a37a0c4813c90e5de1dd42044b5f6aca4a3fc5a42b685fa32" + }, + { + "path": "docs/research/agent-task-catalog.json", + "usage": "provenance", + "git_blob": "e8870e5917057d59b730eb14721a778639eca050", + "sha256": "d46eb6d5b3e279428753d770653663fbdf1063e55c255ea073d768f344927ef7" + }, + { + "path": "research/complex-t16-rare-pattern-exchanges/upstream1087.tar.gz", + "usage": "input", + "git_blob": "2970ef79b0441e937449bed30f68f2e0558186ba", + "sha256": "d4acf04daef85d4514f80ec5fcd2492d0c60e5d6c49fa71b3e6523f8db2dea86" + }, + { + "path": "scripts/verify_frontier1094.py", + "usage": "input", + "git_blob": "96e6c1386bd052b9bcaf136d934406f3f0c3f777", + "sha256": "c7e20f59968ed5736fb859735de4de207de3418083e37012310ebcded946b949" + }, + { + "path": "research/community-batch1099-audit/check_frontier1094.py", + "usage": "input", + "git_blob": "1c171898e4f58fbdeca81424c9932ec2c6bbb9c8", + "sha256": "2608ef213260a43d09a40b3429742f7a5f280861b54acae66400a7c29a123f51" + }, + { + "path": "research/complex-t16-rare-pattern-exchanges/verify.py", + "usage": "input", + "git_blob": "9d471cf90835bc91d32bb0216c2bb867011a7420", + "sha256": "b8c2f76b305c5c9ceb42df203deef564857d17f1f8182d0745dda9ab96e3d4de" + }, + { + "path": "research/t16-owner-audit-seed67/verify.py", + "usage": "input", + "git_blob": "3ff276c3040ec4a52db932e0bcdd31df5a3cf0a4", + "sha256": "f6e27f76c9ccb87b3ce6c5e673588338a09847d22771da7b3f28579661c9404b" + }, + { + "path": "research/pending-claims-independent-pricing/sweep.py", + "usage": "input", + "git_blob": "dc60fab01d7e72b3cbfa536a925c78fdd9ff8f78", + "sha256": "aeafc6a5e39817a893fa8392f4f7e767b23437e3317067075bb9d5552e3df23f" + } + ] +} diff --git a/research/hosted-template-postemit-fields/TASK.json b/research/hosted-template-postemit-fields/TASK.json new file mode 100644 index 0000000000..76055ef30e --- /dev/null +++ b/research/hosted-template-postemit-fields/TASK.json @@ -0,0 +1,80 @@ +{ + "schema_version": 1, + "task_id": "uniform-transfer-audit", + "priority_revision": 4, + "base_commit": "0fdd7d82de03e43c9e5a1000dfbcd380d1b687d2", + "original_card": { + "id": "uniform-transfer-audit", + "question": "Can one exact all-size/compiler, precision, hosting or restoration implication be proved or falsified?", + "starting_points": [ + "certificates/selected-result.json", + "docs/audit.md" + ], + "methods": [ + "Prove one missing implication with explicit quantified hypotheses.", + "Find an exact counterexample at the claimed interface boundary." + ], + "acceptance_gate": "Identify the proposition and what would change downstream; do not equate a finite replay with a universal proof.", + "first_step": { + "command": [ + "python3", + "-B", + "scripts/research_baseline.py" + ], + "expected": "PASS_RESEARCH_BASELINE_BINDINGS_ONLY", + "inspect": "Read the selected review scope and choose one exact all-size or precision implication.", + "scope": "Positive control / source-bound orientation only; this is not a new construction or full cold replay." + }, + "first_experiment": "Write its quantified inputs and conclusion; find a missing hypothesis or construct a minimal exact adversarial instance.", + "bottleneck_link": "Finite supplier improvements are useful only under the retained transfer obligations.", + "allowed_variations": [ + "Choose one tape, precision, hosting or restoration lemma." + ], + "scope_change_triggers": [ + "Replacing a quantified obligation with another finite smoke test." + ], + "overlap_terms": [ + "uniform transfer", + "all-size", + "precision" + ] + }, + "chooser": { + "track": "adversarial-audit", + "nonce": "2bb90ec128a184bdec47e263785b9c5d", + "scope_key": "603f341b99f590f17a76", + "catalog_sha256": "d46eb6d5b3e279428753d770653663fbdf1063e55c255ea073d768f344927ef7", + "selected_record_sha256": "10b9e340fd8e354a37a0c4813c90e5de1dd42044b5f6aca4a3fc5a42b685fa32", + "card_note": "First-choice card selected-stock-envelope was declined under the pair-collision rule (philippeVV live claim comment 18932014 and completed PR2084/PR2120 first-stage coefficient work); second-choice card uniform-transfer-audit taken instead." + }, + "scope_status": "refined", + "actual_scope": "One hosting transfer implication, quantified over pinned bytes: in the universe of all 57 *.py members of research/complex-t16-rare-pattern-exchanges/upstream1087.tar.gz plus five named main-tree scripts (including the import closure of check_frontier1094.py), machine-check that no post-emit consumer of the hosted template performs a name-directed read of the 15 fields PR1959 recorded as audit-unread, enumerate every dynamic-access and whole-object channel by which those fields could still reach a post-emit acceptance decision, and record what would change downstream (the emit-stage file-hash provenance binding is the only such channel).", + "scope_change_reason": "The card asks for one exact all-size/compiler/precision/hosting/restoration implication with explicit quantified hypotheses; the drawn first-choice card selected-stock-envelope matched an already-claimed recent object (philippeVV 2026-10-14 18:57Z claim comment 18932014, plus completed PR2084/PR2120), so the second-choice card was taken and refined to PR1959's explicitly labelled informal claim ('a text search, not a proof'), one named hosting acceptance boundary of the selected chain.", + "bottleneck_link": "The selected record's scope retains whole-call hosting and all-size/transfer obligations as inherited assumptions; PR1959's informal read-set gap sat directly on the hosted-template acceptance boundary of those obligations. Upgrading it to a pinned machine check removes one informal step from the transfer chain and hands the next worker an exact channel map; no kappa arithmetic is changed.", + "budget_minutes": 60, + "stop_rule": "One bounded experiment: the AST inventory plus channel map over the pinned universe. Stop at the first unresolvable dynamic access of one of the 15 names (falsifier) or on inventory completion; one bounded pivot maximum (receiver-closure extension to the frontier1094 import closure).", + "outcome": "completed", + "evidence": "research/hosted-template-postemit-fields/EXPECTED.json pinned inventory (62 files, 58 name-directed occurrences, 54 dynamic sites), verify.py self-tests PASS_POSTEMIT_FIELD_READSET; scope-key overlap searches recorded in the PR (find_overlap.py, 2026-10-15T02:28Z and 02:36Z snapshots).", + "author": "Aaron Wang", + "ai_assistance": "Substantial AI assistance: developed with help from opencode. No independent human review claimed.", + "open_questions": [ + { + "question": "Extend the read-set receipt to the other audit_allcold.py versions (PR1959 open question 1: nine other hashes of the file).", + "why_it_matters": "Each version has its own shipped controls and its own unread-field boundary; the current receipt covers only the frozen PR1087 bytes.", + "first_step": "Parametrize verify.py by archive member and re-run the inventory on the #1042 audit archive.", + "blocked_by": "Locating each version's hosted template in the retained receipts (PR1959's own blocker)." + }, + { + "question": "Which downstream consumers read the five emitted scope receipt strings?", + "why_it_matters": "They are the only occurrences of an audit-unread field name in post-emit code; knowing their readers settles whether they are pure documentation.", + "first_step": "A name-directed scan of report/receipt ['scope'] consumers in the replay drivers and ledger tooling.", + "blocked_by": "Nothing." + }, + { + "question": "Pin the hosted template bytes against a pre-emit value in the frontier1094 driver (the parent template is pinned; the hosted output is not).", + "why_it_matters": "It would make the emit-stage hash binding a two-sided contract instead of same-run self-consistency.", + "first_step": "A two-line pin in the frontier1094 driver, as PR1959 open question 2 proposes for the owner map.", + "blocked_by": "A maintainer decision on wrapping the frozen driver." + } + ] +} diff --git a/research/hosted-template-postemit-fields/VERIFY.json b/research/hosted-template-postemit-fields/VERIFY.json new file mode 100644 index 0000000000..8667d1566d --- /dev/null +++ b/research/hosted-template-postemit-fields/VERIFY.json @@ -0,0 +1,25 @@ +{ + "schema_version": 1, + "status": "ready", + "python": "3.12", + "requirements": [], + "inputs": [ + "research/complex-t16-rare-pattern-exchanges/upstream1087.tar.gz", + "scripts/verify_frontier1094.py", + "research/community-batch1099-audit/check_frontier1094.py", + "research/complex-t16-rare-pattern-exchanges/verify.py", + "research/t16-owner-audit-seed67/verify.py", + "research/pending-claims-independent-pricing/sweep.py" + ], + "commands": [ + { + "argv": [ + "{python}", + "-B", + "{package}/verify.py" + ], + "timeout_seconds": 120, + "checks": "Detector self-test (10 synthetic probe forms must each be classified as intended: subscript read/write, attribute read, dict() keyword, dict-literal key, get() argument, membership test, unbounded/bounded dynamic subscript, top-level iteration, top-level hash); EXPECTED.json inventory equality over 62 pinned files (byte pins plus the complete 58-site name-directed inventory and the 54-site dynamic inventory); S1 zero non-construction name-directed occurrences of the 15 field names in the post-emit closure; S3 no unbounded top-level dynamic read/iteration/hash of the template object and no bounded key set touching the 15 fields; three pinned whole-object channel statements must be present verbatim. Prints PASS_POSTEMIT_FIELD_READSET." + } + ] +} diff --git a/research/hosted-template-postemit-fields/verify.py b/research/hosted-template-postemit-fields/verify.py new file mode 100644 index 0000000000..2497274976 --- /dev/null +++ b/research/hosted-template-postemit-fields/verify.py @@ -0,0 +1,468 @@ +#!/usr/bin/env python3 +"""Machine check for the hosted-template post-emit field read-set claim. + +Scope (agent-45, card uniform-transfer-audit, refined): the frozen PR1087 hosted +template carries 15 fields that the acceptance audit `audit_allcold.py` never +reads. `research/t16-audit-mutant-coverage` (PR1959) asserts by text search +that no stage after `emit_allcold.py` reads any of them either, and labels that +"a text search, not a proof". This script replaces the text search with a +pinned, machine-derived inventory: + + S1 no semantic read/test of any of the 15 field names anywhere in the + post-emit consumer closure (constant-string subscripts, attributes, + get/pop/setdefault/getattr arguments, membership or comparison tests). + The only tolerated occurrences are output-receipt construction keys + (dict()/dict-literal keys), which write other dicts, not the template; + S2 the complete name-directed occurrence inventory of those 15 names over the + whole pinned universe equals EXPECTED.json exactly (drift detection); + S3 the dynamic-access and whole-object-channel inventory of the template + variables in the post-emit closure equals EXPECTED.json exactly, and no + entry is a top-level dynamic read of the template (no `t[k]`, no bare + iteration/serialization/hash of the template object itself); + S4 the detector self-test (corruption control): injected name-directed and + dynamic probes are all detected. + +Universe (pinned by SHA-256 in EXPECTED.json): + A. every ``*.py`` member of research/complex-t16-rare-pattern-exchanges/upstream1087.tar.gz + B. scripts/verify_frontier1094.py, + research/community-batch1099-audit/check_frontier1094.py, + research/complex-t16-rare-pattern-exchanges/verify.py + +This is a static source audit of pinned bytes. It does not replay the selected +chain, does not prove semantic non-interference beyond the recorded site +inventory, and does not cover the external `engines/*.py` moment modules that +`assemble.py` loads from its own package directory. +""" +import ast +import hashlib +import io +import json +import sys +import tarfile +from pathlib import Path + +PKG = Path(__file__).resolve().parent +ROOT = PKG.parents[1] + +ARCHIVE = "research/complex-t16-rare-pattern-exchanges/upstream1087.tar.gz" +MAIN_FILES = [ + "scripts/verify_frontier1094.py", + "research/community-batch1099-audit/check_frontier1094.py", + "research/complex-t16-rare-pattern-exchanges/verify.py", + # import closure of check_frontier1094.py: it loads these in-process and + # passes a template object to them (the ROUND20 parent template, a pre-emit + # artifact -- see README). + "research/t16-owner-audit-seed67/verify.py", + "research/pending-claims-independent-pricing/sweep.py", +] + +# The 15 hosted-template fields the PR1087 audit() never reads (PR1959). +FIELDS = [ + "cover", "m", "version", "port_restriction", "provider_dispatch", + "replica_lift", "route_semantics", "supplier_substitution", + "expanded_scalar_interface", + "rule", "scope", "idle_remainder_semantics", "owner_map_sha256", + "source_plan_sha256", +] +FIELD_PATHS = { + "cover": "cover", "m": "m", "version": "version", + "port_restriction": "port_restriction", "provider_dispatch": "provider_dispatch", + "replica_lift": "replica_lift", "route_semantics": "route_semantics", + "supplier_substitution": "supplier_substitution", + "expanded_scalar_interface": "expanded_scalar_interface", + "rule": "hosting.rule", "scope": "hosting.scope", + "idle_remainder_semantics": "hosting.idle_remainder_semantics", + "owner_map_sha256": "hosting.owner_map_sha256", + "source_plan_sha256": "async_schedule.source_plan_sha256", +} + +# Stage roles from the pinned evidence/STAGES.json order +# (restore-parent, bind, emit, audit, invoice, assembly, admission-controls) +# and the PR1087 code layout. The post-emit consumer closure is audit, invoice, +# assembly, admission-controls plus the modules the audit imports in-process. +POST_EMIT_CLOSURE = [ + "code/audit_allcold.py", + "code/invoice_allcold.py", + "code/assemble.py", + "code/assembly_controls.py", + "code/bit_supplier_controls.py", + "code/witness.py", + "code/generated_identity.py", +] + +# Variables bound to the loaded hosted template (or a mutated copy of it) in the +# post-emit closure; declared here because pure syntax cannot bind receivers. +TEMPLATE_VARS = { + "code/audit_allcold.py": ["ct", "t", "q"], + "code/invoice_allcold.py": ["template"], + "code/assemble.py": [], + "code/assembly_controls.py": [], + "code/bit_supplier_controls.py": [], + "code/witness.py": [], + "code/generated_identity.py": [], +} + +HASH_CALLS = {"sha256", "sha1", "md5", "sha512", "blake2b"} +HASH_HELPERS = {"sha", "filehash", "contenthash", "digest", "programhash", "payload_identity", "json_identity"} + +# Pinned whole-object file-binding channels: the exact statements through which a +# change to any hosted-template field (read or unread) still reaches post-emit +# acceptance. Asserted present verbatim so the README's channel map stays +# checkable at a glance; the files themselves are SHA-256 pinned above. +CHANNEL_PINS = [ + ("archive:code/audit_allcold.py", + "assert hashlib.sha256(raw).hexdigest()==summary['template_sha256']"), + ("archive:code/invoice_allcold.py", + "assert template_hash==control['complex_template_sha256']==owners['template_sha256']==summary['template_sha256']"), + ("archive:code/invoice_allcold.py", + "template_hash=contenthash(template_path)"), +] + + +def sha256_bytes(b): + return hashlib.sha256(b).hexdigest() + + +def load_universe(): + """Return {label: (text, sha256)} for every pinned source file.""" + out = {} + ap = ROOT / ARCHIVE + with tarfile.open(ap, "r:gz") as tf: + for m in sorted(tf.getmembers(), key=lambda x: x.name): + if not m.name.endswith(".py"): + continue + raw = tf.extractfile(m).read() + out["archive:" + m.name] = (raw.decode("utf-8", "replace"), sha256_bytes(raw)) + for rel in MAIN_FILES: + raw = (ROOT / rel).read_bytes() + out["main:" + rel] = (raw.decode("utf-8", "replace"), sha256_bytes(raw)) + return out + + +def const_context(parent_stack, node): + """Classify how a constant string is used: (context, access). + + access is "read" (the field name is looked up), "write" (subscript store), + "construct" (dict literal key / dict() keyword: building some dict), "test" + (membership or comparison), or "opaque" (string passed to an unclassified call). + """ + if not parent_stack: + return "string-expr", "opaque" + par = parent_stack[-1] + if isinstance(par, ast.Subscript): + target = par.slice + if isinstance(target, ast.Constant) and target.value == node.value: + if isinstance(par.ctx, ast.Load): + return "subscript-key", "read" + return "subscript-key", "write" + return "string-expr", "opaque" + if isinstance(par, ast.Dict): + for k in par.keys: + if k is node: + return "dict-literal-key", "construct" + return "dict-literal-value", "opaque" + if isinstance(par, ast.keyword): + return "keyword-value", "opaque" + if isinstance(par, ast.Call): + fn = "" + if isinstance(par.func, ast.Attribute): + fn = par.func.attr + elif isinstance(par.func, ast.Name): + fn = par.func.id + access = "opaque" + if fn in ("get", "pop", "setdefault", "getattr", "hasattr"): + access = "read" + elif fn in ("__setitem__", "setattr", "setdefault"): + access = "write" + return "call-arg:" + fn, access + if isinstance(par, ast.Compare): + return "membership-or-compare", "test" + if isinstance(par, (ast.JoinedStr, ast.FormattedValue)): + return "fstring-part", "opaque" + return "type:" + type(par).__name__, "opaque" + + +def walk_with_parents(tree): + """Yield (node, parent_stack) for every node.""" + stack = [] + + def visit(node): + stack.append(node) + yield node, list(stack[:-1]) + for child in ast.iter_child_nodes(node): + yield from visit(child) + stack.pop() + + yield from visit(tree) + + +def static_path(expr, roots): + """Resolve a chain of constant subscripts/attributes on a root variable. + + Returns ("top", root) for a bare root, ("path", root, "a.b") for a named + subfield, or None when the expression is unrelated to any root. + """ + parts = [] + cur = expr + while True: + if isinstance(cur, ast.Subscript) and isinstance(cur.slice, ast.Constant) and isinstance(cur.slice.value, str): + parts.append(cur.slice.value) + cur = cur.value + continue + if isinstance(cur, ast.Attribute): + parts.append(cur.attr) + cur = cur.value + continue + break + if isinstance(cur, ast.Name) and cur.id in roots: + if not parts: + return ("top", cur.id) + return ("path", cur.id, ".".join(reversed(parts))) + return None + + +def name_sites(text): + """All name-directed occurrences of the 15 field names (S1/S2).""" + tree = ast.parse(text) + sites = [] + for node, parents in walk_with_parents(tree): + name = None + ctx = None + access = None + if isinstance(node, ast.Constant) and isinstance(node.value, str) and node.value in FIELDS: + name = node.value + ctx, access = const_context(parents, node) + elif isinstance(node, ast.Attribute) and node.attr in FIELDS: + name = node.attr + ctx = "attribute" + access = "read" if isinstance(node.ctx, ast.Load) else "write" + elif isinstance(node, ast.keyword) and node.arg in FIELDS: + name, ctx, access = node.arg, "dict-or-call-keyword", "construct" + if name is not None: + line = text.splitlines()[node.lineno - 1].strip() + sites.append({ + "line": node.lineno, "name": name, "field": FIELD_PATHS[name], + "context": ctx, "access": access, "code": line[:160], + }) + sites.sort(key=lambda s: (s["line"], s["name"], s["context"])) + return sites + + +def const_key_bindings(tree): + """Map variable names bound to constant string collections (for-loops and + assignments), so bounded dynamic subscripts can be resolved to finite key sets.""" + binds = {} + for node in ast.walk(tree): + if isinstance(node, ast.For) and isinstance(node.target, ast.Name): + vals = const_str_set(node.iter) + if vals is not None: + binds.setdefault(node.target.id, set()).update(vals) + if isinstance(node, ast.Assign): + vals = const_str_set(node.value) + if vals is not None: + for tgt in node.targets: + if isinstance(tgt, ast.Name): + binds.setdefault(tgt.id, set()).update(vals) + return binds + + +def const_str_set(expr): + if isinstance(expr, (ast.Tuple, ast.List, ast.Set)): + vals = [] + for el in expr.elts: + if isinstance(el, ast.Constant) and isinstance(el.value, str): + vals.append(el.value) + else: + return None + return vals + return None + + +def dynamic_sites(text, roots): + """Dynamic accesses and whole-object channels on template variables (S3).""" + if not roots: + return [] + tree = ast.parse(text) + keybinds = const_key_bindings(tree) + + def resolve_keys(expr): + """Finite key set for a dynamic subscript slice, or None.""" + if isinstance(expr, ast.Name) and expr.id in keybinds: + return sorted(keybinds[expr.id]) + return None + + out = [] + lines = text.splitlines() + for node, parents in walk_with_parents(tree): + kind = None + detail = "" + keys = None + if isinstance(node, ast.Subscript): + sp = static_path(node.value, set(roots)) + if sp is not None and not (isinstance(node.slice, ast.Constant) and isinstance(node.slice.value, str)): + top = sp[0] == "top" + keys = resolve_keys(node.slice) + if keys is not None: + kind = "subscript-bounded-top" if top else "subscript-bounded-path" + detail = sp[1] + ("" if top else "." + sp[2]) + " keys=" + ",".join(keys) + else: + kind = "subscript-dynamic-top" if top else "subscript-dynamic-path" + detail = sp[1] + ("" if top else "." + sp[2]) + elif isinstance(node, (ast.For, ast.comprehension)): + sp = static_path(node.iter, set(roots)) + if sp is not None: + top = sp[0] == "top" + kind = "iter-top" if top else "iter-path" + detail = sp[1] + ("" if top else "." + sp[2]) + elif isinstance(node, ast.Dict): + for k, v in zip(node.keys, node.values): + if k is None: + sp = static_path(v, set(roots)) + if sp is not None: + kind = "dict-unpack" + detail = sp[1] + elif isinstance(node, ast.Call): + fn = node.func.attr if isinstance(node.func, ast.Attribute) else (node.func.id if isinstance(node.func, ast.Name) else "") + for arg in list(node.args) + [k.value for k in node.keywords]: + sp = static_path(arg, set(roots)) + if sp is None: + continue + if fn in HASH_CALLS or fn in HASH_HELPERS: + kind = "hash-of-arg" + elif fn in ("dumps", "dump", "loads", "load"): + kind = "json-of-arg" + elif fn in ("deepcopy", "copy"): + kind = "deepcopy-of-arg" + elif fn == "sorted": + kind = "sorted-of-arg" + elif fn in ("str", "repr", "len", "list", "tuple", "set", "dict"): + kind = "convert-of-arg" + if kind: + detail = sp[1] + ("" if sp[0] == "top" else "." + sp[2]) + elif isinstance(node, ast.Compare): + for operand in [node.left] + list(node.comparators): + sp = static_path(operand, set(roots)) + if sp is not None: + kind = "compare-operand" + detail = sp[1] + ("" if sp[0] == "top" else "." + sp[2]) + if kind: + lineno = getattr(node, "lineno", None) + if lineno is None and hasattr(node, "iter"): + lineno = node.iter.lineno + out.append({ + "line": lineno, "kind": kind, "on": detail, + "keys": sorted(keys) if kind.startswith("subscript-bounded") else None, + "code": lines[lineno - 1].strip()[:160], + }) + out.sort(key=lambda s: (s["line"], s["kind"], s["on"])) + return out + + +def build_inventory(): + universe = load_universe() + inv = { + "universe_sha256": {label: digest for label, (_, digest) in sorted(universe.items())}, + "archive_sha256": sha256_bytes((ROOT / ARCHIVE).read_bytes()), + "channel_pins": [list(p) for p in CHANNEL_PINS], + "post_emit_closure": {rel: universe["archive:" + rel][1] for rel in POST_EMIT_CLOSURE}, + "template_vars": TEMPLATE_VARS, + "post_emit_name_sites": {}, + "universe_name_sites": {}, + "post_emit_dynamic_sites": {}, + } + for label, needle in CHANNEL_PINS: + if needle not in universe[label][0]: + raise AssertionError("channel pin missing from " + label + ": " + needle) + for label, (text, _) in sorted(universe.items()): + sites = name_sites(text) + if sites: + inv["universe_name_sites"][label] = sites + for rel in POST_EMIT_CLOSURE: + text = universe["archive:" + rel][0] + inv["post_emit_name_sites"][rel] = name_sites(text) + inv["post_emit_dynamic_sites"][rel] = dynamic_sites(text, TEMPLATE_VARS[rel]) + return inv + + +def detector_self_test(): + """S4: every probe form must be detected (corruption control).""" + probes = { + "probe_subscript": ("def f(ct):\n return ct['cover']\n", "name", "subscript-key", "read"), + "probe_attribute": ("def f(t):\n return t.owner_map_sha256\n", "name", "attribute", "read"), + "probe_keyword": ("def f():\n return dict(rule='x')\n", "name", "dict-or-call-keyword", "construct"), + "probe_dict_key": ("def f():\n return {'version': 1}\n", "name", "dict-literal-key", "construct"), + "probe_get": ("def f(t):\n return t.get('replica_lift')\n", "name", "call-arg:get", "read"), + "probe_write": ("def f(t):\n t['cover'] = 1\n", "name", "subscript-key", "write"), + "probe_compare": ("def f(t):\n return 'port_restriction' in t\n", "name", "membership-or-compare", "test"), + "probe_dyn_top": ("def f(t, k):\n return t[k]\n", "dyn", "subscript-dynamic-top", None), + "probe_bounded_top": ("def f(t):\n for k in ('a', 'b'):\n assert t[k] == 1\n", "dyn", "subscript-bounded-top", None), + "probe_iter_top": ("def f(t):\n return [x for x in t]\n", "dyn", "iter-top", None), + "probe_hash_top": ("def f(t):\n return sha256(t)\n", "dyn", "hash-of-arg", None), + } + bad = [] + for label, (src, mode, want, want_access) in probes.items(): + if mode == "name": + sites = name_sites(src) + got = [(s["context"], s["access"]) for s in sites] + if (want, want_access) not in got: + bad.append((label, (want, want_access), got)) + else: + got = [s["kind"] for s in dynamic_sites(src, ["t", "ct"])] + if want not in got: + bad.append((label, want, got)) + return bad + + +def main(): + if sys.stdout.encoding and sys.stdout.encoding.lower() != "utf-8": + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") + bad = detector_self_test() + if bad: + for label, want, got in bad: + print("SELF-TEST MISS", label, "want", want, "got", got) + print("FAIL_POSTEMIT_FIELD_READSET_SELFTEST") + raise SystemExit(1) + inv = build_inventory() + expected_path = PKG / "EXPECTED.json" + if "--write" in sys.argv: + expected_path.write_text(json.dumps(inv, indent=1, sort_keys=True) + "\n", encoding="utf-8") + print("WROTE", expected_path) + expected = json.loads(expected_path.read_text(encoding="utf-8")) + if inv != expected: + for section in sorted(set(inv) | set(expected)): + if inv.get(section) != expected.get(section): + print("MISMATCH section:", section) + print("FAIL_POSTEMIT_FIELD_READSET_MISMATCH") + raise SystemExit(1) + # S1: no semantic read/test of any of the 15 names in the post-emit closure. + # The only tolerated occurrences are output-receipt construction keys + # (access == "construct"); every other access class fails the claim. + for rel, sites in inv["post_emit_name_sites"].items(): + for s in sites: + if s["access"] != "construct": + print("POST-EMIT NAME SITE", rel, s["line"], s["name"], s["context"], s["access"], s["code"]) + print("FAIL_POSTEMIT_FIELD_READSET_NAMES") + raise SystemExit(1) + # S3: no unbounded top-level dynamic read/iteration/hash of the template + # object itself, and no bounded dynamic key set touching the 15 fields. + for rel, sites in inv["post_emit_dynamic_sites"].items(): + for s in sites: + if s["kind"] in ("subscript-dynamic-top", "iter-top", "hash-of-arg") and "." not in s["on"]: + print("TOP-LEVEL DYNAMIC CHANNEL", rel, s["line"], s["kind"], s["on"], s["code"]) + print("FAIL_POSTEMIT_FIELD_READSET_DYNAMIC") + raise SystemExit(1) + if s["keys"] and set(s["keys"]) & set(FIELDS): + print("BOUNDED KEYS HIT FIELD", rel, s["line"], s["keys"], s["code"]) + print("FAIL_POSTEMIT_FIELD_READSET_DYNAMIC") + raise SystemExit(1) + n_universe = sum(len(v) for v in inv["universe_name_sites"].values()) + n_dyn = sum(len(v) for v in inv["post_emit_dynamic_sites"].values()) + print("universe files:", len(inv["universe_sha256"])) + print("universe name-directed sites (all classified and pinned):", n_universe) + print("post-emit name-directed sites:", sum(len(v) for v in inv["post_emit_name_sites"].values())) + print("post-emit dynamic/whole-object sites (pinned):", n_dyn) + print("PASS_POSTEMIT_FIELD_READSET") + + +if __name__ == "__main__": + main()