nx_swarm_place.nx source
↩ module page · 333 lines · 14011 B
1// nx_swarm_place.nx -- SWARM FABRIC placement brain (SF-R2): given the fleet snapshot (NODE rows
2// from nx_swarm_beat) pick the best node for a chunky job. The 2025/26 radar's #1+#2 gaps
3// (energy-aware 98 + load-aware 65) in one organ. GREENFIELD: pure integer cost model over the
4// beacon's live truth; freshness is a HARD gate (you cannot place on stale truth -- inherits the
5// beat store's liveness liar-killers); battery politeness EXCLUDES (never cook a phone/laptop);
6// thermal sheds (heavy penalty, still schedulable in an emergency); unknown (-1) sensors are
7// NEUTRAL (honest-absent must not punish a node that cannot report).
8//
9// nx_swarm_place pick <snap> <window_sec> [conf] rank + pick; prints per-node verdicts + winner
10// nx_swarm_place [gate] self-gate (8 tests incl liar-killers)
11//
12// CONF (rule 11, data-driven -- knowledge/swarm/place.conf ships the live lever; bootstrap
13// defaults compiled as the last tier of the config hierarchy): lines "key value":
14// w_load 600 · w_mem 400 · shed_temp_mc 85000 · batt_floor_pct 20
15// SCORE (0..1000): base = (w_load*load_headroom + w_mem*mem_headroom)/(w_load+w_mem);
16// load_headroom = 1000-lpc clamped; mem_headroom = (100-mem_used_pct)*10 clamped;
17// temp_mc >= shed → base/10. EXCLUDED: stale/forged ts · batt < floor · malformed row.
18// Ties: first-in-snap wins (deterministic). license_tier: ORIGINAL expect_exit:0
19import "nx_syscalls.nx"
20import "nx_framed_append.nx"
21import "nx_swarm_lib.nx"
22const SP_MAGIC_85000: i64 = 85000
23const SP_MAGIC_1024: i64 = 1024
24const SP_MAGIC_3600: i64 = 3600
25const SP_MAGIC_90000: i64 = 90000
26const SP_MAGIC_40000: i64 = 40000
27const SP_MAGIC_7200000000: i64 = 7200000000
28
29const SP_SNAP_CAP: i64 = 65536
30const SP_CONF_CAP: i64 = 4096
31
32func sp_puts(s: *u8) -> i64 { sys_write(1, s, fa_len(s)); return 0 }
33
34func sp_eq(a: *u8, b: *u8) -> i64 {
35 var i: i64 = 0
36 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 }
37 if b[i] != (0 as u8) { return 0 }
38 return 1
39}
40
41// does buf[p..] start with key (nul-terminated)? returns index AFTER key, or -1.
42func sp_starts(buf: *u8, n: i64, p: i64, key: *u8) -> i64 {
43 var k: i64 = 0
44 while key[k] != (0 as u8) {
45 if p + k >= n { return 0 - 1 }
46 if buf[p + k] != key[k] { return 0 - 1 }
47 k = k + 1
48 }
49 return p + k
50}
51
52// conf loader: c[0]=w_load c[1]=w_mem c[2]=shed_temp_mc c[3]=batt_floor_pct.
53// Missing file / missing keys keep the compiled bootstrap defaults (config-hierarchy last tier).
54func sp_conf_load(path: *u8, c: *i64) -> i64 {
55 c[0] = 600
56 c[1] = 400
57 c[2] = SP_MAGIC_85000
58 c[3] = 20
59 if (path as i64) == 0 { return 0 }
60 let buf: *u8 = sys_mmap(SP_CONF_CAP)
61 let n: i64 = sb_read(path, buf, SP_CONF_CAP)
62 if n <= 0 { return 0 }
63 let vout: *i64 = sys_mmap(16) as *i64
64 let pend: *i64 = sys_mmap(16) as *i64
65 var i: i64 = 0
66 while i < n {
67 var e: i64 = i
68 var g: i64 = 1
69 while g == 1 { if e >= n { g = 0 } else { if (buf[e] as i64) == 10 { g = 0 } else { e = e + 1 } } }
70 var at: i64 = sp_starts(buf, e, i, "w_load " as *u8)
71 if at >= 0 { if sb_pint(buf, e, at, vout, pend) == 1 { c[0] = vout[0] } }
72 at = sp_starts(buf, e, i, "w_mem " as *u8)
73 if at >= 0 { if sb_pint(buf, e, at, vout, pend) == 1 { c[1] = vout[0] } }
74 at = sp_starts(buf, e, i, "shed_temp_mc " as *u8)
75 if at >= 0 { if sb_pint(buf, e, at, vout, pend) == 1 { c[2] = vout[0] } }
76 at = sp_starts(buf, e, i, "batt_floor_pct " as *u8)
77 if at >= 0 { if sb_pint(buf, e, at, vout, pend) == 1 { c[3] = vout[0] } }
78 i = e + 1
79 }
80 return 0
81}
82
83// score one parsed row. >=0 score / -1 EXCLUDED (why[0]: 1=stale 2=battery).
84// f = cpu,load,ncpu,lpc,memu,mema,memt,conns,ts,temp,batt (sb_fields layout)
85func sp_score(f: *i64, now: i64, window_sec: i64, c: *i64, why: *i64) -> i64 {
86 why[0] = 0
87 if sb_fresh(f[8], now, window_sec) == 0 { why[0] = 1; return 0 - 1 }
88 let batt: i64 = f[10]
89 if batt >= 0 { if batt < c[3] { why[0] = 2; return 0 - 1 } }
90 var load_head: i64 = 1000 - f[3]
91 if load_head < 0 { load_head = 0 }
92 if load_head > 1000 { load_head = 1000 }
93 var mem_head: i64 = (100 - f[4]) * 10
94 if mem_head < 0 { mem_head = 0 }
95 if mem_head > 1000 { mem_head = 1000 }
96 var denom: i64 = c[0] + c[1]
97 if denom < 1 { denom = 1 }
98 var base: i64 = (c[0] * load_head + c[1] * mem_head) / denom
99 let temp: i64 = f[9]
100 if temp >= 0 { if temp >= c[2] { base = base / 10 } }
101 return base
102}
103
104// pick over a snapshot. Prints per-node verdicts + winner line. Returns 0 winner / 3 none.
105// wname/wcap: out-buffer for the winner name (for the gate); pass 0 to skip.
106func sp_pick(snap: *u8, window_sec: i64, confpath: *u8, wname: *u8, wcap: i64) -> i64 {
107 let c: *i64 = sys_mmap(64) as *i64
108 sp_conf_load(confpath, c)
109 let buf: *u8 = sys_mmap(SP_SNAP_CAP)
110 let n: i64 = sb_read(snap, buf, SP_SNAP_CAP)
111 let now: i64 = sys_now_us()
112 let f: *i64 = sys_mmap(128) as *i64
113 let why: *i64 = sys_mmap(16) as *i64
114 let nso: *i64 = sys_mmap(16) as *i64
115 let nlo: *i64 = sys_mmap(16) as *i64
116 let tso: *i64 = sys_mmap(16) as *i64
117 let t: *u8 = sys_mmap(SP_MAGIC_1024)
118 var best: i64 = 0 - 1
119 var bns: i64 = 0
120 var bnl: i64 = 0
121 var i: i64 = 0
122 while i < n {
123 var e: i64 = i
124 var g: i64 = 1
125 while g == 1 { if e >= n { g = 0 } else { if (buf[e] as i64) == 10 { g = 0 } else { e = e + 1 } } }
126 if e > i {
127 let line: *u8 = (buf as i64 + i) as *u8
128 let ln: i64 = e - i
129 var to: i64 = 0
130 if sb_fields(line, ln, f) == 1 {
131 sb_validate(line, ln, nso, nlo, tso)
132 let sc: i64 = sp_score(f, now, window_sec, c, why)
133 if sc >= 0 {
134 to = fa_cat(t, 0, "CANDIDATE score=" as *u8)
135 to = fa_catn(t, to, sc)
136 } else {
137 if why[0] == 1 { to = fa_cat(t, 0, "EXCLUDED-stale" as *u8) } else { to = fa_cat(t, 0, "EXCLUDED-battery" as *u8) }
138 }
139 to = fa_cat(t, to, " " as *u8)
140 sys_write(1, t, to)
141 sys_write(1, line, ln)
142 sp_puts("\n" as *u8)
143 if sc > best {
144 best = sc
145 bns = i + nso[0]
146 bnl = nlo[0]
147 }
148 } else {
149 to = fa_cat(t, 0, "EXCLUDED-badrow " as *u8)
150 sys_write(1, t, to)
151 sys_write(1, line, ln)
152 sp_puts("\n" as *u8)
153 }
154 }
155 i = e + 1
156 }
157 if best < 0 {
158 sp_puts("SWARMPLACE NO-PLACEMENT (no fresh eligible node)\n" as *u8)
159 return 3
160 }
161 var to2: i64 = 0
162 to2 = fa_cat(t, to2, "SWARMPLACE winner=" as *u8)
163 var k: i64 = 0
164 while k < bnl { t[to2] = buf[bns + k]; to2 = to2 + 1; k = k + 1 }
165 to2 = fa_cat(t, to2, " score=" as *u8)
166 to2 = fa_catn(t, to2, best)
167 to2 = fa_cat(t, to2, "\n" as *u8)
168 sys_write(1, t, to2)
169 if (wname as i64) != 0 {
170 var k2: i64 = 0
171 while k2 < bnl { if k2 < wcap - 1 { wname[k2] = buf[bns + k2] } k2 = k2 + 1 }
172 var wl: i64 = bnl
173 if wl > wcap - 1 { wl = wcap - 1 }
174 wname[wl] = 0 as u8
175 }
176 return 0
177}
178
179// gate helpers ------------------------------------------------------------
180func sp_mkrow(dst: *u8, name: *u8, lpc: i64, memu: i64, ts: i64, temp: i64, batt: i64) -> i64 {
181 var o: i64 = 0
182 o = fa_cat(dst, o, "NODE " as *u8)
183 o = fa_cat(dst, o, name)
184 o = fa_cat(dst, o, " 50 " as *u8)
185 o = fa_catn(dst, o, lpc)
186 o = fa_cat(dst, o, " 1 " as *u8)
187 o = fa_catn(dst, o, lpc)
188 o = fa_cat(dst, o, " " as *u8)
189 o = fa_catn(dst, o, memu)
190 o = fa_cat(dst, o, " 1000 2000 0 " as *u8)
191 o = fa_catn(dst, o, ts)
192 o = fa_cat(dst, o, " " as *u8)
193 o = fa_catn(dst, o, temp)
194 o = fa_cat(dst, o, " " as *u8)
195 o = fa_catn(dst, o, batt)
196 o = fa_cat(dst, o, "\n" as *u8)
197 return o
198}
199
200func sp_wfile(path: *u8, buf: *u8, n: i64) -> i64 {
201 let fd: i64 = sys_openat_wr(path, 0x1a4)
202 if fd < 0 { return 0 - 1 }
203 let wr: i64 = fa_write_all(fd, buf, n)
204 sys_close(fd)
205 if wr != n { return 0 - 1 }
206 return 0
207}
208
209func sp_gate() -> i64 {
210 var pass: i64 = 0
211 var total: i64 = 0
212 let now: i64 = sys_now_us()
213 let snap: *u8 = sys_mmap(256)
214 var so: i64 = 0
215 so = fa_cat(snap, so, "/tmp/swp_gate_" as *u8)
216 so = fa_catn(snap, so, now)
217 so = fa_cat(snap, so, ".snap" as *u8)
218 snap[so] = 0 as u8
219 let conf: *u8 = sys_mmap(256)
220 var co: i64 = 0
221 co = fa_cat(conf, co, "/tmp/swp_gate_" as *u8)
222 co = fa_catn(conf, co, now)
223 co = fa_cat(conf, co, ".conf" as *u8)
224 conf[co] = 0 as u8
225 let body: *u8 = sys_mmap(SP_SNAP_CAP)
226 let w: *u8 = sys_mmap(64)
227
228 // T1 idle beats loaded (both fresh, sensors unknown)
229 total = total + 1
230 var o: i64 = 0
231 o = o + sp_mkrow((body as i64 + o) as *u8, "loaded" as *u8, 900, 50, now, 0 - 1, 0 - 1)
232 o = o + sp_mkrow((body as i64 + o) as *u8, "idle" as *u8, 100, 50, now, 0 - 1, 0 - 1)
233 sp_wfile(snap, body, o)
234 var r: i64 = sp_pick(snap, SP_MAGIC_3600, 0 as *u8, w, 64)
235 if r == 0 { if sp_eq(w, "idle" as *u8) == 1 { pass = pass + 1; sp_puts("T1 idle-beats-loaded OK\n" as *u8) } }
236
237 // T2 LIAR-KILLER thermal shed: hot-idle loses to cool-busier
238 total = total + 1
239 o = 0
240 o = o + sp_mkrow((body as i64 + o) as *u8, "hot" as *u8, 100, 50, now, SP_MAGIC_90000, 0 - 1)
241 o = o + sp_mkrow((body as i64 + o) as *u8, "cool" as *u8, 400, 50, now, SP_MAGIC_40000, 0 - 1)
242 sp_wfile(snap, body, o)
243 r = sp_pick(snap, SP_MAGIC_3600, 0 as *u8, w, 64)
244 if r == 0 { if sp_eq(w, "cool" as *u8) == 1 { pass = pass + 1; sp_puts("T2 thermal-shed OK\n" as *u8) } }
245
246 // T3 LIAR-KILLER battery floor: low-battery node EXCLUDED even if otherwise best
247 total = total + 1
248 o = 0
249 o = o + sp_mkrow((body as i64 + o) as *u8, "lowbatt" as *u8, 100, 10, now, 0 - 1, 10)
250 o = o + sp_mkrow((body as i64 + o) as *u8, "plugged" as *u8, 800, 90, now, 0 - 1, 95)
251 sp_wfile(snap, body, o)
252 r = sp_pick(snap, SP_MAGIC_3600, 0 as *u8, w, 64)
253 if r == 0 { if sp_eq(w, "plugged" as *u8) == 1 { pass = pass + 1; sp_puts("T3 battery-floor-excludes OK\n" as *u8) } }
254
255 // T4 LIAR-KILLER stale never placed: ancient perfect node loses to fresh busy one
256 total = total + 1
257 o = 0
258 o = o + sp_mkrow((body as i64 + o) as *u8, "ancient" as *u8, 0, 0, now - SP_MAGIC_7200000000, 0 - 1, 0 - 1)
259 o = o + sp_mkrow((body as i64 + o) as *u8, "alive" as *u8, 800, 80, now, 0 - 1, 0 - 1)
260 sp_wfile(snap, body, o)
261 r = sp_pick(snap, SP_MAGIC_3600, 0 as *u8, w, 64)
262 if r == 0 { if sp_eq(w, "alive" as *u8) == 1 { pass = pass + 1; sp_puts("T4 stale-never-placed OK\n" as *u8) } }
263
264 // T5 honest-absent neutral: unknown sensors still placeable
265 total = total + 1
266 o = 0
267 o = o + sp_mkrow((body as i64 + o) as *u8, "solo" as *u8, 500, 50, now, 0 - 1, 0 - 1)
268 sp_wfile(snap, body, o)
269 r = sp_pick(snap, SP_MAGIC_3600, 0 as *u8, w, 64)
270 if r == 0 { if sp_eq(w, "solo" as *u8) == 1 { pass = pass + 1; sp_puts("T5 honest-absent-neutral OK\n" as *u8) } }
271
272 // T6 conf-driven flip (data-driven weights, rule 11): same snap, two confs, two winners
273 total = total + 1
274 o = 0
275 o = o + sp_mkrow((body as i64 + o) as *u8, "cpuish" as *u8, 200, 80, now, 0 - 1, 0 - 1)
276 o = o + sp_mkrow((body as i64 + o) as *u8, "memish" as *u8, 400, 20, now, 0 - 1, 0 - 1)
277 sp_wfile(snap, body, o)
278 var cb: i64 = 0
279 cb = fa_cat(body, cb, "w_load 1000\nw_mem 0\n" as *u8)
280 sp_wfile(conf, body, cb)
281 r = sp_pick(snap, SP_MAGIC_3600, conf, w, 64)
282 var flip1: i64 = 0
283 if r == 0 { if sp_eq(w, "cpuish" as *u8) == 1 { flip1 = 1 } }
284 cb = 0
285 cb = fa_cat(body, cb, "w_load 0\nw_mem 1000\n" as *u8)
286 sp_wfile(conf, body, cb)
287 r = sp_pick(snap, SP_MAGIC_3600, conf, w, 64)
288 if flip1 == 1 { if r == 0 { if sp_eq(w, "memish" as *u8) == 1 { pass = pass + 1; sp_puts("T6 conf-weight-flip OK\n" as *u8) } } }
289
290 // T7 determinism: same inputs twice -> same winner
291 total = total + 1
292 r = sp_pick(snap, SP_MAGIC_3600, conf, w, 64)
293 var w1ok: i64 = 0
294 if r == 0 { if sp_eq(w, "memish" as *u8) == 1 { w1ok = 1 } }
295 r = sp_pick(snap, SP_MAGIC_3600, conf, w, 64)
296 if w1ok == 1 { if r == 0 { if sp_eq(w, "memish" as *u8) == 1 { pass = pass + 1; sp_puts("T7 deterministic OK\n" as *u8) } } }
297
298 // T8 NEG: empty snap -> NO-PLACEMENT (never fabricate a winner)
299 total = total + 1
300 sp_wfile(snap, body, 0)
301 r = sp_pick(snap, SP_MAGIC_3600, 0 as *u8, w, 64)
302 if r == 3 { pass = pass + 1; sp_puts("T8 empty-no-placement OK\n" as *u8) }
303
304 let t: *u8 = sys_mmap(128)
305 var to: i64 = 0
306 to = fa_cat(t, to, "SWARMPLACEGATE " as *u8)
307 to = fa_catn(t, to, pass)
308 to = fa_cat(t, to, "/" as *u8)
309 to = fa_catn(t, to, total)
310 if pass == total { to = fa_cat(t, to, " verdict=GREEN\n" as *u8) } else { to = fa_cat(t, to, " verdict=RED\n" as *u8) }
311 sys_write(1, t, to)
312 if pass == total { return 0 }
313 return 1
314}
315
316func main(argc: i64, argv: *i64) -> i64 {
317 if argc >= 2 {
318 let verb: *u8 = argv[1] as *u8
319 if sp_eq(verb, "pick" as *u8) == 1 {
320 if argc < 4 { sp_puts("usage: nx_swarm_place pick <snap> <window_sec> [conf]\n" as *u8); return 2 }
321 let snap: *u8 = argv[2] as *u8
322 if sb_path_ok(snap) == 0 { sp_puts("SWARMPLACE pick REFUSED (path law)\n" as *u8); return 3 }
323 let vout: *i64 = sys_mmap(16) as *i64
324 let pend: *i64 = sys_mmap(16) as *i64
325 let ws: *u8 = argv[3] as *u8
326 if sb_pint(ws, fa_len(ws), 0, vout, pend) == 0 { return 2 }
327 var conf: *u8 = 0 as *u8
328 if argc >= 5 { conf = argv[4] as *u8 }
329 return sp_pick(snap, vout[0], conf, 0 as *u8, 0)
330 }
331 }
332 return sp_gate()
333}