#000070: spatial-anchor pi*_w_object ticket + pre-review bench
New ticket for Joseph (@TrudoJo)'s 6-dim procedural spatial-anchor framework as the first verifier kernel under the #000013 v7-W reserved namespace. A single committed 32-byte SHA-256 hash deterministically expands into six 32-byte regions H1..H6 via the HMAC-SHA-512 KDF already shipped in arborist/substrate/anchor_prg.py (#000035); each region drives one quantized object dimension under a fixed canonical mapper. Domain separation from #000035 by dedicated spatial_anchor_seed published in the v7-W manifest -- preserves #000035's KAT freeze + dav1d 2026-05-11 final review intact. Bundle: - docs/tickets/ticket-000070-spatial-anchor-pi-w-object.md (718 lines): full spec with 8 design-choice subsections, working Python sketch, 12-NOT scope boundaries, 8-row cross-references, five-step deletions, 10 open questions for dav1d. - bench/spatial_anchor_validation.py: pure-stdlib pre-review evidence (~2s, RNG-seed-pinned, reproducible). Five benches: avalanche, cell-distribution uniformity, collision vs birthday-bound, cross-region independence, domain separation. - bench/spatial_anchor_validation_results.md: report from first run. - Makefile: 'make bench-spatial-anchor [SPATIAL_N=N]' target + PHONY. - docs/TICKETS.md: index row + Next ID 000070 -> 000071. Bench headlines (N=10000): - Avalanche mean 767.85 bits (PRF null 768, z=-0.49) -> PASS - Cell-distribution chi^2 |z|<1 at L=2,3,4 -> PASS - Birthday-bound ratio obs/exp 0.989/1.038 at populated L -> PASS - Cross-region Pearson all 15 pairs < 2sigma -> PASS - Domain separation Arm A 767.91 / Arm B exact 0 collision -> PASS Five of dav1d's ten open questions (Q1 seed source, Q2 segmentation, Q3 position mapper, Q8 endianness, Q9 KAT adversarial vectors) now resolve with measurements rather than appeals to PRF authority. Q4/Q5/Q6/Q7/Q10 remain non-empirical design decisions. Status: open, awaiting dav1d review + fox go/no-go. No registry slot booked, no substrate-paper amendment landed, no kernel module created.
This commit is contained in:
parent
2b8777c947
commit
55b651f624
5 changed files with 1463 additions and 2 deletions
|
|
@ -111,6 +111,7 @@ Newest first. Update on every open/close.
|
|||
|
||||
| ID | Title | Status | Opened | Directive |
|
||||
|----------|------------------------------------------------|-----------------------|------------|-----------|
|
||||
| #000070 | Spatial-anchor π*_w_object (Joseph 6-dim determination kernel) | **open · awaiting dav1d review + fox go/no-go** (2026-05-31; surfaced when fox brought in Joseph @TrudoJo's procedural-spatial framework — "hashes do not encode the world, hashes determine the world" — and asked whether it fits arborist's substrate model. It does, cleanly. Implements the first verifier kernel under the #000013 v7-W reserved namespace (`arborist/world/__init__.py` `STATUS = "namespace_reserved"` → `kernel_in_progress` on land): a single committed 32-byte SHA-256 hash deterministically expands into six named 32-byte regions `H₁..H₆` via the HMAC-SHA-512 KDF already shipped in `arborist/substrate/anchor_prg.py` (#000035), and each region drives one quantized object dimension under a fixed canonical mapper — `H₁→octree position`, `H₂→scale level`, `H₃→quantized SO(3) rotation`, `H₄→material palette`, `H₅→raw links (reserved for π*_w_relation sibling ticket)`, `H₆→behavior code`. Domain separation from #000035 by dedicated `spatial_anchor_seed` (manifest-published) — keeps #000035's KAT freeze + dav1d 2026-05-11 final review intact. Hard constraints: stays inside A1–A3, no continuous tensors in proof path, no new `audit_mode` token (substrate commitments are not warrants — the four-rung ladder is unchanged), no SQL schema change at Phase 1, `canonicalization_version` absorbs the new `spatial-anchor-object@v1` registry slot. Phase 1 deliverable ~150 LoC + 10 KATs + tests in one PR: `arborist/substrate/spatial_anchor.py` (segmentation), `arborist/world/pi_star/object.py` (six mappers), registry entry, KAT vectors at `bench/fixtures/spatial-anchor/known-answer-tests.jsonl` matching #000035 KAT discipline, `tests/test_spatial_anchor.py` + `tests/test_world_pi_star_object.py`, substrate-paper amendment citing Joseph (@TrudoJo) in `docs/_source/merkle-agi-v7w-spatial-temporal.rst`. Position mapper at Phase 1 = octree (substrate paper §2.1 + §A worked example); H3/S2/Hilbert/Morton siblings deferred — Morton's value is purely as the relation-kernel `pair(A,B)` cheap bit-interleave and surfaces in the sibling ticket. **Ten open questions for dav1d** in §8: seed-source choice, segmentation method, position mapper, scope split (object alone vs object+relation per CLAUDE.md memory `feedback_ticket_proliferation`), privacy-class fail-closed default, `audit_mode` discipline confirmation, manifest-validator timing, endianness reconfirmation, KAT count + adversarial vectors, paper-amendment wording. Five-step §7 deletions captured: dropped the prior `/tmp/arborist-spatial-ontology-plan.md`'s geographic-search backend (encoding-route confusion), `Document.extra` lat/lon hooks (different ticket if at all), `audit_mode=HYBRID` for spatial hits (convention-illegal), geohash (subsumed by Morton), quadtree as separate (octree at z-level-0), Hilbert at Phase 1 (deferred), tier-1/2/3 hash-suite framing (conflated hard vs soft hashes), and `arborist/spatial/` namespace (violates topic-naming rule). Full spec in `docs/tickets/ticket-000070-spatial-anchor-pi-w-object.md`. | 2026-05-31 | — |
|
||||
| #000069 | Arborist VIZ / Merkle Command Center (Pyramid + six.js + SSE browser dashboard) | **open · awaiting go/no-go · doc-only scaffold** (2026-05-27; filed from `/home/fox/Downloads/TICKET_0000VIZ_*`, stack corrected same day per fox). Configurable browser dashboard for inspecting arborist's content-addressed state: Merkle root explorer, proof verifier, claim warrant + graveyard, audit timeline, run-DAG replay, cache-key explainer, root diff, 3D Merkle lattice, optional circuit/activation traces. Read-only consumer; arborist proper stays source-of-truth, dashboard projects state. **Stack pinned to unturf-native** (fox 2026-05-27, supersedes proposal §3): **Pyramid + Jinja2 + SQLAlchemy** (matches `remarkbox` / `make_post_sell` / `unhomeschool.com` idiom), **SSE** (`text/event-stream` via Pyramid streaming response) for live audit/claim/falsifier patches, **vanilla JS + six.js** (fox's patched three.js fork at `git.unturf.com/gumyum/six.js` — three.js r175 + CWE-407 patches incl. ObjectBVH O(N)→O(log N); bundles vendored from `~/git/cupPCB/cdn/six/`; third-instance MOAD-0001 dogfood alongside `java-topology` + gumyum-engine) for 3D widgets and large-graph rendering, SQLite for dashboard metadata (no PostgreSQL/ClickHouse/Redis/NATS by default — promote on measured need), no React / no Next.js / no Node build step. Server-rendered SVG (or Graphviz `.dot` per existing `docs/diagrams/*.dot` pattern) replaces React Flow for run-DAG widgets. Browser-side proof verification dropped from v1 (server-side Pyramid view returns PASS/FAIL + receipt; reinstate phase-N only if third-party-verification use case surfaces). **Three filing-note gates before phase 0** (in ticket body): **F-1** sibling-repo home — implementation lives in a new `~/git/arborist-viz` (Pyramid Python, matches existing unturf apps), not in-tree; arborist's contribution is the read-API spec + view package + arborist library import via `arborist.embed`. **F-2** scope split — proposal carries 8 phases (§17 phases 0–8); recommended cut keeps phases 0–3 (schema + shell + proof/root widgets + claim/audit/run widgets) inside #000069, and spawns sibling tickets for SSE streaming (4), 3D six.js (5), massive-graph (6, only if measured need surfaces), circuit-tracing (7, gated on #000062), embeddable widgets (8) — Dav1d-audience rule. **F-3** upstream prereqs — phase 7 (circuit/activation) consumes **#000062 Mechanistic Witness**'s `MechanisticWitnessRoot`; phase 3's claim-graveyard widget projects **#000059**'s bounded-ingestion graveyard. Hard constraints: arborist soft-vs-hard discipline applies verbatim (attribution weights renderable but never `audit_mode`, never causal without intervention/ablation evidence); private-leaf default-deny (commitments + hashes + redacted maps only without explicit auth); every widget exposes its data query + source roots. Reserved scope: NOT a replacement for `arborist controller-events` / `arborist analyze` / `arborist inspect` CLI — those stay canonical inspector surfaces; VIZ is the projection layer. | 2026-05-27 | — |
|
||||
| #000068 | Verifier-blind missed-answer falsification guard | **in progress · Phase 1+2+3 landed 2026-05-27 · Phase 4 default flip NO-GO** (Phase 2 bench 2026-05-27 76q × n=3 claim_lattice Hermes-3-8B: 2/228 sidecar fires, both STRONG confidence, both the Ballestrini regression fixture, 100% precision, 0/226 false positives across non-Ballestrini runs. Phase 3 demote flag opt-in via `--demote-on-missed-answer` on `query`/`ask` — wires `EVIDENCE-WARRANTED → EVIDENCE-MISSED-PARTIAL` for strong/medium confidence on lattice modes; lower rungs + non-lattice modes get `· missed-answer` tail tag. `answerability_demote_enabled` added to `_VERIFIER_POLICY_FIELDS` so flipping the flag partitions cache via verifier_policy_hash. Default OFF per Dav1d Phase 4 NO-GO — 100% precision at n=2 fires is too few samples to claim precision floor empirically; default flip blocks on wider bench + human spot-check. 47 tests (36 Phase 1 + 11 Phase 3) all passing. End-to-end verified live: 4/4 Hermes runs on Ballestrini with --demote-on-missed-answer rendered EVIDENCE-MISSED-PARTIAL.) Original opening 2026-05-27 (Dav1d de-novo review GO for Phase 1 with seven hardenings folded into spec — subject-token cue-stripping, answer-type alignment, confidence_class, candidate cap=10, precise offset_start/end/basis, cache-hit recompute-on-read, Phase 1 out of verifier_policy_hash). Original opening 2026-05-27; sibling to the user-payload-layout work shipped 2026-05-26, split out per the Dav1d-audience rule — `feedback_ticket_proliferation`). Surfaced by the Ballestrini case: evidence E2 literally contained the song names, Hermes-3-8B under `user_payload_layout=tail` said *"specific songs by her are not mentioned in the provided evidence blocks"*, verifier marked the run `EVIDENCE-WARRANTED` 2/2 because nothing positive was unsupported. **Verifier-blind false-negative class** — existing layered verifier (quote/span/entity/paraphrase + Rule 8 + Rule 9 + claim ceiling) guards unsupported *presence*, has no hook for unsupported *absence*. Layout fixes attention placement on the specific instance (n=3 bench 2026-05-27 confirms bookend/per_chunk recover Ballestrini); layout alone can't close the class — adversarial phrasing or bigger prompt resurfaces it under any layout. Proposed deterministic sidecar in `arborist/qa/inspect.py:diagnose_missed_answer`: three-clause conjunction — **(A)** answer matches denial pattern ("not mentioned", "not provided", "the evidence does not say", …, closed list versioned via `denial_patterns_version`); **(B)** question is extraction shape (reuse `arborist.qa.quantifier` classifier — `ALL`/`COMPREHENSIVE`/`OPEN_REQUEST` intensities, OR surface cues "songs by"/"works by"/"who wrote"/"list"/"name all"); **(C)** evidence contains candidate spans near subject tokens (reuse `entity_proximity_n`/`entity_proximity_window` from verify.py — quoted strings, title-case spans, comma-separated title lists within W chars of stemmed subject content tokens). All three must fire. Output: `result["answerability"]` with `missed_answer_candidate_spans` list (evidence_id + offset + text). **Hash discipline:** sidecar fields (`denial_patterns_version`, `extraction_cues_version`, `answerability_threshold`) fold into `governance_policy_hash` only; an optional `answerability_demote_enabled` flag (default OFF) wires `EVIDENCE-WARRANTED → EVIDENCE-MISSED-PARTIAL` in `_render_audit_label`, and IF on folds into BOTH `governance_policy_hash` AND `verifier_policy_hash` (changes rendered audit_mode, so verifier hash must move — the deliberate opt-in moves the verifier hash, sidecar-only stays out). No LLM-as-judge. Never writes `providence_cache`/`audit_events`. Never promotes claims. Pattern verbatim from `arborist.qa.inspect.diagnose_*` (deflection, coherence, title-relevance). Phases: 1 sidecar read-only, 2 bench + threshold tuning, 3 demote opt-in, 4 default decision (bench-gated). 5F-Falsification fixture: Ballestrini case already in `bench/qa_questions.txt` under "entity list". Full spec in `docs/tickets/ticket-000068-verifier-blind-missed-answer-guard.md`. | 2026-05-27 | D2 |
|
||||
| #000067 | M-aware cold-pack hydration (route incoming docs by content hash into M target shards) | **open · scaffold · prereq for #46 genesis test** (2026-05-26; surfaced while preparing the 3090 SPV-wallet validation). Today's `hydrate_from_metadata_pack` takes a single `conn` and writes every incoming row into one shard. With the corpus now in M=4 hash-routed topology (#000065), a fresh peer needs to land each document on `shard_for_document(document_root, M)` — same routing function as the producer. Without this, a fresh peer's `~/.arborist/shards/` is just one big single-shard DB and the M=4 ATTACH-and-route assumption #000065 was sized for doesn't hold consumer-side. Two coherent shapes: **(α) two-step kludge** — hydrate into single shard, then `arborist corpus reshard --to M` on the consumer. Works today (proven by the 2026-05-26 reshard executor) but doubles the wall time and treats packed shards as if they came from an arbitrary topology. **(β) direct M-aware hydrate** — extend `hydrate_from_metadata_pack` to accept `targets: list[sqlite3.Connection]` + `M: int` and route per-row at restore time (reusing `arborist.document.shard_for_document` + the table-routing rules in `arborist/migrate.py`). Manifest carries `corpus_shard_count` so the unpacker knows M from the pack itself. β is the right answer — α exists only as a fallback if 20-min-window pressure forces it. Sequence: (1) add `corpus_shard_count` to pack manifest (read from source meta during `dump_shard_metadata`); (2) `restore_shard_metadata_routed(targets, M, table_dir)` in `cold_pack_metadata.py` mirroring `_route_per_doc_table` from migrate.py; (3) `hydrate_from_metadata_pack` gains a `targets`/`shards_dir` param; (4) `arborist cold unpack --shards-dir DIR` initialises M target shards from the manifest's `corpus_shard_count` and routes; (5) regression test: pack 2 shards → hydrate into fresh 4 shards → assert every doc on its hash-routed target. Refactor opportunity: the routing rules (ROUTED_BY_DOCUMENT_ROOT, CONSOLIDATED_TABLES) currently live in migrate.py; this ticket can either duplicate them in cold_pack_metadata.py (fast) or factor into a shared `arborist/multi_shard.py` module (cleaner). The shared-module path is more honest given graft mode (#000066) wants the same primitives. Out of scope: graft / overlay mode (that's #000066 — overlays onto populated, this is hydrate-into-empty). | 2026-05-26 | — |
|
||||
|
|
@ -183,4 +184,4 @@ Newest first. Update on every open/close.
|
|||
|
||||
## Next ID
|
||||
|
||||
`000070`
|
||||
`000071`
|
||||
|
|
|
|||
761
docs/tickets/ticket-000070-spatial-anchor-pi-w-object.md
Normal file
761
docs/tickets/ticket-000070-spatial-anchor-pi-w-object.md
Normal file
|
|
@ -0,0 +1,761 @@
|
|||
# Ticket #000070 — Spatial-anchor π*_w_object (Joseph 6-dim determination kernel)
|
||||
|
||||
**Status:** open · awaiting dav1d review + fox go/no-go
|
||||
**Opened:** 2026-05-31
|
||||
**Scope:** Pin the operational spec for **π*_w_object** — the first
|
||||
verifier kernel of v7-W. Implements **Joseph (@TrudoJo)**'s 6-dimension
|
||||
procedural-anchor framework: a single committed 32-byte SHA-256 hash
|
||||
deterministically expands into six named regions `H₁..H₆` via the
|
||||
HMAC-SHA-512 KDF already shipped in `arborist/substrate/anchor_prg.py`
|
||||
(#000035), and each region drives one quantized object dimension under
|
||||
a fixed canonical mapper. This ticket lands segmentation + position
|
||||
mapper + registry slot + KATs. Relation / event / place / agent_trace
|
||||
kernels land as siblings under #000013.
|
||||
**Audience:** dav1d (primary review), v7-W substrate-paper maintainers,
|
||||
Joseph (@TrudoJo, original framework author), #000013 follow-up,
|
||||
#000035 follow-up.
|
||||
**Hard constraint:**
|
||||
|
||||
- Stays inside A1–A3 (canonical encoding, public quantization,
|
||||
collision-resistant hash). No new axiom.
|
||||
- π*_w on **quantized integer state** only; continuous floats do not
|
||||
enter the proof path (v7-W manifest hard rule, paper §1.2).
|
||||
- Hard-hash family stays SHA-256 commit + HMAC-SHA-512 expansion.
|
||||
Soft locality indices (Morton / H3 / S2 / Hilbert / geohash) live
|
||||
**outside** the proof path per CLAUDE.md soft-hash rule.
|
||||
- **Domain separation from #000035.** A NEW seed
|
||||
`spatial_anchor_seed` is published in the v7-W manifest beside
|
||||
`anchor_prg_seed`; #000035 §2.4 "single-purpose — never reuse
|
||||
`anchor_prg_seed`" is honored without a `PHI_PRG_VERSION` bump.
|
||||
- **No new `audit_mode` token.** CLAUDE.md: `audit_mode` is decided
|
||||
by the verifier, never asserted. π*_w_object emits commitments,
|
||||
not warrants. The four-rung ladder (POINTER-LINKED →
|
||||
ANCHOR-WARRANTED → EVIDENCE-WARRANTED → ENTAILMENT-VERIFIED) is
|
||||
not extended by Phase 1.
|
||||
- **Schema column-unchanged.** A new `pi_star/spatial-anchor@v1`
|
||||
registry entry folds into `canonicalization_version` (one of the
|
||||
v9.8 8-dim cache_key dimensions). No new SQL table required for
|
||||
Phase 1; persistence to a `world_state_cells` table is deferred.
|
||||
- Topic-named, not version-prefixed (CLAUDE.md naming rule). Lands
|
||||
under `arborist/world/pi_star/`, not `arborist/v7w/` or
|
||||
`arborist/spatial/`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Problem statement
|
||||
|
||||
### 1.1 What #000013 left undefined
|
||||
|
||||
#000013 closed 2026-05-09 doc-only — substrate paper at
|
||||
`docs/_source/merkle-agi-v7w-spatial-temporal.rst` (658 lines) plus
|
||||
the frontier catalog at `docs/v7w-frontier-catalog.md` plus the
|
||||
namespace stub at `arborist/world/__init__.py` (`STATUS =
|
||||
"namespace_reserved"`). The substrate paper §1.1 names five
|
||||
world-state object kinds:
|
||||
|
||||
```
|
||||
- objects: { id, class, bbox, pose, confidence }
|
||||
- relations: { subject_id, predicate, object_id, time_window }
|
||||
- events: { type, t_start, t_end, participants, place }
|
||||
- places: { id, frame_of_reference, geometry, parent_place }
|
||||
- agents: { id, position_trace, pose_trace, attention_trace }
|
||||
```
|
||||
|
||||
§2.1 specifies the **discretization grammar** (octree / S2 / quadtree
|
||||
with hierarchical levels declared by the deployment manifest). §2.3
|
||||
specifies the **frame discipline** (frame_id = SHA-256 of canonical
|
||||
frame definition; transforms committed). The paper §A worked example
|
||||
walks a 10×10×3 m room with an octree manifest. What the paper does
|
||||
**not** specify operationally is the function
|
||||
|
||||
```
|
||||
H : 32-byte SHA-256 commitment → object record
|
||||
```
|
||||
|
||||
— how a *single anchor hash* determines an object. The paper treats
|
||||
π*_w as an encoder of observations produced by an exogenous
|
||||
world-model engine (SLAM, Gaussian splatting, predictive video). That
|
||||
is the *encoding* model: object → bytes → hash.
|
||||
|
||||
### 1.2 Joseph's framework — determination model
|
||||
|
||||
2026-05-31 fox brought in Joseph (@TrudoJo)'s framework. Verbatim
|
||||
core distinction:
|
||||
|
||||
> **Hashes do not encode the world. Hashes determine the world.**
|
||||
> The hash is not a message. It is a fixed generative coordinate.
|
||||
> Object identity = determined by its own hash. Object expression =
|
||||
> determined by the hash plus its surrounding hashes.
|
||||
|
||||
Operational spec: a single anchor hash splits into six stable regions
|
||||
and each region drives one object dimension via a fixed deterministic
|
||||
mapper.
|
||||
|
||||
```
|
||||
H = 9f3a...c71b
|
||||
H₁ → position
|
||||
H₂ → scale
|
||||
H₃ → rotation
|
||||
H₄ → material
|
||||
H₅ → relation / links
|
||||
H₆ → behavior / motion
|
||||
|
||||
object.position = map(H₁)
|
||||
object.scale = map(H₂)
|
||||
object.rotation = map(H₃)
|
||||
object.material = map(H₄)
|
||||
object.links = map(H₅)
|
||||
object.motion = map(H₆)
|
||||
|
||||
same hash + same rule-field = same object every time
|
||||
```
|
||||
|
||||
Joseph's "necessary rule" (verbatim): the system must fix **hash
|
||||
algorithm, hash length, byte order, segmentation method, pairing
|
||||
method, ordering rule, mapping functions, world version, collision
|
||||
policy**. Otherwise the same hashes generate different worlds under
|
||||
different interpreters.
|
||||
|
||||
### 1.3 Why this fits arborist's substrate model
|
||||
|
||||
Cross-checked against ground truth on 2026-05-31:
|
||||
|
||||
| Joseph spec requirement | Arborist primitive that fulfills it |
|
||||
|---|---|
|
||||
| `hash → rule-field → object` (determination) | `arborist/substrate/anchor_prg.py` `_expand()` — counter-mode HMAC-SHA-512 KDF, 193 LoC, KAT-frozen #000035 |
|
||||
| Fixed hash algo + length | SHA-256 (`arborist/merkle.py:24-40`, `LEAF_PREFIX=0x00`, `NODE_PREFIX=0x03`, 32-byte output) |
|
||||
| Fixed byte order | Little-endian throughout (v7 §A1; `PHI_PRG_VERSION = "phi-prg-v1-hmac-sha512-le"`) |
|
||||
| World version (different interpreters ≠ different worlds) | v9.8 8-dim `cache_key` — `governance_policy_hash` + `canonicalization_version` + `schema_version` + `chunking_version`; bump any dim → prior worlds invalidated on lookup |
|
||||
| Mapping functions | `arborist/pi_star/registry.py` — `register(pi_star: PiStar)` API; one slot per canonical projection (existing slots: `arithmetic@v1`, `logic-kernel@v1`, `algebra-symbolic@v1`, `claim-lattice@v1`, …) |
|
||||
| Object identity (H alone) | π*_w_object — this ticket |
|
||||
| Object expression (H in field) | π*_w_relation — sibling ticket |
|
||||
| Hash + grammar (joint canonicalization) | governance_policy_hash absorbs grammar changes; bumping registry version stales worlds |
|
||||
|
||||
Joseph's framework supplies the **operational layer** the substrate
|
||||
paper deferred. Without it, `world/` stays a namespace stub. With it,
|
||||
`world/pi_star/object.py` becomes the first verifier kernel and the
|
||||
v7-W substrate moves from `namespace_reserved` to
|
||||
`kernel_in_progress`.
|
||||
|
||||
### 1.4 Encoding vs determination — both compose
|
||||
|
||||
Important: arborist's existing merkle commits are *encoding* (object
|
||||
→ canonical bytes → SHA-256 root). Merkle proofs verify "this object
|
||||
hashed to this root." Joseph's framework is *determination* (hash →
|
||||
grammar → object). A determination "proof" verifies "given this seed,
|
||||
grammar, and hash, the object **must** be this."
|
||||
|
||||
These compose. Encoding gives commitment (un-forgeable post-hoc).
|
||||
Determination gives reproducibility (every interpreter agrees on the
|
||||
object). For π*_w_object both hold: the SHA-256 hard hash is the
|
||||
commitment surface (encoding), and the HMAC-SHA-512 expansion plus
|
||||
six mappers is the determination grammar. This is the same shape as
|
||||
verifiable random functions in cryptography; it is the same shape as
|
||||
v7 §9.10 φ_PRG already shipped.
|
||||
|
||||
## 2. Design choices
|
||||
|
||||
### 2.1 Seed source — dedicated `spatial_anchor_seed` vs domain-tag bump
|
||||
|
||||
**A. Dedicated `spatial_anchor_seed` in the v7-W manifest (recommended).**
|
||||
|
||||
Publish a second 32-byte seed beside `anchor_prg_seed`. `_expand()`
|
||||
from `arborist/substrate/anchor_prg.py` is reused as-is with the new
|
||||
seed. No `PHI_PRG_VERSION` bump.
|
||||
|
||||
- **Strength:** respects #000035 §2.4 single-purpose rule exactly. No
|
||||
PRF-security regression. dav1d's 2026-05-11 #000035 final review
|
||||
stays valid.
|
||||
- **Cost:** manifest gains one field. Rotation policy stays at the
|
||||
v7-W manifest layer.
|
||||
|
||||
**B. Domain-tag input under bumped `PHI_PRG_VERSION`.**
|
||||
|
||||
Bump to `phi-prg-v2-hmac-sha512-le-dst` and add a 4-byte
|
||||
little-endian domain tag (e.g. `0x77_77_5f_53` = ASCII `"w_S"`) into
|
||||
the KDF input: `HMAC(seed, hard_hash || domain_tag || counter)`.
|
||||
Reuses `anchor_prg_seed`.
|
||||
|
||||
- **Strength:** cleaner cryptographic story — true domain separation
|
||||
by tag rather than by seed independence.
|
||||
- **Cost:** spec churn. #000035 just KAT-froze (10 KATs at
|
||||
`bench/fixtures/phi-prg/known-answer-tests.jsonl`). Bumping forces
|
||||
regeneration for every v7 anchor-map consumer and invalidates
|
||||
dav1d's 2026-05-11 review.
|
||||
|
||||
**Recommendation: A.** Smaller blast radius; orthogonal to #000035's
|
||||
frozen surface.
|
||||
|
||||
### 2.2 Region segmentation — fixed offsets vs per-region nested HMAC
|
||||
|
||||
**A. Fixed-offset slicing (recommended).**
|
||||
|
||||
Compute `_expand(spatial_anchor_seed, hard_hash_32, 192)` → 192 bytes
|
||||
→ six 32-byte regions at byte offsets `[0,32), [32,64), …,
|
||||
[160,192)`. Three HMAC-SHA-512 blocks (64 B each) cover the 192-byte
|
||||
output exactly.
|
||||
|
||||
- **Strength:** trivial; KAT-able; deterministic; reuses #000035's
|
||||
counter-mode discipline byte-for-byte.
|
||||
- **PRF independence argument:** counter-mode HMAC-SHA-512 blocks are
|
||||
computationally independent under the standard SHA-512 + HMAC
|
||||
assumption — the same argument #000035 §2.1 used to bound the
|
||||
channel. Slicing the concatenation does not weaken independence.
|
||||
|
||||
**B. Per-region nested HMAC.**
|
||||
|
||||
For each region, `H_i = HMAC-SHA-512(spatial_anchor_seed, hard_hash_32
|
||||
|| i_le_u32)[:32]` with `i ∈ {1..6}`.
|
||||
|
||||
- **Strength:** textbook tree-PRF; per-region independence by
|
||||
construction.
|
||||
- **Cost:** 6× HMAC calls vs 3× in A. Negligible at v7-W cadence but
|
||||
pointlessly more code.
|
||||
|
||||
**Recommendation: A.**
|
||||
|
||||
### 2.3 Spatial coordinate output per dimension
|
||||
|
||||
Each region's mapper consumes 32 bytes and emits a canonical integer
|
||||
cell. Per-dimension choice:
|
||||
|
||||
| `H_i` | Dimension | Mapper output | Rationale |
|
||||
|------|----------|---------------|-----------|
|
||||
| `H₁` | position | **octree cell at manifest-declared level `L`** — read `H₁[0:8]` as little-endian uint64, modulo `8**L`, descend bit-by-bit to canonical `cell_id` | Substrate paper §2.1 explicitly recommends octree for object-fixed local frames; §A worked example uses octree with `level_max=18` |
|
||||
| `H₂` | scale | **level integer** in `[level_min, level_max]` — read `H₂[0]` as uint8, modulo `(level_max - level_min + 1)`, offset by `level_min` | Manifest-declared range; uniform modulo across declared levels |
|
||||
| `H₃` | rotation | **quantized SO(3) cell** — read `H₃[0:12]` as three LE uint32, normalize to integer-quaternion grid of step `Δ_rot ≥ 1 mrad` | Paper §A ε budget `Δ_rot ≈ 1 mrad` |
|
||||
| `H₄` | material | **palette index** — read `H₄[0:4]` as LE uint32, modulo manifest-declared palette size | Deployment-specific |
|
||||
| `H₅` | links / relation seed | **opaque 32 bytes carried through** as raw input to the relation kernel (sibling ticket) | Phase boundary — relation kernel canonicalizes the `pair(A,B) → relation-seed` operator |
|
||||
| `H₆` | behavior / motion | **behavior code** — read `H₆[0:4]` as LE uint32, modulo manifest-declared behavior-table size | Deployment-specific |
|
||||
|
||||
`H₅` deliberately stays raw — Joseph's `pair(A, B) → relation-seed`
|
||||
operator consumes raw bytes from both anchors. Canonicalizing `H₅`
|
||||
here would foreclose the relation kernel's design space.
|
||||
|
||||
**Why octree and not Morton / H3 / S2 / Hilbert at Phase 1.** The
|
||||
substrate paper §2.1 names octree for object-fixed frames as the
|
||||
primary recommendation; the §A worked example uses octree. Picking
|
||||
one mapper at Phase 1 keeps KAT scope tractable. Geographic /
|
||||
planetary deployments register `spatial-anchor-s2@v1` later;
|
||||
image-plane / 2D-floor deployments register
|
||||
`spatial-anchor-quadtree@v1`; pairwise-locality deployments register
|
||||
`spatial-anchor-hilbert@v1`. All siblings, all under #000013.
|
||||
Morton's value is purely as a cheap bit-interleave for the relation
|
||||
kernel's `pair(A,B)` operator and surfaces there, not here.
|
||||
|
||||
### 2.4 Scope: does this ticket also land π*_w_relation?
|
||||
|
||||
Joseph's framework treats object and relation as a tightly coupled
|
||||
pair: identity from a single hash, expression from pairs. CLAUDE.md
|
||||
memory: "don't proliferate tickets — prefer extending existing."
|
||||
|
||||
**A. Single ticket lands object + relation.**
|
||||
- Smaller cross-reference graph; one dav1d-review pass covers the
|
||||
full identity+expression substrate.
|
||||
- Larger review surface (~300 LoC + 20 KATs vs ~150 + 10).
|
||||
|
||||
**B. Sibling ticket for relation (recommended pending fox call).**
|
||||
- Object kernel ships and can be benched independently before
|
||||
relation canonicalization is pinned.
|
||||
- Relation introduces the `pair(A,B)` canonicalization choice
|
||||
(symmetric `min || max` vs ordered) — that's a distinct
|
||||
architectural decision dav1d will want to review on its own
|
||||
surface.
|
||||
- #000049 and #000048 split similarly when NLI introduced a fresh
|
||||
audit_mode question; this is the same shape.
|
||||
|
||||
**fox call requested. Open question #4 below.**
|
||||
|
||||
### 2.5 Privacy class — fail-closed manifest declaration
|
||||
|
||||
v7-W paper §6 requires the deployment manifest to declare its
|
||||
privacy class:
|
||||
|
||||
```json
|
||||
{"privacy": {"class": "public | aggregated_only | ZK_with_selective_disclosure"}}
|
||||
```
|
||||
|
||||
The §A worked example defaults to `"public"`.
|
||||
|
||||
**A. Phase 1 requires explicit declaration (recommended).** Manifest
|
||||
loader raises if `privacy.class` is missing.
|
||||
|
||||
- **Strength:** fail-closed (CLAUDE.md guardrail). Anyone shipping a
|
||||
non-public deployment cannot accidentally omit the class.
|
||||
- **Cost:** worked example manifests must be edited to declare
|
||||
`"public"` explicitly — trivial.
|
||||
|
||||
**B. Default to `"public"` if absent.**
|
||||
|
||||
- **Strength:** matches the paper §A example shape.
|
||||
- **Risk:** a downstream operator forgets to declare; deployment
|
||||
ships exposing positions. Surveillance risk per paper §6.
|
||||
|
||||
**Recommendation: A.** Fail-closed beats convenience.
|
||||
|
||||
### 2.6 `audit_mode` discipline — commitments are not warrants
|
||||
|
||||
CLAUDE.md: "`audit_mode` is decided by the verifier, never
|
||||
asserted." A spatial-anchor-derived object is **not** evidence for a
|
||||
spatial claim. It is a commitment that "given THIS seed + grammar +
|
||||
hash, THIS is the object." The verifier discipline (quote / span /
|
||||
entity / paraphrase) is unchanged by Phase 1.
|
||||
|
||||
If a downstream consumer wants to use spatial commitments as
|
||||
warrants for spatial claims, that requires a new verifier method
|
||||
(`spatial_commitment`) — separate ticket, separate
|
||||
`verifier_policy_hash` impact, **not in scope here**. The four-rung
|
||||
ladder (POINTER-LINKED → ANCHOR-WARRANTED → EVIDENCE-WARRANTED →
|
||||
ENTAILMENT-VERIFIED reserved) is not extended by Phase 1.
|
||||
|
||||
This is the single most important conceptual discipline of this
|
||||
ticket. The prior `/tmp/arborist-spatial-ontology-plan.md` proposed
|
||||
"hits carry `audit_mode=HYBRID`" — convention-illegal, rejected.
|
||||
|
||||
### 2.7 Manifest schema — declared or coded?
|
||||
|
||||
`world/manifest.py` is not in Phase 1 scope. Phase 1 accepts a
|
||||
Python `dict` matching the paper §A shape and reads its `grid`,
|
||||
`frames`, `materials`, `behaviors`, `privacy` fields. A JSON-Schema
|
||||
validator + canonical-bytes serializer lands as a separate ticket
|
||||
under #000013.
|
||||
|
||||
**Open question #8 below** — is "manifest-as-dict, no validator" an
|
||||
acceptable Phase 1 contract, or does the validator have to land
|
||||
together?
|
||||
|
||||
### 2.8 Endianness
|
||||
|
||||
Little-endian throughout, matching v7 §A1 / #000035. The Phase 1
|
||||
mapper reads bytes as LE uint8 / uint32 / uint64 for `H₁`, `H₂`,
|
||||
`H₃`, `H₄`, `H₆`. Big-endian readers would be a #000035-style
|
||||
silent-divergence defect.
|
||||
|
||||
## 3. Recommendation
|
||||
|
||||
**Phase 1 deliverable** — ship the segmentation + position kernel
|
||||
under one PR:
|
||||
|
||||
1. **`arborist/substrate/spatial_anchor.py`** — module wrapping
|
||||
`_expand` from `anchor_prg.py`. Constants:
|
||||
- `SPATIAL_ANCHOR_VERSION = "spatial-anchor-v1-hmac-sha512-le"`
|
||||
- `PLACEHOLDER_SPATIAL_SEED: bytes` — 32 bytes, SHA-256 of fixed
|
||||
string for test reproducibility, NOT a security claim, matching
|
||||
`anchor_prg.PLACEHOLDER_SEED` discipline
|
||||
- `class Anchor6(NamedTuple)` — six 32-byte regions
|
||||
- `def split_anchor(hard_hash_32, *, seed) -> Anchor6`
|
||||
2. **`arborist/world/pi_star/object.py`** — six `_map_*` functions
|
||||
per §2.3 table. Public callable
|
||||
`pi_star_w_object(hard_hash_32, manifest, *, seed) -> ObjectRecord`.
|
||||
3. **`arborist/world/pi_star/__init__.py`** — package marker.
|
||||
4. **`arborist/pi_star/registry.py` registration** —
|
||||
`spatial-anchor-object@v1` registered via `register(pi_star)`.
|
||||
The version string folds into `canonicalization_version`
|
||||
(CLAUDE.md schema invariant).
|
||||
5. **KAT vectors** at
|
||||
`bench/fixtures/spatial-anchor/known-answer-tests.jsonl` — 10
|
||||
vectors, matching the #000035 §3.4 KAT discipline. Each vector
|
||||
pins `(seed_hex, hard_hash_hex, manifest_canonical_bytes_hex,
|
||||
octree_cell_id, scale_level, rotation_cell_tuple,
|
||||
material_index, links_blob_hex, behavior_code)`.
|
||||
6. **Tests**:
|
||||
- `tests/test_spatial_anchor.py` — `split_anchor` shape,
|
||||
deterministic, domain separation from `anchor_prg`
|
||||
(`split_anchor(H, seed=S1) ≠ phi_prg(H, …, seed=S1)` outputs),
|
||||
bool-reject + size-reject mirroring `phi_prg`, KAT replay.
|
||||
- `tests/test_world_pi_star_object.py` — per-mapper KAT replay,
|
||||
manifest validation (missing privacy class → raise; missing
|
||||
grid → raise; out-of-range level → raise), determinism under
|
||||
dict ordering.
|
||||
7. **AUTOCOUNT discipline** — wrap any numeric claim added to docs
|
||||
(test count, KAT count) per `docs/tickets/ticket-000044-*`.
|
||||
|
||||
**Phase 2 (separate ticket per §2.4 recommendation B)** —
|
||||
π*_w_relation consuming `H₅` from two anchors. Canonicalization
|
||||
decision: lexicographic `min(A,B) || max(A,B)` for symmetric
|
||||
predicates; ordered for directed. Pinned by
|
||||
`relation_canonicalization_version`.
|
||||
|
||||
**Phase 3 (separate ticket)** — `world/frontier/{pose_integration,
|
||||
observation_update, object_logits, relation_logits}.py` per paper
|
||||
Part 4.
|
||||
|
||||
**Phase 4 (separate ticket)** — `world/manifest.py` JSON-Schema
|
||||
validator + canonical-bytes serializer.
|
||||
|
||||
**Phase 5 (separate ticket)** — SQL persistence layer:
|
||||
`world_state_cells` table or `edges` extension; folds into
|
||||
`schema_version` bump (stales prior records — must be batched with
|
||||
other v9.x → v9.y migrations).
|
||||
|
||||
## 4. Implementation sketch
|
||||
|
||||
```python
|
||||
# arborist/substrate/spatial_anchor.py
|
||||
"""π*_w_object six-region anchor segmentation (Joseph @TrudoJo framework).
|
||||
|
||||
Splits a committed 32-byte SHA-256 hash into six named 32-byte regions
|
||||
using HMAC-SHA-512 counter-mode KDF (reuses ``anchor_prg._expand`` from
|
||||
#000035). Domain separation from #000035 is by **seed**: a dedicated
|
||||
``spatial_anchor_seed`` is published in the v7-W manifest beside
|
||||
``anchor_prg_seed``; never reuse one for the other.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from typing import NamedTuple
|
||||
|
||||
from arborist.substrate.anchor_prg import _expand
|
||||
|
||||
SPATIAL_ANCHOR_VERSION = "spatial-anchor-v1-hmac-sha512-le"
|
||||
|
||||
# Test placeholder; v7-W deployment manifest publishes the real seed.
|
||||
PLACEHOLDER_SPATIAL_SEED: bytes = hashlib.sha256(
|
||||
b"arborist v7-w spatial_anchor placeholder seed -- ticket #000070"
|
||||
).digest()
|
||||
|
||||
# 6 regions × 32 bytes; HMAC-SHA-512 produces 64-byte blocks → 3 blocks.
|
||||
_REGION_BYTES = 32
|
||||
_TOTAL_BYTES = 6 * _REGION_BYTES # 192
|
||||
|
||||
|
||||
class Anchor6(NamedTuple):
|
||||
h1_position: bytes # 32 B → octree cell id
|
||||
h2_scale: bytes # 32 B → manifest grid level
|
||||
h3_rotation: bytes # 32 B → quantized SO(3) cell
|
||||
h4_material: bytes # 32 B → palette index
|
||||
h5_links: bytes # 32 B → raw, consumed by π*_w_relation
|
||||
h6_behavior: bytes # 32 B → manifest behavior code
|
||||
|
||||
|
||||
def split_anchor(
|
||||
hard_hash_32: bytes,
|
||||
*,
|
||||
seed: bytes = PLACEHOLDER_SPATIAL_SEED,
|
||||
) -> Anchor6:
|
||||
"""Determine the six-region anchor for a committed object hash.
|
||||
|
||||
Same hash + same seed = same anchor every time, by HMAC-SHA-512
|
||||
PRF property under the standard SHA-512 + HMAC assumption.
|
||||
"""
|
||||
if not isinstance(hard_hash_32, (bytes, bytearray)) or len(hard_hash_32) != 32:
|
||||
raise ValueError(
|
||||
"hard_hash_32 must be exactly 32 bytes (SHA-256 output)"
|
||||
)
|
||||
if not isinstance(seed, (bytes, bytearray)) or len(seed) != 32:
|
||||
raise ValueError("seed must be exactly 32 bytes")
|
||||
raw = _expand(bytes(seed), bytes(hard_hash_32), _TOTAL_BYTES)
|
||||
return Anchor6(
|
||||
h1_position=raw[0:32],
|
||||
h2_scale=raw[32:64],
|
||||
h3_rotation=raw[64:96],
|
||||
h4_material=raw[96:128],
|
||||
h5_links=raw[128:160],
|
||||
h6_behavior=raw[160:192],
|
||||
)
|
||||
|
||||
|
||||
__all__ = ["Anchor6", "split_anchor", "SPATIAL_ANCHOR_VERSION",
|
||||
"PLACEHOLDER_SPATIAL_SEED"]
|
||||
```
|
||||
|
||||
```python
|
||||
# arborist/world/pi_star/object.py
|
||||
"""π*_w_object — Joseph 6-dim object kernel (#000070).
|
||||
|
||||
Composes ``split_anchor`` (#000070 §3) with six per-dimension mappers
|
||||
to emit a canonical integer ObjectRecord. Output is content-addressable
|
||||
under (seed, hard_hash_32, manifest_canonical_bytes).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TypedDict
|
||||
|
||||
from arborist.substrate.spatial_anchor import Anchor6, split_anchor
|
||||
|
||||
PI_STAR_OBJECT_VERSION = "spatial-anchor-object-v1"
|
||||
|
||||
|
||||
class ObjectRecord(TypedDict):
|
||||
octree_cell_id: int
|
||||
scale_level: int
|
||||
rotation_cell: tuple[int, int, int]
|
||||
material_index: int
|
||||
links_blob_hex: str # raw H5, hex-encoded for canonical JSON
|
||||
behavior_code: int
|
||||
|
||||
|
||||
def pi_star_w_object(
|
||||
hard_hash_32: bytes,
|
||||
manifest: dict,
|
||||
*,
|
||||
seed: bytes,
|
||||
) -> ObjectRecord:
|
||||
_require_manifest(manifest)
|
||||
a = split_anchor(hard_hash_32, seed=seed)
|
||||
grid = manifest["grid"]
|
||||
return ObjectRecord(
|
||||
octree_cell_id=_map_position(a.h1_position, grid),
|
||||
scale_level=_map_scale(a.h2_scale, grid),
|
||||
rotation_cell=_map_rotation(
|
||||
a.h3_rotation,
|
||||
int(manifest.get("rotation_delta_mrad_inv", 1000)),
|
||||
),
|
||||
material_index=_map_material(a.h4_material, len(manifest["materials"])),
|
||||
links_blob_hex=a.h5_links.hex(),
|
||||
behavior_code=_map_behavior(a.h6_behavior, len(manifest["behaviors"])),
|
||||
)
|
||||
|
||||
|
||||
def _require_manifest(manifest: dict) -> None:
|
||||
# Fail-closed (Phase 1 §2.5 recommendation A): explicit privacy class
|
||||
if "privacy" not in manifest or "class" not in manifest["privacy"]:
|
||||
raise ValueError(
|
||||
"manifest must declare privacy.class explicitly (v7-W paper §6); "
|
||||
"see worked example at "
|
||||
"docs/_source/merkle-agi-v7w-spatial-temporal.rst §A"
|
||||
)
|
||||
# Grid declaration required (paper §2.1)
|
||||
if "grid" not in manifest or "type" not in manifest["grid"]:
|
||||
raise ValueError("manifest must declare grid.type (paper §2.1)")
|
||||
# Materials + behaviors required for H4 + H6 mappers
|
||||
if not manifest.get("materials"):
|
||||
raise ValueError("manifest must declare a non-empty materials list")
|
||||
if not manifest.get("behaviors"):
|
||||
raise ValueError("manifest must declare a non-empty behaviors list")
|
||||
|
||||
|
||||
def _map_position(h1: bytes, grid: dict) -> int:
|
||||
"""octree cell id at manifest level `L`.
|
||||
|
||||
Reads h1[0:8] as LE uint64, modulo 8**L → canonical descent
|
||||
address. Higher levels = finer cells; L declared by manifest.
|
||||
"""
|
||||
level = int(grid.get("level_max", 18))
|
||||
cells = 1 << (3 * level) # 8 ** level
|
||||
raw = int.from_bytes(h1[:8], "little")
|
||||
return raw % cells
|
||||
|
||||
|
||||
def _map_scale(h2: bytes, grid: dict) -> int:
|
||||
lo = int(grid.get("level_min", 0))
|
||||
hi = int(grid.get("level_max", 18))
|
||||
span = hi - lo + 1
|
||||
return lo + (h2[0] % span)
|
||||
|
||||
|
||||
def _map_rotation(h3: bytes, delta_inv: int) -> tuple[int, int, int]:
|
||||
"""Three integer Euler-equivalent indices at 1/delta_inv mrad step.
|
||||
|
||||
Reads three LE uint32 from h3[0:12], modulo (2π / step).
|
||||
"""
|
||||
step_count = int(6_283 * delta_inv // 1000) # 2π * 10^3 ≈ 6283 mrad
|
||||
axes = []
|
||||
for i in range(3):
|
||||
u = int.from_bytes(h3[4 * i : 4 * (i + 1)], "little")
|
||||
axes.append(u % step_count)
|
||||
return tuple(axes) # type: ignore[return-value]
|
||||
|
||||
|
||||
def _map_material(h4: bytes, palette_size: int) -> int:
|
||||
u = int.from_bytes(h4[:4], "little")
|
||||
return u % palette_size
|
||||
|
||||
|
||||
def _map_behavior(h6: bytes, table_size: int) -> int:
|
||||
u = int.from_bytes(h6[:4], "little")
|
||||
return u % table_size
|
||||
|
||||
|
||||
__all__ = ["ObjectRecord", "pi_star_w_object", "PI_STAR_OBJECT_VERSION"]
|
||||
```
|
||||
|
||||
```python
|
||||
# arborist/world/pi_star/__init__.py
|
||||
"""``arborist.world.pi_star`` — v7-W π*_w canonical projections (#000070+).
|
||||
|
||||
Per ``arborist/world/__init__.py`` reserved-namespace roadmap:
|
||||
|
||||
pi_star/object.py — π*_w_object (#000070, this package's first kernel)
|
||||
pi_star/relation.py — π*_w_relation (sibling ticket TBD)
|
||||
pi_star/event.py — π*_w_event (sibling ticket TBD)
|
||||
pi_star/place.py — π*_w_place (sibling ticket TBD)
|
||||
pi_star/agent_trace.py — π*_w_agent_trace (sibling ticket TBD)
|
||||
"""
|
||||
```
|
||||
|
||||
(Mapper internals are illustrative; KAT vectors in
|
||||
`bench/fixtures/spatial-anchor/known-answer-tests.jsonl` will pin the
|
||||
exact byte-level behavior under review.)
|
||||
|
||||
## 5. Scope boundaries (what this ticket does NOT do)
|
||||
|
||||
- **No π*_w_relation kernel.** `H₅` is reserved raw; the `pair(A,B)`
|
||||
operator is a separate ticket's decision.
|
||||
- **No event / place / agent_trace kernels.** Separate tickets per
|
||||
paper Part 4.
|
||||
- **No ε-frontier kernels.** `world/frontier/*.py` is Phase 3.
|
||||
- **No `world/manifest.py` validator.** Phase 1 accepts a dict with
|
||||
manual `_require_manifest()`.
|
||||
- **No `world/frame.py`.** Frame discipline (paper §2.3) is honored
|
||||
via manifest declaration but not validated by an in-code kernel.
|
||||
- **No `Document.extra` lat/lon hooks.** The prior
|
||||
`/tmp/arborist-spatial-ontology-plan.md` proposed a
|
||||
geographic-search feature on `Document.extra`; that is a
|
||||
soft-channel consumer of π*_w outputs, not a substrate concern,
|
||||
and lives in a different ticket if at all.
|
||||
- **No new `audit_mode` token.** Substrate commitments are not
|
||||
warrants.
|
||||
- **No SQL schema change.** Phase 1 emits canonical bytes consumed
|
||||
by callers; persistence to a `world_state_cells` table is Phase 5.
|
||||
- **No CLI surface.** Phase 1 ships as a library kernel. CLI
|
||||
(`arborist substrate world-object …`) is a follow-up.
|
||||
- **No SLAM stack.** Paper §6 out-of-scope unchanged.
|
||||
- **No ZK / privacy implementation.** Defers to #000016.
|
||||
- **No mass-storage tier integration.** Cold-pack (#000061)
|
||||
unchanged.
|
||||
- **No bench harness wiring.** Phase 1 is KAT-tested; bench-qa
|
||||
integration follows when relation + event land.
|
||||
|
||||
## 6. Cross-references
|
||||
|
||||
| Ref | Title | Relationship |
|
||||
|---|---|---|
|
||||
| #000013 | Spatial-temporal substrate (Merkle-AGI v7-W) | Parent. Closed doc-only 2026-05-09; this ticket implements the first verifier kernel under that namespace. Reopens #000013 status from `namespace_reserved` to `kernel_in_progress` upon land. |
|
||||
| #000035 | PRG choice for φ_PRG (HMAC-SHA-512 KDF) | Primitive reused. Domain separation by dedicated seed; #000035 KAT freeze stays intact. |
|
||||
| #000018 | Soft-hash covert channel | Hard-hash discipline inherited. Spatial-anchor outputs are integer cells (hard channel); locality indices (Morton / H3) would be soft and never enter proof path. |
|
||||
| #000015 | π* cross-domain composition | Future: composing v9.8 language claims with v7-W spatial claims requires the composition theorem from #000015. Out of scope for #000070 but the registration pattern keeps the door open. |
|
||||
| #000016 | ZK / privacy | Required before any non-public spatial-anchor deployment. Phase 1 fails closed on missing privacy class. |
|
||||
| #000049 | Attribution-aware grounding check | Architectural sibling — split from #000048 because NLI raised a fresh `audit_mode` question that needed its own dav1d-review surface. Same shape as the §2.4 split-or-extend decision here. |
|
||||
| v7-W paper | `docs/_source/merkle-agi-v7w-spatial-temporal.rst` (658 lines) | Specification this kernel implements. §A worked example informs default manifest shape. |
|
||||
| v7 paper | `docs/_source/merkle-agi-dag-v7.rst` §9.10 / §9.10.1 | φ_PRG amendment context. Domain-separation argument inherits from §9.10. |
|
||||
| Joseph framework | Memory: `joseph_trudojo_6dim_spatial_ontology.md` | Author attribution. The six-dimension `H₁..H₆` split is Joseph (@TrudoJo)'s. Substrate paper amendment under this ticket cites him. |
|
||||
| Prior plan | `/tmp/arborist-spatial-ontology-plan.md` (2026-05-31, not in repo) | The plan this ticket replaces. Five-step §2 deletions captured in §7 below. |
|
||||
|
||||
## 7. Five-step alignment
|
||||
|
||||
1. **Requirements less dumb.** Joseph (@TrudoJo) authored the
|
||||
framework; fox brought it in 2026-05-31 and decided which kernel
|
||||
lands first. Names, not departments.
|
||||
2. **Delete the part or the process.** ~40 % of the prior
|
||||
`/tmp/arborist-spatial-ontology-plan.md` deleted before drafting:
|
||||
- Geographic-search backend (encoding route — substrate confusion)
|
||||
- `Document.extra` lat/lon hooks (different ticket if at all)
|
||||
- `audit_mode = HYBRID` for spatial hits (convention-illegal)
|
||||
- Geohash (subsumed by raw Morton)
|
||||
- Quadtree as separate (octree at level-z=0)
|
||||
- Hilbert at Phase 1 (deferred; not used by H₁ mapper)
|
||||
- Five-tier "hash suite" framing (conflated hard vs soft hashes)
|
||||
- `arborist/spatial/` namespace (violates topic-naming rule;
|
||||
`world/pi_star/object.py` is the right home)
|
||||
3. **Simplify.** One registry slot (`spatial-anchor-object@v1`); one
|
||||
new seed; no new SQL; reuses #000035's `_expand`. ~150 LoC
|
||||
excluding KATs + tests.
|
||||
4. **Cycle time.** KATs ship with the projection — replay is the
|
||||
test, no separate harness. Phase 1 is a single PR.
|
||||
5. **Automate.** `arborist/pi_star/registry.py` already automates
|
||||
`name@version` lookup; this ticket adds a row, not a mechanism.
|
||||
|
||||
## 7a. Pre-review empirical evidence
|
||||
|
||||
To shrink dav1d's review surface, ticket #000070 ships a pure-stdlib
|
||||
empirical-validation bench **before** any kernel code lands. It runs
|
||||
against `arborist.substrate.anchor_prg._expand` directly (no new module
|
||||
required) and prototypes `split_anchor` + `map_position_octree` inline.
|
||||
|
||||
Run: `make bench-spatial-anchor` (~2 s, RNG-seed-pinned, byte-identical
|
||||
across re-runs).
|
||||
|
||||
Source: `bench/spatial_anchor_validation.py`
|
||||
Report: `bench/spatial_anchor_validation_results.md`
|
||||
|
||||
Bench results from the first run (2026-05-31, N=10000):
|
||||
|
||||
| Bench | Headline number | Verdict | Answers |
|
||||
|---|---|---|---|
|
||||
| §1 Avalanche (single-bit flip) | mean = 767.85 bits, z = -0.49 vs PRF null 768 | PASS | Q2 |
|
||||
| §2 Cell-distribution uniformity (octree L=2,3,4) | \|z\| < 1.0 at every level | PASS | Q3 |
|
||||
| §3 Collision vs birthday-bound (L=4,6,8,10) | obs/exp ratio = 0.989 / 1.038 at populated L | PASS | Q3, Q9 |
|
||||
| §4 Cross-region independence (Pearson on all 15 pairs of H₁..H₆) | every pair < 2σ, none flag at 4σ | PASS | Q2 (§2.2 option A safe) |
|
||||
| §5 Domain separation (Arm A distinct seeds vs Arm B shared seed) | Arm A: 767.91 bits independent · Arm B: **0.00 bits — collision class confirmed** | PASS | Q1 (§2.1 option A required) |
|
||||
|
||||
Numerical headlines:
|
||||
- **Q1** (seed source): Arm B's exact-zero Hamming distance is the
|
||||
measurable footgun the §2.1 option A discipline protects against.
|
||||
- **Q2** (segmentation method): cross-region Pearson r in
|
||||
[-0.018, +0.012] across 15 pairs, all sub-2σ — counter-mode block
|
||||
independence holds empirically; fixed-offset slicing is safe.
|
||||
- **Q3** (octree position mapper): uniform under chi² at L=2,3,4;
|
||||
birthday-bound holds at L=4,6,8,10.
|
||||
- **Q8** (endianness): inherited from #000035 by byte-identical reuse
|
||||
of `_expand`; no separate test needed.
|
||||
- **Q9** (adversarial KAT vectors): §3 surfaces the structural
|
||||
importance of including `0x00 * 32`, `0xFF * 32`, and at least one
|
||||
low-entropy hash engineered to map to cell 0 at the deployment's L
|
||||
in the KAT set.
|
||||
|
||||
Remaining open questions (Q4 scope split, Q5 privacy default, Q6
|
||||
audit_mode discipline, Q7 manifest validator timing, Q10 paper-amendment
|
||||
wording) are non-empirical — design decisions that stay with dav1d's
|
||||
review.
|
||||
|
||||
## 8. Open questions for dav1d
|
||||
|
||||
1. **§2.1 — dedicated seed vs domain-tag bump.** Recommendation A
|
||||
(dedicated seed) preserves your 2026-05-11 #000035 final review.
|
||||
Acceptable, or do you prefer the cleaner domain-tag separation
|
||||
under a `PHI_PRG_VERSION` bump?
|
||||
2. **§2.2 — fixed-offset slicing vs per-region nested HMAC.**
|
||||
Recommendation A relies on counter-mode block independence —
|
||||
the same PRF argument #000035 §4 used. Confirm the slicing
|
||||
inherits the independence cleanly, or do we need a separate
|
||||
per-region HMAC for paper-citation purposes?
|
||||
3. **§2.3 — H₁ mapper choice.** Octree at Phase 1 matches paper
|
||||
§2.1 + §A. Should we ship a second position mapper
|
||||
(`spatial-anchor-h3@v1` or `spatial-anchor-morton@v1`) at Phase
|
||||
1 to avoid registry churn later, or is one mapper per ticket the
|
||||
right discipline?
|
||||
4. **§2.4 — scope.** Object alone (sibling ticket for relation), or
|
||||
object + relation in one drop? CLAUDE.md memory says don't
|
||||
proliferate; #000049/#000048 says split when the audience
|
||||
differs. Your call.
|
||||
5. **§2.5 — privacy class default.** Recommendation A (fail-closed
|
||||
on missing class) is the safest. Is requiring explicit
|
||||
declaration acceptable, or does the worked-example's silent
|
||||
`"public"` default need to ship as-is?
|
||||
6. **§2.6 — `audit_mode` discipline.** Confirm that a spatial
|
||||
commitment is structurally different from a verifier warrant and
|
||||
that the ladder is not extended by Phase 1.
|
||||
7. **§2.7 — manifest validator timing.** Phase 1 accepts a dict with
|
||||
inline `_require_manifest()`. Acceptable to land
|
||||
`world/manifest.py` as a follow-up ticket, or must the validator
|
||||
land alongside the position kernel?
|
||||
8. **§2.8 — endianness.** Confirm LE throughout matches your
|
||||
2026-05-11 #000035 review (the `-le` suffix discipline).
|
||||
9. **KAT count.** #000035 shipped 10 vectors. Phase 1 plan also
|
||||
says 10. Larger? Specifically: should the KAT set include
|
||||
adversarial cases (zero hash, all-ones hash, low-entropy hash,
|
||||
`phi_prg` output reused as `split_anchor` input) to harden
|
||||
against future-developer foot-guns?
|
||||
10. **Substrate paper amendment wording.** Phase 1 land includes
|
||||
a paragraph in `docs/_source/merkle-agi-v7w-spatial-temporal.rst`
|
||||
introducing the six-dimension framework. Preferred wording for
|
||||
@TrudoJo attribution? Default draft: "The six-dimension anchor
|
||||
split formalized in this section follows the procedural-spatial
|
||||
framework presented by Joseph (@TrudoJo) on 2026-05-31."
|
||||
|
||||
---
|
||||
|
||||
**Land sequence on go:**
|
||||
|
||||
1. Land this ticket file + `Next ID` bump + index row (this commit).
|
||||
2. dav1d review pass.
|
||||
3. fox go.
|
||||
4. Implementation PR per §3.
|
||||
5. Substrate-paper amendment in the same PR.
|
||||
6. Memory update: flip `joseph_trudojo_6dim_spatial_ontology.md`
|
||||
from "reference (cite when used)" to "reference (used in #000070,
|
||||
landed `<sha>`)".
|
||||
7. Reopen #000013 status `namespace_reserved` → `kernel_in_progress`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue