keys.go raw
1 // Package memory provides persistent cross-generation knowledge storage
2 // using Badger v4 with composite binary keys and vector table indexes.
3 //
4 // Key schema follows the ORLY relay pattern: 3-byte ASCII prefixes,
5 // fixed-width binary components, nil-value secondary indexes, and
6 // sorted range iteration for graph traversal.
7 package memory
8
9 import (
10 "crypto/sha256"
11 "encoding/binary"
12 )
13
14 // 3-byte ASCII prefixes for each index table.
15 var (
16 PrefixGen = [3]byte{'g', 'e', 'n'} // generation metadata
17 PrefixTyp = [3]byte{'t', 'y', 'p'} // type signature snapshots
18 PrefixBnd = [3]byte{'b', 'n', 'd'} // bond events
19 PrefixMis = [3]byte{'m', 'i', 's'} // missing site records
20 PrefixCon = [3]byte{'c', 'o', 'n'} // connectivity statistics
21 PrefixFit = [3]byte{'f', 'i', 't'} // fitness scores
22 PrefixHlt = [3]byte{'h', 'l', 't'} // health snapshots
23 PrefixHex = [3]byte{'h', 'e', 'x'} // hexagram operation counts
24 PrefixLck = [3]byte{'l', 'c', 'k'} // lock-in depth distribution
25 PrefixMnd = [3]byte{'m', 'n', 'd'} // mindsicle snapshots
26 PrefixEwm = [3]byte{'e', 'w', 'm'} // EWMA detector state
27 PrefixAdr = [3]byte{'a', 'd', 'r'} // ADSR phase distribution
28 PrefixFsc = [3]byte{'f', 's', 'c'} // file accretion scores
29 PrefixWlk = [3]byte{'w', 'l', 'k'} // walker checkpoint (singleton)
30 PrefixOrc = [3]byte{'o', 'r', 'c'} // oracle state per generation
31 PrefixOhx = [3]byte{'o', 'h', 'x'} // oracle reading history
32 PrefixOsr = [3]byte{'o', 's', 'r'} // oracle directive results
33 PrefixPrf = [3]byte{'p', 'r', 'f'} // recognition profile snapshots
34 PrefixMdl = [3]byte{'m', 'd', 'l'} // model fingerprint spores
35 PrefixCvg = [3]byte{'c', 'v', 'g'} // convergence state
36 )
37
38 // Fitness dimension constants.
39 const (
40 DimSource byte = 0
41 DimBinary byte = 1
42 DimBehav byte = 2
43 DimOverall byte = 3
44 )
45
46 // TagHash produces a truncated 8-byte SHA-256 hash of a tag string.
47 // Same principle as ORLY's PubHash/IdHash: deterministic, fixed-width,
48 // collision-acceptable (used for key prefix, not identification).
49 func TagHash(tag string) [8]byte {
50 h := sha256.Sum256([]byte(tag))
51 var out [8]byte
52 copy(out[:], h[:8])
53 return out
54 }
55
56 // --- Key builders ---
57 // All keys are built by concatenating: prefix(3) + components.
58 // Generation number is always uint32 big-endian (4 bytes).
59
60 // GenKey builds: gen | gen(4)
61 func GenKey(gen uint32) []byte {
62 k := make([]byte, 3+4)
63 copy(k, PrefixGen[:])
64 binary.BigEndian.PutUint32(k[3:], gen)
65 return k
66 }
67
68 // TypKey builds: typ | tag_hash(8) | count(4) | gen(4)
69 func TypKey(tagHash [8]byte, count uint32, gen uint32) []byte {
70 k := make([]byte, 3+8+4+4)
71 copy(k, PrefixTyp[:])
72 copy(k[3:], tagHash[:])
73 binary.BigEndian.PutUint32(k[11:], count)
74 binary.BigEndian.PutUint32(k[15:], gen)
75 return k
76 }
77
78 // TypPrefix builds the seek prefix for a specific tag: typ | tag_hash(8)
79 func TypPrefix(tagHash [8]byte) []byte {
80 k := make([]byte, 3+8)
81 copy(k, PrefixTyp[:])
82 copy(k[3:], tagHash[:])
83 return k
84 }
85
86 // BndKey builds: bnd | tag_hash(8) | gen(4) | site_id(4)
87 func BndKey(tagHash [8]byte, gen uint32, siteID uint32) []byte {
88 k := make([]byte, 3+8+4+4)
89 copy(k, PrefixBnd[:])
90 copy(k[3:], tagHash[:])
91 binary.BigEndian.PutUint32(k[11:], gen)
92 binary.BigEndian.PutUint32(k[15:], siteID)
93 return k
94 }
95
96 // BndPrefix builds the seek prefix for bonds of a tag: bnd | tag_hash(8)
97 func BndPrefix(tagHash [8]byte) []byte {
98 k := make([]byte, 3+8)
99 copy(k, PrefixBnd[:])
100 copy(k[3:], tagHash[:])
101 return k
102 }
103
104 // BndGenPrefix builds: bnd | tag_hash(8) | gen(4) for counting bonds in a gen.
105 func BndGenPrefix(tagHash [8]byte, gen uint32) []byte {
106 k := make([]byte, 3+8+4)
107 copy(k, PrefixBnd[:])
108 copy(k[3:], tagHash[:])
109 binary.BigEndian.PutUint32(k[11:], gen)
110 return k
111 }
112
113 // MisKey builds: mis | tag_hash(8) | gen(4) | count(4)
114 func MisKey(tagHash [8]byte, gen uint32, count uint32) []byte {
115 k := make([]byte, 3+8+4+4)
116 copy(k, PrefixMis[:])
117 copy(k[3:], tagHash[:])
118 binary.BigEndian.PutUint32(k[11:], gen)
119 binary.BigEndian.PutUint32(k[15:], count)
120 return k
121 }
122
123 // MisPrefix builds: mis | tag_hash(8)
124 func MisPrefix(tagHash [8]byte) []byte {
125 k := make([]byte, 3+8)
126 copy(k, PrefixMis[:])
127 copy(k[3:], tagHash[:])
128 return k
129 }
130
131 // ConKey builds: con | tag_hash(8) | gen(4)
132 func ConKey(tagHash [8]byte, gen uint32) []byte {
133 k := make([]byte, 3+8+4)
134 copy(k, PrefixCon[:])
135 copy(k[3:], tagHash[:])
136 binary.BigEndian.PutUint32(k[11:], gen)
137 return k
138 }
139
140 // FitKey builds: fit | dimension(1) | gen(4)
141 func FitKey(dim byte, gen uint32) []byte {
142 k := make([]byte, 3+1+4)
143 copy(k, PrefixFit[:])
144 k[3] = dim
145 binary.BigEndian.PutUint32(k[4:], gen)
146 return k
147 }
148
149 // FitDimPrefix builds: fit | dimension(1)
150 func FitDimPrefix(dim byte) []byte {
151 k := make([]byte, 3+1)
152 copy(k, PrefixFit[:])
153 k[3] = dim
154 return k
155 }
156
157 // HltKey builds: hlt | gen(4)
158 func HltKey(gen uint32) []byte {
159 k := make([]byte, 3+4)
160 copy(k, PrefixHlt[:])
161 binary.BigEndian.PutUint32(k[3:], gen)
162 return k
163 }
164
165 // HexKey builds: hex | operation(1) | gen(4)
166 func HexKey(op byte, gen uint32) []byte {
167 k := make([]byte, 3+1+4)
168 copy(k, PrefixHex[:])
169 k[3] = op
170 binary.BigEndian.PutUint32(k[4:], gen)
171 return k
172 }
173
174 // LckKey builds: lck | bucket(1) | gen(4)
175 func LckKey(bucket byte, gen uint32) []byte {
176 k := make([]byte, 3+1+4)
177 copy(k, PrefixLck[:])
178 k[3] = bucket
179 binary.BigEndian.PutUint32(k[4:], gen)
180 return k
181 }
182
183 // MndKey builds: mnd | gen(4)
184 func MndKey(gen uint32) []byte {
185 k := make([]byte, 3+4)
186 copy(k, PrefixMnd[:])
187 binary.BigEndian.PutUint32(k[3:], gen)
188 return k
189 }
190
191 // EwmKey builds: ewm | gen(4)
192 func EwmKey(gen uint32) []byte {
193 k := make([]byte, 3+4)
194 copy(k, PrefixEwm[:])
195 binary.BigEndian.PutUint32(k[3:], gen)
196 return k
197 }
198
199 // AdrKey builds: adr | gen(4)
200 func AdrKey(gen uint32) []byte {
201 k := make([]byte, 3+4)
202 copy(k, PrefixAdr[:])
203 binary.BigEndian.PutUint32(k[3:], gen)
204 return k
205 }
206
207 // FscKey builds: fsc | file_hash(8)
208 func FscKey(fileHash [8]byte) []byte {
209 k := make([]byte, 3+8)
210 copy(k, PrefixFsc[:])
211 copy(k[3:], fileHash[:])
212 return k
213 }
214
215 // WlkKey builds: wlk (singleton key, no suffix)
216 func WlkKey() []byte {
217 return PrefixWlk[:]
218 }
219
220 // OrcKey builds: orc (singleton key — always the latest oracle state).
221 func OrcKey() []byte {
222 return PrefixOrc[:]
223 }
224
225 // OhxKey builds: ohx | seq(4) | gen(4)
226 func OhxKey(seq, gen uint32) []byte {
227 k := make([]byte, 3+4+4)
228 copy(k, PrefixOhx[:])
229 binary.BigEndian.PutUint32(k[3:], seq)
230 binary.BigEndian.PutUint32(k[7:], gen)
231 return k
232 }
233
234 // OsrKey builds: osr | seq(4) | directive_hash(8)
235 func OsrKey(seq uint32, hash [8]byte) []byte {
236 k := make([]byte, 3+4+8)
237 copy(k, PrefixOsr[:])
238 binary.BigEndian.PutUint32(k[3:], seq)
239 copy(k[7:], hash[:])
240 return k
241 }
242
243 // --- Recognition key builders ---
244
245 // PrfKey builds: prf | gen(4) — profile snapshot for a generation.
246 func PrfKey(gen uint32) []byte {
247 k := make([]byte, 3+4)
248 copy(k, PrefixPrf[:])
249 binary.BigEndian.PutUint32(k[3:], gen)
250 return k
251 }
252
253 // MdlKey builds: mdl | name_hash(8) — model fingerprint spore.
254 func MdlKey(nameHash [8]byte) []byte {
255 k := make([]byte, 3+8)
256 copy(k, PrefixMdl[:])
257 copy(k[3:], nameHash[:])
258 return k
259 }
260
261 // CvgKey builds: cvg | gen(4) — convergence state for a generation.
262 func CvgKey(gen uint32) []byte {
263 k := make([]byte, 3+4)
264 copy(k, PrefixCvg[:])
265 binary.BigEndian.PutUint32(k[3:], gen)
266 return k
267 }
268
269 // DecodeOhx extracts seq and gen from an ohx-prefixed key.
270 func DecodeOhx(key []byte) (seq, gen uint32) {
271 if len(key) < 11 {
272 return
273 }
274 seq = binary.BigEndian.Uint32(key[3:7])
275 gen = binary.BigEndian.Uint32(key[7:11])
276 return
277 }
278
279 // --- Key decoders ---
280
281 // DecodeGen extracts generation from a gen-prefixed key.
282 func DecodeGen(key []byte) uint32 {
283 if len(key) < 7 {
284 return 0
285 }
286 return binary.BigEndian.Uint32(key[3:7])
287 }
288
289 // DecodeTyp extracts tag_hash, count, gen from a typ-prefixed key.
290 func DecodeTyp(key []byte) (tagHash [8]byte, count uint32, gen uint32) {
291 if len(key) < 19 {
292 return
293 }
294 copy(tagHash[:], key[3:11])
295 count = binary.BigEndian.Uint32(key[11:15])
296 gen = binary.BigEndian.Uint32(key[15:19])
297 return
298 }
299
300 // DecodeBnd extracts tag_hash, gen, site_id from a bnd-prefixed key.
301 func DecodeBnd(key []byte) (tagHash [8]byte, gen uint32, siteID uint32) {
302 if len(key) < 19 {
303 return
304 }
305 copy(tagHash[:], key[3:11])
306 gen = binary.BigEndian.Uint32(key[11:15])
307 siteID = binary.BigEndian.Uint32(key[15:19])
308 return
309 }
310
311 // DecodeMis extracts tag_hash, gen, count from a mis-prefixed key.
312 func DecodeMis(key []byte) (tagHash [8]byte, gen uint32, count uint32) {
313 if len(key) < 19 {
314 return
315 }
316 copy(tagHash[:], key[3:11])
317 gen = binary.BigEndian.Uint32(key[11:15])
318 count = binary.BigEndian.Uint32(key[15:19])
319 return
320 }
321
322 // DecodeFit extracts dimension and gen from a fit-prefixed key.
323 func DecodeFit(key []byte) (dim byte, gen uint32) {
324 if len(key) < 8 {
325 return
326 }
327 dim = key[3]
328 gen = binary.BigEndian.Uint32(key[4:8])
329 return
330 }
331
332 // DecodeHlt extracts gen from a hlt-prefixed key.
333 func DecodeHlt(key []byte) uint32 {
334 if len(key) < 7 {
335 return 0
336 }
337 return binary.BigEndian.Uint32(key[3:7])
338 }
339
340 // DecodeHex extracts operation and gen from a hex-prefixed key.
341 func DecodeHex(key []byte) (op byte, gen uint32) {
342 if len(key) < 8 {
343 return
344 }
345 op = key[3]
346 gen = binary.BigEndian.Uint32(key[4:8])
347 return
348 }
349
350 // --- Value encoders/decoders ---
351
352 // EncodeFitValue encodes a numerator/denominator pair.
353 func EncodeFitValue(num, denom int64) []byte {
354 v := make([]byte, 16)
355 binary.BigEndian.PutUint64(v[0:], uint64(num))
356 binary.BigEndian.PutUint64(v[8:], uint64(denom))
357 return v
358 }
359
360 // DecodeFitValue decodes a numerator/denominator pair.
361 func DecodeFitValue(v []byte) (num, denom int64) {
362 if len(v) < 16 {
363 return 0, 1
364 }
365 num = int64(binary.BigEndian.Uint64(v[0:]))
366 denom = int64(binary.BigEndian.Uint64(v[8:]))
367 if denom == 0 {
368 denom = 1
369 }
370 return
371 }
372
373 // EncodeHltValue encodes health snapshot.
374 func EncodeHltValue(occupied, total uint32, avgLockInNum, avgLockInDenom int64) []byte {
375 v := make([]byte, 4+4+8+8)
376 binary.BigEndian.PutUint32(v[0:], occupied)
377 binary.BigEndian.PutUint32(v[4:], total)
378 binary.BigEndian.PutUint64(v[8:], uint64(avgLockInNum))
379 binary.BigEndian.PutUint64(v[16:], uint64(avgLockInDenom))
380 return v
381 }
382
383 // DecodeHltValue decodes health snapshot.
384 func DecodeHltValue(v []byte) (occupied, total uint32, avgLockInNum, avgLockInDenom int64) {
385 if len(v) < 24 {
386 return 0, 0, 0, 1
387 }
388 occupied = binary.BigEndian.Uint32(v[0:])
389 total = binary.BigEndian.Uint32(v[4:])
390 avgLockInNum = int64(binary.BigEndian.Uint64(v[8:]))
391 avgLockInDenom = int64(binary.BigEndian.Uint64(v[16:]))
392 if avgLockInDenom == 0 {
393 avgLockInDenom = 1
394 }
395 return
396 }
397
398 // EncodeConValue encodes connectivity as fixed-point (num/denom).
399 func EncodeConValue(num, denom int64) []byte {
400 v := make([]byte, 16)
401 binary.BigEndian.PutUint64(v[0:], uint64(num))
402 binary.BigEndian.PutUint64(v[8:], uint64(denom))
403 return v
404 }
405
406 // DecodeConValue decodes connectivity fixed-point.
407 func DecodeConValue(v []byte) (num, denom int64) {
408 return DecodeFitValue(v) // same encoding
409 }
410
411 // EncodeU32Value encodes a single uint32 (for hex/lck counts).
412 func EncodeU32Value(n uint32) []byte {
413 v := make([]byte, 4)
414 binary.BigEndian.PutUint32(v, n)
415 return v
416 }
417
418 // DecodeU32Value decodes a single uint32.
419 func DecodeU32Value(v []byte) uint32 {
420 if len(v) < 4 {
421 return 0
422 }
423 return binary.BigEndian.Uint32(v)
424 }
425
426 // EncodeAdrValue encodes 4 ADSR phase counts: [attack, decay, sustain, release].
427 func EncodeAdrValue(counts [4]uint32) []byte {
428 v := make([]byte, 16)
429 for i := range 4 {
430 binary.BigEndian.PutUint32(v[i*4:], counts[i])
431 }
432 return v
433 }
434
435 // DecodeAdrValue decodes 4 ADSR phase counts.
436 func DecodeAdrValue(v []byte) [4]uint32 {
437 var counts [4]uint32
438 if len(v) < 16 {
439 return counts
440 }
441 for i := range 4 {
442 counts[i] = binary.BigEndian.Uint32(v[i*4:])
443 }
444 return counts
445 }
446
447 // PrefixEnd returns the key that is one past the end of all keys
448 // with the given prefix. Used as the upper bound for range scans.
449 func PrefixEnd(prefix []byte) []byte {
450 end := make([]byte, len(prefix))
451 copy(end, prefix)
452 for i := len(end) - 1; i >= 0; i-- {
453 end[i]++
454 if end[i] != 0 {
455 return end
456 }
457 }
458 return nil // overflow: prefix was all 0xFF
459 }
460