nx_stepsolve_lib.nx
buildroot/runtime/nx_stepsolve_lib.nx
about
nx_stepsolve_lib.nx -- ES26 (engineshift al_steps): THE ONE RULER for STEPS-TO-SOLVE PER COMMON TASK.
The operator's 2026-09-06 order: if a task can be solved in ONE step within logic it should be, and when it cannot
the estate explains why two, why three, and so on, from the most common tasks to the least, mining and evaluating
this efficacy continuously. The MEASURED side is the action journal's recurring tool:verb n-grams (nx_actlog's
indexed miner, exact support, adjacent only): a recurring bigram is a 2-step ritual, a trigram a 3-step one, and
its support is how common it is. The DECLARED side is knowledge/stepsolve.conf, DATA rows
steps|<signature>|<min_steps>|<reason>|<one_step_verb>
verbclass|<verb>|<reason>
where signature = tool:verb>tool:verb[>tool:verb] exactly as the journal spells it, min_steps is the LOGICAL
minimum, reason is why it cannot be fewer (a true dependency: a promote must see the sha only a finished build
produces) and one_step_verb names the composed verb on the CANONICAL organ that does it in one call
(nx_organ_ship for the build-stage-judge-promote ritual). A verbclass row is a RULE: every signature whose EVERY
step carries that verb is explained by the rule's reason -- the clock plane and the job lane write <elf>:run for
each organ fork, and a fork is one whole organ run and therefore one step by construction, so two adjacent
scheduled forks are two tasks and not a ritual. A steps row for a specific signature WINS over a rule, so a fork
ritual that does have a composed verb stays declarable. This lib joins the two and classifies every recurring
signature:
ONE-STEP-AVAILABLE min_steps 1 and a composed verb is named: the ritual is an ADOPTION gap, its support should fall
DEPENDENCY min_steps equals the observed steps: the count is explained, the reason travels with it
REDUCIBLE 1 < min_steps < observed: fewer steps are possible by declared logic
BY-RULE no steps row, every step's verb matches a verbclass row: explained by that rule's reason
UNDECLARED no row and no rule: NEVER assumed one-step; it is the worklist, most common first
The published figure is a PARTITION over signature support (sums to the total, printed); per-rule support is
tallied beside it so a rule can never hide what it absorbed; the gauge stamp is the EXPLAINED permil (declared
classes over all), written in the CE9 heartbeat shape so gauge_pass renders it and a stale one reads STALE never
zero. A row that cannot be parsed is counted as malformed, never dropped in silence.
license_tier: ORIGINAL No hw writes.
dependencies 3 imports · 1 importers
imports: nx_sovjson_lib.nxnx_syscalls.nxnx_gauge_lib.nx
imported by: nx_actlog.nx
structs
| none |
consts
| 33 | const SS_CONF_PROD: *u8 = "knowledge/stepsolve.conf" |
| 34 | const SS_SPINE_PROD: *u8 = "knowledge/status/stepsolve.spine" |
| 35 | const SS_STAMP_PROD: *u8 = "knowledge/status/stepsolve.stamp" |
| 36 | const SS_SPINE_SIDECAR: *u8 = ".stepsolve.spine" |
| 37 | const SS_STAMP_SIDECAR: *u8 = ".stepsolve.stamp" |
| 38 | const SS_QSTAMP_PROD: *u8 = "knowledge/status/stepsolve_quality.stamp" // ES27: the QUALITY gauge (1000 - failure permil) beside EXPLAINED |
| 39 | const SS_QSTAMP_SIDECAR: *u8 = ".stepsolve.quality.stamp" |
| 40 | const SS_CADENCE_S: i64 = 86400 // the daily beat that writes the stamp; max_age derives from it in the gauge lib |
| 41 | const SS_AXES: i64 = 2 // the journal and the conf: an unreadable conf is an abstaining axis |
| 42 | const SS_WORD: i64 = 8 |
| 43 | const SS_LINE: i64 = 512 |
| 44 | const SS_PATH: i64 = 1024 |
| 45 | const SS_MODE644: i64 = 420 |
| 46 | const SS_NL: i64 = 10 |
| 47 | const SS_PIPE: i64 = 124 |
| 48 | const SS_HASH: i64 = 35 |
| 49 | const SS_GT: i64 = 62 |
| 50 | const SS_COLON: i64 = 58 |
| 51 | const SS_PERMIL: i64 = 1000 |
| 52 | const SS_ROW_FIELDS: i64 = 5 |
| 53 | const SS_RULE_FIELDS: i64 = 3 |
| 55 | const SS_C_UNDECLARED: i64 = 0 |
| 56 | const SS_C_ONE_STEP: i64 = 1 |
| 57 | const SS_C_DEPENDENCY: i64 = 2 |
| 58 | const SS_C_REDUCIBLE: i64 = 3 |
| 59 | const SS_C_RULE: i64 = 4 |
| 60 | const SS_C_N: i64 = 5 |
| 62 | const SS_K_STEPS: i64 = 1 |
| 63 | const SS_K_RULE: i64 = 2 |
| 65 | const SS_R_SIG: i64 = 0 |
| 66 | const SS_R_SIGLEN: i64 = 1 |
| 67 | const SS_R_MIN: i64 = 2 |
| 68 | const SS_R_REASON: i64 = 3 |
| 69 | const SS_R_VERB: i64 = 4 |
| 70 | const SS_R_HASVERB: i64 = 5 |
| 71 | const SS_R_SLOTS: i64 = 8 |
| 73 | const SS_U_VERB: i64 = 0 |
| 74 | const SS_U_VERBLEN: i64 = 1 |
| 75 | const SS_U_REASON: i64 = 2 |
| 76 | const SS_U_SUP: i64 = 3 |
| 77 | const SS_U_CNT: i64 = 4 |
| 78 | const SS_U_SLOTS: i64 = 8 |
| 80 | const SS_T_SUP: i64 = 0 |
| 81 | const SS_T_CNT: i64 = 5 |
| 82 | const SS_T_TOTAL_SUP: i64 = 10 |
| 83 | const SS_T_TOTAL_CNT: i64 = 11 |
| 84 | const SS_T_CONF_ROWS: i64 = 12 |
| 85 | const SS_T_CONF_MALFORMED: i64 = 13 |
| 86 | const SS_T_CONF_READ: i64 = 14 |
| 87 | const SS_T_CONF_RULES: i64 = 15 |
| 88 | const SS_T_FAIL: i64 = 16 // per class FAILURE support [16..20]: frames of the ritual whose outcome was not ok (ES27) |
| 89 | const SS_T_TOTAL_FAIL: i64 = 21 |
| 90 | const SS_T_SLOTS: i64 = 22 |
functions
| 92 | func ss_capacity(q: *u8, n: i64) -> i64 called by 1: al_steps |
| 98 | func ss_vlen(s: *u8) -> i64 { return sj_vlen(s) } calls 1: sj_vlen |
| 105 | func ss_conf_load(q: *u8, n: i64, tab: *i64, rt: *i64, t: *i64) -> i64 |
| 165 | func ss_conf_find(q: *u8, tab: *i64, rows: i64, sig: *u8, siglen: i64) -> i64 called by 1: al_steps |
| 181 | func ss_rule_find(q: *u8, rt: *i64, rules: i64, sig: *u8, siglen: i64) -> i64 called by 1: al_steps |
| 213 | func ss_classify(row: i64, min_steps: i64, has_verb: i64, steps: i64) -> i64 called by 1: ss_class_of |
| 221 | func ss_class_of(row: i64, min_steps: i64, has_verb: i64, steps: i64, rule: i64) -> i64 |
| 226 | func ss_rule_add(rt: *i64, rule: i64, support: i64) -> i64 called by 1: al_steps |
| 232 | func ss_class_name(c: i64) -> *u8 |
| 239 | func ss_totals_zero(t: *i64) -> i64 { var z: i64 = 0; while z < SS_T_SLOTS { t[z] = 0; z = z + 1 } return 0 } called by 1: al_steps |
| 240 | func ss_totals_add(t: *i64, c: i64, support: i64, fail: i64) -> i64 called by 1: al_steps |
| 249 | func ss_permil(part: i64, whole: i64) -> i64 { if whole <= 0 { return 0 - 1 } return part * SS_PERMIL / whole } |
| 252 | func ss_explained_permil(t: *i64) -> i64 |
| 259 | func ss_fail_permil(support: i64, fail: i64) -> i64 { return ss_permil(fail, support) } |
| 260 | func ss_quality_permil(t: *i64) -> i64 { let fp: i64 = ss_permil(t[SS_T_TOTAL_FAIL], t[SS_T_TOTAL_SUP]); if fp < 0 { return 0 - 1 } return SS_PERMIL - fp } |
| 261 | func ss_risk(support: i64, fail: i64) -> i64 { let fp: i64 = ss_fail_permil(support, fail); if fp < 0 { return 0 } return support * fp } |
| 263 | func ss_emit_totals(d: *u8, p0: i64, t: *i64) -> i64 called by 1: al_steps calls 7: sj_catss_class_namesj_catnss_permilss_fail_permilss_explained_permil+1 |
| 296 | func ss_is_prod(journal: *u8) -> i64 |
| 299 | func ss_side_path(journal: *u8, sfx: *u8, out: *u8) -> i64 { let o: i64 = sj_cat(out, 0, journal); return sj_cat(out, o, sfx) } |
| 301 | func ss_publish_json(d: *u8, p0: i64, journal: *u8, now: i64, t: *i64) -> i64 |