|
| 1 | +# Audit — the 34 NARS recipes against the CURRENT substrate |
| 2 | + |
| 3 | +> 2026-09-14. Read `recipes.rs` (all 34) against `ndarray::simd_masking_ops` |
| 4 | +> (the masking algebra) and the workspace's own iron rules. The question asked: |
| 5 | +> **what needs improving.** |
| 6 | +
|
| 7 | +## ⊘ CORRECTION — `bucket` is NOT a dispatch key (read after writing this) |
| 8 | + |
| 9 | +The audit below says the stale `bucket` column matters because it routes. **It |
| 10 | +does not route.** Measured: |
| 11 | + |
| 12 | +- `recipe_dispatch.rs` — **zero** uses of `bucket`. Dispatch is by |
| 13 | + `RecipeInference` (deduction/induction/abduction/revision/counterfactual), |
| 14 | + `rung` + `dispatch_order` (from `Tier` + `InferenceType::rung_delta`), and |
| 15 | + the `nan_disqualifier` checklist. |
| 16 | +- `recipe_kernels.rs` — **one** use, the default `Tactic::gate`: |
| 17 | + `match bucket { Bucket::Gate => ctx.gate_state() != GateState::Flow, _ => true }`. |
| 18 | + |
| 19 | +So only the **`Gate`** arm is load-bearing, and `Gate` is the one bucket this |
| 20 | +audit found ACCURATE (TCP/CAS/TCF/CUR are the prune/cascade family the masking |
| 21 | +algebra genuinely expresses). `Datapath` vs `Control` is **inert descriptive |
| 22 | +metadata that nothing reads.** |
| 23 | + |
| 24 | +Consequence: the 9 stale `Datapath` strings are **documentation debt, not live |
| 25 | +mis-dispatch.** They still want fixing — a string naming a retired kernel reads |
| 26 | +as a spec — but item 1 below ("re-derive bucket") is NOT urgent and NOT a |
| 27 | +correctness risk. I claimed the opposite in session ("a routing key derived |
| 28 | +from a retired substrate is currently deciding what executes") without reading |
| 29 | +either module. That claim is withdrawn. |
| 30 | + |
| 31 | +## ⊘ ALSO: the loco↔34 bridge already exists — do not build it |
| 32 | + |
| 33 | +`lance-graph-ogar/src/recipe_vocab.rs` is the 34 as loco ops: |
| 34 | +`RECIPE_OP_BASE = DOMAIN_FLOOR`, ids `1..=34` ↔ bytes `0x90..=0xB1`, |
| 35 | +`op_of` / `recipe_of`, `impl Vocabulary for RecipeVocabulary`, and |
| 36 | +`ladder_program() -> Vec<FnIndex>` — the ladder already lowered to a loco |
| 37 | +program in `dispatch_order`. It carries two gates that answer different |
| 38 | +questions (awareness: the kanban census; epistemic: the NaN pothole) with |
| 39 | +`refusal_of` reporting which spoke, "because an unwilling ladder and an unable |
| 40 | +one are different diagnoses." |
| 41 | + |
| 42 | +Its header also settles the dependency question correctly: *"`ogar_loco` is |
| 43 | +zero-dep by design and `lance_graph_contract` is zero-dep by charter. Neither |
| 44 | +may import the other. A vocabulary needs both, so it lives in a consumer that |
| 45 | +already depends on both."* An `ogar-loco/src/nars.rs` with a contract dep — |
| 46 | +which this session started writing — is the wrong home for a reason already |
| 47 | +recorded. |
| 48 | + |
| 49 | +## The finding that IS serious, and is not mine |
| 50 | + |
| 51 | +`E-RECIPE-SELECTOR-REACHABILITY-1`, measured and documented in |
| 52 | +`recipe_dispatch.rs`'s own header: through the shipped saccade selector |
| 53 | +(`materialize::select_tactic`) only **8 of 34 recipes are reachable**, **all 14 |
| 54 | +Infrastructure recipes never win**, and **ICR #31 is permanently shadowed by |
| 55 | +RCR #4** on a lowest-id tie. The `ladder` mode exists to cover exactly those |
| 56 | +three gaps, and `dispatch_mode.rs` routes between the two modes. That is a |
| 57 | +larger fact about the 34 than anything in the substrate-string audit below. |
| 58 | + |
| 59 | +## Headline: the `bucket` column was assigned against a substrate that is gone |
| 60 | + |
| 61 | +**9 of 9 `Datapath` recipes name a retired or forbidden realization.** The tier |
| 62 | +that is supposed to BE the masking ops is the tier most contaminated: |
| 63 | + |
| 64 | +| id | code | substrate string | verdict | |
| 65 | +|---|---|---|---| |
| 66 | +| 19 | ARE | `ABBA unbind: A⊗B⊗B=A` | VSA — retired | |
| 67 | +| 24 | ZCF | `VSA bind(A,B)` | VSA — retired | |
| 68 | +| 25 | HPM | `fingerprint cosine/Hamming sweep` | Hamming — retired | |
| 69 | +| 27 | MPC | `bundle = majority-vote-per-bit` | VSA bundle — retired | |
| 70 | +| 28 | SSAM | `bind+similarity (Gentner)` | VSA — retired | |
| 71 | +| 34 | HKF | `cross-domain bind(A,rel,B)` | VSA — retired | |
| 72 | +| 14 | MCT | `… → one fingerprint` | fingerprint — retired | |
| 73 | +| 12 | TCA | `Markov ±5` | **±5 was retired** by the whole-book finding (63.3% of same-subject links reach beyond ±5) | |
| 74 | +| 32 | SDD | `Berry-Esseen noise floor` | **forbidden by `I-NOISE-FLOOR-JIRAK`** — classical Berry-Esseen is wrong under this system's weak dependence; Jirak 2016 is the rule | |
| 75 | + |
| 76 | +So the `Datapath` label currently means *"was a VSA kernel"*, not *"is a masking |
| 77 | +op"*. **I asserted earlier in this session that `bucket` is still a valid |
| 78 | +routing column and only `substrate` was stale. That was wrong** — the bucket was |
| 79 | +derived FROM the substrate, so it inherited the staleness. |
| 80 | + |
| 81 | +## What the masking algebra DOES express today |
| 82 | + |
| 83 | +Cross-checking the 34 against the real op list (`eq/ne/lt/le/gt/ge_*_to_mask`, |
| 84 | +`ternary_match_*`, each with a gated `_under` twin; `mask_and/or/xor/andnot/not`; |
| 85 | +`mask_ternlog<IMM>` over the full 256-table; `mask_any/all`; `masked_sum/min/max_i32`, |
| 86 | +`masked_strided_group_sum`): |
| 87 | + |
| 88 | +| id | code | bucket | expressible as | note | |
| 89 | +|---|---|---|---|---| |
| 90 | +| 5 | TCP | Gate | a gated predicate — `*_under` | prune = don't evaluate where the gate is empty | |
| 91 | +| 8 | CAS | Gate | a cascade of `_under` tiers | the INT1/4/8/32 ladder is the gate chain | |
| 92 | +| 20 | TCF | Gate | N masks → agreement | `ternlog` majority + `popcount` | |
| 93 | +| 26 | CUR | Gate | coarse-to-fine `_under` chain | same shape as CAS | |
| 94 | +| 30 | SPP | Control | N independent masks → agreement | identical algebra to TCF; the ECC/RAID framing is the same majority | |
| 95 | + |
| 96 | +**The recipes the masking algebra can run TODAY are 4 Gate + 1 Control — and |
| 97 | +zero Datapath.** The tier assignment is inverted relative to the substrate that |
| 98 | +actually exists. |
| 99 | + |
| 100 | +## Other defects found |
| 101 | + |
| 102 | +- **22 ETD** — `"CLAM cluster geometry determines subtasks (no spec)"`. Says so |
| 103 | + itself. Unspecified, not merely stale. |
| 104 | +- **18 CWS** — `"persistent BindSpace"`. The singleton BindSpace was retired |
| 105 | + (`E-MARKOV-TEMPORAL-STREAM-1`: *"in most cases the singleton-BindSpace VSA |
| 106 | + substrate is NOT used"*). |
| 107 | +- **31 ICR** — `"CausalEdge64 −6 mantissa"` cites the **v2** layout. Truth |
| 108 | + (frequency/confidence) is moving to **v3**, so this reference needs re-pinning |
| 109 | + with that change rather than after it. |
| 110 | +- **1 RTE** — `"Berry-Esseen stop"`. Same iron-rule violation as SDD, in a |
| 111 | + Control recipe. |
| 112 | + |
| 113 | +## What needs improving, in order |
| 114 | + |
| 115 | +1. **Re-derive `bucket` from the masking algebra**, not from the VSA substrate. |
| 116 | + The five above are what the algebra can run today, and the table classifies |
| 117 | + them **4 `Gate` + 1 `Control`, zero `Datapath`** — the current nine |
| 118 | + `Datapath` labels are the ones that are not honest. ⊘ This read "the five |
| 119 | + above are the honest `Datapath` set today", contradicting the table two |
| 120 | + sections up; caught in review on PR #1235. |
| 121 | +2. **Rewrite the 9 stale `substrate` strings** to name mask-algebra |
| 122 | + compositions, or mark them `unrealized` — a string naming a retired kernel |
| 123 | + reads as a spec and is worse than an empty one. |
| 124 | +3. ⊘ **CLOSED in the same commit** — both strings now name shipped Jirak |
| 125 | + surfaces (`recipes.rs:97` `SigmaTierBands::jirak_p`, `:408` `jc` Pillar 5), |
| 126 | + and `no_recipe_cites_classical_berry_esseen` guards against a third. The |
| 127 | + two rows above record the PRE-fix state and are kept as the finding, not |
| 128 | + as outstanding work. Originally: **Fix the 2 Berry-Esseen citations** (1 RTE, 32 SDD) to Jirak 2016, per |
| 129 | + `I-NOISE-FLOOR-JIRAK`. These are iron-rule violations sitting in shipped data. |
| 130 | +4. **Re-pin 12 TCA** off the retired ±5 window onto the version-range read |
| 131 | + (`QueryReference::at(v, rung)`), which is what replaced it. |
| 132 | +5. **Re-pin 18 CWS** off the singleton BindSpace. |
| 133 | +6. **31 ICR** rides the CausalEdge64 v3 change. |
| 134 | +7. **22 ETD** needs a spec or an explicit `unrealized` mark. |
| 135 | + |
| 136 | +## What this audit does NOT claim |
| 137 | + |
| 138 | +It does not say the 34 are wrong as *tactics*. It says their recorded |
| 139 | +realization is against a substrate that no longer exists, and that the routing |
| 140 | +column derived from it cannot be trusted until re-derived. (⊘ this said |
| 141 | +"as a dispatch key"; per the correction at the top of this file `bucket` is |
| 142 | +NOT a dispatch key at all except for the `Bucket::Gate` arm, so the phrase |
| 143 | +re-asserted the thing the correction retracted.) |
| 144 | +Nothing here was executed; this is a read of the catalogue against the op list. |
0 commit comments