code wiki / (root) / nx_tropism.nx

nx_tropism.nx source

↩ module page · 188 lines · 7733 B

1// nx_tropism.nx -- location-policy resolver. 2// 3// Biological analogue: tropism is a directional growth response to a 4// stimulus gradient (phototropism toward light, geotropism toward 5// gravity, chemotropism toward nutrient). Nishi tropism resolves a 6// homeostasis migration signal into a concrete destination by 7// consulting the cell's declared preference list against current 8// conditions. Same .nx pathway runs local/NAS/peer/cloud transparently 9// per [[feedback-pathway-tropism-block-composition-location-agnostic]]. 10// 11// The structural EXCEED-axis vs K8s scheduler / Nomad / Argo: those 12// resolve placement at submission time and re-schedule on failure; 13// nx_tropism resolves PER MIGRATION SIGNAL, mid-pathway, with cell 14// memory intact via the existing nx_chromatin replication. 15// 16// Composes: 17// nx_homeostasis -- supplies the migration signal 18// nx_attention_class -- foreground prefers LOCAL_*; idle accepts CLOUD 19// nx_budget -- destination must have headroom for the cell 20// nx_pathway -- pathway declares per-cell tropism preference 21// 22// V1 ships a sealed enum of 10 location targets + a resolver that 23// picks based on signal + attention class. Cost / bandwidth / latency 24// estimation per peer is queued (requires peer-mesh discovery layer). 25// 26// Gap list (V1 honest perf verdict): 27// - no actual peer discovery (returns symbolic target, not address) 28// - no cost estimation (CHEAPEST returns same as LOCAL_DISK) 29// - no FOLLOW_INPUT/FOLLOW_DEST cross-cell resolution (returns 30// LOCAL_CPU placeholder) 31// - no failed-migration retry policy (caller's responsibility) 32// 33// genealogy_id: nishi_cardinal_2026-05-17_pathway_tropism + biology_directional_growth 34// lineage_id: substrate_tropism_v1 35// 36// nx_safety_envelope: 37// intended_use: "Resolve homeostasis migration signal into a 38// concrete location target per cell preference" 39// sil_target: SIL1 40// evidence: [enum_sealed, deterministic_resolution, 41// attention_class_honored] 42// verdict: NOT_YET_EVALUATED 43 44import "nx_syscalls.nx" 45import "nx_tier.nx" 46import "nx_attention_class.nx" 47import "nx_homeostasis.nx" 48const NX_MAGIC_1024: i64 = 1024 49 50// ===== Sealed enum: NxTropism ===================================== 51// 52// Order is preference rank within a cell's declared list -- LOCAL_* 53// is cheapest+lowest-latency, CLOUD is expensive+highest-latency. 54 55const NX_TROP_LOCAL_CPU: nx_int = 0 56const NX_TROP_LOCAL_GPU: nx_int = 1 57const NX_TROP_LOCAL_GPU_MAX_VRAM: nx_int = 2 58const NX_TROP_LOCAL_DISK: nx_int = 3 59const NX_TROP_NAS: nx_int = 4 60const NX_TROP_PEER: nx_int = 5 61const NX_TROP_CLOUD: nx_int = 6 62const NX_TROP_FOLLOW_INPUT: nx_int = 7 // co-locate with upstream cell 63const NX_TROP_CHEAPEST: nx_int = 8 // pick by cost (V2) 64const NX_TROP_USER_ATTENTION: nx_int = 9 // pick by where user is looking 65const NX_TROP_N_TARGETS: nx_int = 10 66 67// ===== Sealed enum: NxTropismVerdict ============================== 68 69const NX_TROP_OK: nx_int = 0 70const NX_TROP_ERR_BAD_TARGET: nx_int = 1 71const NX_TROP_ERR_NO_HEADROOM: nx_int = 2 // resolved target full 72 73// ===== nx_tropism_is_valid ======================================= 74 75func nx_tropism_is_valid(t: nx_int) -> nx_int { 76 if t < 0 { return 0 } 77 if t >= NX_TROP_N_TARGETS { return 0 } 78 return 1 79} 80 81// ===== nx_tropism_is_local ======================================= 82// 83// Local targets (CPU/GPU/disk) keep cell memory in same address space; 84// migration is cheap. Remote targets (NAS/PEER/CLOUD) require 85// chromatin serialization + transport. 86 87func nx_tropism_is_local(t: nx_int) -> nx_int { 88 if t == NX_TROP_LOCAL_CPU { return 1 } 89 if t == NX_TROP_LOCAL_GPU { return 1 } 90 if t == NX_TROP_LOCAL_GPU_MAX_VRAM { return 1 } 91 if t == NX_TROP_LOCAL_DISK { return 1 } 92 return 0 93} 94 95// ===== nx_tropism_is_remote ====================================== 96 97func nx_tropism_is_remote(t: nx_int) -> nx_int { 98 if t == NX_TROP_NAS { return 1 } 99 if t == NX_TROP_PEER { return 1 } 100 if t == NX_TROP_CLOUD { return 1 } 101 return 0 102} 103 104// ===== nx_tropism_resolve ======================================== 105// 106// Pick the destination for the given migration signal. Foreground 107// classes refuse CLOUD (latency floor unacceptable); background 108// classes accept it. Returns NX_TROP_LOCAL_CPU when signal is STEADY 109// (no migration needed); returns the cell's declared `prefer` when 110// it is locally viable, otherwise next viable option. 111// 112// signal -- one of NX_HOMEO_* from nx_homeostasis 113// current -- the cell's current location (NX_TROP_*) 114// attention_class -- one of NX_AC_* 115// prefer -- cell's declared first-choice tropism 116 117func nx_tropism_resolve(signal: nx_int, 118 current: nx_int, 119 attention_class: nx_int, 120 prefer: nx_int) -> nx_int { 121 if signal == NX_HOMEO_STEADY { return current } 122 if nx_tropism_is_valid(prefer) == 0 { return NX_TROP_LOCAL_CPU } 123 124 // Foreground class refuses CLOUD outright (latency floor). 125 let fg: nx_int = nx_ac_is_foreground(attention_class) 126 if fg == 1 { 127 if prefer == NX_TROP_CLOUD { return NX_TROP_NAS } 128 } 129 130 // Migration signals route by resource pressure type. 131 if signal == NX_HOMEO_MIGRATE_VRAM { 132 // VRAM pressure: prefer the local GPU with most VRAM, then 133 // peer with GPU, then CPU fallback for foreground / CLOUD 134 // for background. Do not return current (would no-op). 135 if current != NX_TROP_LOCAL_GPU_MAX_VRAM { return NX_TROP_LOCAL_GPU_MAX_VRAM } 136 if fg == 1 { return NX_TROP_LOCAL_CPU } 137 return NX_TROP_PEER 138 } 139 if signal == NX_HOMEO_MIGRATE_RAM { 140 // RAM pressure: spill to NAS for background, prefer local CPU 141 // re-balance (zero-copy via shared arena) for foreground. 142 if fg == 1 { return NX_TROP_LOCAL_CPU } 143 return NX_TROP_NAS 144 } 145 if signal == NX_HOMEO_MIGRATE_DISK { 146 // Disk pressure: archive to NAS regardless of class. 147 return NX_TROP_NAS 148 } 149 if signal == NX_HOMEO_MIGRATE_THERMAL { 150 // Thermal pressure: offload compute. Foreground stays local 151 // GPU (less hot than CPU); background goes peer. 152 if fg == 1 { return NX_TROP_LOCAL_GPU } 153 return NX_TROP_PEER 154 } 155 if signal == NX_HOMEO_EVICTION_STORM { 156 // The cell is being displaced repeatedly -- relocate to a 157 // larger venue where headroom is more abundant. 158 if fg == 1 { return NX_TROP_LOCAL_GPU_MAX_VRAM } 159 return NX_TROP_PEER 160 } 161 if signal == NX_HOMEO_PROMOTE_TIER { 162 // Metabolism says this site is hot enough for higher tier. 163 if fg == 1 { return NX_TROP_LOCAL_GPU_MAX_VRAM } 164 return NX_TROP_CLOUD 165 } 166 if signal == NX_HOMEO_DEMOTE_TIER { 167 return NX_TROP_LOCAL_CPU 168 } 169 return current 170} 171 172// ===== nx_tropism_cost_q10 ====================================== 173// 174// Coarse Q10 estimate of migration cost for the given target. 175// LOCAL_CPU = 0 (no migration); LOCAL_GPU = 64 (cache invalidate); 176// LOCAL_DISK = 256 (mmap reload); NAS = 512 (network copy); 177// PEER = 768 (network + handshake); CLOUD = 1024 (TLS + region hop). 178 179func nx_tropism_cost_q10(t: nx_int) -> nx_int { 180 if t == NX_TROP_LOCAL_CPU { return 0 } 181 if t == NX_TROP_LOCAL_GPU { return 64 } 182 if t == NX_TROP_LOCAL_GPU_MAX_VRAM { return 96 } 183 if t == NX_TROP_LOCAL_DISK { return 256 } 184 if t == NX_TROP_NAS { return 512 } 185 if t == NX_TROP_PEER { return 768 } 186 if t == NX_TROP_CLOUD { return NX_MAGIC_1024 } 187 return 0 188}