diff --git a/.claude/board/INTEGRATION_PLANS.md b/.claude/board/INTEGRATION_PLANS.md index f48922ff2..84b123d06 100644 --- a/.claude/board/INTEGRATION_PLANS.md +++ b/.claude/board/INTEGRATION_PLANS.md @@ -1,6 +1,6 @@ ## 2026-10-30 — D-LITHO: the photolithography contract → `.claude/plans/d-litho-photolithography-contract-v1.md` -**Status:** PROPOSED, docs only; nothing authorized. **Board:** [entry](entries/2026-10-30-d-litho-photolithography-contract.md), [STATUS_BOARD](STATUS_BOARD.md) D-LITHO. Photolithography as the shader north star: vocabulary (wafer, reticle, exposure, dose, develop), the Abacus as address grammar and mental model (frame, rod, bead position under a DR law), "views are laws, never rotations", ownership, consumers, gates G1–G5 (not run). Clarifies D-DRDT's "rotation" wording without editing it. +**Status:** RETIRED 2026-10-30, folded into D-DT64-6 Amendment A (`d-dt64-6-routing-bindstore-behavior-v1.md`); "photolithography" was a metaphor. **Board:** [entry](entries/2026-10-30-d-litho-photolithography-contract.md), [STATUS_BOARD](STATUS_BOARD.md) D-LITHO. Photolithography as the shader north star: vocabulary (wafer, reticle, exposure, dose, develop), the Abacus as address grammar and mental model (frame, rod, bead position under a DR law), "views are laws, never rotations", ownership, consumers, gates G1–G5 (not run). Clarifies D-DRDT's "rotation" wording without editing it. **Confidence:** decisions recorded; no code. ## 2026-10-30 — D-TRACT-HARVEST-0: Tract as a cold ONNX frontend, admitted onto native methods → `.claude/plans/d-tract-harvest-0-native-algebra-bridge-v1.md` diff --git a/.claude/board/STATUS_BOARD.md b/.claude/board/STATUS_BOARD.md index 6be9e5e0c..8474c13fb 100644 --- a/.claude/board/STATUS_BOARD.md +++ b/.claude/board/STATUS_BOARD.md @@ -4,9 +4,9 @@ | D-id | Deliverable | Status | Gate | |---|---|---|---| -| D-LITHO-0 | contract: vocabulary, Abacus address grammar, design rules, ownership, consumers (docs) | In PR (#1859) | docs review | -| D-LITHO-1 | first consumer operation written in the grammar, with a failing fixture | Queued | G1; needs a consumer signature (EXO-50) | -| D-LITHO-2 | law-not-rotation, Morton-tile, dose-identity and alignment-refusal falsifiers | Queued | G2–G5; after D-LITHO-1 | +| D-LITHO-0 | contract: vocabulary, Abacus address grammar, design rules, ownership, consumers (docs); §4 = DR facts the DTO layer must know (cited) | Folded into D-DT64-6 Amendment A (#1862) | docs review | +| D-LITHO-1 | first consumer operation as a DTO binding, with a failing fixture | Folded into D-DT64-6 Amendment A (#1862) | G1 for a non-ONNX consumer: NodeGuid stand-in, R/S as ClassView × WideFieldMask, count method by reference with `Population::Bag`, expected {2:4, 3:1, 7:1}; refused today with `BagNeedsMultiplicity` | +| D-LITHO-2 | law-not-rotation, Morton-tile, dose-identity and alignment-refusal falsifiers | Folded into D-DT64-6 Amendment A (#1862) | G2 not run | ## D-XLOG-DR64 — XLOG frontend lowered onto the DR64 relation register, CPU only (2026-10-30) diff --git a/.claude/board/entries/2026-10-30-d-litho-photolithography-contract.md b/.claude/board/entries/2026-10-30-d-litho-photolithography-contract.md index 516de34e2..920758c1c 100644 --- a/.claude/board/entries/2026-10-30-d-litho-photolithography-contract.md +++ b/.claude/board/entries/2026-10-30-d-litho-photolithography-contract.md @@ -50,3 +50,35 @@ - the order DR routes → DT64 assigns; - gates G1, G4, G5. - Lesson: D-DRF-1 was not read before geometry was written into this plan. + +## Correction to the scope correction (2026-10-30, user) + +"Of course you need to know the dimensions in order to apply the law effectively." + +- The removal above overcorrected. The error was stating DR's dimensions as this contract's decisions, not stating them. +- Plan §4 is now "What the DTO layer must know": DR's facts, each cited (D-DRF-1 §1–§3, `morton8x8.rs`, D-DRAV-1, `dr256-where-capstone-v1.md`, `mask-risc` `ir.rs:329-337` and `tests/rotation.rs`), with what the DTO layer does with each. The key one: D-DRF-1 says axis semantics are declared by the caller, and the DTO layer is that caller. +- The 8 × 8 / 16 × 16 Morton tile reading is derived from the prefix property and pinned only for 4 × 4; it is gated as G3 before use. +- Gates G2 (law, not rotation) and G3 (Morton tile) are restored. Q1 stays withdrawn: deciding rod width is still DR's. +- Strikes the "Removed as DR's concern" list above; it stays in place as history. + +MIRROR +- LESSON: geometry was first written without reading DR's plans, then removed instead of attributed; both times the sources were not read in full. + +## Correction (2026-10-30, user): metaphor, and the bind store + +- Photolithography was the user's teaching metaphor, not a production name. The plan is now a reading aid that maps the metaphor onto existing seams (banner at the top of the plan). +- "XLOG is the first consumer of the bind store" is withdrawn. D-NFR-0 S5 says the binding store is MISSING. D-DT64-Q0 says the binding is an interface seam, not a store. D-NFR-1 (the S5 × S6 adapter) is the smallest seam and is not built. +- XLOG's `BagNeedsMultiplicity` is S8's existing refusal in `bind_dr64`. D-QSP already says a tile carries no bag multiplicity without a further lawful carrier. The dose test (G4) stays as a measured fact, not a proposed carrier. + +MIRROR +- BLIND SPOT: the binding plans (Q0, D-NFR-0, D-QSP, D-QR-CAP) were not read before the binding was described. + +## Correction to the correction (2026-10-30, user): the bind store plans are authoritative + +- DT is the bind store (D-DT64-6 §1 D4; D-DRDT §1): the existing ClassId-addressed DTO binding store. It holds bindings and their version log, never business data. +- D-NFR-0 S5's "MISSING" is about Quack, which is the query-binding membrane, not about DT. +- XLOG (#1864) is a consumer of the DT bind store. "There is no bind store yet" is withdrawn. + +## Folded (2026-10-30, user) + +- The plan is folded into the bind store plan as D-DT64-6 Amendment A. The D-LITHO file is now only a pointer. diff --git a/.claude/plans/d-dt64-6-routing-bindstore-behavior-v1.md b/.claude/plans/d-dt64-6-routing-bindstore-behavior-v1.md index 49701a177..7d47bbb1b 100644 --- a/.claude/plans/d-dt64-6-routing-bindstore-behavior-v1.md +++ b/.claude/plans/d-dt64-6-routing-bindstore-behavior-v1.md @@ -187,3 +187,54 @@ All OPEN. - OGAR [#363](https://github.com/AdaWorldAPI/OGAR/pull/363) (`ogit_schema_composition.rs`). - crai-rs #1 and #2, CR-H0 / CR-H1 (private repo; a sidecar consumer of #1760; links resolve only with access). - Board coordination: Linear EXO-50 (append-only; coordination, not approval). + +--- + +# Amendment A (2026-10-30): what the bind store applies from DR, the ONNX reference path, and measured gates + +**Status:** PROPOSED / DOCS + two lab tests. Folded in from the retired D-LITHO note (#1859, #1860, #1862), whose "photolithography" wording was the operator's metaphor, not a production name. Nothing here changes §1–§7; it records what a DT binding must know and where the bind store already runs. + +## A.1 DR facts a DT binding must know and apply + +DR owns every fact below. DT decides none of them, but a binding cannot be stated without them. Every source was read in full on 2026-10-30. + +| DR fact | Source | What a DT binding does with it | +|---|---|---| +| DR64 focus: 64 × 64 = 4,096 positions; Boolean tile 512 B; u16 position → SoA-row map 8 KiB; at most 2 MiB of distinct 512 B rows. DR256: 65,536 positions, 8 KiB, 128 KiB, 32 MiB. | D-DRF-1 §1; falsifier G1 (PASS, lab) | Names DR64 or DR256 and states its cost in these units. | +| Dense 64³ volume 32 KiB, 256³ 2 MiB; map plus cube 40 KiB. | D-DRF-1 §1 | Never assumes a cube exists (§7). | +| Axis semantics are declared by the caller; the physical third axis is NFR-OP-2 (DR). | D-DRF-1 §1; capstone DT64-OP-2 | **The DT binding is that caller**: it declares typed axes (`AxisKind`) and never decides the physical third axis. | +| HHTL16 address = `Morton8x8`; an aligned run of 4^j codes is an aligned 2^j × 2^j square (a 64-row word is 8 × 8, a 256-row block 16 × 16). | `morton8x8.rs`; D-DRDT §2; test in A.3 | A view is an address map over the canonical words; rotation is never a mask op (`mask-risc/tests/rotation.rs`). | +| Fixed width 64 / 256; underflow carried by the presence bit; absent is never FALSE or zero. | user ruling 2026-10-30 (EXO-50 17–18); D-DRF-1 G7; D-DRAV-1 AV11 | Out-of-focus contributors are expanded through a witnessed binding or refused. | +| The sealed map is immutable and versioned; the same ordinal under another frame is refused. | D-DRF-1 §0, §2; G3; D-SAG-6 F07 | Consistent with D8: the register copy is keyed to its frame. | +| A Boolean cell is support under a declared semiring; no Bag, NULL or evidence. `FieldMask` is presence, never predicate truth. | D-DRF-1 §1; D-QSP; capstone | A binding declares its population; Bag is refused today (`bind_dr64`: `BagNeedsMultiplicity`). | +| `Keep` → `Plane` reusable under one frame; `ScatterOrU32` is demand-only; a detached `Keep` is recomputed or refused (1,032 vs 31). | `mask-risc ir.rs:329-337`; `dr256-where-capstone-v1.md` B.6, E.5 | No escaped reuse without a complete dependency witness. | +| Map and value lifetimes are separate; a map-only operation needs no value fetch. | D-DRAV-1 §2, §6 | A method binding declares value-free or value-demanding. | +| The 64-thought plane is separate from the relation selector and the map index. | D-DRF-1 §1; R2 | Thoughts are reserved, not claimed (allocate on Thought-Git `Commit`), never a cube axis. | + +## A.2 The bind-store shape runs in a lab for ONNX: `tract-harvest-probe` + +**Status:** the bind store is a plan-level decision (D4, D-DRDT §1); no bind store type exists in the codebase. What exists: the contract pieces DT is built from (`ClassView::fields`, `methods_for`, `actions_for`, `hotplug`) and this lab crate. `crates/tract-harvest-probe` runs the shape of D1–D8 for ONNX op signatures, checked bit for bit against ORT (`tests/tiny.rs`, `tests/jina.rs`). Read in full 2026-10-30. + +| This plan | `tract-harvest-probe` | Test | +|---|---|---| +| DR#3 Identity × Property | `dr3::OnnxGraph`: nodes = Identity, values = Property, `TILE = 64`, else `TileOverflow` | `dep_composition_is_the_source_dataflow` | +| ON / DO share the property domain (§3) | `on`, `do_` relations; `dep = do_ ∘ read_by` via `relcomp::compose`; schedule from `dep` | `schedule_comes_from_dep_not_source_order` | +| D4 classid → polyfill; D5 immutable classid | `registry::Registry`: op signature → one classid (lab ordinals `0x0F..`), DO in `lance-graph-onnx` | `base_through_the_graph_is_bit_exact_against_ort` | +| WHEN is K3; UNKNOWN never TRUE (§3 step 4) | `Registration::when` returns `K3`; resolution refuses non-TRUE | `unknown_shapes_refuse`, `incompatible_broadcast_is_when_false` | +| Unregistered is UNKNOWN (F06) | `Refusal::Unregistered` | `unregistered_op_is_refused` | +| D8 frame-keyed binding | `Frame` revisions = (source digest, registry version, coordinate digest); `FrameStore::check` per run | `stale_generation_is_refused`, `registry_change_is_a_frame_change` | +| Numeric annotation | `Numeric::{Exact, Bounded}`; ULP measured vs ORT and f64 | `erf_sweep_against_f64_and_ort`, `trig_sweep_against_f64_and_ort` | + +Production step (registry module doc): the lab ordinals become OGAR-minted concepts activated through `hotplug` (D6). + +## A.3 Measured gates (lab) + +| Gate | Test | Result | +|---|---|---| +| Morton tile | `lance-graph-contract` `morton8x8::tests::every_aligned_code_run_is_an_aligned_square` (j = 0..=8) | PASS; disable run (runs start one code late) red | +| Count as Boolean planes | `lance-graph-mask-risc/tests/dose.rs`: K = 6 planes over a 4,096-row focus, `And` + `Count` per plane, weighted 2^k, equals the per-position sum at 0/3/50/97/100 % selection; every plane load-bearing | PASS; disable run (swap adjacent weights) red. A measured fact, not an adopted Bag carrier | +| First non-ONNX consumer (stated in a test; no store built) | XLOG #1864: `NodeGuid` stand-in, R/S as `ClassView` × `WideFieldMask`, count method by reference, `Population::Bag`, expected {2:4, 3:1, 7:1} | failing fixture by design: refused with `BagNeedsMultiplicity` | + +## A.4 Open (unchanged owners) + +The Bag carrier (who admits a counted population into `bind_dr64`); the D-DRDT §4 DT gaps (MethodId, K3 guards, effect order, one lookup); §6 questions 1–9. diff --git a/.claude/plans/d-litho-photolithography-contract-v1.md b/.claude/plans/d-litho-photolithography-contract-v1.md index 64f1cf229..b68fe69fc 100644 --- a/.claude/plans/d-litho-photolithography-contract-v1.md +++ b/.claude/plans/d-litho-photolithography-contract-v1.md @@ -1,209 +1,7 @@ -# D-LITHO: the photolithography contract — the DTO layer over DR's 64ⁿ / 256ⁿ hypercube +# D-LITHO (retired 2026-10-30): folded into the bind store plan -**Date:** 2026-10-30. **Status:** PROPOSED / DOCS ONLY. Nothing is authorized: no ABI, kernel, mask-risc -op, terminal, runtime or contract type. -**Board:** [entry](../board/entries/2026-10-30-d-litho-photolithography-contract.md), -[STATUS_BOARD](../board/STATUS_BOARD.md) D-LITHO. -**Builds on, read and not restated:** -- [D-DRF-1](d-dr64-focus-lease-foreign-cache-v1.md) §0–§3: DR64 focus geometry, the u16 pointer map, the - 64³ Boolean relation volume, axis semantics declared by the caller, focus lease. -- [D-DRAV-1](d-dr-address-first-value-demand-v1.md): sealed DR map kept apart from value demand. -- [D-DRDT](d-drdt-dr-dt-ownership-amendment-v1.md) (#1835): DR is the Cartesian adapter plate; DT is the - ClassId binding store. -- [D-DT64 capstone](d-dt64-holographic-predicate-capstone-v1.md): DT64 = DTO Tensor 64, a semantic adapter - plate that "does not itself decide DR64³ axis semantics" (NFR-OP-2 belongs to the DR physical ABI). -- [D-DT64-6](d-dt64-6-routing-bindstore-behavior-v1.md): DR64 routing, DT64 bind store. -- `lance-graph-mask-risc` (`ir.rs`, `exec.rs`), `lance-graph-contract` (`hotplug.rs`, `class_view.rs`, - `canonical_node.rs`). - -**Coordination:** Linear EXO-50, messages 10–18 (2026-10-30). - -> **⊘ Scope correction (2026-10-30, user).** "You're the DTO layer of a holographic hypercube 64ⁿ or 256ⁿ. -> Everything in regards to dimensions is not your concern." Earlier revisions of this plan (#1859 and the -> first commits of #1860) defined coordinate geometry: a Morton tile fact, axis widths, presence-bit -> underflow, coordinate freezing, an address law and a "rotation" reading. All of that is DR's, is already -> written in D-DRF-1, and was written here without reading D-DRF-1 first. It is removed. §4 lists what this -> contract assumes DR provides, by reference only. - -## Overview - -Photolithography is the north star for the relational shader. The wafer (the substrate) never moves. A -reticle is written once and stepped across demanded dies (tiles). Each exposure is one field-parallel -instruction. Dose levels give significance, and develop is the late, demanded readout. Persistence (etch -and deposit) is decoupled from exposure. - -This contract is the **DTO layer** of that picture. DR owns the hypercube: its dimensions, coordinates, -routing and the sealed global → local map. Over a coordinate that DR has already routed, the DTO layer binds -meaning: which identity, which property mappings, which methods and thoughts it may reference. The -**Abacus** is the mental model a shader author uses to read that binding (frame, rod, bead). It names DR -coordinates; it does not define them. - -## Checklist - -- [x] Record the user decisions of 2026-10-30 (§1). -- [x] Vocabulary, with the owner of each row (§2). -- [x] What the DTO layer binds (§3); what it assumes from DR (§4); the order (§5). -- [x] Design rules (§6), non-goals (§7), ownership (§8), consumers (§9). -- [ ] Owner replies on EXO-50 (§10). -- [ ] First consumer writes one binding with a failing fixture (§11, G1). -- [ ] Gates G1, G4, G5 (§11). None run. - -## 1. Decisions recorded - -**DECISION (2026-10-30):** The north star of the relational shader is photolithography. -**SCOPE:** the shader contract and every design that exposes or folds over DR coordinates. -**BASIS:** the user's statement in session (decision, not measurement). -**REVISIT WHEN:** an operation is needed that has no counterpart in the exposure model. - -**DECISION (2026-10-30):** This contract is the DTO layer of a holographic hypercube 64ⁿ or 256ⁿ. -Dimensions are not its concern. -**SCOPE:** everything below. Axes, widths, coordinates and routing are DR's (§4). -**BASIS:** the user's statement in session (decision, not measurement). -**REVISIT WHEN:** a DTO binding cannot be stated without choosing a dimension. - -**DECISION (2026-10-30):** The Abacus is the mental model of a shader. It concerns naming, not -materialization; execution and cost belong to mask-risc, ndarray and the layers below them. -**SCOPE:** the Abacus as notation. It does not cover the `domino.rs` counter fixture in ndarray, which -stays a lab fixture (H13 DEFER). -**BASIS:** the user's statement in session (decision, not measurement). - -**DECISION (2026-10-30):** What is always present and what is not material. - -| Always present | Not material (resolved on demand, never stored per cell) | -|---|---| -| **identity = `NodeGuid`** (`canonical_node.rs`) | **`ClassView` → methods** (DT64, via hotplug) | -| **property mappings**, i.e. which properties and edges are selected | **64 thoughts → Thought-Git** ([D-DT64-4](d-dt64-4-edge-thoughtgit-hypothesis-time-v1.md)) | - -**BASIS:** the user's statements in session (decision, not measurement). - -**DECISION (2026-10-30):** The rule for thoughts is "reserve, don't claim". The mental model is thin -provisioning, not thick: a thought binding allocates on its first write (a Thought-Git `Commit`), never in -advance. Where the thought positions live is DR's and Thought-Git's (§4); the DTO layer only refuses to -preallocate. -**BASIS:** the user's statements in session (decision, not measurement). - -## 2. Vocabulary - -| Lithography | This stack | Owner | -|---|---|---| -| Wafer | the substrate; never copied, never moved | SoA owner | -| Die / exposure field | one demanded tile | DR | -| Stepper stepping die to die | streaming demanded tiles: one shader, many tiles | DR / execution | -| Reticle (mask) | a predicate, or a DR projection | DT64 (predicate) / DR (projection) | -| Exposure | one field-parallel shader instruction | mask-risc / ndarray | -| Dose levels (2^k exposure times) | Abacus rods: significance k of a bound value | DTO notation over DR coordinates | -| Overlay alignment marks | version witnesses: DR's sealed map, the DTO binding's version | DR / DT64 | -| Develop | a fold or terminal; only what is demanded is read out | mask-risc | -| Layer stack | a program: a sequence of exposures | mask-risc | -| Etch / deposit after inspection | witnessed deltas → coalesced dirty rows → asynchronous writer | persistence (D-DRF-1 §6) | - -The dose stack is a mechanism, not decoration. Grayscale exposure from binary masks with doubling exposure -times develops to Σ_k 2^k · mask_k, the bit-plane fold the ndarray Abacus fixtures compute exactly -(`examples/u9_domino/domino.rs`, `Abacus::total`). - -## 3. What the DTO layer binds - -Over a coordinate DR has routed: - -- **Identity:** a `NodeGuid`. The DTO layer never invents or compares local ordinals as identity - (D-DRF-1 §2: "one ordinal shared numerically across datasets is not evidence of identical identity"). -- **Property mappings:** which properties and edges are selected, PSCustomObject-style, the way - `Select-Object -Property` picks fields. The carrier is `ClassView × WideFieldMask` (`class_view.rs`). The - selection is versioned via a table in lance-graph (Q5). -- **Methods:** named by reference and resolved through `ClassView` / hotplug. A shader never carries a copy. -- **Thoughts:** references into Thought-Git, thin-provisioned (§1). -- **Meaning of a rod:** width, signedness and what a count stands for come through DT64 and hotplug - (`Activation::register_law_for`, `RegisterLaw`), never from the coordinate. - -## 4. Assumed from DR (not decided here) - -By reference only. The authoritative text is in the cited plans. - -- **The hypercube, its dimensions and axis semantics:** 64ⁿ / 256ⁿ, the DR64 focus, the u16 pointer map, - the 64³ Boolean relation volume (D-DRF-1 §1). Which axis is which is declared by the caller and decided - under NFR-OP-2, not here. -- **Global → local routing**, amortized, sealed and versioned; the focus lease (D-DRF-1 §2–§3; D-DRDT §1). -- **Fixed widths, the presence bit and sparse write / merge on read, and why coordinates freeze.** The - user's statements of 2026-10-30 on these points are relayed to the DR owner (EXO-50 messages 17–18). They - are DR's rules, recorded here only as what the DTO layer relies on. -- **Projection and views:** a view is a different DR projection over the same words, never a data move. - -## 5. Order - -**DR routes first** (global → local, address → classid). **DT64 then assigns** meaning and methods to the -routed position. Execution (mask-risc, ndarray) comes after both. DT64 does not route, and DR assigns no -meaning. - -## 6. Design rules - -1. **The wafer never moves.** A DTO binding never copies the substrate. -2. **Pay in the reticle, not per die.** Bindings and predicates are prepared once and stepped across tiles. -3. **Exposure is field-parallel.** A binding that has to be walked position by position is the wrong tool. -4. **Alignment is mandatory.** A binding used under a DR seal or a binding version other than its own is a - defect even if it runs. -5. **Develop only what is demanded.** Readout and writeback are late and separate from exposure. -6. **Identity is not multiplied.** Relations are addressed as edges. A binding never adds an edge. - -## 7. Not the goal - -- A mandatory dense 64K³ cube, or a 65,536 × 65,536 matrix. -- A duplicate relationship authority: SoA edges remain the relationship authority. -- Eager global materialization. -- Any bypass of version witnesses. -- A new writer or persistence path. -- An Abacus runtime type. H13 stays deferred in ndarray. -- Any definition of dimensions, axes, widths or coordinates (§1, §4). - -## 8. Ownership - -| Concern | Owner | -|---|---| -| The hypercube: dimensions, axes, coordinates, Morton / HHTL16, global → local routing, focus lease | DR (D-DRF-1, D-DRDT) | -| Class meaning, field laws, method identity, guards, effect order, assigned after DR routes | DT64, through `ClassView` / hotplug / ogar-vocab | -| The shader mental model and the DTO binding vocabulary | this contract | -| Thought positions and commits | Thought-Git (D-TGB, EXO-148) | -| Straight-line programs, tiled execution, terminals | `lance-graph-mask-risc` | -| Kernels | ndarray, through `ndarray::simd` | -| Persistence | resident computation → witnessed dirty rows → asynchronous writer | - -## 9. Consumers - -Each would state its operation as a DTO binding over DR coordinates first. None has sent a signature or a -fixture yet. - -| Consumer | Likely first binding | -|---|---| -| ONNX methods (Tract registry, D-TRACT-HARVEST-0) | count-shaped reductions over a predicate | -| TFLite int8 leaf (D-TFLP) | the same count-shaped reductions | -| XLOG (D-XLOG-DR64-0) | bag multiplicity per answer tuple (EXO-50 message 12) | -| egglog-mlir / DialEgg | offline proof that two exposure sequences develop the same result | -| Identity × Edge evidence → SPO / SPOFC | evidence counts (w⁺, w) folded into frequency and confidence | -| NNUE, cognitive-shader-driver (later) | feature-occurrence counts; Hamming and popcount folds | - -Known misfit, measured earlier: bit-plane *multiplication* (ndarray `u9-abacus-probe.md`, 5–120× slower -than the byte-dot, refused). - -## 10. Open questions - -- **Q2 (DR/DT).** Is DialEgg the place to prove that two exposure sequences develop the same result? -- **Q3 (mask-risc).** Once a consumer writes a binding down, which verbs have no straight-line form today? - Unasked until G1. -- **Q4 (naming).** "DR64K" and "Membrane64" have no definition in code or plans; their owner defines them. -- **Q5 (DR/DT).** Which lance-graph table versions the property-mapping selection. -- Q1 (where the rod width lives) is withdrawn: it is a dimension question, so it belongs to DR (NFR-OP-2). - -## 11. Pre-registered gates (none run) - -- **G1, binding sufficiency.** One named consumer states one operation as a DTO binding over DR - coordinates, with a failing fixture and expected values. **Fails if** the statement needs a dimension - decision. -- **G4, dose identity.** A dose stack of k binary masks develops to Σ 2^k · popcount(mask_k), equal to the - per-position oracle. Disable run: drop one rod; the test turns red. -- **G5, alignment refusal.** A binding used under a DR seal or binding version other than its own is - refused, never executed. Disable run: skip the witness check; the test turns red. -- G2 (law, not rotation) and G3 (Morton tile) are withdrawn as dimension gates. If wanted, they belong in - DR's own falsifier plan ([D-DRF falsifiers](d-dr64-focus-cache-falsifiers-v1.md)). - -## Errata to the shared diagram - -The DR64/DR256 overview says "65,336 global addresses". It should say 65,536 (D-DRF-1 §1: 256 × 256). +"Photolithography" was the operator's metaphor, not a production name. Everything this note carried is now +[D-DT64-6 Amendment A](d-dt64-6-routing-bindstore-behavior-v1.md#amendment-a-2026-10-30-what-the-bind-store-applies-from-dr-the-onnx-reference-path-and-measured-gates): +the DR facts a DT binding applies (A.1), the ONNX path through `tract-harvest-probe` (A.2), and the measured +gates (A.3). History: #1859, #1860, #1862 and the board entry `entries/2026-10-30-d-litho-photolithography-contract.md`. +The D-LITHO-* rows on STATUS_BOARD are folded into D-DT64-6. diff --git a/crates/lance-graph-contract/src/morton8x8.rs b/crates/lance-graph-contract/src/morton8x8.rs index 2a3a1c929..7f63c8c20 100644 --- a/crates/lance-graph-contract/src/morton8x8.rs +++ b/crates/lance-graph-contract/src/morton8x8.rs @@ -283,6 +283,32 @@ mod tests { assert_eq!(by_climb, [0, 344_064, 132_096, 35_904, 9_156]); } + /// FAILS IF: some aligned run of `4^j` consecutive codes (j = 0..=8) is not + /// exactly one aligned `2^j x 2^j` square of distinct `(x, y)` pairs. At + /// j = 3 a run is one 64-row mask word (8 x 8); at j = 4 a 256-row block + /// (16 x 16). D-LITHO G3. + #[test] + fn every_aligned_code_run_is_an_aligned_square() { + for j in 0..=8u32 { + let run = 1u32 << (2 * j); + let side = 1u32 << j; + for start in (0..=u16::MAX as u32).step_by(run as usize) { + let first = Morton8x8::from_code(start as u16); + let (x0, y0) = (u32::from(first.x()), u32::from(first.y())); + assert_eq!((x0 % side, y0 % side), (0, 0), "j={j} run {start}: corner not aligned"); + let mut seen = vec![false; run as usize]; + for c in start..start + run { + let m = Morton8x8::from_code(c as u16); + let (dx, dy) = (u32::from(m.x()) - x0, u32::from(m.y()) - y0); + assert!(dx < side && dy < side, "j={j} code {c} leaves its square"); + let cell = (dy * side + dx) as usize; + assert!(!seen[cell], "j={j} code {c} repeats a cell"); + seen[cell] = true; + } + } + } + } + /// FAILS IF: on a 4 x 4 grid (2-bit axes) the in-grid test `code < 16` /// disagrees with the geometry, or the visit count is not 84. #[test] diff --git a/crates/lance-graph-mask-risc/tests/dose.rs b/crates/lance-graph-mask-risc/tests/dose.rs new file mode 100644 index 000000000..f1c4af205 --- /dev/null +++ b/crates/lance-graph-mask-risc/tests/dose.rs @@ -0,0 +1,137 @@ +//! D-LITHO G4: the dose identity, on the real executor. +//! +//! A per-position count `c(i) < 2^K` (a bag multiplicity, an evidence count) +//! is held as K Boolean planes ("rods"): plane `k` has bit `i` set iff bit `k` +//! of `c(i)` is set. The planes stay Boolean; nothing about a DR cell +//! changes. Under a selection `R`, the total develops as +//! +//! `Σ_{i ∈ R} c(i) = Σ_k 2^k · popcount(R ∧ plane_k)`, +//! +//! one `And` + `Count` program per rod. This is the counted semiring over +//! Boolean planes; the oracle below sums `c(i)` per position. + +use lance_graph_mask_risc::exec::{execute_into, Scratch}; +use lance_graph_mask_risc::{ + scratch_words_for, Foreign, MaskOp, Operand, Out, Planes, Program, Terminal, Value, +}; + +/// One DR64 focus. +const N: usize = 4096; +const WORDS: usize = N / 64; +/// Counts up to 2^K - 1. +const K: usize = 6; + +fn xorshift(s: &mut u64) -> u64 { + *s ^= *s << 13; + *s ^= *s >> 7; + *s ^= *s << 17; + *s +} + +/// The rods of `counts`: plane `k` holds bit `k` of every count. +fn rods(counts: &[u32]) -> Vec> { + let mut planes = vec![vec![0u64; WORDS]; K]; + for (i, &c) in counts.iter().enumerate() { + for (k, plane) in planes.iter_mut().enumerate() { + if c >> k & 1 == 1 { + plane[i / 64] |= 1 << (i % 64); + } + } + } + planes +} + +/// `popcount(R ∧ plane_k)` on the executor. Plane 0 is R, plane `1 + k` is rod k. +fn count_under(planes: &Planes<'_>, rod: u16) -> u64 { + let program = Program::new( + vec![MaskOp::And { + a: Operand::Plane(0), + b: Operand::Plane(1 + rod), + dst: 0, + }], + Terminal::Count { + mask: Operand::Scratch(0), + }, + ); + let slots = program.scratch_slots as usize; + let mut buf = vec![0u64; scratch_words_for(N, slots).expect("sized")]; + let mut scratch = Scratch::over(&mut buf, N, slots).expect("carves"); + match execute_into(&program, planes, &Foreign::NONE, &mut scratch, Out::None).expect("runs") { + Value::Count(c) => c as u64, + other => panic!("expected a count, got {other:?}"), + } +} + +/// The developed total: Σ_k 2^k · popcount(R ∧ plane_k). +fn develop(planes: &Planes<'_>, rods_used: &[usize]) -> u64 { + rods_used + .iter() + .map(|&k| (1u64 << k) * count_under(planes, k as u16)) + .sum() +} + +fn fixture(seed: u64, density: u64) -> (Vec, Vec) { + let mut s = seed; + let counts: Vec = (0..N) + .map(|_| (xorshift(&mut s) % (1 << K)) as u32) + .collect(); + let mut sel = vec![0u64; WORDS]; + for i in 0..N { + if xorshift(&mut s) % 100 < density { + sel[i / 64] |= 1 << (i % 64); + } + } + (counts, sel) +} + +fn oracle(counts: &[u32], sel: &[u64]) -> u64 { + (0..N) + .filter(|&i| sel[i / 64] >> (i % 64) & 1 == 1) + .map(|i| u64::from(counts[i])) + .sum() +} + +/// FAILS IF: the developed total differs from the per-position sum, at any +/// selection density including empty and full. +#[test] +fn the_dose_stack_develops_to_the_per_position_sum() { + for (seed, density) in [(1, 0), (2, 3), (3, 50), (4, 97), (5, 100)] { + let (counts, sel) = fixture(seed, density); + let rods = rods(&counts); + let masks: Vec<&[u64]> = std::iter::once(sel.as_slice()) + .chain(rods.iter().map(Vec::as_slice)) + .collect(); + let planes = Planes { + n_rows: N, + masks: &masks, + lanes: &[], + }; + let all: Vec = (0..K).collect(); + assert_eq!( + develop(&planes, &all), + oracle(&counts, &sel), + "seed {seed}, density {density}%" + ); + } +} + +/// FAILS IF: leaving one rod out of the develop step still matches the +/// oracle. Every rod must be load-bearing on a non-trivial fixture. +#[test] +fn every_rod_is_load_bearing() { + let (counts, sel) = fixture(7, 50); + let rods = rods(&counts); + let masks: Vec<&[u64]> = std::iter::once(sel.as_slice()) + .chain(rods.iter().map(Vec::as_slice)) + .collect(); + let planes = Planes { + n_rows: N, + masks: &masks, + lanes: &[], + }; + let want = oracle(&counts, &sel); + for drop in 0..K { + let kept: Vec = (0..K).filter(|&k| k != drop).collect(); + assert_ne!(develop(&planes, &kept), want, "rod {drop} was not needed"); + } +}