code wiki / (root) / nx_sketch_buglog.nx

nx_sketch_buglog.nx source

↩ module page · 338 lines · 11238 B

1// sketch_buglog.nx -- 5W+H+GLP provenance ledger primitive. 2// 3// NOT JUST FOR BUGS. This is the general provenance-emit primitive every 4// tool / sketch / capability uses to declare itself. The "bug log" is just 5// one filtered view (kind=BUG) of a broader ledger that also holds: 6// 7// kind = CAPABILITY -- primitive declares what it does 8// kind = BUG -- something failed; root-cause + fix 9// kind = IMPROVEMENT_OPP -- lineage step exists but unshipped (e.g., 10// heule_bias_table is on sketch_hll's 11// lineage but the table isn't in code yet) 12// kind = CROSS_REF -- primitive A composes against B 13// 14// G (Genealogy) and L (Lineage) are stored as arrays of SHORT IDs that 15// reference docs/genealogy.md and docs/lineage.md. Lightweight entries, 16// full provenance, joinable for tree views. 17// 18// SCHEMA (10 fields): 19// kind entry type (sealed enum below) 20// W Who primitive name 21// W What workload / scenario / capability description 22// W When ISO timestamp + commit hash 23// W Where sealed axis enum (accuracy/memory/time/capability/usability) 24// W Why root cause (for bugs) / motivation (for capabilities) 25// H How repro + fix (bugs) / usage example (capabilities) 26// G genealogy_ids IDs into docs/genealogy.md 27// L lineage_ids IDs into docs/lineage.md (TODO items here = improvement 28// opportunities a human or AI 29// can pick up directly) 30// P performance JSON object of measured metrics 31// 32// All callers append to _offc/provenance.jsonl (one JSON line per entry). 33// Bug-table is just `grep '"kind":"BUG"' _offc/provenance.jsonl`. 34 35// nx_safety_envelope: 36// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 37// sil_target: SIL1 38// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 39// verdict: NOT_YET_EVALUATED 40 41import "nx_syscalls.nx" 42import "nx_sketch_types.nx" 43const NX_MAGIC_1000000000: i64 = 1000000000 44 45const NX_PROV_KIND_BUG: i64 = 0 46const NX_PROV_KIND_CAPABILITY: i64 = 1 47const NX_PROV_KIND_IMPROVEMENT_OPP: i64 = 2 48const NX_PROV_KIND_CROSS_REF: i64 = 3 49 50const NX_BUG_AXIS_ACCURACY: i64 = 0 51const NX_BUG_AXIS_MEMORY: i64 = 1 52const NX_BUG_AXIS_TIME: i64 = 2 53const NX_BUG_AXIS_CAPABILITY: i64 = 3 54const NX_BUG_AXIS_USABILITY: i64 = 4 55 56const NX_BUG_MAX_GENEALOGY: i64 = 64 57const NX_BUG_MAX_LINEAGE: i64 = 64 58 59struct StrSlice { 60 s: *u8, 61 len: i64, 62} 63 64struct BugLog { 65 kind: i64, 66 who: *u8, 67 who_len: i64, 68 what: *u8, 69 what_len: i64, 70 when_iso: *u8, 71 when_iso_len: i64, 72 where_axis: i64, 73 why: *u8, 74 why_len: i64, 75 how: *u8, 76 how_len: i64, 77 genealogy: *StrSlice, 78 n_genealogy: i64, 79 lineage: *StrSlice, 80 n_lineage: i64, 81 performance: *u8, 82 performance_len: i64, 83} 84 85func nx_buglog_slen(s: *u8) -> i64 { 86 var i: i64 = 0 87 while s[i] != 0 { i = i + 1 } 88 return i 89} 90 91func nx_buglog_alloc() -> *BugLog { 92 let raw: *u8 = sys_mmap(192) 93 let e: *BugLog = raw as *BugLog 94 let empty: *u8 = sys_mmap(1) 95 empty[0] = 0 96 e.kind = NX_PROV_KIND_BUG 97 e.who = empty 98 e.who_len = 0 99 e.what = empty 100 e.what_len = 0 101 e.when_iso = empty 102 e.when_iso_len = 0 103 e.where_axis = NX_BUG_AXIS_ACCURACY 104 e.why = empty 105 e.why_len = 0 106 e.how = empty 107 e.how_len = 0 108 let gen_raw: *u8 = sys_mmap(NX_BUG_MAX_GENEALOGY * 16) 109 e.genealogy = gen_raw as *StrSlice 110 e.n_genealogy = 0 111 let lin_raw: *u8 = sys_mmap(NX_BUG_MAX_LINEAGE * 16) 112 e.lineage = lin_raw as *StrSlice 113 e.n_lineage = 0 114 e.performance = empty 115 e.performance_len = 0 116 return e 117} 118 119func nx_buglog_slice_at(arr: *StrSlice, i: i64) -> *StrSlice { 120 return (arr as i64 + i * 16) as *StrSlice 121} 122 123// === base setters (must precede _z wrappers per forward-decl rule) === 124 125func nx_buglog_set_kind(e: *BugLog, kind: i64) -> i64 { 126 if kind < 0 { return -1 } 127 if kind > NX_PROV_KIND_CROSS_REF { return -1 } 128 e.kind = kind 129 return 0 130} 131 132func nx_buglog_kind_str(kind: i64) -> *u8 { 133 if kind == NX_PROV_KIND_BUG { return "BUG" } 134 if kind == NX_PROV_KIND_CAPABILITY { return "CAPABILITY" } 135 if kind == NX_PROV_KIND_IMPROVEMENT_OPP { return "IMPROVEMENT_OPP" } 136 if kind == NX_PROV_KIND_CROSS_REF { return "CROSS_REF" } 137 return "UNKNOWN" 138} 139 140func nx_buglog_kind_strlen(kind: i64) -> i64 { 141 if kind == NX_PROV_KIND_BUG { return 3 } 142 if kind == NX_PROV_KIND_CAPABILITY { return 10 } 143 if kind == NX_PROV_KIND_IMPROVEMENT_OPP { return 15 } 144 if kind == NX_PROV_KIND_CROSS_REF { return 9 } 145 return 7 146} 147 148func nx_buglog_set_who(e: *BugLog, s: *u8, len: i64) -> i64 { 149 e.who = s 150 e.who_len = len 151 return 0 152} 153 154func nx_buglog_set_what(e: *BugLog, s: *u8, len: i64) -> i64 { 155 e.what = s 156 e.what_len = len 157 return 0 158} 159 160func nx_buglog_set_when(e: *BugLog, s: *u8, len: i64) -> i64 { 161 e.when_iso = s 162 e.when_iso_len = len 163 return 0 164} 165 166func nx_buglog_set_axis(e: *BugLog, axis: i64) -> i64 { 167 if axis < 0 { return -1 } 168 if axis > NX_BUG_AXIS_USABILITY { return -1 } 169 e.where_axis = axis 170 return 0 171} 172 173func nx_buglog_set_why(e: *BugLog, s: *u8, len: i64) -> i64 { 174 e.why = s 175 e.why_len = len 176 return 0 177} 178 179func nx_buglog_set_how(e: *BugLog, s: *u8, len: i64) -> i64 { 180 e.how = s 181 e.how_len = len 182 return 0 183} 184 185func nx_buglog_set_performance(e: *BugLog, s: *u8, len: i64) -> i64 { 186 e.performance = s 187 e.performance_len = len 188 return 0 189} 190 191func nx_buglog_add_genealogy(e: *BugLog, s: *u8, len: i64) -> i64 { 192 if e.n_genealogy >= NX_BUG_MAX_GENEALOGY { return -1 } 193 let slot: *StrSlice = nx_buglog_slice_at(e.genealogy, e.n_genealogy) 194 slot.s = s 195 slot.len = len 196 e.n_genealogy = e.n_genealogy + 1 197 return 0 198} 199 200func nx_buglog_add_lineage(e: *BugLog, s: *u8, len: i64) -> i64 { 201 if e.n_lineage >= NX_BUG_MAX_LINEAGE { return -1 } 202 let slot: *StrSlice = nx_buglog_slice_at(e.lineage, e.n_lineage) 203 slot.s = s 204 slot.len = len 205 e.n_lineage = e.n_lineage + 1 206 return 0 207} 208 209// === _z wrappers (defined AFTER base setters) ==================== 210 211func nx_buglog_set_who_z(e: *BugLog, s: *u8) -> i64 { 212 return nx_buglog_set_who(e, s, nx_buglog_slen(s)) 213} 214func nx_buglog_set_what_z(e: *BugLog, s: *u8) -> i64 { 215 return nx_buglog_set_what(e, s, nx_buglog_slen(s)) 216} 217func nx_buglog_set_when_z(e: *BugLog, s: *u8) -> i64 { 218 return nx_buglog_set_when(e, s, nx_buglog_slen(s)) 219} 220func nx_buglog_set_why_z(e: *BugLog, s: *u8) -> i64 { 221 return nx_buglog_set_why(e, s, nx_buglog_slen(s)) 222} 223func nx_buglog_set_how_z(e: *BugLog, s: *u8) -> i64 { 224 return nx_buglog_set_how(e, s, nx_buglog_slen(s)) 225} 226func nx_buglog_set_performance_z(e: *BugLog, s: *u8) -> i64 { 227 return nx_buglog_set_performance(e, s, nx_buglog_slen(s)) 228} 229func nx_buglog_add_genealogy_z(e: *BugLog, s: *u8) -> i64 { 230 return nx_buglog_add_genealogy(e, s, nx_buglog_slen(s)) 231} 232func nx_buglog_add_lineage_z(e: *BugLog, s: *u8) -> i64 { 233 return nx_buglog_add_lineage(e, s, nx_buglog_slen(s)) 234} 235 236// === axis -> string ============================================== 237 238func nx_buglog_axis_str(axis: i64) -> *u8 { 239 if axis == NX_BUG_AXIS_ACCURACY { return "accuracy" } 240 if axis == NX_BUG_AXIS_MEMORY { return "memory" } 241 if axis == NX_BUG_AXIS_TIME { return "time" } 242 if axis == NX_BUG_AXIS_CAPABILITY { return "capability" } 243 if axis == NX_BUG_AXIS_USABILITY { return "usability" } 244 return "unknown" 245} 246 247func nx_buglog_axis_strlen(axis: i64) -> i64 { 248 if axis == NX_BUG_AXIS_ACCURACY { return 8 } 249 if axis == NX_BUG_AXIS_MEMORY { return 6 } 250 if axis == NX_BUG_AXIS_TIME { return 4 } 251 if axis == NX_BUG_AXIS_CAPABILITY { return 10 } 252 if axis == NX_BUG_AXIS_USABILITY { return 9 } 253 return 7 254} 255 256// === JSON emit =================================================== 257 258func nx_buglog_w(s: *u8, len: i64) -> i64 { 259 sys_write(1, s, len) 260 return 0 261} 262 263func nx_buglog_emit_field(name: *u8, name_len: i64, 264 value: *u8, value_len: i64, 265 trailing_comma: i64) -> i64 { 266 nx_buglog_w("\"", 1) 267 nx_buglog_w(name, name_len) 268 nx_buglog_w("\":\"", 3) 269 nx_buglog_w(value, value_len) 270 nx_buglog_w("\"", 1) 271 if trailing_comma == 1 { nx_buglog_w(",", 1) } 272 return 0 273} 274 275func nx_buglog_emit_id_array(name: *u8, name_len: i64, 276 arr: *StrSlice, n: i64, 277 trailing_comma: i64) -> i64 { 278 nx_buglog_w("\"", 1) 279 nx_buglog_w(name, name_len) 280 nx_buglog_w("\":[", 3) 281 var i: i64 = 0 282 while i < n { 283 let slot: *StrSlice = nx_buglog_slice_at(arr, i) 284 nx_buglog_w("\"", 1) 285 nx_buglog_w(slot.s, slot.len) 286 nx_buglog_w("\"", 1) 287 if i < n - 1 { nx_buglog_w(",", 1) } 288 i = i + 1 289 } 290 nx_buglog_w("]", 1) 291 if trailing_comma == 1 { nx_buglog_w(",", 1) } 292 return 0 293} 294 295func nx_buglog_emit_raw_json(name: *u8, name_len: i64, 296 value: *u8, value_len: i64, 297 trailing_comma: i64) -> i64 { 298 nx_buglog_w("\"", 1) 299 nx_buglog_w(name, name_len) 300 nx_buglog_w("\":", 2) 301 if value_len == 0 { nx_buglog_w("null", 4) } 302 if value_len > 0 { nx_buglog_w(value, value_len) } 303 if trailing_comma == 1 { nx_buglog_w(",", 1) } 304 return 0 305} 306 307func nx_buglog_emit(e: *BugLog) -> i64 { 308 nx_buglog_w("{", 1) 309 let kind_s: *u8 = nx_buglog_kind_str(e.kind) 310 let kind_l: i64 = nx_buglog_kind_strlen(e.kind) 311 nx_buglog_emit_field("kind", 4, kind_s, kind_l, 1) 312 nx_buglog_emit_field("who", 3, e.who, e.who_len, 1) 313 nx_buglog_emit_field("what", 4, e.what, e.what_len, 1) 314 nx_buglog_emit_field("when", 4, e.when_iso, e.when_iso_len, 1) 315 let axis_s: *u8 = nx_buglog_axis_str(e.where_axis) 316 let axis_l: i64 = nx_buglog_axis_strlen(e.where_axis) 317 nx_buglog_emit_field("where", 5, axis_s, axis_l, 1) 318 nx_buglog_emit_field("why", 3, e.why, e.why_len, 1) 319 nx_buglog_emit_field("how", 3, e.how, e.how_len, 1) 320 nx_buglog_emit_id_array("genealogy_ids", 13, e.genealogy, e.n_genealogy, 1) 321 nx_buglog_emit_id_array("lineage_ids", 11, e.lineage, e.n_lineage, 1) 322 nx_buglog_emit_raw_json("performance", 11, e.performance, e.performance_len, 0) 323 nx_buglog_w("}\n", 2) 324 return 0 325} 326 327func nx_buglog_query(e: *BugLog) -> *ApproxI64 { 328 return nx_approx_new(e.where_axis, NX_ENV_ABS, 0, NX_MAGIC_1000000000, 329 NX_MATURITY_PRODUCTION, 330 NX_ADV_HONEST) 331} 332 333func nx_buglog_n_genealogy(e: *BugLog) -> i64 { return e.n_genealogy } 334func nx_buglog_n_lineage(e: *BugLog) -> i64 { return e.n_lineage } 335 336func nx_buglog_memory_bytes(e: *BugLog) -> i64 { 337 return 192 + NX_BUG_MAX_GENEALOGY * 16 + NX_BUG_MAX_LINEAGE * 16 338}