code wiki / _hdl_build / nx_ecomat_lib.nx
nx_ecomat_lib.nx source
↩ module page · 836 lines · 46743 B
1// nx_ecomat_lib.nx -- shared core for the ECOSYSTEM MATURITY ROLLUP (the unifier), SOVEREIGN edition.
2// Operator: "get away from tsv and other 3rd party formats -- use the nishi ecosystem, get to S-class."
3// So the maturity chart lives in the NATIVE seg_store (knowledge/store/ecomat) as BINARY records (the
4// store's own ss_w32/ss_r32 codec -- no TSV, no delimiter format), and the rollup MEASURES from the
5// store + the live autonomy ledger, enforcing a LIAR-KILL (no S-CLASS claim without evidence).
6// Pairs with nx_seg_store (the sovereign store) + nx_maturity_auditor (the ladder). NO FLOAT.
7// RECORD layout (one value per domain, key "ecomat:dom:N"):
8// w32@0 axis(0=DEPTH 1=BREADTH 2=META) | @4 layer | @8 cur | @12 bar | @16 weight | @20 ev
9// @24: domain\0 bench\0 next_rung\0
10// license_tier: ORIGINAL
11import "nx_seg_store.nx"
12import "nx_syscalls.nx"
13// EC2 (2026-09-01): the ONE resolver for compare data split across two trees -- regen.list and every
14// <dom>.plan are buildroot-owned, and this lib's consumers run from BOTH the estate root and buildroot,
15// so a hand-rolled path here would be correct in one caller and a latent defect in the other.
16import "nx_comparetree_lib.nx"
17import "nx_maturity_auditor.nx"
18import "../nx_compare_growth_json.nx"
19
20const ECOMAT_STORE: *u8 = "knowledge/store/ecomat"
21
22// Byte offset where the record's 7 NUL-terminated strings begin (the w32 header occupies 0..31).
23// Named, not magic: it IS the record layout documented above ec_pack.
24const ECOMAT_REC_STRBASE: i64 = 32
25
26// Read-side scratch sizes for ec_str. Named so the ALLOCATION and the BOUND are the same symbol and
27// can never drift apart -- the drift is exactly how an unbounded copy turns into a silent overrun.
28const ECOMAT_DOM_CAP: i64 = 128
29const ECOMAT_NR_CAP: i64 = 160
30const ECOMAT_EVLOG_CAP: i64 = 256
31const ECOMAT_EVPAT_CAP: i64 = 64
32
33func el_len(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
34func _p(s: *u8) -> i64 { let n: i64=el_len(s); sys_write(1,s,n); return 0 }
35func _fp(fd: i64, s: *u8) -> i64 { let n: i64=el_len(s); sys_write(fd,s,n); return 0 }
36func _fn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m; sys_write(fd,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 }
37func el_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 }
38func el_match(buf: *u8, i: i64, pat: *u8, pl: i64) -> i64 { var k: i64=0; while k<pl { if buf[i+k]!=pat[k] { return 0 } k=k+1 } return 1 }
39
40// value of the LAST integer following pat in buf (e.g. "permil=") -- reads the live ledger, -1 if none.
41func el_last_after(buf: *u8, n: i64, pat: *u8) -> i64 {
42 let pl: i64 = el_len(pat)
43 var res: i64 = 0 - 1
44 var i: i64 = 0
45 while i + pl <= n {
46 if el_match(buf, i, pat, pl) == 1 {
47 var j: i64 = i + pl
48 var v: i64 = 0
49 var any: i64 = 0
50 var go: i64 = 1
51 while go == 1 {
52 if j >= n { go = 0 } else {
53 let c: i64 = buf[j] as i64
54 var d: i64 = 0
55 if c >= 48 { if c <= 57 { d = 1 } }
56 if d == 1 { v = v*10 + (c-48); j = j + 1; any = 1 } else { go = 0 }
57 }
58 }
59 if any == 1 { res = v }
60 }
61 i = i + 1
62 }
63 return res
64}
65
66// gate-liveness: is the LAST occurrence of pat (e.g. "verdict=") followed by "GREEN"? (handles RED-then-GREEN logs)
67func el_last_green(buf: *u8, n: i64, pat: *u8) -> i64 {
68 let pl: i64 = el_len(pat)
69 var res: i64 = 0
70 var i: i64 = 0
71 while i + pl <= n {
72 if el_match(buf, i, pat, pl) == 1 {
73 var ok: i64 = 0
74 if el_match(buf, i + pl, "GREEN" as *u8, 5) == 1 { ok = 1 }
75 if el_match(buf, i + pl, "PASS" as *u8, 4) == 1 { ok = 1 }
76 if el_match(buf, i + pl, "VALID" as *u8, 5) == 1 { ok = 1 }
77 res = ok
78 }
79 i = i + 1
80 }
81 return res
82}
83
84// ---- native seg_store record codec (no TSV) ----
85func ec_axis_label(a: i64) -> *u8 { if a==0 { return "DEPTH" as *u8 } if a==1 { return "BREADTH" as *u8 } return "META" as *u8 }
86func em_tri_label(t: i64) -> *u8 { if t==2 { return "[triangulated]" as *u8 } if t==3 { return "[CONFLICT]" as *u8 } if t==1 { return "[single-src]" as *u8 } if t==4 { return "[dangling]" as *u8 } return "[stored]" as *u8 }
87
88// key "ecomat:dom:N" into out
89func ec_key(k: i64, out: *u8) -> i64 {
90 let p: *u8 = "ecomat:dom:" as *u8
91 var o: i64 = 0
92 var i: i64 = 0
93 while p[i] != (0 as u8) { out[o]=p[i]; o=o+1; i=i+1 }
94 if k == 0 { out[o]=48 as u8; o=o+1 } else { let t: *u8=sys_mmap(24); var m: i64=k; var n: i64=0; while m>0 { t[n]=(48+(m%10)) as u8; m=m/10; n=n+1 } var j: i64=0; while j<n { out[o]=t[n-1-j]; o=o+1; j=j+1 } }
95 out[o]=0 as u8; return o
96}
97
98// BOUNDED append: returns the new offset, or -1 if the string plus its NUL would pass cap.
99// Fail-closed and PROPAGATING -- a negative offset in feeds a negative offset out, so one refusal
100// aborts the whole ec_pack chain instead of letting a half-written record reach the store.
101func ec_putstr(buf: *u8, cap: i64, off: i64, s: *u8) -> i64 {
102 if off < 0 { return 0 - 1 }
103 let n: i64 = el_len(s)
104 if off + n + 1 > cap { return 0 - 1 }
105 var o: i64 = off
106 var i: i64 = 0
107 while i < n { buf[o]=s[i]; o=o+1; i=i+1 }
108 buf[o]=0 as u8
109 return o + 1
110}
111
112// EXACT bytes ec_pack will write for these fields. Callers size the allocation from the DATA
113// instead of guessing a fixed cap, so an oversized row is impossible BY CONSTRUCTION rather than
114// rejected after the fact -- this is what let the lab-science domain die on a bogus "record too
115// large" while the seeder's 512-byte buffers were silently overrun.
116func ec_reclen(domain: *u8, bench: *u8, nextrung: *u8, evlog: *u8, evpat: *u8, evlog2: *u8, evpat2: *u8) -> i64 {
117 var n: i64 = ECOMAT_REC_STRBASE
118 n = n + el_len(domain) + 1
119 n = n + el_len(bench) + 1
120 n = n + el_len(nextrung) + 1
121 n = n + el_len(evlog) + 1
122 n = n + el_len(evpat) + 1
123 n = n + el_len(evlog2) + 1
124 n = n + el_len(evpat2) + 1
125 return n
126}
127
128// pack a record into buf; return total byte length.
129// record: w32 @0 axis @4 layer @8 cur @12 bar @16 weight @20 ev @24 evkind @28 evkind2 ; strings @32
130// evkind/evkind2: 0=none 1=permil-derive 2=gate-liveness. TWO INDEPENDENT sources -> TRIANGULATION: a grade is
131// trusted only when its sources CONVERGE (<=1 level apart); divergence = CONFLICT (flagged); one source = SINGLE
132// (un-triangulated, flagged). The consensus is the conservative MIN -- never overclaim past the weaker witness.
133// cap = the writable size of buf. Returns the packed length, or -1 if buf cannot hold the record
134// (no partial write ever lands). Size buf with ec_reclen and this can only fire on a caller bug.
135func ec_pack(buf: *u8, cap: i64, axis: i64, layer: i64, cur: i64, bar: i64, weight: i64, ev: i64, evkind: i64, evkind2: i64, domain: *u8, bench: *u8, nextrung: *u8, evlog: *u8, evpat: *u8, evlog2: *u8, evpat2: *u8) -> i64 {
136 if cap < ECOMAT_REC_STRBASE { return 0 - 1 }
137 ss_w32(buf, 0, axis); ss_w32(buf, 4, layer); ss_w32(buf, 8, cur); ss_w32(buf, 12, bar); ss_w32(buf, 16, weight); ss_w32(buf, 20, ev); ss_w32(buf, 24, evkind); ss_w32(buf, 28, evkind2)
138 var o: i64 = ECOMAT_REC_STRBASE
139 o = ec_putstr(buf, cap, o, domain)
140 o = ec_putstr(buf, cap, o, bench)
141 o = ec_putstr(buf, cap, o, nextrung)
142 o = ec_putstr(buf, cap, o, evlog)
143 o = ec_putstr(buf, cap, o, evpat)
144 o = ec_putstr(buf, cap, o, evlog2)
145 o = ec_putstr(buf, cap, o, evpat2)
146 return o
147}
148func ec_axis(v: *u8) -> i64 { return ss_r32(v, 0) }
149func ec_layer(v: *u8) -> i64 { return ss_r32(v, 4) }
150func ec_cur(v: *u8) -> i64 { return ss_r32(v, 8) }
151func ec_bar(v: *u8) -> i64 { return ss_r32(v, 12) }
152func ec_weight(v: *u8) -> i64 { return ss_r32(v, 16) }
153func ec_ev(v: *u8) -> i64 { return ss_r32(v, 20) }
154func ec_evkind(v: *u8) -> i64 { return ss_r32(v, 24) }
155func ec_evkind2(v: *u8) -> i64 { return ss_r32(v, 28) }
156// extract string field: which 0=domain 1=bench 2=next_rung 3=evlog 4=evpat 5=evlog2 6=evpat2
157// cap = writable size of out. Returns the field length, or -1 if it will not fit -- and on refusal
158// out is set EMPTY, never partially filled, so a caller that ignores the return reads "" rather than
159// a truncated-but-plausible domain name. Mirrors db_dec_str(g,out,cap); ec_str was the outlier that
160// copied a stored field into a fixed buffer with no idea how big that buffer was.
161func ec_str(v: *u8, which: i64, out: *u8, cap: i64) -> i64 {
162 if cap < 1 { return 0 - 1 }
163 out[0] = 0 as u8
164 var off: i64 = ECOMAT_REC_STRBASE
165 var idx: i64 = 0
166 while idx < which { while v[off]!=(0 as u8){ off=off+1 } off=off+1; idx=idx+1 }
167 var n: i64 = 0
168 while v[off+n]!=(0 as u8){ n=n+1 }
169 if n + 1 > cap { return 0 - 1 }
170 var o: i64 = 0
171 while o < n { out[o]=v[off+o]; o=o+1 }
172 out[o]=0 as u8; return o
173}
174// STORED mode (no live source) -- used by the gates.
175func ec_seed_one(w: *i64, idx: i64, axis: i64, layer: i64, cur: i64, bar: i64, weight: i64, ev: i64, domain: *u8, bench: *u8, nextrung: *u8) -> i64 {
176 let key: *u8 = sys_mmap(64); ec_key(idx, key)
177 let cap: i64 = ec_reclen(domain, bench, nextrung, "" as *u8, "" as *u8, "" as *u8, "" as *u8)
178 let val: *u8 = sys_mmap(cap); let vlen: i64 = ec_pack(val, cap, axis, layer, cur, bar, weight, ev, 0, 0, domain, bench, nextrung, "" as *u8, "" as *u8, "" as *u8, "" as *u8)
179 if vlen < 0 { return 0 - 1 }
180 if ss_add(w, 1, key, val, vlen) != 0 { return 0 - 1 }
181 return 0
182}
183// SINGLE live source (un-triangulated).
184func ec_seed_one_ev(w: *i64, idx: i64, axis: i64, layer: i64, cur: i64, bar: i64, weight: i64, ev: i64, evkind: i64, domain: *u8, bench: *u8, nextrung: *u8, evlog: *u8, evpat: *u8) -> i64 {
185 let key: *u8 = sys_mmap(64); ec_key(idx, key)
186 let cap: i64 = ec_reclen(domain, bench, nextrung, evlog, evpat, "" as *u8, "" as *u8)
187 let val: *u8 = sys_mmap(cap); let vlen: i64 = ec_pack(val, cap, axis, layer, cur, bar, weight, ev, evkind, 0, domain, bench, nextrung, evlog, evpat, "" as *u8, "" as *u8)
188 if vlen < 0 { return 0 - 1 }
189 if ss_add(w, 1, key, val, vlen) != 0 { return 0 - 1 }
190 return 0
191}
192// TWO independent live sources -> the rollup TRIANGULATES (checks convergence).
193func ec_seed_two(w: *i64, idx: i64, axis: i64, layer: i64, cur: i64, bar: i64, weight: i64, ev: i64, evkind: i64, evkind2: i64, domain: *u8, bench: *u8, nextrung: *u8, evlog: *u8, evpat: *u8, evlog2: *u8, evpat2: *u8) -> i64 {
194 let key: *u8 = sys_mmap(64); ec_key(idx, key)
195 let cap: i64 = ec_reclen(domain, bench, nextrung, evlog, evpat, evlog2, evpat2)
196 let val: *u8 = sys_mmap(cap); let vlen: i64 = ec_pack(val, cap, axis, layer, cur, bar, weight, ev, evkind, evkind2, domain, bench, nextrung, evlog, evpat, evlog2, evpat2)
197 if vlen < 0 { return 0 - 1 }
198 if ss_add(w, 1, key, val, vlen) != 0 { return 0 - 1 }
199 return 0
200}
201
202// permil (0..1000) -> maturity level (0..5): live-derive a grade from a live meter so it can't rot.
203func permil_to_level(p: i64) -> i64 {
204 // â›”A COVERAGE PERCENTAGE MUST NEVER REACH A RUNG THAT NAMES AN EVIDENCE PROPERTY.
205 // nx_maturity_auditor defines MAT_SCLASS(4) as TRIANGULATED PARITY vs a named best-in-class
206 // competitor and MAT_EXCEED(5) as a triangulated WIN. Those are CLAIMS ABOUT A COMPARISON, not
207 // capability tiers. This function used to award them from a permil (p>=700 -> 4, p>=900 -> 5),
208 // so a domain reporting high COVERAGE was stamped "parity with gcc/llvm" WITH NO COMPARISON
209 // HAVING RUN -- the laundering path behind cov=1000 rows sitting in CLAIM-ONLY while
210 // nx_sota_status reports PROVEN 0/40. Ceiling is now PRODUCTION(3); 4 and 5 require an explicit
211 // comparator row (competitor + method + verdict), never a number.
212 // INERT ON ADOPTION: the rollup reported sclass_plus=0, so no domain held 4 or 5 when this
213 // landed -- it removes a FUTURE inflation path, it does not restate any current grade.
214 if p >= 500 { return 3 }
215 if p >= 150 { return 2 }
216 return 1
217}
218
219// derive a maturity level from ONE evidence source. THREE distinct outcomes (the split is load-bearing):
220// 0..5 = a real MEASURED level (the source was readable and gave an answer)
221// -1 = NO source declared (evkind 0) -- fall back to the stored assertion
222// -2 = source DECLARED but DANGLING (file missing/unreadable, or evkind-1 pattern absent) -- we CANNOT measure
223// The -2 vs (1) distinction is the whole point: a RED gate (file PRESENT, verdict not GREEN) is a real
224// measurement of TOY(1); a MISSING gate is the ABSENCE of measurement (-2). Conflating them (the old bug)
225// let a dead evidence pointer read as a low-but-"measured" grade, and worse, two missing gates "converged"
226// at TOY and got stamped [triangulated] -- a validation claim with zero readable sources behind it.
227// evkind 1 = permil-derive (evlog's evpat reading -> level); 2 = gate-liveness (last evpat verdict GREEN/PASS
228// -> the stored level is live-confirmed, else PRESENT-but-not-GREEN = RED = demote to TOY).
229func em_derive_level(evkind: i64, evlog: *u8, evpat: *u8, stored: i64) -> i64 {
230 if evkind == 0 { return 0 - 1 }
231 let szp: *i64 = sys_mmap(16) as *i64
232 let eb: *u8 = ss_readall(evlog, szp)
233 let en: i64 = szp[0]
234 // en == 0 is an EMPTY log: the file exists but carries no verdict. That is the ABSENCE of a
235 // measurement, not a RED one, so it must be DANGLING like a missing file -- otherwise a gate
236 // that opened its log and died before writing scores as a real TOY(1), and two such logs
237 // "converge" at TOY and get stamped [triangulated]: a validation claim with zero readable
238 // sources, which is the exact bug this split was introduced to kill.
239 if en <= 0 { return 0 - 2 }
240 if evkind == 1 {
241 let p: i64 = el_last_after(eb, en, evpat)
242 if p >= 0 { return permil_to_level(p) }
243 return 0 - 2
244 }
245 if evkind == 2 {
246 let g: i64 = el_last_green(eb, en, evpat)
247 if g == 1 {
248 // â›”A GREEN GATE PROVES THE CAPABILITY RUNS. IT SAYS NOTHING ABOUT A COMPETITOR.
249 // MAT_SCLASS(4) and MAT_EXCEED(5) are defined as TRIANGULATED PARITY / WIN vs a NAMED
250 // best-in-class. Gate-liveness is CAPABILITY evidence, so it can confirm at most
251 // PRODUCTION(3). Letting a green gate carry a stored 4/5 through was the LAST path to
252 // an unearned comparative rung, after permil_to_level was capped the same day.
253 // Comparative rungs require an ADMITTED claim (nx_vsbest_lib: named competitor +
254 // re-runnable method + readable evidence containing the declared pattern).
255 // INERT ON ADOPTION: the rollup reported sclass_plus=0, so nothing is demoted by this;
256 // it closes a FUTURE inflation path rather than restating any current grade.
257 if stored > MAT_PRODUCTION { return MAT_PRODUCTION }
258 return stored
259 }
260 return 1
261 }
262 return 0 - 1
263}
264
265// THE single source of truth for a domain's live grade + validation status -- used by BOTH the rollup
266// AND the page so they can never diverge. tout[0]: 0 stored / 1 single-src / 2 triangulated / 3 CONFLICT /
267// 4 DANGLING (a source was DECLARED but no witness is currently readable -> UNVERIFIED, never [triangulated]).
268// Two REAL measured witnesses -> conservative MIN consensus; convergence (<=1 apart) = triangulated, else conflict.
269// One readable witness -> single-src (the OTHER being absent OR dangling must NOT discard the readable one --
270// the old code fell straight to stored whenever witness-1 was unreadable, throwing away a live witness-2).
271func em_domain_level(v: *u8, tout: *i64) -> i64 {
272 let stored: i64 = ec_cur(v)
273 let evk1: i64 = ec_evkind(v)
274 let evk2: i64 = ec_evkind2(v)
275 let elog: *u8 = sys_mmap(ECOMAT_EVLOG_CAP)
276 let epat: *u8 = sys_mmap(ECOMAT_EVPAT_CAP)
277 let elog2: *u8 = sys_mmap(ECOMAT_EVLOG_CAP)
278 let epat2: *u8 = sys_mmap(ECOMAT_EVPAT_CAP)
279 ec_str(v, 3, elog, ECOMAT_EVLOG_CAP); ec_str(v, 4, epat, ECOMAT_EVPAT_CAP); ec_str(v, 5, elog2, ECOMAT_EVLOG_CAP); ec_str(v, 6, epat2, ECOMAT_EVPAT_CAP)
280 let l1: i64 = em_derive_level(evk1, elog, epat, stored)
281 let l2: i64 = em_derive_level(evk2, elog2, epat2, stored)
282 let DANG: i64 = 0 - 2
283 if l1 >= 0 {
284 if l2 >= 0 {
285 var diff: i64 = l1 - l2
286 if diff < 0 { diff = 0 - diff }
287 var lo: i64 = l1
288 if l2 < lo { lo = l2 }
289 if diff <= 1 { tout[0] = 2 } else { tout[0] = 3 }
290 return lo
291 }
292 tout[0] = 1
293 return l1
294 }
295 if l2 >= 0 {
296 tout[0] = 1
297 return l2
298 }
299 // NEITHER witness readable. A DECLARED-but-dangling pointer is UNVERIFIED (show the stored assertion,
300 // flagged [dangling], counted apart, and -- via the rollup -- ev=0 so a high claim still liar-kills).
301 // No pointer declared at all -> the honest stored baseline.
302 if l1 == DANG { tout[0] = 4; return stored }
303 if l2 == DANG { tout[0] = 4; return stored }
304 tout[0] = 0
305 return stored
306}
307
308// A ledger older than this is STALE: the rollup must not present it as "live". Two days, so a
309// daily meter beat has a full miss of slack before it is called out, and a meter that has silently
310// stopped is named within 48h instead of within 23 days.
311const ECOMAT_AUTO_STALE_S: i64 = 172800
312
313// ---- the measured core: MEASURE from the store + the live autonomy ledger ----
314// out[0]=overall_permil out[1]=liar_kill out[2]=domains out[3]=sclass_plus
315// out[4]=absent out[5]=auto_permil out[6]=sum_cur out[7]=sum_bar ; returns 0 GREEN / 1 RED.
316func em_rollup_store(prefix: *u8, autolog: *u8, out: *i64, verbose: i64) -> i64 {
317 let szp: *i64 = sys_mmap(16) as *i64
318 let abuf: *u8 = ss_readall(autolog, szp)
319 var an: i64 = szp[0]
320 if an < 0 { an = 0 }
321 var auto_permil: i64 = 0 - 1
322 if an > 0 { auto_permil = el_last_after(abuf, an, "permil=" as *u8) }
323 // ★FIXED 2026-08-07 -- AGE THE LEDGER YOU ARE ABOUT TO CALL "LIVE".
324 // This reader took the LAST permil= in the autonomy ledger and the rollup printed it under the
325 // label "live autonomy", with NO freshness check of any kind. MEASURED: the autonomy meter last
326 // wrote on 2026-07-15; for 23 DAYS every rollup, page and dashboard published that frozen 328 as
327 // a live figure, and the durable ecosystem_maturity.log recorded it hourly. When the meter was
328 // finally run the true value was 705 -- so the estate under-reported its own autonomy by 377
329 // permil for three weeks, and nothing anywhere said the number was old.
330 // A READER THAT LABELS ITS INPUT "LIVE" WITHOUT CHECKING ITS AGE LAUNDERS A STALE NUMBER INTO A
331 // FRESH-LOOKING ONE. Fixing the writer did not fix this; the reader is a separate defect.
332 // out[12]=age_seconds of the newest ledger row (-1 = no epoch found), out[13]=1 if STALE.
333 var auto_epoch: i64 = 0 - 1
334 if an > 0 { auto_epoch = el_last_after(abuf, an, "epoch=" as *u8) }
335 var auto_age: i64 = 0 - 1
336 var auto_stale: i64 = 0
337 if auto_epoch > 0 {
338 auto_age = sys_now_realtime_sec() - auto_epoch
339 if auto_age > ECOMAT_AUTO_STALE_S { auto_stale = 1 }
340 }
341 // No epoch at all is NOT freshness -- an unagedable ledger is treated as stale, fail-closed.
342 if auto_epoch <= 0 { if an > 0 { auto_stale = 1 } }
343 // DECLARE THE DENOMINATOR YOU AVERAGED OVER (2026-08-22), for exactly the reason the age is declared
344 // above. nx_autonomy_meter averages ONLY the axes it could score and publishes `axes_known=N of_4 ...
345 // verdict=PARTIAL` so a reader can tell a genuinely low grade from a partly blind one. MEASURED:
346 // a3_daemon_runs=-1 with n3=0 (BOTH pulse ledgers ABSENT), so 705 is an average over THREE axes --
347 // and every consumer printed it as a whole-system figure. An abstention nobody reads is a lie
348 // nobody told. The 4-axis figure is NOT recoverable by rescaling: dividing by 4 treats an UNMEASURED
349 // axis as a measured ZERO, the exact error the meter refuses. It is UNKNOWN, and we say so.
350 // out[14]=axes_known (-1 = never declared), out[15]=1 when the average is PARTIAL.
351 var auto_axes: i64 = 0 - 1
352 if an > 0 { auto_axes = el_last_after(abuf, an, "axes_known=" as *u8) }
353 var auto_partial: i64 = 0
354 if auto_axes > 0 { if auto_axes < 4 { auto_partial = 1 } }
355 out[14] = auto_axes
356 out[15] = auto_partial
357 let h: *i64 = ss_open(prefix)
358 var sum_cur: i64 = 0
359 var sum_bar: i64 = 0
360 var domains: i64 = 0
361 var bad: i64 = 0
362 var sclass_plus: i64 = 0
363 var absent: i64 = 0
364 var triangulated: i64 = 0
365 var conflict: i64 = 0
366 var single: i64 = 0
367 var dangling: i64 = 0
368 let pq: *i64 = sys_mmap(16) as *i64
369 let lq: *i64 = sys_mmap(16) as *i64
370 let dom: *u8 = sys_mmap(ECOMAT_DOM_CAP)
371 let nr: *u8 = sys_mmap(ECOMAT_NR_CAP)
372 let elog: *u8 = sys_mmap(ECOMAT_EVLOG_CAP)
373 let epat: *u8 = sys_mmap(ECOMAT_EVPAT_CAP)
374 let elog2: *u8 = sys_mmap(ECOMAT_EVLOG_CAP)
375 let epat2: *u8 = sys_mmap(ECOMAT_EVPAT_CAP)
376 let szp2: *i64 = sys_mmap(16) as *i64
377 if (h as i64) != 0 {
378 var k: i64 = 0
379 var go: i64 = 1
380 while go == 1 {
381 let key: *u8 = sys_mmap(64)
382 ec_key(k, key)
383 if ss_hget(h, key, pq, lq) == 1 {
384 let v: *u8 = pq[0] as *u8
385 ec_str(v, 0, dom, ECOMAT_DOM_CAP)
386 var cur: i64 = ec_cur(v)
387 let bar: i64 = ec_bar(v)
388 var ev: i64 = ec_ev(v)
389 // LIVE-DERIVE per the record's own evidence pointer (data-driven, anti-staleness): a grade
390 // is only what its live source currently supports. evkind 1 = permil-derive the LEVEL from
391 // evlog's evpat reading; 2 = gate-liveness (level holds while the gate is GREEN, else demote).
392 // TRIANGULATE via the shared em_domain_level (same logic the page uses, so they can't diverge).
393 let tout: *i64 = sys_mmap(16) as *i64
394 let dl: i64 = em_domain_level(v, tout)
395 let tstat: i64 = tout[0]
396 // any derived status overrides the stored LEVEL; the EVIDENCE flag is set only when a witness
397 // was actually READABLE (single/tri/conflict). DANGLING keeps ev=0 -> a high claim behind a
398 // dead pointer still trips the liar-kill instead of hiding as a silently-demoted TOY.
399 if tstat != 0 { cur = dl }
400 if tstat == 1 { single = single + 1; ev = 1 }
401 if tstat == 2 { triangulated = triangulated + 1; ev = 1 }
402 if tstat == 3 { conflict = conflict + 1; ev = 1 }
403 if tstat == 4 { dangling = dangling + 1; ev = 0 }
404 var viol: i64 = 0
405 if cur >= MAT_SCLASS { if ev == 0 { viol = 1 } }
406 if viol == 1 { bad = bad + 1 }
407 sum_cur = sum_cur + cur
408 sum_bar = sum_bar + bar
409 domains = domains + 1
410 if cur >= MAT_SCLASS { sclass_plus = sclass_plus + 1 }
411 if cur == 0 { absent = absent + 1 }
412 if verbose == 1 {
413 ec_str(v, 0, dom, ECOMAT_DOM_CAP); ec_str(v, 2, nr, ECOMAT_NR_CAP)
414 let lc: *u8 = mat_label(cur)
415 let lb: *u8 = mat_label(bar)
416 let ax: *u8 = ec_axis_label(ec_axis(v))
417 _p(" " as *u8); _p(ax); _p(" / " as *u8); _p(dom); _p(" [" as *u8); _p(lc); _p(" -> " as *u8); _p(lb); _p("] " as *u8)
418 let tl: *u8 = em_tri_label(tstat); _p(tl); _p(" next: " as *u8); _p(nr)
419 if viol == 1 { _p(" <== LIAR-KILL: S-CLASS claim, no evidence" as *u8) }
420 _p("\n" as *u8)
421 }
422 k = k + 1
423 } else { go = 0 }
424 }
425 }
426 var permil: i64 = 0
427 if sum_bar > 0 { permil = (1000 * sum_cur) / sum_bar }
428 out[0] = permil; out[1] = bad; out[2] = domains; out[3] = sclass_plus
429 out[4] = absent; out[5] = auto_permil; out[6] = sum_cur; out[7] = sum_bar
430 out[8] = triangulated; out[9] = conflict; out[10] = single; out[11] = dangling
431 out[12] = auto_age; out[13] = auto_stale
432 if bad > 0 { return 1 }
433 return 0
434}
435
436// ---- TARGET EMIT core (R1): the maturity gaps BECOME ranked work for the loop ----
437func el_contains(buf: *u8, n: i64, pat: *u8) -> i64 {
438 let pl: i64 = el_len(pat)
439 if pl == 0 { return 0 }
440 var i: i64 = 0
441 while i + pl <= n { if el_match(buf, i, pat, pl) == 1 { return 1 } i = i + 1 }
442 return 0
443}
444// ---- EC2 (ecosystem rung, the roadmap ranker's #1 on 2026-09-01): PLAN COVERAGE AS A PUBLISHED ROW ----
445// MEASURED BY HAND 2026-08-21 and then never again: 70 domains, 63 with a plan, 7 without. A number that
446// lives in a session transcript is folklore by the next session. This emits the partition EVERY BEAT,
447// names every planless and ladderless domain (a count without a worklist is not actionable), asserts
448// planless + with_plan = rankable in the row itself, and attributes a ranking refusal to the MISSING PLAN
449// -- refusing a planless domain is the ranker behaving CORRECTLY and must never read as a ranker fault.
450// A domain with a plan but no ver| ladder is counted and named SEPARATELY: the weaker artifact must never
451// be counted as the stronger one, because a plan with no ladder ranks by value alone and sorts wrong for
452// the wrong reason. UNPROVEN is its own exit: an unreadable regen.list publishes NO counts, because an
453// empty population reading as zero-everything would be the vacuous-green defect wearing a census's name.
454const EPC_MODE_LOG: i64 = 0x1a4
455func em_plan_coverage(logpath: *u8) -> i64 {
456 let outn: *i64 = sys_mmap(16) as *i64
457 let which: *i64 = sys_mmap(16) as *i64
458 let lst: *u8 = ct_compare_readall_published("regen" as *u8, ".list" as *u8, outn, which)
459 let ln: i64 = outn[0]
460 if ln <= 0 { _p("PLAN-COVERAGE UNPROVEN -- regen.list unreadable from either compare tree; no counts published\n" as *u8); return 3 }
461 var rankable: i64 = 0
462 var with_plan: i64 = 0
463 var with_ladder: i64 = 0
464 let pn: *i64 = sys_mmap(16) as *i64
465 let pw: *i64 = sys_mmap(16) as *i64
466 let lfd: i64 = sys_openat_append(logpath, EPC_MODE_LOG)
467 var p: i64 = 0
468 while p < ln {
469 var e: i64 = p
470 while e < ln { if lst[e] == (10 as u8) { break } e = e + 1 }
471 var t: i64 = e
472 if t > p { if lst[t-1] == (13 as u8) { t = t - 1 } }
473 lst[t] = 0 as u8
474 let dom: *u8 = ((lst as i64) + p) as *u8
475 p = e + 1
476 if dom[0] != (0 as u8) { if dom[0] != (35 as u8) {
477 rankable = rankable + 1
478 pn[0] = 0
479 let pb: *u8 = ct_compare_readall_published(dom, ".plan" as *u8, pn, pw)
480 if pn[0] > 0 {
481 with_plan = with_plan + 1
482 if el_contains(pb, pn[0], "\nver|" as *u8) == 1 { with_ladder = with_ladder + 1 } else {
483 _p(" NO-LADDER " as *u8); _p(dom); _p(" -- ranks by value alone; UNBLOCK: add ver| rows to its .plan\n" as *u8)
484 if lfd >= 0 { _fp(lfd, "NO-LADDER " as *u8); _fp(lfd, dom); _fp(lfd, "\n" as *u8) }
485 }
486 sys_free_file(pb, pn[0])
487 } else {
488 _p(" PLANLESS " as *u8); _p(dom); _p(" -- the ranker's refusal is CORRECT and attributed HERE, to the missing plan\n" as *u8)
489 if lfd >= 0 { _fp(lfd, "PLANLESS " as *u8); _fp(lfd, dom); _fp(lfd, "\n" as *u8) }
490 }
491 } }
492 }
493 let planless: i64 = rankable - with_plan
494 _p("PLAN-COVERAGE rankable=" as *u8); _fn(1, rankable)
495 _p(" with_plan=" as *u8); _fn(1, with_plan)
496 _p(" planless=" as *u8); _fn(1, planless)
497 _p(" with_ladder=" as *u8); _fn(1, with_ladder)
498 _p(" ladderless_planned=" as *u8); _fn(1, with_plan - with_ladder)
499 _p(" (partition: with_plan+planless=rankable)\n" as *u8)
500 if lfd >= 0 {
501 _fp(lfd, "PLAN-COVERAGE epoch=" as *u8); _fn(lfd, sys_now_realtime_sec())
502 _fp(lfd, " rankable=" as *u8); _fn(lfd, rankable)
503 _fp(lfd, " with_plan=" as *u8); _fn(lfd, with_plan)
504 _fp(lfd, " planless=" as *u8); _fn(lfd, planless)
505 _fp(lfd, " with_ladder=" as *u8); _fn(lfd, with_ladder)
506 _fp(lfd, "\n" as *u8)
507 sys_close(lfd)
508 }
509 return 0
510}
511
512// ---- EC3 (ecosystem rung, ranked #2 on 2026-09-01): CONSUMERS CARRY THE ABSTENTION ----
513// The lib has DECLARED the denominator since 2026-08-22 (out[14]=axes_known, out[15]=partial) and every
514// consumer kept printing the bare permil -- 705 published as a whole-system figure while it averaged 3 of
515// 4 axes; the honest 4-axis reading is UNKNOWN, not 529, because dividing by 4 scores an unmeasured axis
516// as a measured zero. This is the ONE renderer of the autonomy figure: it writes the permil, brands it
517// -PARTIAL inline when the source was partial (so the number cannot be quoted without its caveat riding
518// inside the same token), and appends the machine-readable denominator. A parser taking digits after
519// permil= still reads the same value, so every existing trend reader is untouched -- strictly additive.
520func em_axes_known_guard(fd: i64, permil: i64, axes: i64, partial: i64) -> i64 {
521 _fn(fd, permil)
522 if partial == 1 { _fp(fd, "-PARTIAL" as *u8) }
523 _fp(fd, " autonomy_axes_known=" as *u8); _fn(fd, axes)
524 _fp(fd, " autonomy_partial=" as *u8); _fn(fd, partial)
525 return partial
526}
527
528func et_mkid(domain: *u8, out: *u8) -> i64 {
529 let pre: *u8 = "GEN-MAT-" as *u8
530 var o: i64 = 0
531 var i: i64 = 0
532 while pre[i] != (0 as u8) { out[o]=pre[i]; o=o+1; i=i+1 }
533 i = 0
534 while domain[i] != (0 as u8) { out[o]=domain[i]; o=o+1; i=i+1 }
535 out[o] = 0 as u8
536 return o
537}
538func et_should_emit(domain: *u8, cur: i64, bar: i64, qb: *u8, qn: i64) -> i64 {
539 if cur >= bar { return 0 }
540 let idp: *u8 = sys_mmap(160)
541 et_mkid(domain, idp)
542 if el_contains(qb, qn, idp) == 1 { return 0 }
543 return 1
544}
545// count the targets the emitter WOULD append, reading the STORE (gate proves this without the loop).
546func et_count_targets_store(prefix: *u8, qb: *u8, qn: i64) -> i64 {
547 // ss_open_cached (seq905/962 class fix, seq1347 migration, 2026-07-30). SAFE: open -> ss_hget loop
548 // against this same handle -> return; nothing re-enters the store while the handle is held.
549 let h: *i64 = ss_open_cached(prefix)
550 if (h as i64) == 0 { return 0 }
551 let pq: *i64 = sys_mmap(16) as *i64
552 let lq: *i64 = sys_mmap(16) as *i64
553 let dom: *u8 = sys_mmap(ECOMAT_DOM_CAP)
554 var cnt: i64 = 0
555 var k: i64 = 0
556 var go: i64 = 1
557 while go == 1 {
558 let key: *u8 = sys_mmap(64)
559 ec_key(k, key)
560 if ss_hget(h, key, pq, lq) == 1 {
561 let v: *u8 = pq[0] as *u8
562 let cur: i64 = ec_cur(v)
563 let bar: i64 = ec_bar(v)
564 ec_str(v, 0, dom, ECOMAT_DOM_CAP)
565 let se: i64 = et_should_emit(dom, cur, bar, qb, qn)
566 if se == 1 { cnt = cnt + 1 }
567 k = k + 1
568 } else { go = 0 }
569 }
570 return cnt
571}
572
573// ---- R2 PUBLISH: emit the maturity dashboard as HTML (last-mile render, organ-authored) ----
574func pg_thead(buf: *u8, off: i64) -> i64 {
575 return ss_cat(buf, off, "<tr><th>domain</th><th>level</th><th></th><th>target</th><th>next rung</th><th>w</th></tr>\n" as *u8)
576}
577// emit one <tr> per domain whose axis == want, reading the sovereign store.
578func pg_emit_axis(buf: *u8, off: i64, h: *i64, want: i64) -> i64 {
579 var o: i64 = off
580 let pq: *i64 = sys_mmap(16) as *i64
581 let lq: *i64 = sys_mmap(16) as *i64
582 let dom: *u8 = sys_mmap(ECOMAT_DOM_CAP)
583 let nr: *u8 = sys_mmap(ECOMAT_NR_CAP)
584 var k: i64 = 0
585 var go: i64 = 1
586 while go == 1 {
587 let key: *u8 = sys_mmap(64); ec_key(k, key)
588 if ss_hget(h, key, pq, lq) == 1 {
589 let v: *u8 = pq[0] as *u8
590 if ec_axis(v) == want {
591 let tout: *i64 = sys_mmap(16) as *i64
592 let cur: i64 = em_domain_level(v, tout)
593 let bar: i64 = ec_bar(v)
594 let w: i64 = ec_weight(v)
595 ec_str(v, 0, dom, ECOMAT_DOM_CAP); ec_str(v, 2, nr, ECOMAT_NR_CAP)
596 let lc: *u8 = mat_label(cur)
597 let lb: *u8 = mat_label(bar)
598 let tlab: *u8 = em_tri_label(tout[0])
599 o = ss_cat(buf, o, "<tr><td class=dom>" as *u8); o = ss_cat(buf, o, dom)
600 o = ss_cat(buf, o, "</td><td><span class='b l" as *u8); o = ss_catn(buf, o, cur)
601 o = ss_cat(buf, o, "'>" as *u8); o = ss_cat(buf, o, lc); o = ss_cat(buf, o, "</span> <span class=tri>" as *u8); o = ss_cat(buf, o, tlab); o = ss_cat(buf, o, "</span></td><td class=bar>" as *u8)
602 var s: i64 = 0
603 while s < 5 { if s < cur { o = ss_cat(buf, o, "█" as *u8) } else { o = ss_cat(buf, o, "░" as *u8) } s = s + 1 }
604 o = ss_cat(buf, o, "</td><td>→ " as *u8); o = ss_cat(buf, o, lb)
605 o = ss_cat(buf, o, "</td><td class=nx>" as *u8); o = ss_cat(buf, o, nr)
606 o = ss_cat(buf, o, "</td><td class=w>" as *u8); o = ss_catn(buf, o, w)
607 o = ss_cat(buf, o, "</td></tr>\n" as *u8)
608 }
609 k = k + 1
610 } else { go = 0 }
611 }
612 return o
613}
614// build the whole dashboard from the store + autonomy ledger, write to outhtml. Returns the
615// rollup verdict (0 GREEN, 1 RED liar-kill), or -1 if the store is missing. NO TSV, NO JS.
616func em_emit_page(prefix: *u8, autolog: *u8, outhtml: *u8) -> i64 {
617 let out: *i64 = sys_mmap(256)
618 let verdict: i64 = em_rollup_store(prefix, autolog, out, 0)
619 let h: *i64 = ss_open(prefix)
620 if (h as i64) == 0 { return 0 - 1 }
621 let buf: *u8 = sys_mmap(262144)
622 var o: i64 = 0
623 o = ss_cat(buf, o, "<!doctype html><html lang=en><head><meta charset=utf-8><meta name=viewport content='width=device-width,initial-scale=1'><title>Nishi Ecosystem Maturity</title><style>" as *u8)
624 o = ss_cat(buf, o, "body{margin:0;font:15px/1.5 -apple-system,Segoe UI,Roboto,sans-serif;background:#0e1116;color:#e6edf3}" as *u8)
625 o = ss_cat(buf, o, "header{padding:32px 24px;background:linear-gradient(135deg,#161b22,#0e1116);border-bottom:1px solid #30363d}" as *u8)
626 o = ss_cat(buf, o, "h1{margin:0 0 8px;font-size:22px}.big{font-size:54px;font-weight:800;color:#3fb950;line-height:1}" as *u8)
627 o = ss_cat(buf, o, ".sub{color:#8b949e;font-size:14px;margin-top:6px}.track{height:10px;background:#21262d;border-radius:6px;margin-top:16px;max-width:640px;overflow:hidden}" as *u8)
628 o = ss_cat(buf, o, ".fill{height:100%;background:linear-gradient(90deg,#1f6feb,#3fb950)}h2{margin:28px 24px 10px;font-size:13px;text-transform:uppercase;letter-spacing:.08em;color:#8b949e}" as *u8)
629 o = ss_cat(buf, o, "table{border-collapse:collapse;margin:0 24px 8px;max-width:980px}td,th{padding:8px 10px;border-bottom:1px solid #21262d;text-align:left;font-size:14px}" as *u8)
630 o = ss_cat(buf, o, "th{color:#8b949e;font-size:12px;text-transform:uppercase}.dom{font-weight:650}.bar{font-family:monospace;letter-spacing:2px;color:#3fb950}.nx{color:#8b949e;font-size:13px}.w{text-align:right;color:#d29922}.tri{font-size:11px;color:#6e7681}" as *u8)
631 o = ss_cat(buf, o, ".b{display:inline-block;padding:2px 8px;border-radius:10px;font-size:12px;font-weight:600}" as *u8)
632 o = ss_cat(buf, o, ".l0{background:#490202;color:#ff7b72}.l1{background:#5a1e02;color:#ffa657}.l2{background:#5c4302;color:#e3b341}.l3{background:#234d0a;color:#a5d65b}.l4{background:#0d4429;color:#3fb950}.l5{background:#0a3d62;color:#58a6ff}" as *u8)
633 o = ss_cat(buf, o, "footer{padding:20px 24px;color:#6e7681;font-size:12px;border-top:1px solid #21262d;margin-top:20px}" as *u8)
634 o = ss_cat(buf, o, "</style></head><body><header><h1>Nishi Ecosystem Maturity</h1><div class=big>" as *u8)
635 o = ss_catn(buf, o, out[0]); o = ss_cat(buf, o, "‰</div><div class=sub>toward S-class across " as *u8)
636 o = ss_catn(buf, o, out[2]); o = ss_cat(buf, o, " domains · " as *u8); o = ss_catn(buf, o, out[3])
637 o = ss_cat(buf, o, " at S-class · live autonomy " as *u8); o = ss_catn(buf, o, out[5]); o = ss_cat(buf, o, "‰ · triangulated " as *u8); o = ss_catn(buf, o, out[8]); o = ss_cat(buf, o, "/" as *u8); o = ss_catn(buf, o, out[2]); o = ss_cat(buf, o, " · conflicts " as *u8); o = ss_catn(buf, o, out[9]); o = ss_cat(buf, o, " · dangling " as *u8); o = ss_catn(buf, o, out[11]); o = ss_cat(buf, o, "</div>" as *u8)
638 let pct: i64 = out[0] / 10
639 o = ss_cat(buf, o, "<div class=track><div class=fill style='width:" as *u8); o = ss_catn(buf, o, pct); o = ss_cat(buf, o, "%'></div></div></header>" as *u8)
640 o = ss_cat(buf, o, "<h2>Depth — substrate</h2><table>" as *u8); o = pg_thead(buf, o); o = pg_emit_axis(buf, o, h, 0); o = ss_cat(buf, o, "</table>" as *u8)
641 o = ss_cat(buf, o, "<h2>Breadth — products</h2><table>" as *u8); o = pg_thead(buf, o); o = pg_emit_axis(buf, o, h, 1); o = ss_cat(buf, o, "</table>" as *u8)
642 o = ss_cat(buf, o, "<h2>Meta</h2><table>" as *u8); o = pg_thead(buf, o); o = pg_emit_axis(buf, o, h, 2); o = ss_cat(buf, o, "</table>" as *u8)
643 o = ss_cat(buf, o, "<footer>sourced from the sovereign seg_store (knowledge/store/ecomat) · no TSV · generated epoch " as *u8)
644 o = ss_catn(buf, o, sys_now_realtime_sec()); o = ss_cat(buf, o, " · measured, never asserted" as *u8)
645 if verdict != 0 { o = ss_cat(buf, o, " · <b style=color:#ff7b72>LIAR-KILL FIRED</b>" as *u8) }
646 o = ss_cat(buf, o, "</footer></body></html>\n" as *u8)
647 ss_writefile(outhtml, buf, o)
648 return verdict
649}
650
651// ---- shared target-emit loop (used by the emitter CLI AND the flywheel beat) ----
652// Caller holds the lock and supplies open append fds qf (queue) + lf (targets log). Iterates the store,
653// appends one TODO target per below-bar domain (idempotent vs qb), writes an auto-close marker per at-bar
654// domain. out[0]=emitted out[1]=done_marks. Returns 0, or -1 if the store is missing.
655func et_emit_targets_core(store: *u8, qb: *u8, qn: i64, qf: i64, lf: i64, out: *i64) -> i64 {
656 let h: *i64 = ss_open(store)
657 if (h as i64) == 0 { out[0] = 0; out[1] = 0; return 0 - 1 }
658 let pq: *i64 = sys_mmap(16) as *i64
659 let lq: *i64 = sys_mmap(16) as *i64
660 let idp: *u8 = sys_mmap(160)
661 let dom: *u8 = sys_mmap(ECOMAT_DOM_CAP)
662 let nr: *u8 = sys_mmap(ECOMAT_NR_CAP)
663 let szb: *u8 = sys_mmap(2)
664 var emitted: i64 = 0
665 var done_marks: i64 = 0
666 var k: i64 = 0
667 var go: i64 = 1
668 while go == 1 {
669 let key: *u8 = sys_mmap(64); ec_key(k, key)
670 if ss_hget(h, key, pq, lq) == 1 {
671 let v: *u8 = pq[0] as *u8
672 let cur: i64 = ec_cur(v)
673 let bar: i64 = ec_bar(v)
674 let w: i64 = ec_weight(v)
675 ec_str(v, 0, dom, ECOMAT_DOM_CAP); ec_str(v, 2, nr, ECOMAT_NR_CAP)
676 if cur >= bar {
677 if lf >= 0 { _fp(lf, "ECOMAT-DONE domain=" as *u8); _fp(lf, dom); _fp(lf, " at-bar epoch=" as *u8); _fn(lf, sys_now_realtime_sec()); _fp(lf, "\n" as *u8) }
678 done_marks = done_marks + 1
679 } else {
680 let se: i64 = et_should_emit(dom, cur, bar, qb, qn)
681 if se == 1 {
682 et_mkid(dom, idp)
683 let gap: i64 = bar - cur
684 var sz: i64 = 83
685 if gap == 2 { sz = 77 }
686 if gap >= 3 { sz = 76 }
687 szb[0] = sz as u8; szb[1] = 0 as u8
688 _fp(qf, idp); _fp(qf, "\tMAT\t" as *u8); _fn(qf, w)
689 _fp(qf, "\t" as *u8); _fp(qf, szb)
690 _fp(qf, "\tPM\tTODO\t-\tecomat-" as *u8); _fp(qf, dom)
691 _fp(qf, "-at-bar||MARK=knowledge/status/ecomat_targets.log::ECOMAT-DONE domain=" as *u8); _fp(qf, dom)
692 _fp(qf, "\tmaturity target: raise " as *u8); _fp(qf, dom)
693 _fp(qf, " toward bar -- " as *u8); _fp(qf, nr)
694 _fp(qf, " (autogenerated; w=" as *u8); _fn(qf, w)
695 _fp(qf, "; auto-closes when domain reaches bar)\n" as *u8)
696 if lf >= 0 { _fp(lf, "ECOMAT-TARGET id=" as *u8); _fp(lf, idp); _fp(lf, " w=" as *u8); _fn(lf, w); _fp(lf, " gap=" as *u8); _fn(lf, gap); _fp(lf, "\n" as *u8) }
697 emitted = emitted + 1
698 }
699 }
700 k = k + 1
701 } else { go = 0 }
702 }
703 out[0] = emitted
704 out[1] = done_marks
705 return 0
706}
707
708// Additive requirements-v1: authored investment contract, never a maturity scorer.
709const EM_REQUIREMENT_COUNT:i64=6
710func em_req_id(i:i64)->*u8 {
711 if i==0 {return "defined" as *u8}
712 if i==1 {return "callable" as *u8}
713 if i==2 {return "composable" as *u8}
714 if i==3 {return "dependable" as *u8}
715 if i==4 {return "adaptive" as *u8}
716 if i==5 {return "frontier-qualified" as *u8}
717 return "" as *u8
718}
719func em_req_label(i:i64)->*u8 {
720 if i==0 {return "Defined" as *u8}
721 if i==1 {return "Callable" as *u8}
722 if i==2 {return "Composable" as *u8}
723 if i==3 {return "Dependable" as *u8}
724 if i==4 {return "Adaptive" as *u8}
725 if i==5 {return "Frontier-qualified" as *u8}
726 return "" as *u8
727}
728func em_req_is(b:*u8,p:i64,e:i64,col:i64,s:*u8)->i64 {
729 var o:i64=0;let n:i64=bf_field(b,p,e,col,&o)
730 return pb_equal(b,o,n,s,0,bf_slen(s))
731}
732func em_req_validate(b:*u8,n:i64)->i64 {
733 if n<=0 {return -1}
734 if pb_input_ok(b,n)==0 {return -1}
735 if b[n-1]!=(10 as u8) {return -1}
736 var p:i64=0;var r:i64=0;var investments:i64=0
737 while p<n {
738 let raw:i64=bf_line_end(b,n,p);let e:i64=pb_trim_cr(b,p,raw)
739 var fields:i64=0;var scratch:i64=0
740 let req:i64=bf_line_starts(b,p,e,"maturityrequirement|")
741 let inv:i64=bf_line_starts(b,p,e,"maturityinvestment|")
742 if req+inv!=1 {return -2}
743 if req==1 {fields=8} else {fields=12}
744 if pb_field_count(b,p,e,&scratch)!=fields {return -2}
745 var c:i64=1;while c<fields {if bf_field(b,p,e,c,&scratch)<=0 {return -2};c=c+1}
746 if em_req_is(b,p,e,1,"1")==0 {return -3}
747 let idn:i64=bf_field(b,p,e,2,&scratch)
748 if cg_ident(b,scratch,idn)==0 {return -3}
749 var prev:i64=0
750 while prev<p {let pe:i64=bf_line_end(b,n,prev);var po:i64=0;let pn:i64=bf_field(b,prev,pe,2,&po);if pb_equal(b,scratch,idn,b,po,pn)==1 {return -4};prev=pe+1}
751 if req==1 {
752 if investments>0||r>=EM_REQUIREMENT_COUNT {return -5}
753 if em_req_is(b,p,e,2,em_req_id(r))==0||em_req_is(b,p,e,3,em_req_label(r))==0 {return -5}
754 var dep:*u8="-" as *u8;if r>0 {dep=em_req_id(r-1)}
755 if em_req_is(b,p,e,4,dep)==0 {return -5}
756 r=r+1
757 } else {
758 if r!=EM_REQUIREMENT_COUNT {return -5}
759 var io:i64=0;let bn:i64=bf_field(b,p,e,3,&io);if cg_ident(b,io,bn)==0 {return -3}
760 let cn:i64=bf_field(b,p,e,4,&io);if cg_ident(b,io,cn)==0 {return -3}
761 if em_req_is(b,p,e,11,"pending-acceptance")==0 {return -6}
762 investments=investments+1
763 }
764 p=raw+1
765 }
766 if r!=EM_REQUIREMENT_COUNT||investments==0 {return -5}
767 return investments
768}
769func em_req_key(col:i64,kind:i64)->*u8 {
770 if col==2 {return "id" as *u8}
771 if kind==1 {
772 if col==3 {return "label" as *u8};if col==4 {return "prerequisite" as *u8}
773 if col==5 {return "required_evidence" as *u8};if col==6 {return "acceptance_rule" as *u8}
774 return "workflow_steps" as *u8
775 }
776 if col==3 {return "board" as *u8};if col==4 {return "capability_id" as *u8}
777 if col==5 {return "operator_priority" as *u8};if col==6 {return "dependency_refs_authored" as *u8}
778 if col==7 {return "evidence_refs_authored" as *u8};if col==8 {return "next_action" as *u8}
779 if col==9 {return "reusable_reach_authored" as *u8};if col==10 {return "measurement_requirements" as *u8}
780 return "acceptance_state" as *u8
781}
782func em_req_rows(w:*JsonWriter,b:*u8,n:i64,kind:i64)->i64 {
783 if json_begin_array(w)<0 {return -1}
784 var p:i64=0
785 while p<n {
786 let raw:i64=bf_line_end(b,n,p);let e:i64=pb_trim_cr(b,p,raw)
787 var tag:*u8="maturityrequirement|" as *u8;var fields:i64=8
788 if kind==2 {tag="maturityinvestment|" as *u8;fields=12}
789 if bf_line_starts(b,p,e,tag)==1 {
790 if json_begin_object(w)<0 {return -1}
791 var c:i64=2
792 while c<fields {var o:i64=0;let len:i64=bf_field(b,p,e,c,&o);if cg_jkey(w,em_req_key(c,kind))<0 {return -1};if json_emit_string(w,((b as i64)+o) as *u8,len)<0 {return -1};c=c+1}
793 if cg_jnull(w,"evidence_verified")<0 {return -1}
794 if cg_jnull(w,"maturity_achieved")<0 {return -1}
795 if cg_jnull(w,"investment_return_measured")<0 {return -1}
796 if cg_jkey(w,"reference_resolution")<0 {return -1}
797 if cg_jstr(w,"external_evidence_and_capability_refs_unresolved")<0 {return -1}
798 if json_end_object(w)<0 {return -1}
799 }
800 p=raw+1
801 }
802 return json_end_array(w)
803}
804func em_requirements_into(b:*u8,n:i64,out:*u8,cap:i64)->i64 {
805 let valid:i64=em_req_validate(b,n);if valid<0 {return valid}
806 if cap<=0||(out as i64)<=0 {return -7}
807 let w:*JsonWriter=sys_mmap(CG_JSON_WRITER_WORDS*8) as *JsonWriter
808 if (w as i64)<=0 {return -7}
809 if json_writer_init(w,out,cap)<0 {return -7}
810 var ok:i64=json_begin_object(w)
811 if ok>=0 {ok=cg_jkey(w,"version")};if ok>=0 {ok=json_emit_int(w,1)}
812 if ok>=0 {ok=cg_jkey(w,"scope")};if ok>=0 {ok=cg_jstr(w,"requirements_and_pending_investment_not_achieved_maturity")}
813 if ok>=0 {ok=cg_jkey(w,"legacy_grade_conversion")};if ok>=0 {ok=json_emit_null(w)}
814 if ok>=0 {ok=cg_jkey(w,"requirements")};if ok>=0 {ok=em_req_rows(w,b,n,1)}
815 if ok>=0 {ok=cg_jkey(w,"investments")};if ok>=0 {ok=em_req_rows(w,b,n,2)}
816 if ok>=0 {ok=json_end_object(w)}
817 let length:i64=w.pos
818 sys_munmap(w.prior,JE_MAX_DEPTH+16);sys_munmap(w as *u8,CG_JSON_WRITER_WORDS*8)
819 if ok<0 {return -7};return length
820}
821func em_req_capacity(s:*u8)->i64 {
822 var i:i64=0;var v:i64=0
823 while s[i]!=(0 as u8) {let d:i64=(s[i] as i64)-48;if d<0||d>9 {return -1};if v>(PB_I64_MAX-d)/10 {return -1};v=v*10+d;i=i+1}
824 if i==0||v<=0 {return -1};return v
825}
826func em_requirements_run(path:*u8,inputcap:i64,outputcap:i64)->i64 {
827 if inputcap<=0||outputcap<=0 {return 2}
828 let b:*u8=sys_mmap(inputcap);let out:*u8=sys_mmap(outputcap);let st:*i64=sys_mmap(24) as *i64
829 if (b as i64)<=0||(out as i64)<=0||(st as i64)<=0 {return 3}
830 let n:i64=rc_read_file_into(path,b,inputcap,st)
831 if rc_complete(st)==0 {sys_munmap(b,inputcap);sys_munmap(out,outputcap);sys_munmap(st as *u8,24);return 3}
832 let length:i64=em_requirements_into(b,n,out,outputcap)
833 var rc:i64=4
834 if length>=0 {if sys_write(1,out,length)==length {sys_write(1,"\n",1);rc=0}}
835 sys_munmap(b,inputcap);sys_munmap(out,outputcap);sys_munmap(st as *u8,24);return rc
836}