code wiki / (root) / nx_organism.nx

nx_organism.nx source

↩ module page · 344 lines · 12699 B

1// nx_organism.nx -- ecosystem-wide pathway + symbiote container. 2// 3// Biological analogue: an organism is the multi-pathway entity that 4// coordinates many pathways across many tissues with shared homeostasis. 5// In Nishi terms: an organism holds N nx_pathways (Nishi-native cells) 6// AND N nx_symbiotes (foreign processes integrated into the ecosystem 7// like Steam-hosted NMS, Chrome, OBS) and arbitrates resources across 8// the WHOLE union. 9// 10// THIS IS THE ECOSYSTEM-WIDE OPTIMIZATION SUBSTRATE. Per user 2026-05- 11// 19: "i want it work across the whole nishi ecosystem and then across 12// the whole nishi ecosystem + (nishi native and non native things that 13// are integrated)." Single host machine running Nishi cells + Steam + 14// NMS + dev tools simultaneously: organism is the layer that decides 15// which gets displaced when the host's VRAM crosses 90%. 16// 17// Composes: 18// nx_pathway -- each contributes its own cells + budgets 19// nx_symbiote -- foreign-process virtual cells with observed 20// (not promised) resource consumption 21// nx_budget -- organism has its OWN host-aggregate budget 22// (the physical hardware ceiling) 23// nx_evict_journal -- organism-level events log here 24// nx_attention_class -- per-cell + per-symbiote class drives priority 25// nx_treaty -- bilateral agreements between organism members 26// 27// V1 ships a flat container with built-in arbitration. The hypothalamus 28// (master regulator) function is folded in as nx_organism_pick_dis- 29// placement; if it grows, a separate nx_hypothalamus primitive is 30// extracted. 31// 32// Gap list (V1 honest perf verdict): 33// - no actual host-resource probe (host_budget supplied by caller) 34// - no peer-mesh federation (one organism per host) 35// - flat membership (no nested organism-of-organisms) 36// - no fairness scheduling within same attention class 37// 38// genealogy_id: nishi_cardinal_2026-05-19_ecosystem_wide + biology_multi_pathway_organism 39// lineage_id: substrate_organism_v1 40// 41// nx_safety_envelope: 42// intended_use: "Ecosystem-wide arbitration across Nishi 43// pathways and integrated foreign processes" 44// sil_target: SIL2 45// asil_target: QM 46// evidence: [bounded_capacity, deterministic_pick, 47// host_budget_honored_above_pathway_budgets] 48// verdict: NOT_YET_EVALUATED 49 50import "nx_syscalls.nx" 51import "nx_tier.nx" 52import "nx_budget.nx" 53import "nx_attention_class.nx" 54import "nx_evict_journal.nx" 55import "nx_pathway.nx" 56import "nx_symbiote.nx" 57const NX_MAGIC_1024: i64 = 1024 58 59// ===== Sealed enum: NxOrganismVerdict ============================= 60 61const NX_ORG_OK: nx_int = 0 62const NX_ORG_ERR_FULL: nx_int = 1 63const NX_ORG_ERR_NOT_FOUND: nx_int = 2 64const NX_ORG_ERR_BAD_MEMBER: nx_int = 3 65 66// ===== Sealed enum: NxDisplacementVerdict ========================= 67// 68// Outcome from nx_organism_pick_displacement. Picked member's cell_id 69// is written into displaced_cell_id pointer; member kind tells caller 70// whether to call nx_yield_request (native) or nx_symbiote_throttle 71// (foreign) for the actual enforcement. 72 73const NX_DISP_NONE: nx_int = 0 // no displacement needed 74const NX_DISP_NATIVE_CELL: nx_int = 1 75const NX_DISP_SYMBIOTE: nx_int = 2 76 77// ===== Struct: NxOrganism ========================================= 78// 79// host_budget is the physical hardware ceiling (e.g., total host RAM, 80// total VRAM). aggregate budgets across pathways + symbiotes must not 81// exceed this; if they do, organism fires displacement. 82// 83// pathways and symbiotes are arrays of pointers, not value arrays -- 84// the lifetimes of pathway/symbiote structs live with their owners. 85 86struct NxOrganism { 87 host_budget: *NxBudget, 88 pathways: **NxPathway, 89 pathway_capacity: nx_size, 90 n_pathways: nx_size, 91 symbiotes: **NxSymbiote, 92 symbiote_capacity: nx_size, 93 n_symbiotes: nx_size, 94 journal: *NxEvictJournal, 95} 96 97// ===== Constructor =============================================== 98 99func nx_organism_new(host_budget: *NxBudget, 100 pathway_capacity: nx_size, 101 symbiote_capacity: nx_size, 102 journal: *NxEvictJournal) -> *NxOrganism { 103 let o: *NxOrganism = (sys_mmap(72)) as *NxOrganism 104 o.host_budget = host_budget 105 let pw_bytes: nx_size = pathway_capacity * 8 106 let sb_bytes: nx_size = symbiote_capacity * 8 107 o.pathways = (sys_mmap(pw_bytes)) as **NxPathway 108 o.pathway_capacity = pathway_capacity 109 o.n_pathways = 0 110 o.symbiotes = (sys_mmap(sb_bytes)) as **NxSymbiote 111 o.symbiote_capacity = symbiote_capacity 112 o.n_symbiotes = 0 113 o.journal = journal 114 return o 115} 116 117// ===== _organism_pathway_at / _organism_symbiote_at ============== 118 119func _organism_pathway_at(o: *NxOrganism, idx: nx_size) -> *NxPathway { 120 let slot: *i64 = (o.pathways as i64 + (idx as i64) * 8) as *i64 121 return slot[0] as *NxPathway 122} 123 124func _organism_symbiote_at(o: *NxOrganism, idx: nx_size) -> *NxSymbiote { 125 let slot: *i64 = (o.symbiotes as i64 + (idx as i64) * 8) as *i64 126 return slot[0] as *NxSymbiote 127} 128 129func _organism_pathway_set(o: *NxOrganism, idx: nx_size, p: *NxPathway) -> nx_int { 130 let slot: *i64 = (o.pathways as i64 + (idx as i64) * 8) as *i64 131 slot[0] = p as i64 132 return 0 133} 134 135func _organism_symbiote_set(o: *NxOrganism, idx: nx_size, s: *NxSymbiote) -> nx_int { 136 let slot: *i64 = (o.symbiotes as i64 + (idx as i64) * 8) as *i64 137 slot[0] = s as i64 138 return 0 139} 140 141// ===== nx_organism_add_pathway =================================== 142 143func nx_organism_add_pathway(o: *NxOrganism, p: *NxPathway) -> nx_int { 144 if (p as i64) == 0 { return NX_ORG_ERR_BAD_MEMBER } 145 if o.n_pathways >= o.pathway_capacity { return NX_ORG_ERR_FULL } 146 _organism_pathway_set(o, o.n_pathways, p) 147 o.n_pathways = o.n_pathways + 1 148 return NX_ORG_OK 149} 150 151// ===== nx_organism_add_symbiote ================================== 152 153func nx_organism_add_symbiote(o: *NxOrganism, s: *NxSymbiote) -> nx_int { 154 if (s as i64) == 0 { return NX_ORG_ERR_BAD_MEMBER } 155 if o.n_symbiotes >= o.symbiote_capacity { return NX_ORG_ERR_FULL } 156 _organism_symbiote_set(o, o.n_symbiotes, s) 157 o.n_symbiotes = o.n_symbiotes + 1 158 return NX_ORG_OK 159} 160 161// ===== nx_organism_total_ram_max ================================= 162// 163// Sum of declared RAM ceilings across all pathways + symbiotes. The 164// caller compares this against host_budget.ram_max to know whether 165// the ecosystem is over-committing the physical machine. 166 167func nx_organism_total_ram_max(o: *NxOrganism) -> nx_size { 168 var total: nx_size = 0 169 var i: nx_size = 0 170 while i < o.n_pathways { 171 total = total + nx_pathway_aggregate_ram_max(_organism_pathway_at(o, i)) 172 i = i + 1 173 } 174 var j: nx_size = 0 175 while j < o.n_symbiotes { 176 let s: *NxSymbiote = _organism_symbiote_at(o, j) 177 if (s.virtual_budget as i64) != 0 { 178 total = total + s.virtual_budget.ram_max 179 } 180 j = j + 1 181 } 182 return total 183} 184 185// ===== nx_organism_total_vram_max ================================ 186 187func nx_organism_total_vram_max(o: *NxOrganism) -> nx_size { 188 var total: nx_size = 0 189 var i: nx_size = 0 190 while i < o.n_pathways { 191 total = total + nx_pathway_aggregate_vram_max(_organism_pathway_at(o, i)) 192 i = i + 1 193 } 194 var j: nx_size = 0 195 while j < o.n_symbiotes { 196 let s: *NxSymbiote = _organism_symbiote_at(o, j) 197 if (s.virtual_budget as i64) != 0 { 198 total = total + s.virtual_budget.vram_max 199 } 200 j = j + 1 201 } 202 return total 203} 204 205// ===== nx_organism_total_observed_ram ============================ 206// 207// Same shape as _max but uses ACTUAL observed consumption from 208// symbiotes (since we don't trust their declared maxes -- foreign 209// processes may overshoot). For native pathways, used == ram_used 210// from each cell's budget (an aggregate would need walking each 211// cell; V1 uses ram_max as conservative upper bound for natives). 212 213func nx_organism_total_observed_ram(o: *NxOrganism) -> nx_size { 214 var total: nx_size = 0 215 var i: nx_size = 0 216 while i < o.n_pathways { 217 total = total + nx_pathway_aggregate_ram_max(_organism_pathway_at(o, i)) 218 i = i + 1 219 } 220 var j: nx_size = 0 221 while j < o.n_symbiotes { 222 let s: *NxSymbiote = _organism_symbiote_at(o, j) 223 total = total + s.observed_ram_bytes 224 j = j + 1 225 } 226 return total 227} 228 229// ===== nx_organism_host_pressure_q10 ============================= 230// 231// Q10 ratio of (total observed consumption) / (host budget ceiling) 232// for the requested resource kind. >= 921 (90%) is migration trigger. 233 234func nx_organism_host_pressure_q10(o: *NxOrganism, kind: nx_int) -> nx_int { 235 if (o.host_budget as i64) == 0 { return 0 } 236 var max: nx_size = 0 237 var used: nx_size = 0 238 if kind == NX_RES_RAM { 239 max = o.host_budget.ram_max 240 used = nx_organism_total_observed_ram(o) 241 } 242 if kind == NX_RES_VRAM { 243 max = o.host_budget.vram_max 244 var i: nx_size = 0 245 while i < o.n_pathways { 246 used = used + nx_pathway_aggregate_vram_max(_organism_pathway_at(o, i)) 247 i = i + 1 248 } 249 var j: nx_size = 0 250 while j < o.n_symbiotes { 251 let s: *NxSymbiote = _organism_symbiote_at(o, j) 252 used = used + s.observed_vram_bytes 253 j = j + 1 254 } 255 } 256 if max <= 0 { return 0 } 257 return ((used as i64) * NX_MAGIC_1024) / (max as i64) 258} 259 260// ===== nx_organism_pick_displacement ============================= 261// 262// The arbitration decision. Walks all members; picks the LOWEST- 263// priority member (highest numeric attention_class value) as the 264// displacement target. On tie, foreign symbiotes go before native 265// cells (symbiotes are observed-only; cells get the benefit of 266// cooperative yield first). 267// 268// Returns NX_DISP_NONE if no member needs displacing (host pressure 269// is below threshold). Otherwise writes the picked member's cell_id 270// (or symbiote pid) into out_id and returns NX_DISP_NATIVE_CELL or 271// NX_DISP_SYMBIOTE. 272 273func nx_organism_pick_displacement(o: *NxOrganism, 274 kind: nx_int, 275 out_id: *i64) -> nx_int { 276 let pressure: nx_int = nx_organism_host_pressure_q10(o, kind) 277 if pressure < 921 { return NX_DISP_NONE } 278 279 var worst_priority: nx_int = -1 280 var winner_id: nx_int = 0 281 var winner_kind: nx_int = NX_DISP_NONE 282 283 // Walk pathways' cells -- pick the highest-numeric attention_class 284 // (== lowest priority) cell as the candidate for native displace- 285 // ment. Tie -> first encountered. 286 var i: nx_size = 0 287 while i < o.n_pathways { 288 let p: *NxPathway = _organism_pathway_at(o, i) 289 var ci: nx_size = 0 290 while ci < p.n_cells { 291 let c: *NxCellSpec = (p.cells as i64 + (ci as i64) * 64) as *NxCellSpec 292 let prio: nx_int = nx_ac_priority(c.attention_class) 293 if prio > worst_priority { 294 worst_priority = prio 295 winner_id = c.cell_id 296 winner_kind = NX_DISP_NATIVE_CELL 297 } 298 ci = ci + 1 299 } 300 i = i + 1 301 } 302 303 // Walk symbiotes -- compare same priority axis. Foreign tie-break 304 // goes to symbiote (foreign processes lack the cooperative yield 305 // contract; preferable to displace observed-only first). 306 var j: nx_size = 0 307 while j < o.n_symbiotes { 308 let s: *NxSymbiote = _organism_symbiote_at(o, j) 309 let prio_s: nx_int = nx_ac_priority(s.attention_class) 310 if prio_s >= worst_priority { 311 worst_priority = prio_s 312 winner_id = s.pid 313 winner_kind = NX_DISP_SYMBIOTE 314 } 315 j = j + 1 316 } 317 318 out_id[0] = winner_id as i64 319 return winner_kind 320} 321 322// ===== nx_organism_count_members ================================= 323 324func nx_organism_count_members(o: *NxOrganism) -> nx_size { 325 return o.n_pathways + o.n_symbiotes 326} 327 328// ===== nx_organism_total_observed_vram =========================== 329 330func nx_organism_total_observed_vram(o: *NxOrganism) -> nx_size { 331 var total: nx_size = 0 332 var i: nx_size = 0 333 while i < o.n_pathways { 334 total = total + nx_pathway_aggregate_vram_max(_organism_pathway_at(o, i)) 335 i = i + 1 336 } 337 var j: nx_size = 0 338 while j < o.n_symbiotes { 339 let s: *NxSymbiote = _organism_symbiote_at(o, j) 340 total = total + s.observed_vram_bytes 341 j = j + 1 342 } 343 return total 344}