code wiki / (root) / nx_asset_signals.nx

nx_asset_signals.nx source

↩ module page · 441 lines · 22826 B

1// nx_asset_signals.nx -- "WHAT WE NEED TO DO" pillar (R4 of the universal organization-tooling arc). 2// 3// Derives TASK SIGNALS from CATALOG STATE -- "what to do" is not a hand-maintained list, it is a set of 4// PREDICATES evaluated over the inventory snapshot (org_research.tsv CONFIRMED: task-signals-derived, 5// dam-lifecycle). A signal is a deterministic fact about a record that implies follow-up work 6// (provenance missing, untagged, metadata gap, near-duplicate, stale, orphaned, un-transcoded). The 7// derived signals are then EMITTED as work items into a DEDICATED, NAMESPACED workstream store so the 8// live 1265-stream production board (prefix "knowledge/store/ws-") is NEVER disturbed (ADDITIVE law #13). 9// 10// ZERO NEW STORAGE / ZERO NEW IDENTITY / ZERO NEW CRYPTO -- pure COMPOSITION (Rule 15, DRY): 11// * catalog enumeration + bytes -> nx_asset_catalog (cat_list / cat_get / cat_count) 12// * record field access -> nx_asset_record (ar_decode / ar_get : tags, is_current, 13// relations, type, width, height, 14// encoding_format, lifecycle_stage) 15// * cryptographic provenance check -> nx_asset_provenance(prov_verify : a record HAS a verifiable 16// R2 credential iff prov_verify==1) 17// * perceptual near-dup grouping -> nx_asset_autotag (at_neardup over per-record dHashes) 18// * work-item write/list (NAMESPACED)-> nx_seg_store (ss_get / ss_begin / ss_add / ss_commit / 19// ss_open / ss_hget) into a DEDICATED prefix 20// 21// WMS WIRING / PRODUCTION CUTOVER SEAM: 22// The emitted work items use the EXACT record contract of nx_workstream_store (key "sig:<cid>:<code>", 23// a TAB-separated value record, and a "ws:ids" enumeration index), written over the SAME substrate the 24// WMS itself is built on (ss_*). We do NOT import nx_workstream_store directly: it lives in 25// runtime/_hdl_build/ and the sovereign import resolver resolves transitive imports relative to the 26// importing file's directory, so a runtime/ organ cannot reach a _hdl_build/ organ (verified: importing 27// it -> "expand_imports failed"). Emitting straight onto ss_* with the dedicated prefix is therefore 28// the clean isolation: the live board store (WS_PREFIX="knowledge/store/ws-") is a DIFFERENT store and 29// is never opened, read, or written here. THE CUTOVER: when the signals organ is co-located with the 30// WMS (move both under one dir, or expose nx_workstream_store from runtime/), as_emit's ss_* calls map 31// 1:1 onto ws_put_p(AS_PREFIX(), key, val) and as_list onto ws_manifest_p(AS_PREFIX(), ...) -- same 32// keys, same TAB record, same ws:ids index -- so the production daemon can adopt them unchanged. 33// 34// PURITY: as_scan is a pure/deterministic function of the catalog snapshot PLUS caller-supplied parallel 35// auxiliary arrays (perceptual hashes + provenance credentials), because two of the seven predicates 36// CANNOT be answered from the record bytes alone and we refuse to fabricate the answer (Rule 4 / honesty): 37// * NEAR_DUP needs a PERCEPTUAL fingerprint -- the record stores none (a dHash is over the pixels, the 38// decode step is the caller's, per nx_asset_autotag's documented boundary). phashes[i] is record i's 39// dHash, or 0 to mean "no fingerprint available -> cannot be a near-dup". 40// * MISSING_PROVENANCE needs the record's CREDENTIAL + the trusted platform pubkey -- a record alone is 41// unverifiable. cred_ptr[i]/cred_len[i] point at record i's R2 credential (len 0 = none); a record 42// "has verifiable provenance" IFF prov_verify(cred, len, pubkey, cid)==1 (deny-by-default). 43// The other five predicates (UNTAGGED / MISSING_METADATA / STALE / ORPHANED / UNTRANSCODED) are pure 44// over the decoded record fields. Aux arrays are indexed PARALLEL to cat_list order (snapshot order). 45// 46// No hardware/persistent-firmware writes (Rule 26). license_tier: ORIGINAL 47import "nx_syscalls.nx" 48import "nx_asset_record.nx" 49import "nx_asset_catalog.nx" 50import "nx_asset_provenance.nx" 51import "nx_asset_autotag.nx" 52import "nx_seg_store.nx" 53const K_MAGIC_4096: i64 = 4096 54 55// ---- SIGNAL CODE vocabulary (data-driven label set, one definition -- Rule 11, no magic strings) ---- 56// Each code is the machine-readable reason a record implies follow-up work. 57func SIG_MISSING_PROVENANCE() -> *u8 { return "MISSING_PROVENANCE\x00" as *u8 } 58func SIG_UNTAGGED() -> *u8 { return "UNTAGGED\x00" as *u8 } 59func SIG_MISSING_METADATA() -> *u8 { return "MISSING_METADATA\x00" as *u8 } 60func SIG_NEAR_DUP() -> *u8 { return "NEAR_DUP\x00" as *u8 } 61func SIG_STALE() -> *u8 { return "STALE\x00" as *u8 } 62func SIG_ORPHANED() -> *u8 { return "ORPHANED\x00" as *u8 } 63func SIG_UNTRANSCODED() -> *u8 { return "UNTRANSCODED\x00" as *u8 } 64 65// near-dup threshold (STRICT < threshold): 1 == "Hamming 0 only" = perceptually identical fingerprints. 66// Data-driven so a future caller can loosen it without a code edit (Rule 11). 67func AS_NEARDUP_THRESHOLD() -> i64 { return 1 } 68 69// the DEDICATED, isolated namespace prefix for emitted asset-signal work items. DISTINCT from the 70// production board prefix WS_PREFIX="knowledge/store/ws-" by construction, so emission is purely additive 71// and CANNOT pollute the live workstream board (the load-bearing isolation guarantee of this rung). 72func AS_PREFIX() -> *u8 { return "knowledge/store/asset-signals-\x00" as *u8 } 73 74// ---- small helpers ---- 75func as_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 76func as_streq(a: *u8, b: *u8) -> i64 { 77 var i: i64 = 0 78 while 1 == 1 { 79 if a[i] != b[i] { return 0 } 80 if a[i] == (0 as u8) { return 1 } 81 i = i + 1 82 } 83 return 1 84} 85// present = non-null pointer AND non-empty string (mirrors ar_present semantics for decoded fields) 86func as_present(v: *u8) -> i64 { 87 if (v as i64) == 0 { return 0 } 88 if v[0] == (0 as u8) { return 0 } 89 return 1 90} 91// copy src -> dst (NUL-terminated), returns length copied 92func as_cpy(dst: *u8, src: *u8) -> i64 { 93 var i: i64 = 0 94 while src[i] != (0 as u8) { dst[i] = src[i]; i = i + 1 } 95 dst[i] = 0 as u8 96 return i 97} 98// append src at dst[off] (NUL-terminated result), returns new offset 99func as_cat(dst: *u8, off: i64, src: *u8) -> i64 { 100 var i: i64 = 0 101 while src[i] != (0 as u8) { dst[off + i] = src[i]; i = i + 1 } 102 dst[off + i] = 0 as u8 103 return off + i 104} 105 106// ---- minimal WMS-contract write/list over ss_* (the production cutover seam, see header) ---- 107// next segment id for a commit under `prefix` = fresh max+1 (ss_next_segid, UNCAPPED; mirrors ws_seg_next). 108// was 1 + capped ss_manifest count -> clobbered the cap segment past the cap. Empty store stays 1-based. 109func as_seg_next(prefix: *u8) -> i64 { 110 let n: i64 = ss_next_segid(prefix) 111 if n < 1 { return 1 } 112 return n 113} 114 115// as_put: register/update ONE record (idempotent: skip-if-unchanged via current-value byte-compare; 116// additive new version otherwise). BYTE-IDENTICAL semantics to ws_put_p, over ss_*. Returns 117// 0 committed a new version / 1 unchanged-skipped / <0 commit error. 118func as_put(prefix: *u8, key: *u8, val: *u8) -> i64 { 119 let pq: *i64 = sys_mmap(16) as *i64 120 let lq: *i64 = sys_mmap(16) as *i64 121 let vl: i64 = as_len(val) 122 if ss_get(prefix, key, pq, lq) == 1 { 123 if lq[0] == vl { 124 let b: *u8 = pq[0] as *u8 125 var same: i64 = 1 126 var i: i64 = 0 127 while i < vl { if b[i] != val[i] { same = 0; i = vl } else { i = i + 1 } } 128 if same == 1 { return 1 } 129 } 130 } 131 let w: *i64 = ss_begin() 132 ss_add(w, 1, key, val, vl) 133 let segid: i64 = as_seg_next(prefix) 134 return ss_commit(prefix, w, segid) 135} 136 137// is NUL-terminated `tok` a TAB-bounded member of list[0..llen)? (whole-field match, mirrors ws_member: 138// "sig:X:UNTAGGED" must not match a longer field). The ws:ids index dedupe predicate. 139func as_member(list: *u8, llen: i64, tok: *u8) -> i64 { 140 let tl: i64 = as_len(tok) 141 var i: i64 = 0 142 while i < llen { 143 var atstart: i64 = 0 144 if i == 0 { atstart = 1 } 145 if i > 0 { if list[i - 1] == (9 as u8) { atstart = 1 } } 146 if atstart == 1 { 147 var fe: i64 = i 148 var go: i64 = 1 149 while go == 1 { 150 if fe >= llen { go = 0 } else { 151 if list[fe] == (9 as u8) { go = 0 } else { fe = fe + 1 } 152 } 153 } 154 if fe - i == tl { 155 var eq: i64 = 1 156 var j: i64 = 0 157 while j < tl { if list[i + j] != tok[j] { eq = 0; j = tl } else { j = j + 1 } } 158 if eq == 1 { return 1 } 159 } 160 } 161 i = i + 1 162 } 163 return 0 164} 165 166// ---- the SIGNAL TABLE (out_signals) layout, heap-mmap parallel arrays (no struct aliasing) ---- 167// A signal is the triple {cid, signal_code, detail}. out_signals is an i64[] the CALLER mmaps with 168// 3*cap slots; we fill it as 3 parallel runs to keep field access by offset (build-rule idiom): 169// out_signals[0*cap + k] = ptr to NUL-term CID (k-th signal) 170// out_signals[1*cap + k] = ptr to NUL-term signal_code 171// out_signals[2*cap + k] = ptr to NUL-term detail 172// as_scan returns the number of signals written (k count). Each string is a fresh mmap copy so the 173// signal table outlives the catalog snapshot buffers. 174func as_sig_cid(out_signals: *i64, cap: i64, k: i64) -> *u8 { return out_signals[0 * cap + k] as *u8 } 175func as_sig_code(out_signals: *i64, cap: i64, k: i64) -> *u8 { return out_signals[1 * cap + k] as *u8 } 176func as_sig_detail(out_signals: *i64, cap: i64, k: i64) -> *u8 { return out_signals[2 * cap + k] as *u8 } 177 178// emit ONE signal into the table at index k (fresh NUL-term copies); returns k+1. detail may be empty. 179func as_emit_one(out_signals: *i64, cap: i64, k: i64, cid: *u8, code: *u8, detail: *u8) -> i64 { 180 if k >= cap { return k } 181 let cb: *u8 = sys_mmap(as_len(cid) + 8) 182 as_cpy(cb, cid) 183 out_signals[0 * cap + k] = cb as i64 184 let sb: *u8 = sys_mmap(as_len(code) + 8) 185 as_cpy(sb, code) 186 out_signals[1 * cap + k] = sb as i64 187 let db: *u8 = sys_mmap(as_len(detail) + 8) 188 as_cpy(db, detail) 189 out_signals[2 * cap + k] = db as i64 190 return k + 1 191} 192 193// ---- as_scan: derive ALL task signals over the catalog snapshot + parallel aux arrays ---- 194// prefix : the catalog store prefix to scan (cat_list/cat_get). 195// phashes[i] : record i's perceptual dHash (0 = none -> never NEAR_DUP). 196// cred_ptr[i] / cred_len[i] : record i's R2 provenance credential bytes (len 0 = none). 197// pubkey : the 32-byte trusted platform public key prov_verify checks against. 198// out_signals : caller-mmap'd i64[3*cap] (see layout above). cap = max signals. 199// Returns the number of signals derived (>=0). PURE/deterministic over (snapshot, phashes, creds). 200// Records are visited in cat_list order; aux arrays are indexed by that same order. 201func as_scan(prefix: *u8, phashes: *i64, cred_ptr: *i64, cred_len: *i64, pubkey: *u8, 202 out_signals: *i64, cap: i64) -> i64 { 203 // 1) enumerate the catalog membership (snapshot order). 204 let lcap: i64 = K_MAGIC_4096 205 let cids: *i64 = sys_mmap(8 * lcap) as *i64 206 let n: i64 = cat_list(prefix, cids, lcap) 207 208 // 2) NEAR_DUP needs the near-dup GROUPING first: group records by perceptual fingerprint, then a 209 // record is a near-dup iff its group has >1 member. at_neardup assigns each record the index of 210 // its earliest within-threshold peer; we count group sizes to find groups with >1 member. 211 let groups: *i64 = sys_mmap(8 * (n + 16)) as *i64 212 at_neardup(phashes, n, AS_NEARDUP_THRESHOLD(), groups) 213 let gsize: *i64 = sys_mmap(8 * (n + 16)) as *i64 214 var gi: i64 = 0 215 while gi < n { gsize[gi] = 0; gi = gi + 1 } 216 gi = 0 217 while gi < n { 218 // a record with NO fingerprint (phash==0) is its own singleton group id == gi (at_neardup sets 219 // out_groups[i]=i when nothing is within threshold); excluding it from near-dup counting is 220 // handled below by the phash!=0 guard, so we count every group membership here honestly. 221 let g: i64 = groups[gi] 222 gsize[g] = gsize[g] + 1 223 gi = gi + 1 224 } 225 226 // 3) per-record predicate evaluation. 227 let dk: *i64 = sys_mmap(8 * 64) as *i64 228 let dv: *i64 = sys_mmap(8 * 64) as *i64 229 let pp: *i64 = sys_mmap(16) as *i64 230 let ll: *i64 = sys_mmap(16) as *i64 231 var k: i64 = 0 232 var i: i64 = 0 233 while i < n { 234 let cid: *u8 = cids[i] as *u8 235 // fetch + decode the record (snapshot is internally consistent). 236 let got: i64 = cat_get(prefix, cid, pp, ll) 237 if got == 1 { 238 let nf: i64 = ar_decode(pp[0] as *u8, ll[0], dk, dv, 64) 239 let typ: *u8 = ar_get(dk, dv, nf, "type\x00" as *u8) 240 let tags: *u8 = ar_get(dk, dv, nf, "tags\x00" as *u8) 241 let w: *u8 = ar_get(dk, dv, nf, "width\x00" as *u8) 242 let hgt: *u8 = ar_get(dk, dv, nf, "height\x00" as *u8) 243 let enc: *u8 = ar_get(dk, dv, nf, "encoding_format\x00" as *u8) 244 let cur: *u8 = ar_get(dk, dv, nf, "is_current\x00" as *u8) 245 let life: *u8 = ar_get(dk, dv, nf, "lifecycle_stage\x00" as *u8) 246 let rel: *u8 = ar_get(dk, dv, nf, "relations\x00" as *u8) 247 248 // -- MISSING_PROVENANCE: no verifiable R2 credential bound to this record CID. -- 249 // deny-by-default: a record HAS provenance only if a credential is present AND prov_verify==1. 250 var has_prov: i64 = 0 251 if cred_len[i] > 0 { 252 if prov_verify(cred_ptr[i] as *u8, cred_len[i], pubkey, cid) == 1 { has_prov = 1 } 253 } 254 if has_prov == 0 { 255 k = as_emit_one(out_signals, cap, k, cid, SIG_MISSING_PROVENANCE(), 256 "no verifiable C2PA credential bound to record CID\x00" as *u8) 257 } 258 259 // -- UNTAGGED: the tags facet is empty. -- 260 if as_present(tags) == 0 { 261 k = as_emit_one(out_signals, cap, k, cid, SIG_UNTAGGED(), 262 "tags facet empty -- needs keyword tagging\x00" as *u8) 263 } 264 265 // -- MISSING_METADATA: type=image but width/height absent. -- 266 if as_present(typ) == 1 { 267 if as_streq(typ, "image\x00" as *u8) == 1 { 268 if as_present(w) == 0 { k = as_emit_one(out_signals, cap, k, cid, SIG_MISSING_METADATA(), 269 "image missing width/height -- needs metadata extraction\x00" as *u8) } 270 else { if as_present(hgt) == 0 { k = as_emit_one(out_signals, cap, k, cid, SIG_MISSING_METADATA(), 271 "image missing width/height -- needs metadata extraction\x00" as *u8) } } 272 } 273 } 274 275 // -- NEAR_DUP: record is in a perceptual group with >1 member (and HAS a fingerprint). -- 276 if phashes[i] != 0 { 277 if gsize[groups[i]] > 1 { 278 k = as_emit_one(out_signals, cap, k, cid, SIG_NEAR_DUP(), 279 "perceptual near-duplicate of another asset -- needs de-dup review\x00" as *u8) 280 } 281 } 282 283 // -- STALE: is_current=="0", OR lifecycle_stage retired/archive. -- 284 var stale: i64 = 0 285 if as_present(cur) == 1 { if as_streq(cur, "0\x00" as *u8) == 1 { stale = 1 } } 286 if as_present(life) == 1 { 287 if as_streq(life, "retire\x00" as *u8) == 1 { stale = 1 } 288 if as_streq(life, "archive\x00" as *u8) == 1 { stale = 1 } 289 } 290 if stale == 1 { 291 k = as_emit_one(out_signals, cap, k, cid, SIG_STALE(), 292 "soft-retired/archived (is_current=0 or lifecycle retired)\x00" as *u8) 293 } 294 295 // -- ORPHANED: relations field empty (no graph edges to/from). -- 296 if as_present(rel) == 0 { 297 k = as_emit_one(out_signals, cap, k, cid, SIG_ORPHANED(), 298 "no relations -- unlinked in the asset graph\x00" as *u8) 299 } 300 301 // -- UNTRANSCODED: type=video/audio with no web-friendly encoding_format. -- 302 if as_present(typ) == 1 { 303 var av: i64 = 0 304 if as_streq(typ, "video\x00" as *u8) == 1 { av = 1 } 305 if as_streq(typ, "audio\x00" as *u8) == 1 { av = 1 } 306 if av == 1 { 307 if as_present(enc) == 0 { 308 k = as_emit_one(out_signals, cap, k, cid, SIG_UNTRANSCODED(), 309 "av asset has no web-friendly encoding_format -- needs transcode\x00" as *u8) 310 } 311 } 312 } 313 } 314 i = i + 1 315 } 316 return k 317} 318 319// ---- as_emit: write each derived signal as a work item into the DEDICATED asset-signals namespace ---- 320// Each signal -> one work item record in the store at prefix AS_PREFIX() (NOT the production board): 321// key = "sig:" + cid + ":" + signal_code (deterministic -> idempotent re-emit via ws_put_p) 322// val (TAB-separated, the WMS record shape) = signal_code <TAB> cid <TAB> detail <TAB> ACTIVE <TAB> asset 323// field 0 = signal_code field 1 = cid field 2 = detail field 3 = state field 4 = empire 324// Also maintains a "ws:ids" index (TAB-joined keys) in the SAME dedicated prefix so as_list can 325// enumerate via ws_manifest_p -- exactly the WMS SSOT contract, in an isolated store. Returns the 326// number of work items committed-or-already-present (>=0), or <0 on a store error. Idempotent: a 327// re-emit of identical signals re-states the same keys (ws_put_p skips unchanged) and the same index. 328func as_emit(out_signals: *i64, cap: i64, count: i64) -> i64 { 329 let prefix: *u8 = AS_PREFIX() 330 // build/extend the ws:ids index in-memory as we go (TAB-joined keys). 331 let idxbuf: *u8 = sys_mmap(count * 160 + 256) 332 var io: i64 = 0 333 // seed idxbuf with any EXISTING index so re-emit across runs stays additive (membership preserved). 334 let pq: *i64 = sys_mmap(16) as *i64 335 let lq: *i64 = sys_mmap(16) as *i64 336 if ss_get(prefix, "ws:ids\x00" as *u8, pq, lq) == 1 { 337 let eb: *u8 = pq[0] as *u8 338 var e: i64 = 0 339 while e < lq[0] { idxbuf[io] = eb[e]; io = io + 1; e = e + 1 } 340 } 341 var wrote: i64 = 0 342 var k: i64 = 0 343 while k < count { 344 let cid: *u8 = as_sig_cid(out_signals, cap, k) 345 let code: *u8 = as_sig_code(out_signals, cap, k) 346 let detail: *u8 = as_sig_detail(out_signals, cap, k) 347 // key = "sig:" + cid + ":" + code 348 let key: *u8 = sys_mmap(as_len(cid) + as_len(code) + 16) 349 var ko: i64 = as_cat(key, 0, "sig:\x00" as *u8) 350 ko = as_cat(key, ko, cid) 351 ko = as_cat(key, ko, ":\x00" as *u8) 352 ko = as_cat(key, ko, code) 353 // val = code TAB cid TAB detail TAB ACTIVE TAB asset (the WMS TAB record shape) 354 let val: *u8 = sys_mmap(as_len(code) + as_len(cid) + as_len(detail) + 64) 355 var vo: i64 = as_cat(val, 0, code) 356 val[vo] = 9 as u8; vo = vo + 1 357 vo = as_cat(val, vo, cid) 358 val[vo] = 9 as u8; vo = vo + 1 359 vo = as_cat(val, vo, detail) 360 val[vo] = 9 as u8; vo = vo + 1 361 vo = as_cat(val, vo, "ACTIVE\x00" as *u8) 362 val[vo] = 9 as u8; vo = vo + 1 363 vo = as_cat(val, vo, "asset\x00" as *u8) 364 // commit the work item (idempotent: as_put skips if byte-identical -- production: ws_put_p). 365 let rc: i64 = as_put(prefix, key, val) 366 if rc < 0 { return rc } 367 // extend the index iff this key is not already a TAB-member (idempotent membership). 368 if as_member(idxbuf, io, key) == 0 { 369 if io > 0 { idxbuf[io] = 9 as u8; io = io + 1 } 370 var t: i64 = 0 371 while key[t] != (0 as u8) { idxbuf[io] = key[t]; io = io + 1; t = t + 1 } 372 } 373 wrote = wrote + 1 374 k = k + 1 375 } 376 // commit the (possibly extended) ws:ids index so as_list can enumerate (production: ws_manifest_p). 377 if io > 0 { 378 idxbuf[io] = 0 as u8 379 let rc2: i64 = as_put(prefix, "ws:ids\x00" as *u8, idxbuf) 380 if rc2 < 0 { return rc2 } 381 } 382 return wrote 383} 384 385// ---- as_list: read emitted work items back from the dedicated namespace ---- 386// Enumerates the asset-signals store at AS_PREFIX() by reading the ws:ids index and TAB-splitting it 387// (BYTE-IDENTICAL walk to ws_manifest_p, the WMS SSOT enumeration), writing each work-item KEY pointer 388// (fresh NUL-term copy) into out_keys[] (up to cap). Returns the count (>=0), or 0 if nothing emitted. 389// The production board (WS_PREFIX) is never read here -- this reads ONLY the isolated asset namespace. 390func as_list(out_keys: *i64, cap: i64) -> i64 { 391 let h: *i64 = ss_open(AS_PREFIX()) 392 if (h as i64) == 0 { return 0 } 393 let pq: *i64 = sys_mmap(16) as *i64 394 let lq: *i64 = sys_mmap(16) as *i64 395 if ss_hget(h, "ws:ids\x00" as *u8, pq, lq) != 1 { return 0 } 396 let ids: *u8 = pq[0] as *u8 397 let idn: i64 = lq[0] 398 var cnt: i64 = 0 399 var i: i64 = 0 400 while i < idn { 401 let kb: *u8 = sys_mmap(256) 402 var o: i64 = 0 403 var go: i64 = 1 404 while go == 1 { 405 if i >= idn { go = 0 } else { 406 if ids[i] == (9 as u8) { i = i + 1; go = 0 } else { kb[o] = ids[i]; o = o + 1; i = i + 1 } 407 } 408 } 409 kb[o] = 0 as u8 410 if o > 0 { if cnt < cap { out_keys[cnt] = kb as i64; cnt = cnt + 1 } } 411 } 412 return cnt 413} 414 415// as_get: retrieve one emitted work item's TAB record by its key (ptr/len out). 1 found / 0 tombstoned 416// / -1 absent -- ss_get semantics (== ws_get_p) over the dedicated namespace. Lets a reader pull field 417// values (signal_code/cid/detail/state/empire) with ws_field / as_field. 418func as_get(key: *u8, ptrout: *i64, lenout: *i64) -> i64 { 419 return ss_get(AS_PREFIX(), key, ptrout, lenout) 420} 421 422// as_field: extract the f-th (0-based) TAB-separated field of rec[0..rlen) into out (NUL-terminated); 423// returns field length. Same parser as ws_field, for readers of an emitted work-item record. 424func as_field(rec: *u8, rlen: i64, f: i64, out: *u8) -> i64 { 425 var cur: i64 = 0 426 var i: i64 = 0 427 var o: i64 = 0 428 while cur < f { 429 if i >= rlen { out[0] = 0 as u8; return 0 } 430 if rec[i] == (9 as u8) { cur = cur + 1 } 431 i = i + 1 432 } 433 var go: i64 = 1 434 while go == 1 { 435 if i >= rlen { go = 0 } else { 436 if rec[i] == (9 as u8) { go = 0 } else { out[o] = rec[i]; o = o + 1; i = i + 1 } 437 } 438 } 439 out[o] = 0 as u8 440 return o 441}