nx_tier_ladder_lib.nx source
↩ module page · 783 lines · 42140 B
1// nx_tier_ladder_lib.nx -- THE RENDER-DOOR LADDER RULER (LIB, no main). gpu GP3 rk_tier_ladder / gameengine GE45.
2//
3// THE DEFECT THIS EXISTS TO MAKE REFUSABLE. Every world page chose its renderer by a chain of ifs buried in
4// emitted JS (WebGPU only under ?gpu=1, WebGL2 by default, the sovereign rasteriser on ?gl=0 or on refusal),
5// announced the winner as a free-text badge, and said NOTHING about why the higher doors were not taken. A
6// headless capture of nishifamily.com/world/beach?gpu=1 on 2026-09-02 read `kernel unrun` on the WebGL2 tier
7// with no word about WebGPU: levered off? adapter absent? device limits? a wedged requestAdapter? Four causes,
8// one silence -- and the operator's question "which door drew this frame and why" had no mechanical answer.
9//
10// ONE TABLE, TWO SURFACES (the nx_glprobe_lib law). The ladder is DATA in knowledge/tier_ladder.conf: one
11// door| row per renderer with its order, its state (default / levered / fallback), the URL lever that asks for
12// it, the capability it requires and the badge it announces, plus limit| rows naming the GPUSupportedLimits
13// minima the GE43 kernel needs. This lib parses those rows, walks them natively (tl_pick, tl_reason) and EMITS
14// the same rows plus the JS that walks them in the page (tl_js). nx_tier_ladder_gate pins the native walk with
15// a truth table and pins the emitted JS to the same ids and the same reason vocabulary, so the page and the
16// ruler cannot disagree. The ORDER lives in the conf and nowhere in code: flipping WebGPU to the default
17// (gameengine GE1) is an edit to that file under the operator's order, never a code change.
18//
19// REFUSE, NEVER GUESS. A conf whose fallback is not the last row, whose orders regress, whose door carries a
20// double quote or a backslash (it is emitted into a JS string literal verbatim) or whose limit is not a positive
21// integer is REFUSED with a numbered verdict and the offending line, and tl_emit then emits a NAMED absence
22// (window.__nx_ladder=null plus window.__nx_ladder_absent) and announces it on stderr, so a page built from a
23// broken conf says so on its HUD instead of drawing an unexplained frame.
24//
25// WHAT THE DOOR DRAWS IS DATA TOO (S0, 2026-09-04). Each door row carries a draws word -- world / world+cast /
26// world+markers -- parsed here (tl_door_draws), carried into window.__nx_ladder, read back for the active
27// door by nxDoorDraws() and appended to the tier badge by the page emitter, so a gate, the HUD, page-verify
28// and the referee can STATE that a WebGPU frame carries no character instead of inferring it from prose (the
29// fact lived only in the webgpu row's announce field and the token cast occurred 0 times in this lib). An
30// unknown draws word REFUSES (TL_E_DRAWS) and a door row without the field REFUSES BY NAME (TL_E_DRAWS_ABSENT)
31// -- never a default to the permissive value: pr_mode silently defaulting an unrecognised route mode to the
32// open value is the measured defect this must not repeat, and a row written before the field existed must be
33// re-declared by a reader of the emitter, not guessed at by the parser.
34//
35// PLAIN-IF ONLY (no else) and NO BITWISE OPERATORS -- the imported-else parser landmine, debt 1784673261;
36// per-door lever flags travel as an i64 array, never as bits.
37// license_tier: ORIGINAL No hw writes (Rule 26).
38import "nx_syscalls.nx"
39
40const TL_CONF: *u8 = "../knowledge/tier_ladder.conf"
41
42// TABLE LAYOUT (i64 cells). Header, then TL_MAXD door records of TL_DW cells, then TL_MAXL limit records
43// of TL_LW cells. Strings are OFFSETS into the parsed buffer (tbl[TL_H_BUF]), NUL-terminated in place.
44const TL_TBL_CELLS: i64 = 112
45const TL_TBL_BYTES: i64 = 896
46const TL_MAXD: i64 = 8
47const TL_MAXL: i64 = 8
48const TL_H_ND: i64 = 0
49const TL_H_NL: i64 = 1
50const TL_H_ERR: i64 = 2
51const TL_H_BUF: i64 = 3
52const TL_H_N: i64 = 4
53const TL_H_LINE: i64 = 5
54const TL_DOOR0: i64 = 8
55const TL_DW: i64 = 8
56const TL_D_ID: i64 = 0
57const TL_D_ORDER: i64 = 1
58const TL_D_STATE: i64 = 2
59const TL_D_LEVER: i64 = 3
60const TL_D_REQ: i64 = 4
61const TL_D_ANN: i64 = 5
62const TL_D_DRAWS: i64 = 6 // S0: cell 6 of the TL_DW=8 door record (cells 0..5 were in use; 7 stays spare)
63const TL_LIM0: i64 = 72
64const TL_LW: i64 = 4
65const TL_L_KEY: i64 = 0
66const TL_L_MIN: i64 = 1
67const TL_L_WHY: i64 = 2
68// the WebGPU door's boot ceiling as data (boot| rows, all three REQUIRED): the race budget, the URL lever a probe
69// may raise it with, and the clamp no lever can exceed. A headless capture under a virtual-time budget finished
70// after the old 4000 ms constant and was refused as failed:finished-after-boot-ceiling (measured 2026-09-02), so
71// the ceiling had to become a row a probe can lift and a visitor can never be held past.
72const TL_H_NB: i64 = 6
73const TL_BOOT0: i64 = 104
74const TL_B_MS: i64 = 0
75const TL_B_LEVER: i64 = 1
76const TL_B_MAX: i64 = 2
77const TL_BOOT_KEYS: i64 = 3
78const TL_K_BOOT: *u8 = "boot"
79const TL_BK_MS: *u8 = "gpu_boot_ms"
80const TL_BK_LEVER: *u8 = "gpu_boot_lever"
81const TL_BK_MAX: *u8 = "gpu_boot_max_ms"
82const TL_BOOT_FIELDS: i64 = 4
83// THE THREAD LADDER (gameengine GE30). The render doors above answer "which renderer draws the
84// frame"; this answers "across how many cores", which is the SECOND scaling axis the estate's
85// standing order names -- and like the first it is DATA with a floor and a ceiling, chosen at run
86// time from MEASURED capability (navigator.hardwareConcurrency / nproc), never from a device class
87// or a number typed into a page. The floor is the scale-down door: one worker IS the single-thread
88// twin, so a visitor with no isolation, no SharedArrayBuffer or one core still gets a frame.
89// DELIBERATELY OPTIONAL, unlike boot|: the parser must keep accepting a conf written before this
90// existed, so a lib and a conf can land independently. Absent rows emit a NAMED absence
91// (window.__nx_threads=null + __nx_threads_absent) and the page holds at one worker and says so --
92// nx_tier_ladder_gate is what refuses a LIVE conf that has quietly lost them.
93const TL_H_NT: i64 = 7
94const TL_THREAD0: i64 = 108
95const TL_T_FLOOR: i64 = 0
96const TL_T_CEIL: i64 = 1
97const TL_T_LEVER: i64 = 2
98const TL_THREAD_KEYS: i64 = 3
99const TL_K_THREAD: *u8 = "thread"
100const TL_TK_FLOOR: *u8 = "thread_floor"
101const TL_TK_CEIL: *u8 = "thread_ceiling"
102const TL_TK_LEVER: *u8 = "thread_lever"
103const TL_THREAD_FIELDS: i64 = 4
104const TL_BOOT_DEFAULT_MS: i64 = 4000 // only the ABSENT twin carries it: the page still boots when the conf is gone
105
106// door states and requirements: the NAMES are the conf vocabulary AND the emitted JS vocabulary
107const TL_ST_DEFAULT: i64 = 0
108const TL_ST_LEVERED: i64 = 1
109const TL_ST_FALLBACK: i64 = 2
110const TL_S_DEFAULT: *u8 = "default"
111const TL_S_LEVERED: *u8 = "levered"
112const TL_S_FALLBACK: *u8 = "fallback"
113const TL_RQ_WEBGPU: i64 = 0
114const TL_RQ_WEBGL2: i64 = 1
115const TL_RQ_ALWAYS: i64 = 2
116const TL_Q_WEBGPU: *u8 = "webgpu"
117const TL_Q_WEBGL2: *u8 = "webgl2"
118const TL_Q_ALWAYS: *u8 = "always"
119const TL_K_DOOR: *u8 = "door"
120const TL_K_LIMIT: *u8 = "limit"
121// DRAWS VOCABULARY (S0) -- what a door puts on the frame; the NAMES are the conf vocabulary AND the emitted JS
122// vocabulary (window.__nx_ladder[i].draws, nxDoorDraws()). world = the voxel world and NO character of any
123// kind; world+cast = the world AND the engine's RESIDENT cast as skinned figures (wc_mob_mesh on the CPU tier,
124// the GL character programs + TEXM atlas on WebGL2) -- the VISITING cast of world_npcs.conf rides the GL
125// programs only and is announced by its own badge, so it is deliberately NOT part of this word; world+markers =
126// the cast reduced to markers, declared now so a future marker tier cannot be filed as world+cast.
127const TL_DR_WORLD: i64 = 0
128const TL_DR_WORLD_CAST: i64 = 1
129const TL_DR_WORLD_MARKERS: i64 = 2
130const TL_W_WORLD: *u8 = "world"
131const TL_W_WORLD_CAST: *u8 = "world+cast"
132const TL_W_WORLD_MARKERS: *u8 = "world+markers"
133
134// PARSE VERDICTS. One scale: the number tl_load returns is the number the HUD absence names.
135const TL_OK: i64 = 0
136const TL_E_UNREADABLE: i64 = 1
137const TL_E_FIELDS: i64 = 2
138const TL_E_STATE: i64 = 3
139const TL_E_REQ: i64 = 4
140const TL_E_FALLBACK: i64 = 6
141const TL_E_ORDER: i64 = 7
142const TL_E_NO_DOORS: i64 = 8
143const TL_E_QUOTE: i64 = 9
144const TL_E_TOO_MANY: i64 = 10
145const TL_E_LIMIT: i64 = 11
146const TL_E_KIND: i64 = 12
147const TL_E_BOOT: i64 = 13
148const TL_E_THREAD: i64 = 14
149const TL_E_DRAWS: i64 = 15 // S0: a door's draws word is outside the vocabulary -- REFUSED, never defaulted
150const TL_E_DRAWS_ABSENT: i64 = 16 // S0: a door row carries no draws field (the pre-S0 seven-field shape) -- REFUSED BY NAME
151
152// REASON VOCABULARY -- one table, two surfaces: tl_reason returns these; nxDoorReport (emitted by tl_js)
153// prints the same words. nx_tier_ladder_gate asserts every one of them appears in the emitted JS.
154const TL_R_TAKEN: *u8 = "taken"
155const TL_R_BELOW: *u8 = "below-taken"
156const TL_R_LEVER_OFF: *u8 = "levered-off"
157const TL_R_NOCAP: *u8 = "capability-absent"
158const TL_R_FAILED: *u8 = "failed"
159const TL_R_UNEXPLAINED: *u8 = "not-taken:unexplained"
160const TL_R_UNDECIDED: *u8 = "undecided"
161const TL_R_ABSENT: *u8 = "ladder-absent"
162const TL_R_UNMAPPED: *u8 = "unmapped:" // nxDoorId / nxDoorDraws prefix for a requirement or door the ladder does not carry
163// THREAD-LADDER REASON VOCABULARY -- one table, two surfaces, exactly as the door reasons are:
164// tl_thread_why returns these words and nxThreadsWhy (emitted by tl_js) prints the same ones, so a
165// HUD that says "1 core" always says WHY it is one.
166const TL_T_R_ABSENT: *u8 = "thread-rows-absent"
167const TL_T_R_NOSHARE: *u8 = "no-shared-memory"
168const TL_T_R_LEVER: *u8 = "lever"
169const TL_T_R_CEIL: *u8 = "clamped-to-ceiling"
170const TL_T_R_FLOOR: *u8 = "clamped-to-floor"
171const TL_T_R_MEASURED: *u8 = "measured-cores"
172
173const TL_A_NL: i64 = 10
174const TL_A_CR: i64 = 13
175const TL_A_HASH: i64 = 35
176const TL_A_PIPE: i64 = 124
177const TL_A_QUOTE: i64 = 34
178const TL_A_BSLASH: i64 = 92
179const TL_A_0: i64 = 48
180const TL_A_9: i64 = 57
181const TL_B10: i64 = 10
182const TL_JS_CAP: i64 = 32768 // raised with the GE30 thread block; the door twin alone used ~6 KB
183const TL_NUM_SCRATCH: i64 = 32
184const TL_LP_BYTES: i64 = 16
185const TL_FIELD_SLOTS: i64 = 8
186const TL_FIELD_BYTES: i64 = 64
187const TL_DOOR_FIELDS: i64 = 8 // S0: door|id|order|state|lever|requires|draws|announce
188const TL_DOOR_FIELDS_LEGACY: i64 = 7 // the pre-S0 row shape: refused as TL_E_DRAWS_ABSENT so the verdict names the missing field, not a bare count
189const TL_LIMIT_FIELDS: i64 = 4
190const TL_STDERR: i64 = 2
191const TL_COMPOSE_MARK: *u8 = "tl_emit()"
192
193func tl_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
194func tl_seq(a: *u8, b: *u8) -> i64 {
195 var i: i64 = 0
196 while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 }
197 if b[i] != (0 as u8) { return 0 }
198 return 1
199}
200func tl_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; var p: i64 = o; while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 } return p }
201func tl_catn(d: *u8, o: i64, v: i64) -> i64 {
202 let t: *u8 = sys_mmap(TL_NUM_SCRATCH)
203 var m: i64 = v
204 var p: i64 = o
205 var k: i64 = 0
206 if m == 0 { t[0] = TL_A_0 as u8; k = 1 }
207 while m > 0 { t[k] = (TL_A_0 + (m % TL_B10)) as u8; m = m / TL_B10; k = k + 1 }
208 var i: i64 = 0
209 while i < k { d[p] = t[k - 1 - i]; p = p + 1; i = i + 1 }
210 return p
211}
212// decimal of a whole NUL-terminated field: -1 when empty or any byte is not a digit
213func tl_num(s: *u8) -> i64 {
214 var v: i64 = 0
215 var i: i64 = 0
216 if s[0] == (0 as u8) { return 0 - 1 }
217 while s[i] != (0 as u8) {
218 let c: i64 = s[i] as i64
219 if c < TL_A_0 { return 0 - 1 }
220 if c > TL_A_9 { return 0 - 1 }
221 v = v * TL_B10 + (c - TL_A_0)
222 i = i + 1
223 }
224 return v
225}
226// first offset of needle in buf[0..n) at or after from, or -1
227func tl_find(buf: *u8, n: i64, from: i64, needle: *u8) -> i64 {
228 let ml: i64 = tl_slen(needle)
229 if ml == 0 { return 0 - 1 }
230 var i: i64 = from
231 while i + ml <= n {
232 var k: i64 = 0
233 var hit: i64 = 1
234 while k < ml { if buf[i + k] != needle[k] { hit = 0; k = ml } k = k + 1 }
235 if hit == 1 { return i }
236 i = i + 1
237 }
238 return 0 - 1
239}
240func tl_has_quote_or_bslash(s: *u8) -> i64 {
241 var i: i64 = 0
242 while s[i] != (0 as u8) {
243 let c: i64 = s[i] as i64
244 if c == TL_A_QUOTE { return 1 }
245 if c == TL_A_BSLASH { return 1 }
246 i = i + 1
247 }
248 return 0
249}
250
251// ---- table accessors -----------------------------------------------------------------------------
252func tl_str(tbl: *i64, off: i64) -> *u8 { return (tbl[TL_H_BUF] + off) as *u8 }
253func tl_doors(tbl: *i64) -> i64 { return tbl[TL_H_ND] }
254func tl_limits(tbl: *i64) -> i64 { return tbl[TL_H_NL] }
255func tl_dcell(tbl: *i64, i: i64, f: i64) -> i64 { return tbl[TL_DOOR0 + i * TL_DW + f] }
256func tl_lcell(tbl: *i64, i: i64, f: i64) -> i64 { return tbl[TL_LIM0 + i * TL_LW + f] }
257func tl_door_id(tbl: *i64, i: i64) -> *u8 { return tl_str(tbl, tl_dcell(tbl, i, TL_D_ID)) }
258func tl_door_order(tbl: *i64, i: i64) -> i64 { return tl_dcell(tbl, i, TL_D_ORDER) }
259func tl_door_state(tbl: *i64, i: i64) -> i64 { return tl_dcell(tbl, i, TL_D_STATE) }
260func tl_door_lever(tbl: *i64, i: i64) -> *u8 { return tl_str(tbl, tl_dcell(tbl, i, TL_D_LEVER)) }
261func tl_door_req(tbl: *i64, i: i64) -> i64 { return tl_dcell(tbl, i, TL_D_REQ) }
262func tl_door_announce(tbl: *i64, i: i64) -> *u8 { return tl_str(tbl, tl_dcell(tbl, i, TL_D_ANN)) }
263func tl_door_draws(tbl: *i64, i: i64) -> i64 { return tl_dcell(tbl, i, TL_D_DRAWS) }
264func tl_limit_key(tbl: *i64, i: i64) -> *u8 { return tl_str(tbl, tl_lcell(tbl, i, TL_L_KEY)) }
265func tl_limit_min(tbl: *i64, i: i64) -> i64 { return tl_lcell(tbl, i, TL_L_MIN) }
266func tl_limit_why(tbl: *i64, i: i64) -> *u8 { return tl_str(tbl, tl_lcell(tbl, i, TL_L_WHY)) }
267func tl_boot_ms(tbl: *i64) -> i64 { return tbl[TL_BOOT0 + TL_B_MS] }
268func tl_boot_lever(tbl: *i64) -> *u8 { return tl_str(tbl, tbl[TL_BOOT0 + TL_B_LEVER]) }
269func tl_boot_max(tbl: *i64) -> i64 { return tbl[TL_BOOT0 + TL_B_MAX] }
270func tl_state_name(st: i64) -> *u8 {
271 if st == TL_ST_LEVERED { return TL_S_LEVERED }
272 if st == TL_ST_FALLBACK { return TL_S_FALLBACK }
273 return TL_S_DEFAULT
274}
275func tl_req_name(rq: i64) -> *u8 {
276 if rq == TL_RQ_WEBGL2 { return TL_Q_WEBGL2 }
277 if rq == TL_RQ_ALWAYS { return TL_Q_ALWAYS }
278 return TL_Q_WEBGPU
279}
280func tl_state_of(s: *u8) -> i64 {
281 if tl_seq(s, TL_S_DEFAULT) == 1 { return TL_ST_DEFAULT }
282 if tl_seq(s, TL_S_LEVERED) == 1 { return TL_ST_LEVERED }
283 if tl_seq(s, TL_S_FALLBACK) == 1 { return TL_ST_FALLBACK }
284 return 0 - 1
285}
286func tl_req_of(s: *u8) -> i64 {
287 if tl_seq(s, TL_Q_WEBGPU) == 1 { return TL_RQ_WEBGPU }
288 if tl_seq(s, TL_Q_WEBGL2) == 1 { return TL_RQ_WEBGL2 }
289 if tl_seq(s, TL_Q_ALWAYS) == 1 { return TL_RQ_ALWAYS }
290 return 0 - 1
291}
292func tl_draws_name(dr: i64) -> *u8 {
293 if dr == TL_DR_WORLD_CAST { return TL_W_WORLD_CAST }
294 if dr == TL_DR_WORLD_MARKERS { return TL_W_WORLD_MARKERS }
295 return TL_W_WORLD
296}
297// -1 for any word outside the vocabulary and the caller REFUSES: there is deliberately no permissive default
298func tl_draws_of(s: *u8) -> i64 {
299 if tl_seq(s, TL_W_WORLD) == 1 { return TL_DR_WORLD }
300 if tl_seq(s, TL_W_WORLD_CAST) == 1 { return TL_DR_WORLD_CAST }
301 if tl_seq(s, TL_W_WORLD_MARKERS) == 1 { return TL_DR_WORLD_MARKERS }
302 return 0 - 1
303}
304
305// ---- parse ---------------------------------------------------------------------------------------
306// b[0..n) is MUTATED in place (separators become NUL) and b[n] is written, so the caller must own a buffer
307// with at least n+1 bytes (tl_load copies the file for exactly that reason). Returns a TL_* verdict and
308// leaves it in tbl[TL_H_ERR] with the 1-based line in tbl[TL_H_LINE] when it refused.
309func tl_parse(b: *u8, n: i64, tbl: *i64) -> i64 {
310 var i: i64 = 0
311 while i < TL_TBL_CELLS { tbl[i] = 0; i = i + 1 }
312 tbl[TL_H_BUF] = b as i64
313 tbl[TL_H_N] = n
314 let f: *i64 = sys_mmap(TL_FIELD_BYTES) as *i64
315 var p: i64 = 0
316 var line: i64 = 0
317 var err: i64 = TL_OK
318 var fallback_at: i64 = 0 // 1-based door index of the fallback row, 0 while none seen
319 var last_order: i64 = 0
320 var go: i64 = 1
321 while go == 1 {
322 if p >= n { go = 0 }
323 if go == 1 {
324 line = line + 1
325 var e: i64 = p
326 while e < n { if (b[e] as i64) == TL_A_NL { e = n + e } e = e + 1 }
327 if e > n { e = e - n - 1 }
328 if e > n { e = n }
329 // strip a CR, terminate the line
330 var eol: i64 = e
331 if eol > p { if (b[eol - 1] as i64) == TL_A_CR { eol = eol - 1 } }
332 b[eol] = 0 as u8
333 var skip: i64 = 0
334 if eol == p { skip = 1 }
335 if skip == 0 { if (b[p] as i64) == TL_A_HASH { skip = 1 } }
336 if skip == 0 {
337 // split on | in place
338 var nf: i64 = 1
339 f[0] = p
340 var j: i64 = p
341 while j < eol {
342 if (b[j] as i64) == TL_A_PIPE {
343 b[j] = 0 as u8
344 if nf < TL_FIELD_SLOTS { f[nf] = j + 1 }
345 nf = nf + 1
346 }
347 j = j + 1
348 }
349 let kind: *u8 = (b as i64 + f[0]) as *u8
350 var handled: i64 = 0
351 if tl_seq(kind, TL_K_DOOR) == 1 {
352 handled = 1
353 // S0: a seven-field row is the shape written before draws existed -- refused BY NAME, so the
354 // remedy (declare what the door draws) is in the verdict rather than behind a bare field count
355 if nf == TL_DOOR_FIELDS_LEGACY { err = TL_E_DRAWS_ABSENT }
356 if err == TL_OK { if nf != TL_DOOR_FIELDS { err = TL_E_FIELDS } }
357 if err == TL_OK {
358 var q: i64 = 1
359 while q < nf { if tl_has_quote_or_bslash((b as i64 + f[q]) as *u8) == 1 { err = TL_E_QUOTE } q = q + 1 }
360 }
361 if err == TL_OK { if tbl[TL_H_ND] >= TL_MAXD { err = TL_E_TOO_MANY } }
362 if err == TL_OK { if fallback_at != 0 { err = TL_E_FALLBACK } }
363 var order: i64 = 0
364 var st: i64 = 0
365 var rq: i64 = 0
366 var dr: i64 = 0
367 if err == TL_OK {
368 order = tl_num((b as i64 + f[2]) as *u8)
369 if order <= last_order { err = TL_E_ORDER }
370 }
371 if err == TL_OK {
372 st = tl_state_of((b as i64 + f[3]) as *u8)
373 if st < 0 { err = TL_E_STATE }
374 }
375 if err == TL_OK {
376 rq = tl_req_of((b as i64 + f[5]) as *u8)
377 if rq < 0 { err = TL_E_REQ }
378 }
379 if err == TL_OK {
380 dr = tl_draws_of((b as i64 + f[6]) as *u8)
381 if dr < 0 { err = TL_E_DRAWS }
382 }
383 if err == TL_OK { if st == TL_ST_FALLBACK { if rq != TL_RQ_ALWAYS { err = TL_E_FALLBACK } } }
384 if err == TL_OK {
385 let d: i64 = tbl[TL_H_ND]
386 let base: i64 = TL_DOOR0 + d * TL_DW
387 tbl[base + TL_D_ID] = f[1]
388 tbl[base + TL_D_ORDER] = order
389 tbl[base + TL_D_STATE] = st
390 tbl[base + TL_D_LEVER] = f[4]
391 tbl[base + TL_D_REQ] = rq
392 tbl[base + TL_D_DRAWS] = dr
393 tbl[base + TL_D_ANN] = f[7]
394 tbl[TL_H_ND] = d + 1
395 last_order = order
396 if st == TL_ST_FALLBACK { fallback_at = d + 1 }
397 }
398 }
399 if handled == 0 { if tl_seq(kind, TL_K_LIMIT) == 1 {
400 handled = 1
401 if nf != TL_LIMIT_FIELDS { err = TL_E_FIELDS }
402 if err == TL_OK {
403 var q2: i64 = 1
404 while q2 < nf { if tl_has_quote_or_bslash((b as i64 + f[q2]) as *u8) == 1 { err = TL_E_QUOTE } q2 = q2 + 1 }
405 }
406 if err == TL_OK { if tbl[TL_H_NL] >= TL_MAXL { err = TL_E_TOO_MANY } }
407 var mn: i64 = 0
408 if err == TL_OK {
409 mn = tl_num((b as i64 + f[2]) as *u8)
410 if mn <= 0 { err = TL_E_LIMIT }
411 }
412 if err == TL_OK {
413 let l: i64 = tbl[TL_H_NL]
414 let lbase: i64 = TL_LIM0 + l * TL_LW
415 tbl[lbase + TL_L_KEY] = f[1]
416 tbl[lbase + TL_L_MIN] = mn
417 tbl[lbase + TL_L_WHY] = f[3]
418 tbl[TL_H_NL] = l + 1
419 }
420 } }
421 if handled == 0 { if tl_seq(kind, TL_K_BOOT) == 1 {
422 handled = 1
423 if nf != TL_BOOT_FIELDS { err = TL_E_FIELDS }
424 if err == TL_OK {
425 var q3: i64 = 1
426 while q3 < nf { if tl_has_quote_or_bslash((b as i64 + f[q3]) as *u8) == 1 { err = TL_E_QUOTE } q3 = q3 + 1 }
427 }
428 if err == TL_OK {
429 let bk: *u8 = (b as i64 + f[1]) as *u8
430 var known: i64 = 0
431 if tl_seq(bk, TL_BK_MS) == 1 {
432 known = 1
433 if tbl[TL_BOOT0 + TL_B_MS] != 0 { err = TL_E_BOOT }
434 let ms: i64 = tl_num((b as i64 + f[2]) as *u8)
435 if ms <= 0 { err = TL_E_BOOT }
436 if err == TL_OK { tbl[TL_BOOT0 + TL_B_MS] = ms; tbl[TL_H_NB] = tbl[TL_H_NB] + 1 }
437 }
438 if tl_seq(bk, TL_BK_LEVER) == 1 {
439 known = 1
440 if tbl[TL_BOOT0 + TL_B_LEVER] != 0 { err = TL_E_BOOT }
441 if b[f[2]] == (0 as u8) { err = TL_E_BOOT }
442 if err == TL_OK { tbl[TL_BOOT0 + TL_B_LEVER] = f[2]; tbl[TL_H_NB] = tbl[TL_H_NB] + 1 }
443 }
444 if tl_seq(bk, TL_BK_MAX) == 1 {
445 known = 1
446 if tbl[TL_BOOT0 + TL_B_MAX] != 0 { err = TL_E_BOOT }
447 let mx: i64 = tl_num((b as i64 + f[2]) as *u8)
448 if mx <= 0 { err = TL_E_BOOT }
449 if err == TL_OK { tbl[TL_BOOT0 + TL_B_MAX] = mx; tbl[TL_H_NB] = tbl[TL_H_NB] + 1 }
450 }
451 if known == 0 { err = TL_E_BOOT }
452 }
453 } }
454 if handled == 0 { if tl_seq(kind, TL_K_THREAD) == 1 {
455 handled = 1
456 if nf != TL_THREAD_FIELDS { err = TL_E_FIELDS }
457 if err == TL_OK {
458 var q4: i64 = 1
459 while q4 < nf { if tl_has_quote_or_bslash((b as i64 + f[q4]) as *u8) == 1 { err = TL_E_QUOTE } q4 = q4 + 1 }
460 }
461 if err == TL_OK {
462 let tk: *u8 = (b as i64 + f[1]) as *u8
463 var tknown: i64 = 0
464 if tl_seq(tk, TL_TK_FLOOR) == 1 {
465 tknown = 1
466 if tbl[TL_THREAD0 + TL_T_FLOOR] != 0 { err = TL_E_THREAD }
467 let fl: i64 = tl_num((b as i64 + f[2]) as *u8)
468 if fl <= 0 { err = TL_E_THREAD }
469 if err == TL_OK { tbl[TL_THREAD0 + TL_T_FLOOR] = fl; tbl[TL_H_NT] = tbl[TL_H_NT] + 1 }
470 }
471 if tl_seq(tk, TL_TK_CEIL) == 1 {
472 tknown = 1
473 if tbl[TL_THREAD0 + TL_T_CEIL] != 0 { err = TL_E_THREAD }
474 let ce: i64 = tl_num((b as i64 + f[2]) as *u8)
475 if ce <= 0 { err = TL_E_THREAD }
476 if err == TL_OK { tbl[TL_THREAD0 + TL_T_CEIL] = ce; tbl[TL_H_NT] = tbl[TL_H_NT] + 1 }
477 }
478 if tl_seq(tk, TL_TK_LEVER) == 1 {
479 tknown = 1
480 if tbl[TL_THREAD0 + TL_T_LEVER] != 0 { err = TL_E_THREAD }
481 if b[f[2]] == (0 as u8) { err = TL_E_THREAD }
482 if err == TL_OK { tbl[TL_THREAD0 + TL_T_LEVER] = f[2]; tbl[TL_H_NT] = tbl[TL_H_NT] + 1 }
483 }
484 if tknown == 0 { err = TL_E_THREAD }
485 }
486 } }
487 if handled == 0 { err = TL_E_KIND }
488 }
489 if err != TL_OK { go = 0 }
490 p = e + 1
491 }
492 }
493 if err == TL_OK { if tbl[TL_H_ND] == 0 { err = TL_E_NO_DOORS } }
494 if err == TL_OK { if fallback_at != tbl[TL_H_ND] { err = TL_E_FALLBACK } }
495 if err == TL_OK { if tbl[TL_H_NB] != TL_BOOT_KEYS { err = TL_E_BOOT } }
496 if err == TL_OK { if tbl[TL_BOOT0 + TL_B_MAX] < tbl[TL_BOOT0 + TL_B_MS] { err = TL_E_BOOT } }
497 // the thread block is OPTIONAL, but PARTIAL IS NOT A STATE: all three keys or none. A conf
498 // carrying a ceiling and no floor would otherwise read as floor=0 and pick zero workers.
499 if err == TL_OK { if tbl[TL_H_NT] != 0 { if tbl[TL_H_NT] != TL_THREAD_KEYS { err = TL_E_THREAD } } }
500 if err == TL_OK { if tbl[TL_H_NT] == TL_THREAD_KEYS { if tbl[TL_THREAD0 + TL_T_CEIL] < tbl[TL_THREAD0 + TL_T_FLOOR] { err = TL_E_THREAD } } }
501 tbl[TL_H_ERR] = err
502 if err != TL_OK { tbl[TL_H_LINE] = line }
503 return err
504}
505
506// read TL_CONF into an OWNED buffer with one byte of slack (tl_parse writes b[n]) and parse it
507func tl_load(tbl: *i64) -> i64 {
508 let lp: *i64 = sys_mmap(TL_LP_BYTES) as *i64
509 let raw: *u8 = sys_read_file(TL_CONF, lp)
510 var ok: i64 = 1
511 if (raw as i64) == 0 { ok = 0 }
512 if ok == 1 { if lp[0] <= 0 { ok = 0 } }
513 if ok == 0 {
514 var i: i64 = 0
515 while i < TL_TBL_CELLS { tbl[i] = 0; i = i + 1 }
516 tbl[TL_H_ERR] = TL_E_UNREADABLE
517 return TL_E_UNREADABLE
518 }
519 let n: i64 = lp[0]
520 let b: *u8 = sys_mmap(n + 1)
521 var k: i64 = 0
522 while k < n { b[k] = raw[k]; k = k + 1 }
523 b[n] = 0 as u8
524 return tl_parse(b, n, tbl)
525}
526
527// ---- the native walk ------------------------------------------------------------------------------
528// cap_webgpu / cap_webgl2 = 1 when that capability is present on the host; levers[i] = 1 when door i's
529// lever appears in the URL. A fallback door whose lever is on FORCES it from any position (?gl=0). Otherwise
530// the first door in order whose requirement holds (and, for a levered door, whose lever is on) is taken; the
531// fallback always holds, and tl_parse guarantees it is last, so the walk always returns a door.
532func tl_cap_ok(rq: i64, cap_webgpu: i64, cap_webgl2: i64) -> i64 {
533 if rq == TL_RQ_WEBGPU { return cap_webgpu }
534 if rq == TL_RQ_WEBGL2 { return cap_webgl2 }
535 return 1
536}
537func tl_pick(tbl: *i64, cap_webgpu: i64, cap_webgl2: i64, levers: *i64) -> i64 {
538 let nd: i64 = tbl[TL_H_ND]
539 var i: i64 = 0
540 while i < nd {
541 if tl_door_state(tbl, i) == TL_ST_FALLBACK { if levers[i] == 1 { return i } }
542 i = i + 1
543 }
544 i = 0
545 while i < nd {
546 let st: i64 = tl_door_state(tbl, i)
547 var ok: i64 = tl_cap_ok(tl_door_req(tbl, i), cap_webgpu, cap_webgl2)
548 if st == TL_ST_LEVERED { if levers[i] == 0 { ok = 0 } }
549 if st == TL_ST_FALLBACK { ok = 1 }
550 if ok == 1 { return i }
551 i = i + 1
552 }
553 return nd - 1
554}
555// why door i stands where it does relative to the door that was picked
556func tl_reason(tbl: *i64, i: i64, picked: i64, cap_webgpu: i64, cap_webgl2: i64, levers: *i64) -> *u8 {
557 if i == picked { return TL_R_TAKEN }
558 if i > picked { return TL_R_BELOW }
559 if tl_door_state(tbl, i) == TL_ST_LEVERED { if levers[i] == 0 { return TL_R_LEVER_OFF } }
560 if tl_cap_ok(tl_door_req(tbl, i), cap_webgpu, cap_webgl2) == 0 { return TL_R_NOCAP }
561 return TL_R_FAILED
562}
563
564// ---- the emitted twin ------------------------------------------------------------------------------
565// window.__nx_ladder = the door rows verbatim; window.__nx_gpu_limits = the limit rows; nxDoorId(requires)
566// = the id of the first door carrying that requirement (so the page never spells a door id itself);
567// nxDoorReport() = "<id>:<reason>,..." over every door, the reason words being the TL_R_* vocabulary above,
568// with the runtime detail (the thrown WebGPU/WebGL message, the GL probe's state) appended after a colon;
569// nxDoorDraws() = the draws word of the door that drew the frame (S0), published on window.
570// ---- the thread ladder: accessors and THE NATIVE WALK the gate pins the emitted JS against ----
571func tl_threads_declared(tbl: *i64) -> i64 { if tbl[TL_H_NT] == TL_THREAD_KEYS { return 1 } return 0 }
572func tl_thread_floor(tbl: *i64) -> i64 { return tbl[TL_THREAD0 + TL_T_FLOOR] }
573func tl_thread_ceiling(tbl: *i64) -> i64 { return tbl[TL_THREAD0 + TL_T_CEIL] }
574func tl_thread_lever(tbl: *i64) -> *u8 { return tl_str(tbl, tbl[TL_THREAD0 + TL_T_LEVER]) }
575// measured = the cores the host reports (navigator.hardwareConcurrency / nproc), lever = the count a
576// URL asked for (0 = none), shared = 1 only when the page can really share memory (cross-origin
577// isolated AND SharedArrayBuffer present). Without shared memory the answer is ONE, because the
578// bands would have nowhere to meet -- the scale-down door, taken by measurement rather than assumed.
579func tl_thread_pick(tbl: *i64, measured: i64, lever: i64, shared: i64) -> i64 {
580 if tl_threads_declared(tbl) == 0 { return 1 }
581 if shared == 0 { return 1 }
582 var n: i64 = measured
583 if lever > 0 { n = lever }
584 if n < tl_thread_floor(tbl) { n = tl_thread_floor(tbl) }
585 if n > tl_thread_ceiling(tbl) { n = tl_thread_ceiling(tbl) }
586 return n
587}
588// WHY that many -- so a one-worker frame is never an unexplained frame
589func tl_thread_why(tbl: *i64, measured: i64, lever: i64, shared: i64) -> *u8 {
590 if tl_threads_declared(tbl) == 0 { return TL_T_R_ABSENT }
591 if shared == 0 { return TL_T_R_NOSHARE }
592 var n: i64 = measured
593 if lever > 0 { n = lever }
594 if n > tl_thread_ceiling(tbl) { return TL_T_R_CEIL }
595 if n < tl_thread_floor(tbl) { return TL_T_R_FLOOR }
596 if lever > 0 { return TL_T_R_LEVER }
597 return TL_T_R_MEASURED
598}
599// the thread half of the emitted twin: the same floor, ceiling, lever and reason words, walked by
600// the same rules. Emitted as a NAMED ABSENCE when the conf carries no thread rows.
601func tl_js_threads(d: *u8, p0: i64, tbl: *i64) -> i64 {
602 var p: i64 = p0
603 if tl_threads_declared(tbl) == 0 {
604 p = tl_cat(d, p, "window.__nx_threads=null;window.__nx_threads_absent=\"" as *u8)
605 p = tl_cat(d, p, TL_T_R_ABSENT)
606 p = tl_cat(d, p, "\";\nfunction nxThreads(){return 1;}\nfunction nxThreadsWhy(){return \"" as *u8)
607 p = tl_cat(d, p, TL_T_R_ABSENT)
608 p = tl_cat(d, p, "\";}\n" as *u8)
609 p = tl_cat(d, p, "window.nxThreads=nxThreads;window.nxThreadsWhy=nxThreadsWhy;window.nxThreadShared=nxThreadShared;
610" as *u8)
611 return p
612 }
613 p = tl_cat(d, p, "window.__nx_threads={floor:" as *u8); p = tl_catn(d, p, tl_thread_floor(tbl))
614 p = tl_cat(d, p, ",ceiling:" as *u8); p = tl_catn(d, p, tl_thread_ceiling(tbl))
615 p = tl_cat(d, p, ",lever:\"" as *u8); p = tl_cat(d, p, tl_thread_lever(tbl))
616 p = tl_cat(d, p, "\"};\n" as *u8)
617 // the shared-memory precondition is MEASURED in the page, never assumed from a header
618 p = tl_cat(d, p, "function nxThreadShared(){return (self.crossOriginIsolated===true&&typeof SharedArrayBuffer!==\"undefined\")?1:0;}\n" as *u8)
619 p = tl_cat(d, p, "function nxThreadLever(){var t=window.__nx_threads;var s=location.search;var i=s.indexOf(t.lever+\"=\");if(i<0)return 0;var v=parseInt(s.substring(i+t.lever.length+1),10);if(!(v>0))return 0;return v;}\n" as *u8)
620 p = tl_cat(d, p, "function nxThreads(){var t=window.__nx_threads;if(!t)return 1;if(!nxThreadShared())return 1;var n=(navigator.hardwareConcurrency|0);var L=nxThreadLever();if(L>0)n=L;if(n<t.floor)n=t.floor;if(n>t.ceiling)n=t.ceiling;return n;}\n" as *u8)
621 p = tl_cat(d, p, "function nxThreadsWhy(){var t=window.__nx_threads;if(!t)return \"" as *u8)
622 p = tl_cat(d, p, TL_T_R_ABSENT)
623 p = tl_cat(d, p, "\";if(!nxThreadShared())return \"" as *u8)
624 p = tl_cat(d, p, TL_T_R_NOSHARE)
625 p = tl_cat(d, p, "\";var n=(navigator.hardwareConcurrency|0);var L=nxThreadLever();if(L>0)n=L;\nif(n>t.ceiling)return \"" as *u8)
626 p = tl_cat(d, p, TL_T_R_CEIL)
627 p = tl_cat(d, p, "\";if(n<t.floor)return \"" as *u8)
628 p = tl_cat(d, p, TL_T_R_FLOOR)
629 p = tl_cat(d, p, "\";if(L>0)return \"" as *u8)
630 p = tl_cat(d, p, TL_T_R_LEVER)
631 p = tl_cat(d, p, "\";return \"" as *u8)
632 p = tl_cat(d, p, TL_T_R_MEASURED)
633 p = tl_cat(d, p, "\";}\n" as *u8)
634 p = tl_cat(d, p, "window.nxThreads=nxThreads;window.nxThreadsWhy=nxThreadsWhy;window.nxThreadShared=nxThreadShared;
635" as *u8)
636 return p
637}
638
639func tl_js(tbl: *i64) -> *u8 {
640 let d: *u8 = sys_mmap(TL_JS_CAP)
641 var p: i64 = 0
642 p = tl_cat(d, p, "// nx_tier_ladder_lib: the render-door ladder -- ONE table (knowledge/tier_ladder.conf), emitted here and walked natively by tl_pick/tl_reason, pinned by nx_tier_ladder_gate.\nwindow.__nx_ladder=[" as *u8)
643 let nd: i64 = tbl[TL_H_ND]
644 var i: i64 = 0
645 while i < nd {
646 if i > 0 { p = tl_cat(d, p, "," as *u8) }
647 p = tl_cat(d, p, "{id:\"" as *u8); p = tl_cat(d, p, tl_door_id(tbl, i))
648 p = tl_cat(d, p, "\",order:" as *u8); p = tl_catn(d, p, tl_door_order(tbl, i))
649 p = tl_cat(d, p, ",state:\"" as *u8); p = tl_cat(d, p, tl_state_name(tl_door_state(tbl, i)))
650 p = tl_cat(d, p, "\",lever:\"" as *u8); p = tl_cat(d, p, tl_door_lever(tbl, i))
651 p = tl_cat(d, p, "\",requires:\"" as *u8); p = tl_cat(d, p, tl_req_name(tl_door_req(tbl, i)))
652 p = tl_cat(d, p, "\",draws:\"" as *u8); p = tl_cat(d, p, tl_draws_name(tl_door_draws(tbl, i)))
653 p = tl_cat(d, p, "\",announce:\"" as *u8); p = tl_cat(d, p, tl_door_announce(tbl, i))
654 p = tl_cat(d, p, "\"}" as *u8)
655 i = i + 1
656 }
657 p = tl_cat(d, p, "];\nwindow.__nx_gpu_limits={" as *u8)
658 let nl: i64 = tbl[TL_H_NL]
659 var l: i64 = 0
660 while l < nl {
661 if l > 0 { p = tl_cat(d, p, "," as *u8) }
662 p = tl_cat(d, p, "\"" as *u8); p = tl_cat(d, p, tl_limit_key(tbl, l))
663 p = tl_cat(d, p, "\":" as *u8); p = tl_catn(d, p, tl_limit_min(tbl, l))
664 l = l + 1
665 }
666 p = tl_cat(d, p, "};\nwindow.__nx_gpu_boot={ms:" as *u8); p = tl_catn(d, p, tl_boot_ms(tbl))
667 p = tl_cat(d, p, ",lever:\"" as *u8); p = tl_cat(d, p, tl_boot_lever(tbl))
668 p = tl_cat(d, p, "\",max:" as *u8); p = tl_catn(d, p, tl_boot_max(tbl))
669 p = tl_cat(d, p, "};\nfunction nxGpuBootMs(){var b=window.__nx_gpu_boot;var s=location.search;var i=s.indexOf(b.lever+\"=\");if(i>=0){var v=parseInt(s.substring(i+b.lever.length+1),10);if(v>0){return v>b.max?b.max:v;}}return b.ms;}\n" as *u8)
670 p = tl_cat(d, p, "function nxDoorId(req){var L=window.__nx_ladder||[];for(var i=0;i<L.length;i++){if(L[i].requires===req)return L[i].id;}return \"" as *u8)
671 p = tl_cat(d, p, TL_R_UNMAPPED)
672 p = tl_cat(d, p, "\"+req;}\n" as *u8)
673 p = tl_cat(d, p, "function nxDoor(){return window.__sov_door||\"" as *u8)
674 p = tl_cat(d, p, TL_R_UNDECIDED)
675 p = tl_cat(d, p, "\";}\n" as *u8)
676 // S0: nxDoorDraws() = the draws word of the door that drew the frame (window.__sov_door), so the badge, the
677 // HUD and any external probe can STATE what the frame carries -- undecided before the ladder resolves, and a
678 // door the ladder does not carry reads unmapped:<id> exactly as nxDoorId does for a requirement. PUBLISHED on
679 // window for the same reason the thread doors are: this JS lands inside the instantiate callback.
680 p = tl_cat(d, p, "function nxDoorDraws(){var L=window.__nx_ladder||[];var d=window.__sov_door||\"\";if(d===\"\")return \"" as *u8)
681 p = tl_cat(d, p, TL_R_UNDECIDED)
682 p = tl_cat(d, p, "\";for(var i=0;i<L.length;i++){if(L[i].id===d)return L[i].draws;}return \"" as *u8)
683 p = tl_cat(d, p, TL_R_UNMAPPED)
684 p = tl_cat(d, p, "\"+d;}\nwindow.nxDoorDraws=nxDoorDraws;\n" as *u8)
685 p = tl_cat(d, p, "function nxDoorReport(){var L=window.__nx_ladder||[];var d=window.__sov_door||\"" as *u8)
686 p = tl_cat(d, p, TL_R_UNDECIDED)
687 p = tl_cat(d, p, "\";var out=[];var seen=0;for(var i=0;i<L.length;i++){var r=L[i];var w=\"\";\nif(r.id===d){w=\"" as *u8)
688 p = tl_cat(d, p, TL_R_TAKEN)
689 p = tl_cat(d, p, "\";seen=1;}\nelse if(seen){w=\"" as *u8)
690 p = tl_cat(d, p, TL_R_BELOW)
691 p = tl_cat(d, p, "\";}\nelse if(r.state===\"" as *u8)
692 p = tl_cat(d, p, TL_S_LEVERED)
693 p = tl_cat(d, p, "\"&&location.search.indexOf(r.lever)<0){w=\"" as *u8)
694 p = tl_cat(d, p, TL_R_LEVER_OFF)
695 p = tl_cat(d, p, "\";}\nelse if(r.requires===\"" as *u8)
696 p = tl_cat(d, p, TL_Q_WEBGPU)
697 p = tl_cat(d, p, "\"&&(navigator.gpu?0:1)){w=\"" as *u8)
698 p = tl_cat(d, p, TL_R_NOCAP)
699 p = tl_cat(d, p, "\";}\nelse if(r.requires===\"" as *u8)
700 p = tl_cat(d, p, TL_Q_WEBGPU)
701 p = tl_cat(d, p, "\"&&window.__sov_gpufail){w=\"" as *u8)
702 p = tl_cat(d, p, TL_R_FAILED)
703 p = tl_cat(d, p, ":\"+String(window.__sov_gpufail).slice(0,96);}\nelse if(r.requires===\"" as *u8)
704 p = tl_cat(d, p, TL_Q_WEBGL2)
705 p = tl_cat(d, p, "\"&&window.__nx_gl&&window.__nx_gl.gl2===0){w=\"" as *u8)
706 p = tl_cat(d, p, TL_R_NOCAP)
707 p = tl_cat(d, p, ":\"+window.__nx_gl.state;}\nelse if(r.requires===\"" as *u8)
708 p = tl_cat(d, p, TL_Q_WEBGL2)
709 p = tl_cat(d, p, "\"&&window.__sov_glfail){w=\"" as *u8)
710 p = tl_cat(d, p, TL_R_FAILED)
711 p = tl_cat(d, p, ":\"+String(window.__sov_glfail).slice(0,96);}\nelse{w=\"" as *u8)
712 p = tl_cat(d, p, TL_R_UNEXPLAINED)
713 p = tl_cat(d, p, "\";}\nout.push(r.id+\":\"+w);}\nreturn out.join(\",\");}\n" as *u8)
714 p = tl_js_threads(d, p, tbl) // GE30: the second scaling axis, same table, same file
715 d[p] = 0 as u8
716 return d
717}
718
719// the NAMED absence: what a page carries when the conf could not be read or refused to parse
720func tl_js_absent(rc: i64, line: i64) -> *u8 {
721 let d: *u8 = sys_mmap(TL_JS_CAP)
722 var p: i64 = 0
723 p = tl_cat(d, p, "window.__nx_ladder=null;window.__nx_gpu_limits={};window.__nx_gpu_boot={ms:" as *u8)
724 p = tl_catn(d, p, TL_BOOT_DEFAULT_MS)
725 p = tl_cat(d, p, ",lever:\"\",max:" as *u8)
726 p = tl_catn(d, p, TL_BOOT_DEFAULT_MS)
727 p = tl_cat(d, p, "};function nxGpuBootMs(){return window.__nx_gpu_boot.ms;}\nwindow.__nx_ladder_absent=\"tier_ladder.conf unreadable or malformed at emit rc=" as *u8)
728 p = tl_catn(d, p, rc)
729 p = tl_cat(d, p, " line=" as *u8)
730 p = tl_catn(d, p, line)
731 p = tl_cat(d, p, "\";\nfunction nxDoorId(req){return \"" as *u8)
732 p = tl_cat(d, p, TL_R_ABSENT)
733 p = tl_cat(d, p, ":\"+req;}\nfunction nxDoor(){return window.__sov_door||\"" as *u8)
734 p = tl_cat(d, p, TL_R_UNDECIDED)
735 p = tl_cat(d, p, "\";}\nfunction nxDoorReport(){return \"" as *u8)
736 p = tl_cat(d, p, TL_R_ABSENT)
737 p = tl_cat(d, p, "\";}\nfunction nxDoorDraws(){return \"" as *u8)
738 p = tl_cat(d, p, TL_R_ABSENT)
739 p = tl_cat(d, p, "\";}\nwindow.nxDoorDraws=nxDoorDraws;\n" as *u8)
740 // GE30: a page built from a BROKEN conf must still define the thread doors, or the frame loop
741 // dies on an undefined call and the honest "the ladder is absent" badge never reaches the HUD.
742 // One worker, named reason -- the same scale-down answer the declared path gives without sharing.
743 p = tl_cat(d, p, "window.__nx_threads=null;window.__nx_threads_absent=\"" as *u8)
744 p = tl_cat(d, p, TL_T_R_ABSENT)
745 p = tl_cat(d, p, "\";\nfunction nxThreadShared(){return 0;}\nfunction nxThreads(){return 1;}\nfunction nxThreadsWhy(){return \"" as *u8)
746 p = tl_cat(d, p, TL_T_R_ABSENT)
747 p = tl_cat(d, p, "\";}\n" as *u8)
748 // *PUBLISH THE DOORS ON window, NOT ONLY IN SCOPE. MEASURED 2026-09-03 on the LIVE /world/beach:
749 // window.__nx_threads read back correctly from a headless browser while nxThreads, nxThreadsWhy AND the
750 // older nxDoor all read NOFN -- the emitter appends this JS INSIDE the instantiate callback, so the
751 // function declarations are closure-scoped and no external instrument can call them. The page itself is
752 // fine (its frame loop shares that scope); every PROBE is blind. The page already uses this idiom for
753 // __nx_frame_once, so the ladder follows it: a ruler nothing outside can read cannot referee the page.
754 p = tl_cat(d, p, "window.nxThreads=nxThreads;window.nxThreadsWhy=nxThreadsWhy;window.nxThreadShared=nxThreadShared;
755" as *u8)
756 d[p] = 0 as u8
757 return d
758}
759
760// THE ONE CALL AN EMITTER MAKES. Loads the conf, emits the twin, or emits and ANNOUNCES the absence (stderr)
761// so a build log shows a page shipped without its ladder rather than a page that quietly draws unexplained.
762func tl_emit() -> *u8 {
763 let tbl: *i64 = sys_mmap(TL_TBL_BYTES) as *i64
764 let rc: i64 = tl_load(tbl)
765 if rc == TL_OK { return tl_js(tbl) }
766 let m: *u8 = sys_mmap(TL_NUM_SCRATCH * TL_B10)
767 var p: i64 = 0
768 p = tl_cat(m, p, "TIER-LADDER-ABSENT-AT-EMIT rc=" as *u8)
769 p = tl_catn(m, p, rc)
770 p = tl_cat(m, p, " line=" as *u8)
771 p = tl_catn(m, p, tbl[TL_H_LINE])
772 p = tl_cat(m, p, " conf=" as *u8)
773 p = tl_cat(m, p, TL_CONF)
774 p = tl_cat(m, p, " -- the page carries window.__nx_ladder=null and the HUD reads ladder-absent\n" as *u8)
775 sys_write(TL_STDERR, m, p)
776 return tl_js_absent(rc, tbl[TL_H_LINE])
777}
778
779// does an emitter source compose the ladder (calls tl_emit())? shared by the gate so there is ONE detector
780func tl_composes(buf: *u8, n: i64) -> i64 {
781 if tl_find(buf, n, 0, TL_COMPOSE_MARK) >= 0 { return 1 }
782 return 0
783}