code wiki / (root) / nx_intent_survival.nx

nx_intent_survival.nx source

↩ module page · 243 lines · 9479 B

1// nx_intent_survival.nx -- did the director's intent survive the render? 2// 3// Closes the loop between the DirectorsNote (what was requested) and 4// the rendered image (what came out). Per cardinal feedback-graduated- 5// intervention-no-chainsaw: emits a TIERED verdict (GOOD/DRIFT/BROKEN), 6// never binary pass/fail. 7// 8// === Division of responsibility ===================================== 9// 10// This substrate primitive does TWO things: 11// 12// (a) Defines the typed schema for per-element survival verdicts. 13// Each of the 7 director-named elements (outfit, location, pose, 14// affect, perspective, shot_size, camera_motivation) gets a 15// sealed-enum survival verdict. 16// 17// (b) Aggregates per-element verdicts into a single PreflightTier 18// per the graduated-intervention cardinal: 19// all SURVIVED -> GOOD 20// any MISSING -> BROKEN 21// any PARTIAL (no missing)-> DRIFT 22// 23// What this primitive does NOT do: compute the per-element verdict. 24// That's downstream work (CLIP probe, color histogram, learned classifier, 25// human label, etc.) — its output is fed in as a *i64 array of verdicts. 26// 27// The substrate-typed envelope is the canonical interchange; whoever 28// produces the per-element check (Python now, NishiLang vision primitive 29// when nx_vision_check ships, human reviewer in a labelled batch) all 30// feed the same schema. 31// 32// === Composition ==================================================== 33// 34// nx_directors_note.nx -- DirectorsNote (the requested intent; 35// PreflightTier sealed enum) 36// nx_tier.nx -- nx_int alias 37// 38// genealogy_id: clip_2021 + checklist_alignment_eval + 39// in_toto_2019_provenance + faithful_explanation_inseq_2022 40// lineage_id: nx_intent_survival_v1 41 42// nx_safety_envelope: 43// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 44// sil_target: SIL1 45// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 46// verdict: NOT_YET_EVALUATED 47 48import "nx_syscalls.nx" 49import "nx_tier.nx" 50import "nx_directors_note.nx" 51 52// ===== Sealed-enum: per-element survival ============================ 53// 54// What happened to a specific requested element (outfit / location / 55// pose / affect / etc.) in the rendered image. 56 57const NX_IS_SURVIVED: nx_int = 0 // clearly present, recognisable 58const NX_IS_PARTIAL: nx_int = 1 // present but drifted (different color, soft proportion shift) 59const NX_IS_MISSING: nx_int = 2 // not present at all in the render 60const NX_IS_UNMEASURED: nx_int = 3 // no probe ran (caller didn't fill this slot) 61const NX_IS_N_VERDICTS: nx_int = 4 62 63func nx_is_verdict_is_valid(v: nx_int) -> nx_int { 64 if v < 0 { return 0 } 65 if v >= NX_IS_N_VERDICTS { return 0 } 66 return 1 67} 68 69// ===== Sealed-enum: element kind (slot in the verdicts buffer) ===== 70// 71// The fixed-size flat-array layout of per-element verdicts. Indexing 72// is positional; caller writes verdicts[NX_IS_ELEM_OUTFIT] = SURVIVED, 73// etc. 74 75const NX_IS_ELEM_OUTFIT: nx_int = 0 76const NX_IS_ELEM_LOCATION: nx_int = 1 77const NX_IS_ELEM_POSE: nx_int = 2 78const NX_IS_ELEM_AFFECT: nx_int = 3 79const NX_IS_ELEM_PERSPECTIVE: nx_int = 4 80const NX_IS_ELEM_SHOT_SIZE: nx_int = 5 81const NX_IS_ELEM_CAMERA_MOTIVATION: nx_int = 6 82const NX_IS_ELEM_BODY_ARCHETYPE: nx_int = 7 83const NX_IS_N_ELEMS: nx_int = 8 84 85func nx_is_elem_is_valid(e: nx_int) -> nx_int { 86 if e < 0 { return 0 } 87 if e >= NX_IS_N_ELEMS { return 0 } 88 return 1 89} 90 91// ===== SurvivalReport struct ======================================== 92// 93// The typed envelope per intent-survival pass. 94 95struct SurvivalReport { 96 moment_seq: nx_int, // which moment this report covers 97 arc_id: nx_int, 98 n_elems: nx_int, // = NX_IS_N_ELEMS for full coverage 99 verdicts: *i64, // [n_elems] of NX_IS_* sealed values 100 n_survived: nx_int, // count of NX_IS_SURVIVED 101 n_partial: nx_int, // count of NX_IS_PARTIAL 102 n_missing: nx_int, // count of NX_IS_MISSING 103 n_unmeasured: nx_int, // count of NX_IS_UNMEASURED 104 coverage_q10: nx_int, // = (n_survived * 1024) / n_elems 105 preflight_tier: nx_int // aggregated tier per graduated-intervention 106} 107 108const NX_IS_REPORT_BYTES: nx_int = 80 // 10 fields * 8 bytes/nx_int 109 110// ===== Builder ====================================================== 111// 112// Allocate a SurvivalReport with a fresh verdicts buffer initialised 113// to UNMEASURED across all element slots. Caller fills via _set. 114 115func nx_is_alloc(arc_id: nx_int, moment_seq: nx_int) -> *SurvivalReport { 116 let r: *SurvivalReport = (sys_mmap(NX_IS_REPORT_BYTES)) as *SurvivalReport 117 r.arc_id = arc_id 118 r.moment_seq = moment_seq 119 r.n_elems = NX_IS_N_ELEMS 120 r.verdicts = (sys_mmap(NX_IS_N_ELEMS * NX_SIZEOF_NX_INT)) as *i64 121 var i: nx_int = 0 122 while i < NX_IS_N_ELEMS { 123 r.verdicts[i] = NX_IS_UNMEASURED 124 i = i + 1 125 } 126 r.n_survived = 0 127 r.n_partial = 0 128 r.n_missing = 0 129 r.n_unmeasured = NX_IS_N_ELEMS 130 r.coverage_q10 = 0 131 r.preflight_tier = NX_PFT_DRIFT // UNMEASURED defaults to DRIFT 132 return r 133} 134 135// ===== Per-element setter =========================================== 136// 137// Caller (CLIP probe / color check / human reviewer) writes the 138// verdict for one element. Returns -1 if elem or verdict invalid. 139 140func nx_is_set_verdict(r: *SurvivalReport, elem: nx_int, verdict: nx_int) -> nx_int { 141 if nx_is_elem_is_valid(elem) == 0 { return 0 - 1 } 142 if nx_is_verdict_is_valid(verdict) == 0 { return 0 - 1 } 143 r.verdicts[elem] = verdict 144 return 0 145} 146 147// ===== Per-element getter =========================================== 148 149func nx_is_get_verdict(r: *SurvivalReport, elem: nx_int) -> nx_int { 150 if nx_is_elem_is_valid(elem) == 0 { return NX_IS_UNMEASURED } 151 return r.verdicts[elem] 152} 153 154// ===== Aggregator: counts + coverage + tier ========================= 155// 156// Walks the verdicts buffer, computes counts + coverage + PreflightTier 157// per graduated-intervention. Must be called after all per-element 158// verdicts have been set; idempotent — safe to re-call after updates. 159// 160// Tier logic (per the cardinal): 161// any MISSING -> BROKEN (regen with corrective phrasing) 162// any PARTIAL (no missing) -> DRIFT (ship + log trend, NO regen) 163// any UNMEASURED (rest ok) -> DRIFT (cautious ship until probe lands) 164// all SURVIVED -> GOOD (ship + exemplar archive) 165 166func nx_is_aggregate(r: *SurvivalReport) -> nx_int { 167 var ns: nx_int = 0 168 var np: nx_int = 0 169 var nm: nx_int = 0 170 var nu: nx_int = 0 171 var i: nx_int = 0 172 while i < r.n_elems { 173 let v: nx_int = r.verdicts[i] 174 if v == NX_IS_SURVIVED { ns = ns + 1 } 175 if v == NX_IS_PARTIAL { np = np + 1 } 176 if v == NX_IS_MISSING { nm = nm + 1 } 177 if v == NX_IS_UNMEASURED { nu = nu + 1 } 178 i = i + 1 179 } 180 r.n_survived = ns 181 r.n_partial = np 182 r.n_missing = nm 183 r.n_unmeasured = nu 184 185 // coverage_q10 = (n_survived * 1024) / n_elems 186 if r.n_elems > 0 { 187 r.coverage_q10 = (ns * 1024) / r.n_elems 188 } else { 189 r.coverage_q10 = 0 190 } 191 192 // Tier routing 193 var tier: nx_int = NX_PFT_GOOD 194 if nm > 0 { 195 tier = NX_PFT_BROKEN 196 } else { 197 if np > 0 { tier = NX_PFT_DRIFT } 198 if nu > 0 { tier = NX_PFT_DRIFT } // unmeasured = cautious ship 199 } 200 r.preflight_tier = tier 201 return tier 202} 203 204// ===== Underspec mapping =========================================== 205// 206// When the SurvivalReport indicates a BROKEN tier, name the FIRST 207// missing element so the auto-fix pipeline knows what to correct. 208// Returns one of nx_directors_note's NX_DN_UNDERSPEC_* codes. 209 210func nx_is_first_missing_underspec(r: *SurvivalReport) -> nx_int { 211 var i: nx_int = 0 212 while i < r.n_elems { 213 if r.verdicts[i] == NX_IS_MISSING { 214 if i == NX_IS_ELEM_OUTFIT { return NX_DN_UNDERSPEC_OUTFIT } 215 if i == NX_IS_ELEM_LOCATION { return NX_DN_UNDERSPEC_LOCATION } 216 if i == NX_IS_ELEM_POSE { return NX_DN_UNDERSPEC_POSE } 217 if i == NX_IS_ELEM_AFFECT { return NX_DN_UNDERSPEC_AFFECT } 218 if i == NX_IS_ELEM_PERSPECTIVE { return NX_DN_UNDERSPEC_CAMERA } 219 if i == NX_IS_ELEM_SHOT_SIZE { return NX_DN_UNDERSPEC_CAMERA } 220 if i == NX_IS_ELEM_CAMERA_MOTIVATION { return NX_DN_UNDERSPEC_CAMERA } 221 if i == NX_IS_ELEM_BODY_ARCHETYPE { return NX_DN_UNDERSPEC_BODY_ARCHETYPE } 222 return NX_DN_UNDERSPEC_NONE 223 } 224 i = i + 1 225 } 226 return NX_DN_UNDERSPEC_NONE 227} 228 229// ===== Apply to DirectorsNote ====================================== 230// 231// After aggregation, push the result back onto the DirectorsNote so 232// downstream services (auto-fix, exemplar memory, trend log) read 233// the tier directly from the envelope they already carry. 234 235func nx_is_apply_to_dn(r: *SurvivalReport, dn: *DirectorsNote) -> nx_int { 236 dn.preflight_tier = r.preflight_tier 237 if r.preflight_tier == NX_PFT_BROKEN { 238 dn.underspec_code = nx_is_first_missing_underspec(r) 239 } else { 240 dn.underspec_code = NX_DN_UNDERSPEC_NONE 241 } 242 return 0 243}