code wiki / (root) / nx_compost.nx

nx_compost.nx source

↩ module page · 238 lines · 8752 B

1// nx_compost.nx -- graceful retirement + nutrient harvest from retired primitives. 2// 3// Biology: when an organism dies, its constituent atoms are decomposed by 4// fungi+bacteria and returned to the soil pool, where they're available 5// for re-uptake by living plants. Forests recycle ~90% of their nutrients 6// through this loop. Without compost, ecosystems collapse from depletion. 7// 8// In Nishi: extends [[nx_prune]] (which only REMOVES dead/orphan code) by 9// adding nutrient-harvest -- when a primitive retires, identify its 10// reusable parts (constants, types, helper functions, schemas) and route 11// them back to the substrate pool for adoption by living primitives. This 12// is the difference between "delete file" (current prune) and "compost" 13// (extract value before disposing). 14// 15// Composes [[feedback-forest-meta-vision-drift-lifecycle]] + 16// [[feedback-thymus-sovereignty-audit-soma-germline]] (composted nutrients 17// retain soma/germline class) + [[feedback-regenerative-stewardship- 18// doctrine-captain-moroni]] (recycling is regeneration not extraction) + 19// Cardinal 13 (history is sacred -- compost record is permanent additive 20// log, not destructive delete). 21 22import "nx_syscalls.nx" 23import "nx_tier.nx" 24 25// ===== Sealed enum: NxNutrientKind ================================ 26// 27// What kinds of value can be harvested from a retiring primitive. 28 29const NX_CP_NUT_CONST_DEFINITION: nx_int = 0 // sealed enum / const block 30const NX_CP_NUT_TYPE_DEFINITION: nx_int = 1 // struct / type alias 31const NX_CP_NUT_HELPER_FUNCTION: nx_int = 2 // pure utility function 32const NX_CP_NUT_SCHEMA: nx_int = 3 // serialization layout 33const NX_CP_NUT_TEST_SCAFFOLD: nx_int = 4 // assertion patterns / fixtures 34const NX_CP_NUT_DOCUMENTATION: nx_int = 5 // header comment / spec 35const NX_CP_NUT_BENCHMARK: nx_int = 6 // perf harness 36const NX_CP_NUT_N: nx_int = 7 37 38// ===== Sealed enum: NxCompostStage ================================ 39 40const NX_CP_STAGE_FRESH: nx_int = 0 // just retired 41const NX_CP_STAGE_DECOMPOSING: nx_int = 1 // nutrients being extracted 42const NX_CP_STAGE_HARVESTED: nx_int = 2 // nutrients reabsorbed 43const NX_CP_STAGE_REFUSED: nx_int = 3 // unsafe to recycle (soma) 44const NX_CP_STAGE_N: nx_int = 4 45 46// ===== Sealed enum: NxCompostVerdict ============================== 47 48const NX_CP_V_OK: nx_int = 0 49const NX_CP_V_REFUSED_GERMLINE: nx_int = 1 // germline never composts 50const NX_CP_V_REFUSED_ACTIVE: nx_int = 2 // not yet retired 51const NX_CP_V_REFUSED_CLIMAX: nx_int = 3 // climax-stage never composts 52const NX_CP_V_INVALID: nx_int = 4 53const NX_CP_V_NULL: nx_int = 5 54const NX_CP_V_N: nx_int = 6 55 56// ===== Struct: NxNutrient ========================================= 57 58struct NxNutrient { 59 kind: nx_int, 60 source_primitive_id: nx_int, 61 content_hash: nx_size, 62 extracted_at_us: nx_size, 63 reused_by: nx_int, // 0 if unclaimed, else primitive_id 64} 65 66const NX_CP_N_BYTES: nx_int = 40 67 68struct NxCompostPile { 69 primitive_id: nx_int, // the retiring primitive 70 stage: nx_int, 71 nutrients: *u8, 72 n_nutrients: nx_int, 73 capacity: nx_int, 74 is_germline: nx_int, // refused if 1 75 is_climax: nx_int, // refused if 1 76 retired_at_us: nx_size, 77} 78 79const NX_CP_BYTES: nx_int = 56 80 81// ===== Validators ================================================= 82 83func nx_cp_nut_is_valid(k: nx_int) -> nx_int { 84 if k < 0 { return 0 } 85 if k >= NX_CP_NUT_N { return 0 } 86 return 1 87} 88 89func nx_cp_stage_is_valid(s: nx_int) -> nx_int { 90 if s < 0 { return 0 } 91 if s >= NX_CP_STAGE_N { return 0 } 92 return 1 93} 94 95func nx_cp_v_is_valid(v: nx_int) -> nx_int { 96 if v < 0 { return 0 } 97 if v >= NX_CP_V_N { return 0 } 98 return 1 99} 100 101// ===== Construction (begins compost cycle) ======================== 102 103func nx_cp_new(primitive_id: nx_int, 104 capacity: nx_int, 105 is_germline: nx_int, 106 is_climax: nx_int, 107 now_us: nx_size) -> *NxCompostPile { 108 if capacity <= 0 { return 0 as *NxCompostPile } 109 if primitive_id == 0 { return 0 as *NxCompostPile } 110 let raw: *u8 = sys_mmap(NX_CP_BYTES) 111 let p: *NxCompostPile = raw as *NxCompostPile 112 p.primitive_id = primitive_id 113 p.nutrients = sys_mmap(capacity * NX_CP_N_BYTES) 114 p.n_nutrients = 0 115 p.capacity = capacity 116 p.is_germline = is_germline 117 p.is_climax = is_climax 118 p.retired_at_us = now_us 119 // If germline or climax, refuse to compost (stage REFUSED) 120 if is_germline == 1 { p.stage = NX_CP_STAGE_REFUSED } 121 if p.stage != NX_CP_STAGE_REFUSED { 122 if is_climax == 1 { p.stage = NX_CP_STAGE_REFUSED } 123 } 124 if p.stage != NX_CP_STAGE_REFUSED { p.stage = NX_CP_STAGE_FRESH } 125 return p 126} 127 128func _cp_nutrient_at(p: *NxCompostPile, idx: nx_int) -> *NxNutrient { 129 if idx < 0 { return 0 as *NxNutrient } 130 if idx >= p.n_nutrients { return 0 as *NxNutrient } 131 let off: nx_int = idx * NX_CP_N_BYTES 132 return (p.nutrients + off) as *NxNutrient 133} 134 135// ===== Begin decomposition ======================================== 136 137func nx_cp_begin_decompose(p: *NxCompostPile) -> nx_int { 138 if (p as i64) == 0 { return NX_CP_V_NULL } 139 if p.is_germline == 1 { return NX_CP_V_REFUSED_GERMLINE } 140 if p.is_climax == 1 { return NX_CP_V_REFUSED_CLIMAX } 141 if p.stage != NX_CP_STAGE_FRESH { return NX_CP_V_INVALID } 142 p.stage = NX_CP_STAGE_DECOMPOSING 143 return NX_CP_V_OK 144} 145 146// ===== Extract nutrient =========================================== 147 148func nx_cp_extract_nutrient(p: *NxCompostPile, 149 kind: nx_int, 150 content_hash: nx_size, 151 now_us: nx_size) -> nx_int { 152 if (p as i64) == 0 { return NX_CP_V_NULL } 153 if nx_cp_nut_is_valid(kind) == 0 { return NX_CP_V_INVALID } 154 if p.is_germline == 1 { return NX_CP_V_REFUSED_GERMLINE } 155 if p.is_climax == 1 { return NX_CP_V_REFUSED_CLIMAX } 156 if p.stage != NX_CP_STAGE_DECOMPOSING { return NX_CP_V_INVALID } 157 if p.n_nutrients >= p.capacity { return NX_CP_V_INVALID } 158 let off: nx_int = p.n_nutrients * NX_CP_N_BYTES 159 let n: *NxNutrient = (p.nutrients + off) as *NxNutrient 160 n.kind = kind 161 n.source_primitive_id = p.primitive_id 162 n.content_hash = content_hash 163 n.extracted_at_us = now_us 164 n.reused_by = 0 165 p.n_nutrients = p.n_nutrients + 1 166 return NX_CP_V_OK 167} 168 169// ===== Reabsorb (mark nutrient claimed by living primitive) ======= 170 171func nx_cp_reabsorb(p: *NxCompostPile, 172 content_hash: nx_size, 173 reusing_primitive_id: nx_int) -> nx_int { 174 if (p as i64) == 0 { return NX_CP_V_NULL } 175 if reusing_primitive_id == 0 { return NX_CP_V_INVALID } 176 var i: nx_int = 0 177 while i < p.n_nutrients { 178 let n: *NxNutrient = _cp_nutrient_at(p, i) 179 if n.content_hash == content_hash { 180 n.reused_by = reusing_primitive_id 181 return NX_CP_V_OK 182 } 183 i = i + 1 184 } 185 return NX_CP_V_INVALID 186} 187 188// ===== Mark harvested ============================================= 189 190func nx_cp_mark_harvested(p: *NxCompostPile) -> nx_int { 191 if (p as i64) == 0 { return NX_CP_V_NULL } 192 if p.stage != NX_CP_STAGE_DECOMPOSING { return NX_CP_V_INVALID } 193 p.stage = NX_CP_STAGE_HARVESTED 194 return NX_CP_V_OK 195} 196 197// ===== Aggregations =============================================== 198 199func nx_cp_count_by_kind(p: *NxCompostPile, kind: nx_int) -> nx_int { 200 if (p as i64) == 0 { return 0 } 201 var count: nx_int = 0 202 var i: nx_int = 0 203 while i < p.n_nutrients { 204 let n: *NxNutrient = _cp_nutrient_at(p, i) 205 if n.kind == kind { count = count + 1 } 206 i = i + 1 207 } 208 return count 209} 210 211func nx_cp_reused_count(p: *NxCompostPile) -> nx_int { 212 if (p as i64) == 0 { return 0 } 213 var count: nx_int = 0 214 var i: nx_int = 0 215 while i < p.n_nutrients { 216 let n: *NxNutrient = _cp_nutrient_at(p, i) 217 if n.reused_by != 0 { count = count + 1 } 218 i = i + 1 219 } 220 return count 221} 222 223func nx_cp_unclaimed_count(p: *NxCompostPile) -> nx_int { 224 if (p as i64) == 0 { return 0 } 225 var count: nx_int = 0 226 var i: nx_int = 0 227 while i < p.n_nutrients { 228 let n: *NxNutrient = _cp_nutrient_at(p, i) 229 if n.reused_by == 0 { count = count + 1 } 230 i = i + 1 231 } 232 return count 233} 234 235func nx_cp_stage(p: *NxCompostPile) -> nx_int { 236 if (p as i64) == 0 { return NX_CP_V_NULL } 237 return p.stage 238}