nx_gen_pipecheck.nx source
↩ module page · 177 lines · 6654 B
1// nx_gen_pipecheck.nx -- the front door. Read a pipeline descriptor, VERIFY every declared part
2// against the file itself, and report RUNNABLE or BLOCKED with named reasons.
3//
4// This is the "comfyui capabilities without the messy interface" surface: you declare the set of
5// parts once, and the system tells you whether that set can actually generate -- before it spends
6// a single matmul on it.
7//
8// ★★★★★ THE DESCRIPTOR IS A CLAIM; THE FILE IS THE EVIDENCE. Every role is re-derived from the
9// container's tensor names. A descriptor that names a LoKr adapter as its `dit` is REFUSED, not
10// run: the estate has already paid for self-declared status that nobody measured.
11//
12// ★ REPORT WHAT IS MISSING BY NAME. A bare NO is not actionable; every blocker below says which
13// part failed and why, so the next step is obvious.
14//
15// ⚠NAMED pipecheck, NOT pipeline: `nx_gen_pipeline` was ALREADY TAKEN by the sovereign gen-img
16// core (runtime/_hdl_build/nx_gen_pipeline.nx -- base64 -> GENREC tEXt -> CID sidecar for the
17// gallery). Uploading a same-named file into runtime/ shadowed it and the build failed with
18// "UNDEFINED label: main", because that core is a main-less library gated by nx_gen_pipeline_gate.
19// ★★★★★ A BUILD ERROR ABOUT *YOUR* FILE CAN BE EVIDENCE THAT THE BUILDER COMPILED SOMEONE ELSE'S.
20// The name told the truth the diagnostic did not: the estate already owns this word.
21//
22// Usage: nx_gen_pipecheck <descriptor.pipe>
23// license_tier: ORIGINAL
24
25import "nx_syscalls.nx"
26import "nx_le.nx"
27import "nx_f32.nx"
28import "nx_f32_div.nx"
29import "nx_f32_cvt.nx"
30import "nx_f16.nx"
31import "nx_strconv.nx"
32import "nx_genver.nx"
33import "nx_genweights.nx"
34import "nx_genarch.nx"
35import "nx_genrole.nx"
36import "nx_genpipe.nx"
37
38func gp_puts(s: *u8) -> i64 {
39 var n: i64 = 0
40 while s[n] != (0 as u8) { n = n + 1 }
41 return sys_write(1, s, n)
42}
43func gp_i(v: i64) -> i64 {
44 let b: *u8 = sys_mmap(32)
45 return sys_write(1, b, nx_strconv_format_i64(v, b))
46}
47func gp_pad(s: *u8, w: i64) -> i64 {
48 var n: i64 = 0
49 while s[n] != (0 as u8) { n = n + 1 }
50 sys_write(1, s, n)
51 var i: i64 = n
52 while i < w { sys_write(1, " " as *u8, 1); i = i + 1 }
53 return 0
54}
55// tail of a path, so the report reads as parts rather than as wall-to-wall directories
56func gp_base(p: *u8) -> *u8 {
57 var n: i64 = 0
58 var last: i64 = 0
59 while p[n] != (0 as u8) {
60 if p[n] == (0x2F as u8) { last = n + 1 }
61 n = n + 1
62 }
63 return ((p as i64) + last) as *u8
64}
65
66static g_blockers: i64
67
68// Check one declared part. want_role is what the descriptor CLAIMS; the file decides the truth.
69func gp_part(label: *u8, path: *u8, want_role: i64, want_family: i64) -> i64 {
70 gp_pad(label, 14)
71 if (path as i64) == 0 {
72 gp_puts("-- not declared\n" as *u8)
73 g_blockers = g_blockers + 1
74 return 0
75 }
76 gp_pad(gp_base(path), 46)
77 let gw: *i64 = nx_gw_open(path)
78 if (gw as i64) == 0 {
79 gp_puts("UNREADABLE (neither gguf nor safetensors)\n" as *u8)
80 g_blockers = g_blockers + 1
81 return 0
82 }
83 let rl: *i64 = sys_mmap(RL_SLOTS * 8 + 64) as *i64
84 nx_role_probe(gw, rl)
85
86 gp_pad(nx_family_name(rl[RL_FAMILY]), 10)
87 gp_pad(nx_role_name(rl[RL_ROLE]), 14)
88
89 if rl[RL_ROLE] != want_role {
90 gp_puts("REFUSED: declared " as *u8)
91 gp_puts(nx_role_name(want_role))
92 gp_puts(", file is " as *u8)
93 gp_puts(nx_role_name(rl[RL_ROLE]))
94 gp_puts("\n" as *u8)
95 g_blockers = g_blockers + 1
96 return 0
97 }
98 // A family mismatch is the failure that produces a picture instead of an error: a Flux DiT
99 // driven by a Z-Image encoder runs to completion and returns noise with no diagnostic.
100 if want_family != FAM_UNKNOWN {
101 if rl[RL_FAMILY] != want_family {
102 if want_role != ROLE_VAE_DEC {
103 if want_role != ROLE_TEXTENC {
104 gp_puts("REFUSED: family mismatch (pipeline declares " as *u8)
105 gp_puts(nx_family_name(want_family))
106 gp_puts(")\n" as *u8)
107 g_blockers = g_blockers + 1
108 return 0
109 }
110 }
111 }
112 }
113 if rl[RL_RUNNABLE] != 1 {
114 gp_puts("BLOCKED: " as *u8)
115 gp_puts(nx_role_blocker(rl))
116 gp_puts("\n" as *u8)
117 g_blockers = g_blockers + 1
118 return 0
119 }
120 gp_puts("ok\n" as *u8)
121 return 1
122}
123
124func main(argc: i64, argv: *i64) -> i64 {
125 if argc < 2 {
126 gp_puts("usage: nx_gen_pipecheck <descriptor.pipe>\n" as *u8)
127 return 2
128 }
129 let pp: *i64 = sys_mmap(PP_SLOTS * 8 + 64) as *i64
130 let rc: i64 = nx_pipe_parse(argv[1] as *u8, pp)
131 if rc == 0 - 1 { gp_puts("descriptor unreadable\n" as *u8); return 3 }
132 if rc < 0 {
133 gp_puts("descriptor rejected at line " as *u8)
134 gp_i(0 - rc)
135 gp_puts(" (unknown key, missing value, or unknown family)\n" as *u8)
136 return 4
137 }
138 g_blockers = 0
139
140 gp_puts("=== PIPELINE " as *u8)
141 if pp[PP_NAME] != 0 { gp_puts(pp[PP_NAME] as *u8) } else { gp_puts("(unnamed)" as *u8) }
142 gp_puts(" family=" as *u8)
143 gp_puts(nx_family_name(pp[PP_FAMILY]))
144 gp_puts("\n" as *u8)
145
146 let fam: i64 = pp[PP_FAMILY]
147 gp_part("dit" as *u8, pp[PP_DIT] as *u8, ROLE_DIT, fam)
148 gp_part("vae_decoder" as *u8, pp[PP_VAEDEC] as *u8, ROLE_VAE_DEC, fam)
149 gp_part("text_encoder" as *u8, pp[PP_TEXTENC] as *u8, ROLE_TEXTENC, fam)
150
151 var a: i64 = 0
152 while a < pp[PP_N_ADAPT] {
153 let s: i64 = PP_ADAPT0 + a * 2
154 // An adapter trained against a DIFFERENT family folds cleanly into nothing: its keys never
155 // match, so it applies to zero tensors and changes zero pixels -- silently.
156 // ★ AN ADAPTER THAT MATCHES NO KEYS IS INDISTINGUISHABLE FROM ONE THAT IS WORKING WEAKLY.
157 if gp_part("adapter" as *u8, pp[s] as *u8, ROLE_ADAPTER, fam) == 1 {
158 gp_puts(" multiplier_milli=" as *u8)
159 gp_i(pp[s + 1])
160 gp_puts("\n" as *u8)
161 }
162 a = a + 1
163 }
164
165 nx_genver_emit("steps" as *u8, pp[PP_STEPS])
166 nx_genver_emit("cfg_milli" as *u8, pp[PP_CFG_MIL])
167 nx_genver_emit("adapters" as *u8, pp[PP_N_ADAPT])
168 nx_genver_emit("negative_prompt" as *u8, nx_pipe_has_cap(pp, "negative_prompt" as *u8))
169 nx_genver_emit("blockers" as *u8, g_blockers)
170
171 if g_blockers == 0 {
172 gp_puts("VERDICT: RUNNABLE -- every declared part verified against its own tensor names\n" as *u8)
173 return 0
174 }
175 gp_puts("VERDICT: BLOCKED -- see the named reasons above\n" as *u8)
176 return 1
177}