code wiki / (root) / sketch_buglog.nx

sketch_buglog.nx source

↩ module page · 331 lines · 11259 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 35import "syscalls.nx" 36import "sketch_types.nx" 37 38const NX_PROV_KIND_BUG: i64 = 0 39const NX_PROV_KIND_CAPABILITY: i64 = 1 40const NX_PROV_KIND_IMPROVEMENT_OPP: i64 = 2 41const NX_PROV_KIND_CROSS_REF: i64 = 3 42 43const NX_BUG_AXIS_ACCURACY: i64 = 0 44const NX_BUG_AXIS_MEMORY: i64 = 1 45const NX_BUG_AXIS_TIME: i64 = 2 46const NX_BUG_AXIS_CAPABILITY: i64 = 3 47const NX_BUG_AXIS_USABILITY: i64 = 4 48 49const NX_BUG_MAX_GENEALOGY: i64 = 64 50const NX_BUG_MAX_LINEAGE: i64 = 64 51 52struct StrSlice { 53 s: *u8, 54 len: i64, 55} 56 57struct BugLog { 58 kind: i64, 59 who: *u8, 60 who_len: i64, 61 what: *u8, 62 what_len: i64, 63 when_iso: *u8, 64 when_iso_len: i64, 65 where_axis: i64, 66 why: *u8, 67 why_len: i64, 68 how: *u8, 69 how_len: i64, 70 genealogy: *StrSlice, 71 n_genealogy: i64, 72 lineage: *StrSlice, 73 n_lineage: i64, 74 performance: *u8, 75 performance_len: i64, 76} 77 78func nx_buglog_slen(s: *u8) -> i64 { 79 var i: i64 = 0 80 while s[i] != 0 { i = i + 1 } 81 return i 82} 83 84func nx_buglog_alloc() -> *BugLog { 85 let raw: *u8 = sys_mmap(192) 86 let e: *BugLog = raw as *BugLog 87 let empty: *u8 = sys_mmap(1) 88 empty[0] = 0 89 e.kind = NX_PROV_KIND_BUG 90 e.who = empty 91 e.who_len = 0 92 e.what = empty 93 e.what_len = 0 94 e.when_iso = empty 95 e.when_iso_len = 0 96 e.where_axis = NX_BUG_AXIS_ACCURACY 97 e.why = empty 98 e.why_len = 0 99 e.how = empty 100 e.how_len = 0 101 let gen_raw: *u8 = sys_mmap(NX_BUG_MAX_GENEALOGY * 16) 102 e.genealogy = gen_raw as *StrSlice 103 e.n_genealogy = 0 104 let lin_raw: *u8 = sys_mmap(NX_BUG_MAX_LINEAGE * 16) 105 e.lineage = lin_raw as *StrSlice 106 e.n_lineage = 0 107 e.performance = empty 108 e.performance_len = 0 109 return e 110} 111 112func nx_buglog_slice_at(arr: *StrSlice, i: i64) -> *StrSlice { 113 return (arr as i64 + i * 16) as *StrSlice 114} 115 116// === base setters (must precede _z wrappers per forward-decl rule) === 117 118func nx_buglog_set_kind(e: *BugLog, kind: i64) -> i64 { 119 if kind < 0 { return -1 } 120 if kind > NX_PROV_KIND_CROSS_REF { return -1 } 121 e.kind = kind 122 return 0 123} 124 125func nx_buglog_kind_str(kind: i64) -> *u8 { 126 if kind == NX_PROV_KIND_BUG { return "BUG" } 127 if kind == NX_PROV_KIND_CAPABILITY { return "CAPABILITY" } 128 if kind == NX_PROV_KIND_IMPROVEMENT_OPP { return "IMPROVEMENT_OPP" } 129 if kind == NX_PROV_KIND_CROSS_REF { return "CROSS_REF" } 130 return "UNKNOWN" 131} 132 133func nx_buglog_kind_strlen(kind: i64) -> i64 { 134 if kind == NX_PROV_KIND_BUG { return 3 } 135 if kind == NX_PROV_KIND_CAPABILITY { return 10 } 136 if kind == NX_PROV_KIND_IMPROVEMENT_OPP { return 15 } 137 if kind == NX_PROV_KIND_CROSS_REF { return 9 } 138 return 7 139} 140 141func nx_buglog_set_who(e: *BugLog, s: *u8, len: i64) -> i64 { 142 e.who = s 143 e.who_len = len 144 return 0 145} 146 147func nx_buglog_set_what(e: *BugLog, s: *u8, len: i64) -> i64 { 148 e.what = s 149 e.what_len = len 150 return 0 151} 152 153func nx_buglog_set_when(e: *BugLog, s: *u8, len: i64) -> i64 { 154 e.when_iso = s 155 e.when_iso_len = len 156 return 0 157} 158 159func nx_buglog_set_axis(e: *BugLog, axis: i64) -> i64 { 160 if axis < 0 { return -1 } 161 if axis > NX_BUG_AXIS_USABILITY { return -1 } 162 e.where_axis = axis 163 return 0 164} 165 166func nx_buglog_set_why(e: *BugLog, s: *u8, len: i64) -> i64 { 167 e.why = s 168 e.why_len = len 169 return 0 170} 171 172func nx_buglog_set_how(e: *BugLog, s: *u8, len: i64) -> i64 { 173 e.how = s 174 e.how_len = len 175 return 0 176} 177 178func nx_buglog_set_performance(e: *BugLog, s: *u8, len: i64) -> i64 { 179 e.performance = s 180 e.performance_len = len 181 return 0 182} 183 184func nx_buglog_add_genealogy(e: *BugLog, s: *u8, len: i64) -> i64 { 185 if e.n_genealogy >= NX_BUG_MAX_GENEALOGY { return -1 } 186 let slot: *StrSlice = nx_buglog_slice_at(e.genealogy, e.n_genealogy) 187 slot.s = s 188 slot.len = len 189 e.n_genealogy = e.n_genealogy + 1 190 return 0 191} 192 193func nx_buglog_add_lineage(e: *BugLog, s: *u8, len: i64) -> i64 { 194 if e.n_lineage >= NX_BUG_MAX_LINEAGE { return -1 } 195 let slot: *StrSlice = nx_buglog_slice_at(e.lineage, e.n_lineage) 196 slot.s = s 197 slot.len = len 198 e.n_lineage = e.n_lineage + 1 199 return 0 200} 201 202// === _z wrappers (defined AFTER base setters) ==================== 203 204func nx_buglog_set_who_z(e: *BugLog, s: *u8) -> i64 { 205 return nx_buglog_set_who(e, s, nx_buglog_slen(s)) 206} 207func nx_buglog_set_what_z(e: *BugLog, s: *u8) -> i64 { 208 return nx_buglog_set_what(e, s, nx_buglog_slen(s)) 209} 210func nx_buglog_set_when_z(e: *BugLog, s: *u8) -> i64 { 211 return nx_buglog_set_when(e, s, nx_buglog_slen(s)) 212} 213func nx_buglog_set_why_z(e: *BugLog, s: *u8) -> i64 { 214 return nx_buglog_set_why(e, s, nx_buglog_slen(s)) 215} 216func nx_buglog_set_how_z(e: *BugLog, s: *u8) -> i64 { 217 return nx_buglog_set_how(e, s, nx_buglog_slen(s)) 218} 219func nx_buglog_set_performance_z(e: *BugLog, s: *u8) -> i64 { 220 return nx_buglog_set_performance(e, s, nx_buglog_slen(s)) 221} 222func nx_buglog_add_genealogy_z(e: *BugLog, s: *u8) -> i64 { 223 return nx_buglog_add_genealogy(e, s, nx_buglog_slen(s)) 224} 225func nx_buglog_add_lineage_z(e: *BugLog, s: *u8) -> i64 { 226 return nx_buglog_add_lineage(e, s, nx_buglog_slen(s)) 227} 228 229// === axis -> string ============================================== 230 231func nx_buglog_axis_str(axis: i64) -> *u8 { 232 if axis == NX_BUG_AXIS_ACCURACY { return "accuracy" } 233 if axis == NX_BUG_AXIS_MEMORY { return "memory" } 234 if axis == NX_BUG_AXIS_TIME { return "time" } 235 if axis == NX_BUG_AXIS_CAPABILITY { return "capability" } 236 if axis == NX_BUG_AXIS_USABILITY { return "usability" } 237 return "unknown" 238} 239 240func nx_buglog_axis_strlen(axis: i64) -> i64 { 241 if axis == NX_BUG_AXIS_ACCURACY { return 8 } 242 if axis == NX_BUG_AXIS_MEMORY { return 6 } 243 if axis == NX_BUG_AXIS_TIME { return 4 } 244 if axis == NX_BUG_AXIS_CAPABILITY { return 10 } 245 if axis == NX_BUG_AXIS_USABILITY { return 9 } 246 return 7 247} 248 249// === JSON emit =================================================== 250 251func nx_buglog_w(s: *u8, len: i64) -> i64 { 252 sys_write(1, s, len) 253 return 0 254} 255 256func nx_buglog_emit_field(name: *u8, name_len: i64, 257 value: *u8, value_len: i64, 258 trailing_comma: i64) -> i64 { 259 nx_buglog_w("\"", 1) 260 nx_buglog_w(name, name_len) 261 nx_buglog_w("\":\"", 3) 262 nx_buglog_w(value, value_len) 263 nx_buglog_w("\"", 1) 264 if trailing_comma == 1 { nx_buglog_w(",", 1) } 265 return 0 266} 267 268func nx_buglog_emit_id_array(name: *u8, name_len: i64, 269 arr: *StrSlice, n: i64, 270 trailing_comma: i64) -> i64 { 271 nx_buglog_w("\"", 1) 272 nx_buglog_w(name, name_len) 273 nx_buglog_w("\":[", 3) 274 var i: i64 = 0 275 while i < n { 276 let slot: *StrSlice = nx_buglog_slice_at(arr, i) 277 nx_buglog_w("\"", 1) 278 nx_buglog_w(slot.s, slot.len) 279 nx_buglog_w("\"", 1) 280 if i < n - 1 { nx_buglog_w(",", 1) } 281 i = i + 1 282 } 283 nx_buglog_w("]", 1) 284 if trailing_comma == 1 { nx_buglog_w(",", 1) } 285 return 0 286} 287 288func nx_buglog_emit_raw_json(name: *u8, name_len: i64, 289 value: *u8, value_len: i64, 290 trailing_comma: i64) -> i64 { 291 nx_buglog_w("\"", 1) 292 nx_buglog_w(name, name_len) 293 nx_buglog_w("\":", 2) 294 if value_len == 0 { nx_buglog_w("null", 4) } 295 if value_len > 0 { nx_buglog_w(value, value_len) } 296 if trailing_comma == 1 { nx_buglog_w(",", 1) } 297 return 0 298} 299 300func nx_buglog_emit(e: *BugLog) -> i64 { 301 nx_buglog_w("{", 1) 302 let kind_s: *u8 = nx_buglog_kind_str(e.kind) 303 let kind_l: i64 = nx_buglog_kind_strlen(e.kind) 304 nx_buglog_emit_field("kind", 4, kind_s, kind_l, 1) 305 nx_buglog_emit_field("who", 3, e.who, e.who_len, 1) 306 nx_buglog_emit_field("what", 4, e.what, e.what_len, 1) 307 nx_buglog_emit_field("when", 4, e.when_iso, e.when_iso_len, 1) 308 let axis_s: *u8 = nx_buglog_axis_str(e.where_axis) 309 let axis_l: i64 = nx_buglog_axis_strlen(e.where_axis) 310 nx_buglog_emit_field("where", 5, axis_s, axis_l, 1) 311 nx_buglog_emit_field("why", 3, e.why, e.why_len, 1) 312 nx_buglog_emit_field("how", 3, e.how, e.how_len, 1) 313 nx_buglog_emit_id_array("genealogy_ids", 13, e.genealogy, e.n_genealogy, 1) 314 nx_buglog_emit_id_array("lineage_ids", 11, e.lineage, e.n_lineage, 1) 315 nx_buglog_emit_raw_json("performance", 11, e.performance, e.performance_len, 0) 316 nx_buglog_w("}\n", 2) 317 return 0 318} 319 320func nx_buglog_query(e: *BugLog) -> *ApproxI64 { 321 return nx_approx_new(e.where_axis, NX_ENV_ABS, 0, 1000000000, 322 NX_MATURITY_PRODUCTION, 323 NX_ADV_HONEST) 324} 325 326func nx_buglog_n_genealogy(e: *BugLog) -> i64 { return e.n_genealogy } 327func nx_buglog_n_lineage(e: *BugLog) -> i64 { return e.n_lineage } 328 329func nx_buglog_memory_bytes(e: *BugLog) -> i64 { 330 return 192 + NX_BUG_MAX_GENEALOGY * 16 + NX_BUG_MAX_LINEAGE * 16 331}