code wiki / _hdl_build / nx_pattern_classify.nx

nx_pattern_classify.nx source

↩ module page · 140 lines · 8736 B

1// nx_pattern_classify.nx -- the BUILDER's pattern CLASSIFIER (the rung nx_pattern_library itself flags: 2// "a real classifier would infer shape from the spec's in/out types"). Until now the pipeline trusted a 3// hand-assigned shape_id -- which means a human (or Claude) still classified every spec. This module 4// closes that: a spec is described by a small FEATURE VECTOR (what its inputs/outputs ARE), and a 5// data-driven DECISION TABLE maps features -> pattern id. Adding a shape = adding a row, not code 6// (rule 11). First-match-in-order resolves overlaps (PID before GOVERNOR: both stateful, plant wins; 7// STATE_FLOW before THRESHOLD_TABLE: both table-driven, verdict-out vs value-out splits them). 8// 0 = NOVEL -> NEEDS_TUTOR, honest and measured, exactly as bp_claude_touch counts it. 9// RACI: BUILDER owns this (AUTHOR's front door: spec -> which emitter authors it). 10// LAWS: struct-free, integer-only, flat ifs. license_tier: ORIGINAL 11import "nx_pattern_library.nx" 12import "nx_syscalls.nx" 13 14// ---- the feature vector: f[i] = 1 if the spec has the trait (indices are the contract) ---- 15const PLC_IN_BYTES: i64 = 0 // consumes a byte buffer (parse) 16const PLC_IN_ARRAY: i64 = 1 // consumes an i64 array (fold) 17const PLC_IN_PAIR: i64 = 2 // compares two scalars (a vs b) 18const PLC_IN_STATE: i64 = 3 // mutates carried state (integ, per-host last-hit) 19const PLC_IN_TABLE: i64 = 4 // core logic IS a data table (curve, transitions) 20const PLC_IN_COORDS: i64 = 5 // nm coordinates / dimensions 21const PLC_HAS_TIME: i64 = 6 // timestamps / rates / pacing 22const PLC_HAS_PLANT: i64 = 7 // closed feedback loop against a plant 23const PLC_OUT_VERDICT:i64 = 8 // output is a small enum (UNDER/OK/OVER, winner, next-state) 24const PLC_OUT_VALUE: i64 = 9 // output is a computed quantity 25const PLC_IS_META: i64 = 10 // emits modules/boilerplate rather than computing 26const PLC_IN_COEFFS: i64 = 11 // spec is a coefficient/constant table (oracle-generated f64 kernels) 27const PLC_IN_FRAMED: i64 = 12 // framed binary layout (TLV / length-prefixed field sequences) 28const PLC_IN_MARKED: i64 = 13 // prefix+marker stream (JPEG-style: standalone table, terminator) 29const PLC_HAS_INVERSE:i64 = 14 // lossless round-trip law: an exact inverse must reconstruct the 30 // input bit-for-bit (predictor/residual coders, codecs) 31const PLC_IN_INGEST: i64 = 15 // the COMPOSE-shape: a spec that wires a fixed pipeline of named 32 // organ fns (walk-all-chunks -> field-split -> canon/CID -> 33 // idempotent store). Routes PL_PNG_INGEST (emit15). DECLARED- 34 // SCAFFOLD trait, R3-authorized (X-AUT-NCF-001). 35// shape-20 LOG_SCAN traits (additive; NO existing index changes). A spec that READS a log/universe 36// and DERIVES a permil scoreboard. Deliberately distinct from in_bytes so it never touches the 37// t[15..17] zero-gap row (proven DIFFS=0). 38const PLC_READS_LOG: i64 = 16 // consumes a log/universe + target stream to count coverage 39const PLC_DERIVES_PERMIL:i64 = 17 // derives permil=count*1000/total + a verdict-band ladder 40// shape-21 RANK_FUSE trait (additive; no existing index changes): a spec consuming K source-rankings to FUSE 41// (internal+external) via reciprocal-rank fusion. Routes PL_RANK_FUSE (emitter nx_pattern_emit_rankfuse). 42const PLC_IN_RANKINGS: i64 = 18 // consumes K rankings to fuse (RRF) 43const PLC_IN_CORPUS: i64 = 19 // consumes a doc corpus + query -> ranked TF retrieval (RANK_RETRIEVE) 44const PLC_IN_OPDAG: i64 = 20 // consumes a 3-address op-DAG -> lowered dataflow core (RTL_SYNTH) 45const PLC_IN_SUBFABRICS: i64 = 21 // consumes K sub-fabrics to fold via fab_append (NETLIST_COMPOSE) 46const PLC_IN_FABRIC: i64 = 22 // emits a gate-level LUT4 fabric (cells+nets) -> runs on fab_eval (FABRIC_NETLIST) 47const PLC_N_FEATURES: i64 = 23 48 49// ---- the decision table: ordered (pattern_id, must_a, must_b) triples; must_b = -1 means one trait 50// suffices. FIRST full match wins; table order IS the disambiguation policy. ---- 51func plc_table_rows() -> i64 { return 25 } 52func plc_table() -> *i64 { 53 let t: *i64 = sys_mmap(640) as *i64 54 // PNG_INGEST (compose-shape) FIRST: in_ingest is a distinct trait so it routes here 55 // before the is_meta SCAFFOLD/IO_CONTRACT rows could absorb it (order = policy). 56 t[0]=PL_PNG_INGEST; t[1]=PLC_IN_INGEST; t[2]=0-1 57 t[3]=PL_PID_LOOP; t[4]=PLC_HAS_PLANT; t[5]=PLC_IN_STATE 58 t[6]=PL_GOVERNOR; t[7]=PLC_HAS_TIME; t[8]=0-1 59 t[9]=PL_GEOMETRY; t[10]=PLC_IN_COORDS; t[11]=0-1 60 t[12]=PL_MATH_KERNEL; t[13]=PLC_IN_COEFFS; t[14]=0-1 61 t[18]=PL_IO_CONTRACT; t[19]=PLC_IS_META; t[20]=PLC_IN_FRAMED 62 t[21]=PL_STRUCT_WALK; t[22]=PLC_IN_FRAMED; t[23]=PLC_IN_TABLE 63 t[24]=PL_WIRE_MARKER; t[25]=PLC_IN_MARKED; t[26]=0-1 64 t[27]=PL_WIRE_TLV; t[28]=PLC_IN_FRAMED; t[29]=0-1 65 // TEMPLATE_TABLE before STATE_FLOW/THRESHOLD_TABLE: a renderer spec is 66 // table-driven AND consumes payload bytes; verdict/value-out specs lack 67 // IN_BYTES so the older rows keep their routes (order = policy). 68 t[30]=PL_TEMPLATE_TABLE; t[31]=PLC_IN_TABLE; t[32]=PLC_IN_BYTES 69 // STATE_MACHINE before STATE_FLOW (index order IS the policy): both are 70 // table-driven w/ enum out, but a machine spec CARRIES state between 71 // events (IN_STATE); flow specs do not. 72 t[33]=PL_STATE_MACHINE; t[34]=PLC_IN_TABLE; t[35]=PLC_IN_STATE 73 t[36]=PL_STATE_FLOW; t[37]=PLC_IN_TABLE; t[38]=PLC_OUT_VERDICT 74 t[39]=PL_THRESHOLD_TABLE;t[40]=PLC_IN_TABLE; t[41]=PLC_OUT_VALUE 75 t[42]=PL_PARSER_KAT; t[43]=PLC_IN_BYTES; t[44]=PLC_OUT_VALUE 76 t[45]=PL_PREDICTOR_CODER;t[46]=PLC_IN_ARRAY; t[47]=PLC_HAS_INVERSE 77 t[48]=PL_ACCUMULATOR; t[49]=PLC_IN_ARRAY; t[50]=0-1 78 t[51]=PL_COMPARATOR; t[52]=PLC_IN_PAIR; t[53]=PLC_OUT_VERDICT 79 t[54]=PL_SCAFFOLD; t[55]=PLC_IS_META; t[56]=0-1 80 // shape-20 LOG_SCAN (NEW scanned row r=19): reads_log + derives_permil. Placed AFTER all other 81 // rows so nothing it could shadow exists; the t[15..17] zero gap is left untouched (proven safe). 82 t[57]=PL_LOG_SCAN; t[58]=PLC_READS_LOG; t[59]=PLC_DERIVES_PERMIL 83 // VERDICT_GATE kept in the catalog but DORMANT (unscanned, exactly as before): relocated to 84 // t[60..62] which sits past plc_table_rows(); out_verdict-only specs stay NOVEL as today. 85 t[60]=PL_RANK_FUSE; t[61]=PLC_IN_RANKINGS;t[62]=0-1 86 // shape-22 RANK_RETRIEVE (active row 21): a spec consuming a corpus+query routes here (IN_CORPUS, a new trait). 87 t[63]=PL_RANK_RETRIEVE; t[64]=PLC_IN_CORPUS; t[65]=0-1 88 // shape-23 RTL_SYNTH (active row 22): a spec consuming a 3-address op-DAG routes here (IN_OPDAG, a new trait). 89 t[66]=PL_RTL_SYNTH; t[67]=PLC_IN_OPDAG; t[68]=0-1 90 // shape-24 NETLIST_COMPOSE (active row 23): a spec consuming K sub-fabrics routes here (IN_SUBFABRICS, a new trait). 91 t[69]=PL_NETLIST_COMPOSE;t[70]=PLC_IN_SUBFABRICS;t[71]=0-1 92 // shape-25 FABRIC_NETLIST (active row 24): a spec emitting a gate-level fabric routes here (IN_FABRIC, a new trait). 93 t[72]=PL_FABRIC_NETLIST; t[73]=PLC_IN_FABRIC; t[74]=0-1 94 t[75]=PL_VERDICT_GATE; t[76]=PLC_OUT_VERDICT;t[77]=0-1 95 return t 96} 97 98// classify a spec's feature vector -> pattern id (0 = NOVEL -> NEEDS_TUTOR, measured not hidden) 99func plc_classify(f: *i64) -> i64 { 100 let t: *i64 = plc_table() 101 let nr: i64 = plc_table_rows() 102 var r: i64 = 0 103 while r < nr { 104 let pa: i64 = t[r*3+1] 105 let pb: i64 = t[r*3+2] 106 var hit: i64 = 0 107 if f[pa] == 1 { hit = 1 } 108 if hit == 1 { if pb >= 0 { if f[pb] != 1 { hit = 0 } } } 109 if hit == 1 { return t[r*3] } 110 r = r + 1 111 } 112 return 0 113} 114 115// the pipeline's new front door: classify, then confirm the library covers it (always true for a 116// table row, by construction -- but the check keeps the contract explicit if rows outpace emitters) 117func plc_match_spec(f: *i64) -> i64 { 118 let p: i64 = plc_classify(f) 119 if p == 0 { return 0 } 120 if pl_covered(p) == 1 { return p } 121 return 0 122} 123 124// fresh all-zero feature vector (callers set traits then classify) 125func plc_new_features() -> *i64 { 126 return sys_mmap(160) as *i64 127} 128 129// the highest pattern id the decision table can route (the sync gate's coverage probe: 130// emitters past this id exist but have no classifier route = census drift) 131func plc_max_covered() -> i64 { 132 let t: *i64 = plc_table() 133 var best: i64 = 0 134 var r: i64 = 0 135 while r < plc_table_rows() { 136 if t[r*3] > best { best = t[r*3] } 137 r = r + 1 138 } 139 return best 140}