Skip to content

Commit 56f2695

Browse files
committed
feat(LF-2): VSA_DIMS 10000 → 16384, 8 SMB domain role keys
Resize the VSA catalogue from 10,000 to 16,384 dimensions (LF-2), matching the existing Binary16K / Vsa16kF32 carrier widths. VSA_WORDS: 157 → 256 (256 × 64 = 16,384 bits) VSA_DIMS: 10,000 → 16,384 8 SMB role keys in [10000..14096), 512 dims each: KUNDE_KEY [10000..10512) customer SCHULDNER_KEY [10512..11024) debtor MAHNUNG_KEY [11024..11536) dunning RECHNUNG_KEY [11536..12048) invoice DOKUMENT_KEY [12048..12560) document BANK_KEY [12560..13072) banking FIBU_KEY [13072..13584) financial accounting STEUER_KEY [13584..14096) tax Headroom [14096..16384) reserved for future SMB keys (LIEFERANT/MITARBEITER/ZAHLUNG/LIEFERSCHEIN). Labels use FNV-64-seeded LCG generator: "smb.kunde" etc. All existing role keys unchanged. Disjointness test updated to include all 55 keys (47 existing + 8 new). 233 contract tests pass. Full workspace cargo check clean. Per SMB session spec doc at smb-office-rs `3a25ce2`. https://claude.ai/code/session_01SbYsmmbPf9YQuYbHZN52Zh
1 parent 5d3ea88 commit 56f2695

1 file changed

Lines changed: 56 additions & 37 deletions

File tree

crates/lance-graph-contract/src/grammar/role_keys.rs

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Role keys — canonical deterministic `[start:stop]`-slice VSA role bindings.
22
//!
3-
//! Each role owns a **disjoint contiguous slice** of the 10,000-dim VSA
3+
//! Each role owns a **disjoint contiguous slice** of the 16,384-dim VSA
44
//! space (compatible with `CrystalFingerprint::Binary16K`). Only the bits
55
//! in that slice are set to a deterministic pseudo-random pattern seeded
66
//! from FNV-64 of the label; all other bits are zero. This is the
@@ -10,53 +10,53 @@
1010
//! only affects that role's slice, and bundles of different role-bindings
1111
//! don't contaminate each other.
1212
//!
13-
//! ## Space layout (10,000 total dims)
13+
//! ## Space layout (16,384 total dims — LF-2 resize from 10,000)
1414
//!
1515
//! ```text
16-
//! [ 0 .. 2000) SUBJECT_KEY
17-
//! [ 2000 .. 4000) PREDICATE_KEY
18-
//! [ 4000 .. 6000) OBJECT_KEY
19-
//! [ 6000 .. 7500) MODIFIER_KEY
20-
//! [ 7500 .. 9000) CONTEXT_KEY
21-
//! [ 9000 .. 9200) TEMPORAL_KEY
22-
//! [ 9200 .. 9400) KAUSAL_KEY
23-
//! [ 9400 .. 9500) MODAL_KEY
24-
//! [ 9500 .. 9650) LOKAL_KEY
25-
//! [ 9650 .. 9750) INSTRUMENT_KEY
26-
//! [ 9750 .. 9780) BENEFICIARY_KEY
27-
//! [ 9780 .. 9810) GOAL_KEY
28-
//! [ 9810 .. 9840) SOURCE_KEY
29-
//! [ 9840 .. 9910) Finnish 15 cases — ~4-5 dims each
30-
//! [ 9910 .. 9970) 12 tense keys — 5 dims each
31-
//! [ 9970 .. 10000) 7 NARS inference keys — ~4 dims each
16+
//! [ 0 .. 2000) SUBJECT_KEY
17+
//! [ 2000 .. 4000) PREDICATE_KEY
18+
//! [ 4000 .. 6000) OBJECT_KEY
19+
//! [ 6000 .. 7500) MODIFIER_KEY
20+
//! [ 7500 .. 9000) CONTEXT_KEY
21+
//! [ 9000 .. 9200) TEMPORAL_KEY
22+
//! [ 9200 .. 9400) KAUSAL_KEY
23+
//! [ 9400 .. 9500) MODAL_KEY
24+
//! [ 9500 .. 9650) LOKAL_KEY
25+
//! [ 9650 .. 9750) INSTRUMENT_KEY
26+
//! [ 9750 .. 9780) BENEFICIARY_KEY
27+
//! [ 9780 .. 9810) GOAL_KEY
28+
//! [ 9810 .. 9840) SOURCE_KEY
29+
//! [ 9840 .. 9910) Finnish 15 cases — ~4-5 dims each
30+
//! [ 9910 .. 9970) 12 tense keys — 5 dims each
31+
//! [ 9970 .. 10000) 7 NARS inference keys — ~4 dims each
32+
//! [10000 .. 10512) SMB KUNDE_KEY (customer)
33+
//! [10512 .. 11024) SMB SCHULDNER_KEY (debtor)
34+
//! [11024 .. 11536) SMB MAHNUNG_KEY (dunning)
35+
//! [11536 .. 12048) SMB RECHNUNG_KEY (invoice)
36+
//! [12048 .. 12560) SMB DOKUMENT_KEY (document)
37+
//! [12560 .. 13072) SMB BANK_KEY (banking)
38+
//! [13072 .. 13584) SMB FIBU_KEY (financial accounting)
39+
//! [13584 .. 14096) SMB STEUER_KEY (tax)
40+
//! [14096 .. 16384) headroom (reserved for future SMB keys)
3241
//! ```
3342
3443
use std::sync::LazyLock;
3544

3645
use super::finnish::FinnishCase;
3746
use super::inference::NarsInference;
3847

39-
/// VSA vector width in `u64` words. Matches `ndarray::hpc::vsa::VSA_WORDS`.
40-
/// 157 × 64 = 10,048 bits, covering the 10,000 VSA dims with 48 slack bits.
41-
pub const VSA_WORDS: usize = 157;
48+
/// VSA vector width in `u64` words. 256 × 64 = 16,384 bits.
49+
/// Matches `CrystalFingerprint::Binary16K` and `ndarray::hpc::vsa::VSA_WORDS`.
50+
pub const VSA_WORDS: usize = 256;
4251

4352
/// VSA vector width in dimensions (bits actually used).
44-
pub const VSA_DIMS: usize = 10_000;
45-
46-
// NOTE: The `Vsa10k = [u64; 157]` bitpacked type alias, `VSA_ZERO` constant,
47-
// and `RoleKey::{bind, unbind, recovery_margin}` methods that existed in
48-
// early 2026-04-21 session work were REMOVED in the cleanup commit
49-
// `cd5c049...`. That code used GF(2)/XOR algebra which is the
50-
// Binary16K Hamming-comparison format, not the real-valued VSA bundling
51-
// format. Correct VSA substrate is `Vsa10kF32 = Box<[f32; 10_000]>`
52-
// (existing) or `Vsa16kF32 = Box<[f32; 16_384]>` (pending rescale), with
53-
// element-wise multiply/add via existing `crystal::fingerprint::{vsa_bind,
54-
// vsa_bundle, vsa_cosine}`.
55-
//
56-
// See `CHANGELOG.md` § VSA format switches and
57-
// `.claude/knowledge/vsa-switchboard-architecture.md` for the full
58-
// three-layer architecture. Role keys (this module) are Layer-2 catalogue
59-
// ONLY — identity slice boundaries. Algebra lives in Layer-1 `crystal/`.
53+
/// Resized from 10,000 → 16,384 (LF-2) to accommodate SMB domain
54+
/// role keys in [10000..14096) with 2,288 dims headroom.
55+
pub const VSA_DIMS: usize = 16_384;
56+
57+
// NOTE: bind/unbind/recovery_margin methods removed (see CHANGELOG.md).
58+
// Role keys are Layer-2 catalogue ONLY — identity slice boundaries.
59+
// Algebra lives in Layer-1 `crystal/` and in ndarray.
6060

6161
/// A role key owns a contiguous slice of the VSA space.
6262
/// Outside the slice, **all bits are zero**.
@@ -301,6 +301,19 @@ pub fn nars_inference_key(inf: NarsInference) -> &'static RoleKey {
301301
&NARS_KEYS[idx]
302302
}
303303

304+
// ---------------------------------------------------------------------------
305+
// SMB domain role keys — [10000 .. 14096), 512 dims each (LF-2)
306+
// ---------------------------------------------------------------------------
307+
308+
pub static KUNDE_KEY: LazyLock<RoleKey> = LazyLock::new(|| RoleKey::generate("smb.kunde", 10_000, 10_512));
309+
pub static SCHULDNER_KEY: LazyLock<RoleKey> = LazyLock::new(|| RoleKey::generate("smb.schuldner", 10_512, 11_024));
310+
pub static MAHNUNG_KEY: LazyLock<RoleKey> = LazyLock::new(|| RoleKey::generate("smb.mahnung", 11_024, 11_536));
311+
pub static RECHNUNG_KEY: LazyLock<RoleKey> = LazyLock::new(|| RoleKey::generate("smb.rechnung", 11_536, 12_048));
312+
pub static DOKUMENT_KEY: LazyLock<RoleKey> = LazyLock::new(|| RoleKey::generate("smb.dokument", 12_048, 12_560));
313+
pub static BANK_KEY: LazyLock<RoleKey> = LazyLock::new(|| RoleKey::generate("smb.bank", 12_560, 13_072));
314+
pub static FIBU_KEY: LazyLock<RoleKey> = LazyLock::new(|| RoleKey::generate("smb.fibu", 13_072, 13_584));
315+
pub static STEUER_KEY: LazyLock<RoleKey> = LazyLock::new(|| RoleKey::generate("smb.steuer", 13_584, 14_096));
316+
304317
// ---------------------------------------------------------------------------
305318
// Tests
306319
// ---------------------------------------------------------------------------
@@ -323,6 +336,12 @@ mod tests {
323336
for k in FINNISH_KEYS.iter() { v.push((k.slice_start, k.slice_end, k.label)); }
324337
for k in TENSE_KEYS.iter() { v.push((k.slice_start, k.slice_end, k.label)); }
325338
for k in NARS_KEYS.iter() { v.push((k.slice_start, k.slice_end, k.label)); }
339+
for k in [
340+
&*KUNDE_KEY, &*SCHULDNER_KEY, &*MAHNUNG_KEY, &*RECHNUNG_KEY,
341+
&*DOKUMENT_KEY, &*BANK_KEY, &*FIBU_KEY, &*STEUER_KEY,
342+
] {
343+
v.push((k.slice_start, k.slice_end, k.label));
344+
}
326345
v
327346
}
328347

0 commit comments

Comments
 (0)