Jessedbrown Claude Fable 5 commited on
Commit
a3cd5e5
·
1 Parent(s): 3bd58b0

acer: harden nnest watcher-gate tuple shape (3 findings vs liris patch)

Browse files

Adversarial readback of liris exact-tuple patch found three real bypasses of
the Object.keys check: (1) accessor/getter tuple splitting check-time from
use-time (TOCTOU) -> CHILD_MAY_ACT with chain_sha16 != verified content;
(2) non-enumerable own field smuggled past exact-shape; (3) symbol-keyed field
smuggled. Fix: single-read frozen snapshot via getOwnPropertyNames +
getOwnPropertySymbols + data-descriptor-only; materializeChain single index
read neutralizes proxy arrays. 18-case prefix byte-stable, cases 19-21 added,
self-test 12/12, pyramid 105/105.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

canon/laws/LAW-ASOLARIA-NEURAL-NETWORK.md.sha256 CHANGED
@@ -1 +1 @@
1
- c7ca79de0af96147860a4c136869c1ac7f3dc81975c6999f4bdb8e6e2f3612c9 LAW-ASOLARIA-NEURAL-NETWORK.md
 
1
+ C7CA79DE0AF96147860A4C136869C1AC7F3DC81975C6999F4BDB8E6E2F3612C9 LAW-ASOLARIA-NEURAL-NETWORK.md
docs/ACER-NNEST-GATE-HARDEN-2026-06-11.hbp ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ ACERNNESTHARDENHDR|host=acer|date=2026-06-11|pulled_commit=3bd58b0|topic=component-4-nnest-watcher-gate-acer-adversarial-readback-of-liris-exact-tuple-patch|json=0
2
+ ACERNNESTHARDENVERIFY|blob_level_sidecars=ALL_OK|pyramid_at_pull=105of105_PASS|liris_18case_baseline=BYTE_MATCHED_ON_ACER|gate_selftest=PASS|liris_receipt=READ|json=0
3
+ ACERNNESTHARDENCONCEDE|liris_three_findings=CONFIRMED_REAL_AND_KEPT|F1-extra-enumerable-field=HELD|F2-prototype-inherited=HELD|F3-invalid-hash-not-digested=chain_sha16-none|operator_topology_law=PRESERVED|json=0
4
+ ACERNNESTHARDENFINDINGS|acer_three_NEW_findings_against_liris_patch=THREE_REAL|F1=accessor(getter)tuple-Object.keys-counts-3-keys-but-value-read-MULTIPLE-times-split-check-from-use-granted-CHILD_MAY_ACT-with-chain_sha16-NE-honestly-verified-content(TOCTOU-integrity-break)|F2=non-enumerable-own-field-invisible-to-Object.keys-smuggled-past-exact-shape|F3=symbol-keyed-own-field-invisible-to-Object.keys-smuggled|verdict=THREE_REAL_PATCHED|json=0
5
+ ACERNNESTHARDENPATCH|root_cause=Object.keys-only-counts-enumerable-string-keys-AND-fields-read-more-than-once|fix=snapshotTuple-reads-each-tuple-EXACTLY-ONCE-into-frozen-prototype-free-3-field-object|rejects=non-plain-object+wrong-prototype+symbol-keys+extra-or-non-enumerable-keys(getOwnPropertyNames)+accessor-descriptors(data-value-only)|materializeChain=single-index-read-neutralizes-proxy-arrays|all-bypasses=now-CHILD_HELD-chain-topology-invalid-with-first_bad_depth|json=0
6
+ ACERNNESTHARDENPROBES|F1-getter-now=CHILD_HELD/chain-topology-invalid@1|F2-nonenum-now=CHILD_HELD/chain-topology-invalid|F3-symbol-now=CHILD_HELD/chain-topology-invalid|proxy-array-now=CHILD_MAY_ACT-SAFELY(single-read-froze-honest-content-no-integrity-split)|18-case-prefix=BYTE-STABLE|new-parity-cases=19+20+21|selftest=12of12_PASS|json=0
7
+ ACERNNESTHARDENDOCTRINE|operator_amendment_preserved=hash-match-AND-topology|strengthened=topology-means-EXACT-3-field-plain-DATA-tuple-single-read-snapshot-not-just-3-enumerable-keys|consent_anchor=still-DEFER_TO_OPERATOR-at-apex-T0|executable=0-every-row|json=0
8
+ ACERNNESTHARDENSAFETY|repo_side_only=1|untouched=process-spawn+real-agent-recursion+harness-edits+mint+USB+engine+apex-T0|mutates=receipt+tool+test-files-only|json=0
9
+ ACERNNESTHARDENFTR|state=COMPONENT_4_ACER_HARDENING_READY_FOR_LIRIS_PULL_AND_COUNTER_VERIFY|json=0
docs/ACER-NNEST-GATE-HARDEN-2026-06-11.hbp.sha256 ADDED
@@ -0,0 +1 @@
 
 
1
+ 265895EA76C71BE3C3960E5D110482903D26B6559465FA45F15E3F8D81A7C353 ACER-NNEST-GATE-HARDEN-2026-06-11.hbp
docs/NNEST-WATCHER-GATE-PARITY-BASELINE-2026-06-11.hbp CHANGED
@@ -1,4 +1,4 @@
1
- NNESTGATEPARITYHDR|component=4|cases=18|clock=none-time-free-contract|rule=rows-byte-identical-on-every-machine|json=0
2
  NNESTGATEPARITY|case=01|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=502e00a9b19e839d|verdict=CHILD_MAY_ACT|first_bad_depth=none|gate=none|executable=0|json=0
3
  NNESTGATEPARITY|case=02|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=16|chain_len=17|chain_sha16=58b859999d5e364a|verdict=CHILD_MAY_ACT|first_bad_depth=none|gate=none|executable=0|json=0
4
  NNESTGATEPARITY|case=03|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=f4579dd9c63399f5|verdict=CHILD_HELD|first_bad_depth=2|gate=hash-divergence|executable=0|json=0
@@ -17,4 +17,7 @@ NNESTGATEPARITY|case=15|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|
17
  NNESTGATEPARITY|case=16|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=0|chain_len=1|chain_sha16=8f6d8d4eca0f9e07|verdict=CHILD_MAY_ACT|first_bad_depth=none|gate=none|executable=0|json=0
18
  NNESTGATEPARITY|case=17|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=none|verdict=CHILD_HELD|first_bad_depth=1|gate=chain-topology-invalid|executable=0|json=0
19
  NNESTGATEPARITY|case=18|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=none|verdict=CHILD_HELD|first_bad_depth=0|gate=chain-topology-invalid|executable=0|json=0
20
- NNESTGATEPARITYFTR|cases=18|exit=byte-match-when-regenerated-file-equals-sealed-baseline|json=0
 
 
 
 
1
+ NNESTGATEPARITYHDR|component=4|cases=21|clock=none-time-free-contract|rule=rows-byte-identical-on-every-machine|json=0
2
  NNESTGATEPARITY|case=01|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=502e00a9b19e839d|verdict=CHILD_MAY_ACT|first_bad_depth=none|gate=none|executable=0|json=0
3
  NNESTGATEPARITY|case=02|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=16|chain_len=17|chain_sha16=58b859999d5e364a|verdict=CHILD_MAY_ACT|first_bad_depth=none|gate=none|executable=0|json=0
4
  NNESTGATEPARITY|case=03|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=f4579dd9c63399f5|verdict=CHILD_HELD|first_bad_depth=2|gate=hash-divergence|executable=0|json=0
 
17
  NNESTGATEPARITY|case=16|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=0|chain_len=1|chain_sha16=8f6d8d4eca0f9e07|verdict=CHILD_MAY_ACT|first_bad_depth=none|gate=none|executable=0|json=0
18
  NNESTGATEPARITY|case=17|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=none|verdict=CHILD_HELD|first_bad_depth=1|gate=chain-topology-invalid|executable=0|json=0
19
  NNESTGATEPARITY|case=18|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=none|verdict=CHILD_HELD|first_bad_depth=0|gate=chain-topology-invalid|executable=0|json=0
20
+ NNESTGATEPARITY|case=19|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=none|verdict=CHILD_HELD|first_bad_depth=1|gate=chain-topology-invalid|executable=0|json=0
21
+ NNESTGATEPARITY|case=20|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=none|verdict=CHILD_HELD|first_bad_depth=2|gate=chain-topology-invalid|executable=0|json=0
22
+ NNESTGATEPARITY|case=21|agent=AGT-NNEST-PROBE-0001|action=report-up|max_depth=3|chain_len=4|chain_sha16=none|verdict=CHILD_HELD|first_bad_depth=0|gate=chain-topology-invalid|executable=0|json=0
23
+ NNESTGATEPARITYFTR|cases=21|exit=byte-match-when-regenerated-file-equals-sealed-baseline|json=0
docs/NNEST-WATCHER-GATE-PARITY-BASELINE-2026-06-11.hbp.sha256 CHANGED
@@ -1 +1 @@
1
- C892061D939D3BC32C09EE332B85B2FE2A4540D1EC01FDFEBF1E3C1B44AC97AD NNEST-WATCHER-GATE-PARITY-BASELINE-2026-06-11.hbp
 
1
+ 88F20CBEC126E5194B1C1D04BC83674765DDEC4C0BBBA51DD4E7EFBC4A59F3C7 NNEST-WATCHER-GATE-PARITY-BASELINE-2026-06-11.hbp
specs/SUPERVISOR-COLLISION-ROUTER-SPEC.hbp.sha256 CHANGED
@@ -1 +1 @@
1
- DB7D0E870A9DC4EE8E171B2948825EBE3BED63F1ABF92650BEC028C1D15404B3 SUPERVISOR-COLLISION-ROUTER-SPEC.hbp
 
1
+ DB7D0E870A9DC4EE8E171B2948825EBE3BED63F1ABF92650BEC028C1D15404B3 SUPERVISOR-COLLISION-ROUTER-SPEC.hbp
tests/supervisor-collision-router.fabric.test.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- FE5068E945E1FF147C4FDD0ACF66D42F1908168E1D9A611E307575C6D77AE959 supervisor-collision-router.fabric.test.mjs
 
1
+ FE5068E945E1FF147C4FDD0ACF66D42F1908168E1D9A611E307575C6D77AE959 supervisor-collision-router.fabric.test.mjs
tests/supervisor-collision-router.integration.test.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- DC18C3F7320117A970614BEC4F80569D6E962F1B94492529A890DB83B02E324C supervisor-collision-router.integration.test.mjs
 
1
+ DC18C3F7320117A970614BEC4F80569D6E962F1B94492529A890DB83B02E324C supervisor-collision-router.integration.test.mjs
tests/supervisor-collision-router.suite.test.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- 6F3BB0F545117812E5DC88E4A9D2AAC2F2BB42A15DB0EC3A7433948974E317EB supervisor-collision-router.suite.test.mjs
 
1
+ 6F3BB0F545117812E5DC88E4A9D2AAC2F2BB42A15DB0EC3A7433948974E317EB supervisor-collision-router.suite.test.mjs
tests/supervisor-collision-router.system.test.mjs CHANGED
@@ -39,6 +39,7 @@ const sealedFiles = [
39
  'docs/NNEST-WATCHER-GATE-PARITY-BASELINE-2026-06-11.hbp',
40
  'docs/ACER-NNEST-GATE-SEED-2026-06-11.hbp',
41
  'docs/LIRIS-NNEST-GATE-READBACK-2026-06-11.hbp',
 
42
  'docs/LIRIS-WATCHER-SUPERVISOR-READBACK-2026-06-11.hbp',
43
  'docs/ACER-READBACK-WATCHER-SUPERVISOR-2026-06-11.hbp',
44
  'docs/LIRIS-STEP166-PARITY-CONFIRMED-2026-06-11.hbp',
 
39
  'docs/NNEST-WATCHER-GATE-PARITY-BASELINE-2026-06-11.hbp',
40
  'docs/ACER-NNEST-GATE-SEED-2026-06-11.hbp',
41
  'docs/LIRIS-NNEST-GATE-READBACK-2026-06-11.hbp',
42
+ 'docs/ACER-NNEST-GATE-HARDEN-2026-06-11.hbp',
43
  'docs/LIRIS-WATCHER-SUPERVISOR-READBACK-2026-06-11.hbp',
44
  'docs/ACER-READBACK-WATCHER-SUPERVISOR-2026-06-11.hbp',
45
  'docs/LIRIS-STEP166-PARITY-CONFIRMED-2026-06-11.hbp',
tests/supervisor-collision-router.system.test.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- 43362538920775E6B52C7A9B9C29F1DF614CC5B934FE3925A70976250D55E26C supervisor-collision-router.system.test.mjs
 
1
+ 5098F2E4AC1539D143163B9B735439E1D8CCE753AD442F2CB629F475BB5C45E8 supervisor-collision-router.system.test.mjs
tests/supervisor-collision-router.unit.test.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- C6918820C58ED52939643A82E17D055EBC4F0ED78A4604BB464CA607AEAA2D3F supervisor-collision-router.unit.test.mjs
 
1
+ C6918820C58ED52939643A82E17D055EBC4F0ED78A4604BB464CA607AEAA2D3F supervisor-collision-router.unit.test.mjs
tools/behcs/nnest-watcher-gate.hbi CHANGED
@@ -1,12 +1,13 @@
1
- NNESTGATEINDEX|host=acer|target=nnest-watcher-gate.hbp|tool=nnest-watcher-gate.mjs|rows=11|json=0
2
  INDEXROW|row=1|kind=header|component=architecture-component-4|json=0
3
- INDEXROW|row=2|kind=law|may_act=hash-match-AND-topology-valid-and-exact-tuples|hashes=necessary-not-sufficient|json=0
4
  INDEXROW|row=3|kind=scope|repo_side_draft_only=1|no_spawn=1|no_harness_edit=1|json=0
5
  INDEXROW|row=4|kind=ladder|rungs=9|topology_before_hashes=1|json=0
6
  INDEXROW|row=5|kind=table|actions_free=3|actions_consent=3|consent_cap=DEFER|json=0
7
  INDEXROW|row=6|kind=bound|max_depth=16-proven|json=0
8
  INDEXROW|row=7|kind=leak|held_rows=first_bad_depth+chain_sha16-only|noncanonical_chain_sha16=none|json=0
9
- INDEXROW|row=8|kind=safety|mutates=0|pure_function=1|json=0
10
- INDEXROW|row=9|kind=verify|required=node-check+node-test+self-test+parity-byte-compare|json=0
11
- INDEXROW|row=10|kind=sha|fields=gate_sha256+test_sha256|json=0
12
- INDEXROW|row=11|kind=footer|state=COMPONENT_4_LIRIS_EXACT_TUPLE_PATCH_READY_FOR_ACER_READBACK|json=0
 
 
1
+ NNESTGATEINDEX|host=acer|target=nnest-watcher-gate.hbp|tool=nnest-watcher-gate.mjs|rows=12|json=0
2
  INDEXROW|row=1|kind=header|component=architecture-component-4|json=0
3
+ INDEXROW|row=2|kind=law|may_act=hash-match-AND-topology-valid-and-exact-3-field-plain-data-tuples-single-read|hashes=necessary-not-sufficient|json=0
4
  INDEXROW|row=3|kind=scope|repo_side_draft_only=1|no_spawn=1|no_harness_edit=1|json=0
5
  INDEXROW|row=4|kind=ladder|rungs=9|topology_before_hashes=1|json=0
6
  INDEXROW|row=5|kind=table|actions_free=3|actions_consent=3|consent_cap=DEFER|json=0
7
  INDEXROW|row=6|kind=bound|max_depth=16-proven|json=0
8
  INDEXROW|row=7|kind=leak|held_rows=first_bad_depth+chain_sha16-only|noncanonical_chain_sha16=none|json=0
9
+ INDEXROW|row=8|kind=harden|acer-findings=accessor-toctou+non-enumerable-own+symbol-keyed|fix=single-read-snapshot-data-descriptor-only|json=0
10
+ INDEXROW|row=9|kind=safety|mutates=0|pure_function=1|json=0
11
+ INDEXROW|row=10|kind=verify|required=node-check+node-test+self-test+parity-byte-compare|json=0
12
+ INDEXROW|row=11|kind=sha|fields=gate_sha256+test_sha256|json=0
13
+ INDEXROW|row=12|kind=footer|state=COMPONENT_4_ACER_TUPLE_SHAPE_HARDENING_READY_FOR_LIRIS_READBACK|json=0
tools/behcs/nnest-watcher-gate.hbi.sha256 CHANGED
@@ -1 +1 @@
1
- CC1541258DED6C19A80D76C97AB38C580A1810F3EBDE868CE1523DB16B8F1A87 nnest-watcher-gate.hbi
 
1
+ B1A91A33A0AB317B52228E7C099196A9299D5543D66112C088F3E21021BD0C52 nnest-watcher-gate.hbi
tools/behcs/nnest-watcher-gate.hbp CHANGED
@@ -1,11 +1,12 @@
1
  NNESTGATEHDR|host=acer|component=architecture-component-4|tool=tools/behcs/nnest-watcher-gate.mjs|purpose=n-nest-watcher-gate-child-acts-only-if-reported-equals-recomputed-at-every-level|json=0
2
- NNESTGATELAW|may_act_requires=BOTH(hash-match-every-level)AND(chain-complete-contiguous-unique-ordered-depth-0-to-max+exact-own-field-tuples)|hashes=necessary-but-NOT-sufficient|topology_violations=CHILD_HELD-chain-topology-invalid-with-first_bad_depth(never-merely-malformed)|source=OP-JESSE-amendment-2026-06-11+liris-exact-tuple-patch|composes=TARGET-ARCHITECTURE-VISION-2026-06-10(COMPONENT-4)+N-Nest-Prime-proof(depth-16-2732-files-131071-nodes)+LAW-RECURRENCE-IS-MIND|json=0
3
  NNESTGATESCOPE_DOC|repo_side_draft_only=1|never=process-spawn+recursion-into-real-agents+harness-edits|gate-emits-verdict-rows-it-never-acts|live_harness_embedding=SEPARATE-GATED-FOLLOW-UP-operator-signoff|json=0
4
  NNESTGATELADDER|rungs=9|order=dirty-HELD+malformed-agent-HELD+unknown-action-HELD+invalid-max-depth-HELD+empty-chain-HELD+TOPOLOGY-HELD(first_bad_depth)+hash-format-HELD(first_bad_depth)+hash-divergence-HELD(first_bad_depth)+consent-DEFER+honest-free-CHILD_MAY_ACT|topology_before_hashes=BY-DESIGN|json=0
5
  NNESTGATETABLE|actions_free=observe+report-up+draft-row|actions_consent=act-on-world+spawn-child+modify-self|consent_cap=DEFER_TO_OPERATOR-even-on-perfect-chain(consent-anchors-at-apex-T0-only)|membership=DRAFT_ASSUMPTION-bilateral-contest-welcome|json=0
6
  NNESTGATEBOUND|max_depth=16|why=the-PROVEN-N-Nest-Prime-depth|beyond=CHILD_HELD-invalid-max-depth|json=0
7
  NNESTGATELEAK_DOC|held_rows_carry=first_bad_depth+chain_sha16-only|chain_sha16=none-for-noncanonical-or-invalid-hash-chains|level_hashes=NEVER-echoed-into-rows|catch-at-exact-level=preserved(first_bad_depth-names-the-divergent-depth)|json=0
 
8
  NNESTGATESAFETY|mutates=0|pure_function=1|time_free_contract=1|no_spawn=1|no_recursion_into_real_agents=1|no_harness_edit=1|mints=0|launches=0|usb_writes=0|engine_edits=0|external_calls=0|json=0
9
  NNESTGATEVERIFY|required=node-check+node-test+self-test+parity-byte-compare|parity_baseline=docs/NNEST-WATCHER-GATE-PARITY-BASELINE-2026-06-11.hbp|clock=none-time-free|json=0
10
- NNESTGATESHA|gate_sha256=5BF054CD04C33AD59A8F5F54294C4FACD2D5068E40AEBC18489913BD727D152A|test_sha256=FE5CEAD6034E316F51AA9C72EC05916EBA65349559817B5657C23138B3D79218|json=0
11
- NNESTGATEFTR|state=COMPONENT_4_LIRIS_EXACT_TUPLE_PATCH_READY_FOR_ACER_READBACK|json=0
 
1
  NNESTGATEHDR|host=acer|component=architecture-component-4|tool=tools/behcs/nnest-watcher-gate.mjs|purpose=n-nest-watcher-gate-child-acts-only-if-reported-equals-recomputed-at-every-level|json=0
2
+ NNESTGATELAW|may_act_requires=BOTH(hash-match-every-level)AND(chain-complete-contiguous-unique-ordered-depth-0-to-max+exact-3-field-plain-DATA-tuples-single-read-snapshot)|hashes=necessary-but-NOT-sufficient|topology_violations=CHILD_HELD-chain-topology-invalid-with-first_bad_depth(never-merely-malformed)|source=OP-JESSE-amendment-2026-06-11+liris-exact-tuple-patch+acer-tuple-shape-hardening|composes=TARGET-ARCHITECTURE-VISION-2026-06-10(COMPONENT-4)+N-Nest-Prime-proof(depth-16-2732-files-131071-nodes)+LAW-RECURRENCE-IS-MIND|json=0
3
  NNESTGATESCOPE_DOC|repo_side_draft_only=1|never=process-spawn+recursion-into-real-agents+harness-edits|gate-emits-verdict-rows-it-never-acts|live_harness_embedding=SEPARATE-GATED-FOLLOW-UP-operator-signoff|json=0
4
  NNESTGATELADDER|rungs=9|order=dirty-HELD+malformed-agent-HELD+unknown-action-HELD+invalid-max-depth-HELD+empty-chain-HELD+TOPOLOGY-HELD(first_bad_depth)+hash-format-HELD(first_bad_depth)+hash-divergence-HELD(first_bad_depth)+consent-DEFER+honest-free-CHILD_MAY_ACT|topology_before_hashes=BY-DESIGN|json=0
5
  NNESTGATETABLE|actions_free=observe+report-up+draft-row|actions_consent=act-on-world+spawn-child+modify-self|consent_cap=DEFER_TO_OPERATOR-even-on-perfect-chain(consent-anchors-at-apex-T0-only)|membership=DRAFT_ASSUMPTION-bilateral-contest-welcome|json=0
6
  NNESTGATEBOUND|max_depth=16|why=the-PROVEN-N-Nest-Prime-depth|beyond=CHILD_HELD-invalid-max-depth|json=0
7
  NNESTGATELEAK_DOC|held_rows_carry=first_bad_depth+chain_sha16-only|chain_sha16=none-for-noncanonical-or-invalid-hash-chains|level_hashes=NEVER-echoed-into-rows|catch-at-exact-level=preserved(first_bad_depth-names-the-divergent-depth)|json=0
8
+ NNESTGATEHARDEN_DOC|acer-findings-2026-06-11=THREE-real-bypasses-of-liris-Object.keys-check|F1=accessor(getter)-tuple-split-check-from-use-TOCTOU-granted-CHILD_MAY_ACT-with-chain_sha16-ne-verified-content|F2=non-enumerable-own-field-smuggled-past-exact-shape|F3=symbol-keyed-field-smuggled|fix=single-read-frozen-snapshot+getOwnPropertyNames+getOwnPropertySymbols+data-descriptor-only|proxy-array=neutralized-by-single-index-read|parity_cases_added=19+20+21|json=0
9
  NNESTGATESAFETY|mutates=0|pure_function=1|time_free_contract=1|no_spawn=1|no_recursion_into_real_agents=1|no_harness_edit=1|mints=0|launches=0|usb_writes=0|engine_edits=0|external_calls=0|json=0
10
  NNESTGATEVERIFY|required=node-check+node-test+self-test+parity-byte-compare|parity_baseline=docs/NNEST-WATCHER-GATE-PARITY-BASELINE-2026-06-11.hbp|clock=none-time-free|json=0
11
+ NNESTGATESHA|gate_sha256=81602D6027A19941A38C910D32F8971CEDA137B6EA42FB55210FD3B8024956C7|test_sha256=FE5CEAD6034E316F51AA9C72EC05916EBA65349559817B5657C23138B3D79218|json=0
12
+ NNESTGATEFTR|state=COMPONENT_4_ACER_TUPLE_SHAPE_HARDENING_READY_FOR_LIRIS_READBACK|json=0
tools/behcs/nnest-watcher-gate.hbp.sha256 CHANGED
@@ -1 +1 @@
1
- 3CB8CD5FE5ED175B4D0BFC213F4A3D50B00D5FABA4EC183E99024171978DA0FB nnest-watcher-gate.hbp
 
1
+ EC5D5CED95E47D93C32D10F362B3E7704EFD073188438B381259EFF5D79EFBDC nnest-watcher-gate.hbp
tools/behcs/nnest-watcher-gate.mjs CHANGED
@@ -53,22 +53,41 @@ function echoField(value, validator) {
53
  return validator(clean) ? clean : 'invalid';
54
  }
55
 
56
- function isExactTuple(tuple) {
57
- if (!tuple || typeof tuple !== 'object' || Array.isArray(tuple)) return false;
58
- if (Object.getPrototypeOf(tuple) !== Object.prototype) return false;
59
- const keys = Object.keys(tuple);
60
- return keys.length === TUPLE_KEYS.length && TUPLE_KEYS.every((key) => Object.hasOwn(tuple, key));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
 
63
- function isDigestibleTuple(tuple) {
64
- return isExactTuple(tuple)
65
- && Number.isInteger(tuple.depth)
66
- && typeof tuple.reported_sha16 === 'string'
67
- && typeof tuple.recomputed_sha16 === 'string'
68
- && !DIRTY_RE.test(tuple.reported_sha16)
69
- && !DIRTY_RE.test(tuple.recomputed_sha16)
70
- && HASH_RE.test(tuple.reported_sha16)
71
- && HASH_RE.test(tuple.recomputed_sha16);
 
72
  }
73
 
74
  // chain_sha16 is the only chain-derived value a row may carry: a digest of
@@ -76,20 +95,26 @@ function isDigestibleTuple(tuple) {
76
  // name first_bad_depth (the proven catch-at-exact-level behavior) and
77
  // nothing else about the chain's content. Noncanonical or invalid-hash chains
78
  // produce chain_sha16=none so HELD rows cannot become digest oracles.
79
- function chainDigest(chain) {
80
- if (!Array.isArray(chain) || chain.length === 0) return 'none';
81
- if (!chain.every(isDigestibleTuple)) return 'none';
82
- return sha16(JSON.stringify(chain.map((t) => [t.depth, t.reported_sha16, t.recomputed_sha16])));
 
 
 
 
 
 
 
83
  }
84
 
85
- function buildResult(inp, verdict, gates, firstBadDepth) {
86
- const chain = Array.isArray(inp.chain) ? inp.chain : [];
87
  const fields = {
88
  agent: echoField(inp.agent, (v) => AGENT_ID_RE.test(v)),
89
  action: echoField(inp.action, (v) => Object.hasOwn(ACTIONS, v)),
90
  max_depth: Number.isInteger(inp.max_depth) && inp.max_depth >= 0 && inp.max_depth <= MAX_DEPTH_BOUND ? inp.max_depth : 'invalid',
91
- chain_len: chain.length,
92
- chain_sha16: chainDigest(inp.chain),
93
  verdict,
94
  first_bad_depth: firstBadDepth ?? 'none',
95
  gate: gates.length ? gates.join('+') : 'none',
@@ -112,7 +137,8 @@ function buildResult(inp, verdict, gates, firstBadDepth) {
112
 
113
  export function gateChain(input) {
114
  const inp = input ?? {};
115
- const held = (gate, firstBadDepth) => buildResult(inp, 'CHILD_HELD', [gate], firstBadDepth);
 
116
 
117
  // Rung 1: dirty top-level strings never reach a row.
118
  for (const field of ['agent', 'action']) {
@@ -132,19 +158,21 @@ export function gateChain(input) {
132
  }
133
 
134
  // Rung 5: a chain must exist.
135
- if (!Array.isArray(inp.chain) || inp.chain.length === 0) return held('empty-or-missing-chain');
136
 
137
- // Rung 6: OPERATOR INVARIANT -- topology before hashes. The chain must be
138
- // complete, contiguous, unique, and ordered: position i carries depth i,
139
- // for every i in 0..max_depth, and nothing beyond. The single ordered
140
- // pass makes truncation, duplication, skips, and reorders all land here.
141
- if (inp.chain.length !== inp.max_depth + 1) {
142
- const firstBad = inp.chain.length < inp.max_depth + 1 ? inp.chain.length : inp.max_depth + 1;
 
 
143
  return held('chain-topology-invalid', firstBad);
144
  }
145
  for (let i = 0; i <= inp.max_depth; i += 1) {
146
- const tuple = inp.chain[i];
147
- if (!isExactTuple(tuple) || tuple.depth !== i) {
148
  return held('chain-topology-invalid', i);
149
  }
150
  if (!HASH_RE.test(tuple.reported_sha16 ?? '') || !HASH_RE.test(tuple.recomputed_sha16 ?? '')) {
@@ -155,7 +183,7 @@ export function gateChain(input) {
155
  // Rung 7: hash agreement at EVERY level -- first divergence is named
156
  // exactly (the planted-confab-caught-at-exact-level behavior).
157
  for (let i = 0; i <= inp.max_depth; i += 1) {
158
- if (inp.chain[i].reported_sha16 !== inp.chain[i].recomputed_sha16) {
159
  return held('hash-divergence', i);
160
  }
161
  }
@@ -163,11 +191,11 @@ export function gateChain(input) {
163
  // Rung 8: consent anchors only at apex-T0. A perfect chain does not
164
  // confer consent -- it only proves the report is honest.
165
  if (ACTIONS[inp.action].consent) {
166
- return buildResult(inp, 'DEFER_TO_OPERATOR', ['consent-anchors-at-apex-T0-only'], null);
167
  }
168
 
169
  // Rung 9: honest report + free action -> the child may act.
170
- return buildResult(inp, 'CHILD_MAY_ACT', [], null);
171
  }
172
 
173
  export function statusRows() {
@@ -217,6 +245,12 @@ const PARITY_CASES = Object.freeze([
217
  { id: '16', input: { ...BASE, max_depth: 0, chain: goodChain(0) } },
218
  { id: '17', input: { ...BASE, chain: (() => { const c = goodChain(3); c[1] = { ...c[1], extra: 'ignored-field-must-hold' }; return c; })() } },
219
  { id: '18', input: { ...BASE, chain: (() => { const c = goodChain(3); c[0] = Object.assign(Object.create({ ...c[0] }), {}); return c; })() } },
 
 
 
 
 
 
220
  ]);
221
 
222
  export function emitParityRows() {
@@ -246,6 +280,31 @@ export function selfTest() {
246
  add('every-row-executable-0', emitParityRows().slice(1, -1).every((row) => row.includes('|executable=0|')));
247
  add('rows-hbp-only', [...statusRows(), ...emitParityRows()].every((row) => row.endsWith('json=0') && !row.includes('{"')));
248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  return { ok: checks.every((check) => check.ok), checks };
250
  }
251
 
 
53
  return validator(clean) ? clean : 'invalid';
54
  }
55
 
56
+ // Each reported tuple is read EXACTLY ONCE into an immutable, prototype-free
57
+ // snapshot. Accessor (getter/setter) fields, non-enumerable own fields, symbol
58
+ // keys, extra keys, and non-plain objects are all rejected here -- so a tuple
59
+ // cannot present one value to the verifier and another to the digest (a
60
+ // time-of-check/time-of-use split), nor smuggle hidden own material past the
61
+ // exact-shape rule. Returns the frozen snapshot, or null if the shape is not an
62
+ // exact three-field plain data object. (acer hardening 2026-06-11: liris's
63
+ // Object.keys check missed accessors, non-enumerable, and symbol own fields.)
64
+ function snapshotTuple(raw) {
65
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;
66
+ if (Object.getPrototypeOf(raw) !== Object.prototype) return null;
67
+ if (Object.getOwnPropertySymbols(raw).length !== 0) return null;
68
+ const names = Object.getOwnPropertyNames(raw);
69
+ if (names.length !== TUPLE_KEYS.length) return null;
70
+ for (const key of TUPLE_KEYS) {
71
+ const desc = Object.getOwnPropertyDescriptor(raw, key);
72
+ if (!desc || !Object.hasOwn(desc, 'value')) return null; // reject accessors
73
+ }
74
+ return Object.freeze({
75
+ depth: raw.depth,
76
+ reported_sha16: raw.reported_sha16,
77
+ recomputed_sha16: raw.recomputed_sha16,
78
+ });
79
  }
80
 
81
+ // The reported chain is materialized ONCE: each index is read a single time and
82
+ // each tuple snapshotted, so a proxy array or live object cannot vary between
83
+ // the topology pass, the hash pass, and the digest. Everything downstream reads
84
+ // only this frozen snapshot, never the caller's original object.
85
+ function materializeChain(rawChain) {
86
+ if (!Array.isArray(rawChain)) return { len: 0, snaps: [] };
87
+ const len = rawChain.length;
88
+ const snaps = new Array(len);
89
+ for (let i = 0; i < len; i += 1) snaps[i] = snapshotTuple(rawChain[i]);
90
+ return { len, snaps };
91
  }
92
 
93
  // chain_sha16 is the only chain-derived value a row may carry: a digest of
 
95
  // name first_bad_depth (the proven catch-at-exact-level behavior) and
96
  // nothing else about the chain's content. Noncanonical or invalid-hash chains
97
  // produce chain_sha16=none so HELD rows cannot become digest oracles.
98
+ function chainDigest(mat) {
99
+ if (mat.len === 0) return 'none';
100
+ for (const t of mat.snaps) {
101
+ if (!t
102
+ || !Number.isInteger(t.depth)
103
+ || typeof t.reported_sha16 !== 'string'
104
+ || typeof t.recomputed_sha16 !== 'string'
105
+ || !HASH_RE.test(t.reported_sha16)
106
+ || !HASH_RE.test(t.recomputed_sha16)) return 'none';
107
+ }
108
+ return sha16(JSON.stringify(mat.snaps.map((t) => [t.depth, t.reported_sha16, t.recomputed_sha16])));
109
  }
110
 
111
+ function buildResult(inp, verdict, gates, firstBadDepth, mat) {
 
112
  const fields = {
113
  agent: echoField(inp.agent, (v) => AGENT_ID_RE.test(v)),
114
  action: echoField(inp.action, (v) => Object.hasOwn(ACTIONS, v)),
115
  max_depth: Number.isInteger(inp.max_depth) && inp.max_depth >= 0 && inp.max_depth <= MAX_DEPTH_BOUND ? inp.max_depth : 'invalid',
116
+ chain_len: mat.len,
117
+ chain_sha16: chainDigest(mat),
118
  verdict,
119
  first_bad_depth: firstBadDepth ?? 'none',
120
  gate: gates.length ? gates.join('+') : 'none',
 
137
 
138
  export function gateChain(input) {
139
  const inp = input ?? {};
140
+ const mat = materializeChain(inp.chain);
141
+ const held = (gate, firstBadDepth) => buildResult(inp, 'CHILD_HELD', [gate], firstBadDepth, mat);
142
 
143
  // Rung 1: dirty top-level strings never reach a row.
144
  for (const field of ['agent', 'action']) {
 
158
  }
159
 
160
  // Rung 5: a chain must exist.
161
+ if (!Array.isArray(inp.chain) || mat.len === 0) return held('empty-or-missing-chain');
162
 
163
+ // Rung 6: OPERATOR INVARIANT -- topology before hashes, read off the frozen
164
+ // snapshot. The chain must be complete, contiguous, unique, and ordered:
165
+ // position i carries depth i, for every i in 0..max_depth, and nothing
166
+ // beyond. A null snapshot (accessor/hidden/symbol/extra/non-plain tuple) is
167
+ // a topology violation too. The single ordered pass makes truncation,
168
+ // duplication, skips, reorders, and shape smuggling all land here.
169
+ if (mat.len !== inp.max_depth + 1) {
170
+ const firstBad = mat.len < inp.max_depth + 1 ? mat.len : inp.max_depth + 1;
171
  return held('chain-topology-invalid', firstBad);
172
  }
173
  for (let i = 0; i <= inp.max_depth; i += 1) {
174
+ const tuple = mat.snaps[i];
175
+ if (!tuple || tuple.depth !== i) {
176
  return held('chain-topology-invalid', i);
177
  }
178
  if (!HASH_RE.test(tuple.reported_sha16 ?? '') || !HASH_RE.test(tuple.recomputed_sha16 ?? '')) {
 
183
  // Rung 7: hash agreement at EVERY level -- first divergence is named
184
  // exactly (the planted-confab-caught-at-exact-level behavior).
185
  for (let i = 0; i <= inp.max_depth; i += 1) {
186
+ if (mat.snaps[i].reported_sha16 !== mat.snaps[i].recomputed_sha16) {
187
  return held('hash-divergence', i);
188
  }
189
  }
 
191
  // Rung 8: consent anchors only at apex-T0. A perfect chain does not
192
  // confer consent -- it only proves the report is honest.
193
  if (ACTIONS[inp.action].consent) {
194
+ return buildResult(inp, 'DEFER_TO_OPERATOR', ['consent-anchors-at-apex-T0-only'], null, mat);
195
  }
196
 
197
  // Rung 9: honest report + free action -> the child may act.
198
+ return buildResult(inp, 'CHILD_MAY_ACT', [], null, mat);
199
  }
200
 
201
  export function statusRows() {
 
245
  { id: '16', input: { ...BASE, max_depth: 0, chain: goodChain(0) } },
246
  { id: '17', input: { ...BASE, chain: (() => { const c = goodChain(3); c[1] = { ...c[1], extra: 'ignored-field-must-hold' }; return c; })() } },
247
  { id: '18', input: { ...BASE, chain: (() => { const c = goodChain(3); c[0] = Object.assign(Object.create({ ...c[0] }), {}); return c; })() } },
248
+ // 19-21 (acer hardening 2026-06-11): an accessor tuple that could split
249
+ // check-time from use-time, a non-enumerable own field, and a symbol-keyed
250
+ // field -- all three passed liris's Object.keys check; all three must HELD.
251
+ { id: '19', input: { ...BASE, chain: (() => { const c = goodChain(3); c[1] = Object.defineProperty({ depth: 1, recomputed_sha16: level(1) }, 'reported_sha16', { enumerable: true, get() { return level(1); } }); return c; })() } },
252
+ { id: '20', input: { ...BASE, chain: (() => { const c = goodChain(3); Object.defineProperty(c[2], 'hidden_own_field', { value: 'smuggled', enumerable: false }); return c; })() } },
253
+ { id: '21', input: { ...BASE, chain: (() => { const c = goodChain(3); c[0] = { ...c[0] }; c[0][Symbol.for('nnest-smuggle')] = 'payload'; return c; })() } },
254
  ]);
255
 
256
  export function emitParityRows() {
 
280
  add('every-row-executable-0', emitParityRows().slice(1, -1).every((row) => row.includes('|executable=0|')));
281
  add('rows-hbp-only', [...statusRows(), ...emitParityRows()].every((row) => row.endsWith('json=0') && !row.includes('{"')));
282
 
283
+ // acer hardening: accessor / hidden / symbol tuples are topology violations.
284
+ add('accessor-tuple-held-not-trusted', (() => {
285
+ const c = goodChain(3);
286
+ c[1] = Object.defineProperty({ depth: 1, recomputed_sha16: level(1) }, 'reported_sha16', { enumerable: true, get() { return level(1); } });
287
+ const o = gateChain({ ...BASE, chain: c });
288
+ return o.verdict === 'CHILD_HELD' && o.gate === 'chain-topology-invalid' && o.first_bad_depth === 1;
289
+ })());
290
+ add('non-enumerable-own-field-held', (() => {
291
+ const c = goodChain(3);
292
+ Object.defineProperty(c[2], 'hidden_own_field', { value: 'x', enumerable: false });
293
+ return gateChain({ ...BASE, chain: c }).gate === 'chain-topology-invalid';
294
+ })());
295
+ add('symbol-keyed-field-held', (() => {
296
+ const c = goodChain(3);
297
+ c[0] = { ...c[0] };
298
+ c[0][Symbol.for('nnest-smuggle')] = 'x';
299
+ return gateChain({ ...BASE, chain: c }).gate === 'chain-topology-invalid';
300
+ })());
301
+ add('single-read-digest-matches-verified-content', (() => {
302
+ const c = goodChain(3);
303
+ const o = gateChain({ ...BASE, chain: c });
304
+ const expected = sha16(JSON.stringify(c.map((t) => [t.depth, t.reported_sha16, t.recomputed_sha16])));
305
+ return o.verdict === 'CHILD_MAY_ACT' && o.chain_sha16 === expected;
306
+ })());
307
+
308
  return { ok: checks.every((check) => check.ok), checks };
309
  }
310
 
tools/behcs/nnest-watcher-gate.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- 5BF054CD04C33AD59A8F5F54294C4FACD2D5068E40AEBC18489913BD727D152A nnest-watcher-gate.mjs
 
1
+ 81602D6027A19941A38C910D32F8971CEDA137B6EA42FB55210FD3B8024956C7 nnest-watcher-gate.mjs
tools/behcs/supervisor-collision-router.hbi.sha256 CHANGED
@@ -1 +1 @@
1
- 97AD9A83BA77C6BE5AE1C7E5D781C79EA5F2541E0F456540B89B94A302DB0CD9 supervisor-collision-router.hbi
 
1
+ 97AD9A83BA77C6BE5AE1C7E5D781C79EA5F2541E0F456540B89B94A302DB0CD9 supervisor-collision-router.hbi
tools/behcs/supervisor-collision-router.mjs.sha256 CHANGED
@@ -1 +1 @@
1
- E1B01511D0F141842805C6404921DD095753670A38B003FE0746B6B31B918D62 supervisor-collision-router.mjs
 
1
+ E1B01511D0F141842805C6404921DD095753670A38B003FE0746B6B31B918D62 supervisor-collision-router.mjs