nx_daemon_supervisor_gate.nx source
↩ module page · 103 lines · 6285 B
1// nx_daemon_supervisor_gate.nx -- the fleet supervisor's PURE helpers (nx_dsup_lib), driven in-process:
2// the bounded-life conf parser, the /proc/<pid>/stat parser behind the status child's PARENT PROBE, and the
3// progress trailer the supervisor publishes after every row.
4//
5// WHY (2026-09-02): the conf parser that lived inside nx_daemon_supervisor spun forever on the NAS conf (a cursor
6// sentinel `k = 99` read past its 12-byte key literal), so every supervisor generation sat at state=R wchan=0
7// before its first probe -- the fleet went unsupervised for a day and the only symptom was a /status page that
8// never moved. A laptop control never spun because the laptop has no conf. T2 below is that conf's SHAPE (over
9// 1 KB of comment lines, one of which mentions the key, then the row): a parser that spins there never returns
10// and the gate reads RED by its deadline; a parser that takes the comment's mention reads 0 and fails T2b.
11// license_tier: ORIGINAL No hw writes (Rule 26).
12import "nx_syscalls.nx"
13import "nx_dsup_lib.nx"
14import "nx_gate_verdict.nx"
15
16const GF_FIX_CAP: i64 = 4096
17const GF_NAS_COMMENT_LINES: i64 = 24 // enough copies of a ~90 B comment to pass 1 KB, the live conf's shape
18const GF_HASH: i64 = 35 // the comment byte; the lexer forbids it inside string literals
19
20func gf_line(buf: *u8, w: i64, s: *u8) -> i64 { var o: i64 = ds_sappend(buf, w, s); buf[o] = 10 as u8; return o + 1 }
21func gf_hline(buf: *u8, w: i64, s: *u8) -> i64 { buf[w] = GF_HASH as u8; return gf_line(buf, w + 1, s) }
22// 1 when needle occurs anywhere in hay[0..n)
23func gf_has(hay: *u8, n: i64, needle: *u8) -> i64 {
24 var i: i64 = 0
25 while i < n { if ds_key_at(hay, n, i, needle) == 1 { return 1 } i = i + 1 }
26 return 0
27}
28
29func main() -> i64 {
30 let ctr: *i64 = gv_ctr()
31 gv_head("nx_daemon_supervisor_gate -- conf parse, /proc stat parse and progress trailer: PURE helpers of the fleet supervisor, driven directly" as *u8)
32 let f: *u8 = sys_mmap(GF_FIX_CAP)
33 let key: *u8 = "life_cycles=" as *u8
34
35 // T1 the row alone
36 var w: i64 = gf_line(f, 0, "life_cycles=5760" as *u8)
37 gv_check("T1-key-at-line-start-parses-its-value" as *u8, ds_conf_int(f, w, key) == 5760, ctr)
38
39 // T2 the NAS-shaped conf: many comment lines, one mentioning the key, then the row
40 w = 0
41 var li: i64 = 0
42 while li < GF_NAS_COMMENT_LINES { w = gf_hline(f, w, " daemon_supervisor.conf -- BOUNDED LIFE for the fleet supervisor; the value is DERIVED, not picked" as *u8); li = li + 1 }
43 w = gf_hline(f, w, " 0 or an absent key (life_cycles=0 in this comment) = never recycle" as *u8)
44 w = gf_line(f, w, "life_cycles=5760" as *u8)
45 let nas_len: i64 = w
46 gv_check("T2-fixture-reached-the-condition-over-1KB-of-comments-before-the-row" as *u8, nas_len > 1024, ctr)
47 gv_check("T2-NAS-shaped-conf-terminates-and-parses-5760" as *u8, ds_conf_int(f, nas_len, key) == 5760, ctr)
48
49 // T2b a mention inside a comment BEFORE the row must not shadow the row
50 w = 0
51 w = gf_hline(f, w, " set life_cycles=0 to disarm" as *u8)
52 w = gf_line(f, w, "life_cycles=42" as *u8)
53 gv_check("T2b-a-comment-mention-before-the-row-does-not-shadow-it" as *u8, ds_conf_int(f, w, key) == 42, ctr)
54
55 // T3 absent key
56 w = gf_line(f, 0, "other=1" as *u8)
57 gv_check("T3-absent-key-reads-0" as *u8, ds_conf_int(f, w, key) == 0, ctr)
58
59 // T4 trailing words after the value
60 w = gf_line(f, 0, "life_cycles=12 trailing words" as *u8)
61 gv_check("T4-value-stops-at-the-first-non-digit" as *u8, ds_conf_int(f, w, key) == 12, ctr)
62
63 // neg-control-T5 the key not at a line start is not the row
64 w = gf_line(f, 0, "xlife_cycles=7" as *u8)
65 gv_check("neg-control-T5-key-mid-line-is-not-a-row" as *u8, ds_conf_int(f, w, key) == 0, ctr)
66
67 // T6 /proc/<pid>/stat: ppid is field 4, comm may hold spaces and a paren
68 w = ds_sappend(f, 0, "1234 (dsup.elf) S 987 1234 1234 0 -1 4194560 12 0 0 0" as *u8)
69 gv_check("T6-stat-ppid-is-field-4" as *u8, ds_stat_ppid(f, w) == 987, ctr)
70 let s6: i64 = ds_stat_state_at(f, w)
71 gv_check("T6-stat-state-char-follows-the-comm" as *u8, (f[s6] as i64) == 83, ctr)
72 w = ds_sappend(f, 0, "77 (a b) c) R 5 77 77 0 -1" as *u8)
73 gv_check("T6b-comm-with-spaces-and-a-paren-still-yields-ppid" as *u8, ds_stat_ppid(f, w) == 5, ctr)
74 let s6b: i64 = ds_stat_state_at(f, w)
75 gv_check("T6b-state-is-read-after-the-LAST-paren" as *u8, (f[s6b] as i64) == 82, ctr)
76
77 // neg-control-T7 garbage is -1, never a pid
78 w = ds_sappend(f, 0, "no parens here 42" as *u8)
79 gv_check("neg-control-T7-unparseable-stat-is-minus-one" as *u8, ds_stat_ppid(f, w) == (0 - 1), ctr)
80
81 // T8 the trailer is bounded and self-delimiting even at the widest name and numbers
82 let tb: *u8 = sys_mmap(512)
83 let nm: *u8 = sys_mmap(80)
84 var ni: i64 = 0
85 while ni < 63 { nm[ni] = 110 as u8; ni = ni + 1 }
86 nm[63] = 0 as u8
87 let tw: i64 = ds_trailer(tb, 999999999999, 64, nm, 123456789012, 123456789012, 123456789012, 1, 0)
88 gv_check("T8-trailer-stays-under-DSL_TRAILER_MAX-at-the-widest-inputs" as *u8, tw < DSL_TRAILER_MAX, ctr)
89 gv_check("T8-trailer-leads-with-a-newline-then-tick=" as *u8, (tb[0] as i64) == 10, ctr)
90 gv_check("T8-trailer-names-tick-first" as *u8, ds_key_at(tb, tw, 1, "tick=999999999999 row=64 last=nnn" as *u8) == 1, ctr)
91 gv_check("T8-trailer-ends-with-a-newline" as *u8, (tb[tw - 1] as i64) == 10, ctr)
92 gv_check("neg-control-T8-a-partial-trailer-carries-no-cycle_ms" as *u8, gf_has(tb, tw, "cycle_ms=" as *u8) == 0, ctr)
93
94 // T9 the cycle-end trailer carries cycle_ms
95 let tw2: i64 = ds_trailer(tb, 5, 3, "-" as *u8, 0, 0, 0, 0, 4321)
96 gv_check("T9-cycle-end-trailer-carries-cycle_ms" as *u8, gf_has(tb, tw2, " partial=0 cycle_ms=4321" as *u8) == 1, ctr)
97
98 // T10 negative stage costs (a clock step) print as 0, never as a sign the parser would choke on
99 let tw3: i64 = ds_trailer(tb, 1, 0, "stage:regread" as *u8, 0 - 5, 0 - 5, 0 - 5, 1, 0)
100 gv_check("T10-negative-stage-costs-clamp-to-0" as *u8, gf_has(tb, tw3, "ms_sweep=0 ms_probe=0 ms_after=0 partial=1" as *u8) == 1, ctr)
101
102 return gv_verdict("nx_daemon_supervisor_gate" as *u8, ctr, "the supervisor's conf, /proc and trailer helpers are pure and gate-driven" as *u8)
103}