nx_workmix.nx source
↩ module page · 180 lines · 8434 B
1// nx_workmix.nx -- THE WORK-MIX CENSUS (ecosystem EC56, 2026-09-17): what LANDED in the window, classed FEATURE,
2// ENABLEMENT, REWORK or UNCLASSED, so investment is a measured axis and the mix can be steered toward features.
3// usage: nx_workmix census [days] [ledger]
4// reads the costcal ledger (land, retract and open rows; ONE reader of the boards' journals wrote them),
5// every published board's plan (rungrole rows and deps only), the class table compare/workmix.conf
6// prints the partition, the boards no class row names (the shrink-only worklist), then ONE canonical WORKMIX line LAST
7// writes that line to knowledge/status/workmix.status (truncate) and appends it to knowledge/status/workmix.log;
8// a run over a non-default ledger writes BESIDE that ledger, never over the production status
9// exit 0 CENSUSED | 2 usage | 3 NO-LEDGER or NO-POPULATION (could not look is never an empty window)
10// The ruler is nx_workmix_lib (wm_mix_census); this file only gathers the inputs and publishes the line.
11// license_tier: ORIGINAL No hw writes (Rule 26).
12import "nx_syscalls.nx"
13import "nx_costest_lib.nx"
14import "nx_ladder_lib.nx"
15import "nx_comparetree_lib.nx"
16import "nx_workmix_lib.nx"
17
18const WP_LEDGER: *u8 = "knowledge/status/costcal.ledger"
19const WP_STATUS: *u8 = "knowledge/status/workmix.status" // ONE canonical line, truncate-written
20const WP_LOG: *u8 = "knowledge/status/workmix.log" // the same line appended: one census says a level, two say a trend
21const WP_STATUS_SFX: *u8 = ".workmix.status"
22const WP_LOG_SFX: *u8 = ".workmix.log"
23const WP_CONF_NAME: *u8 = "workmix"
24const WP_CONF_SFX: *u8 = ".conf"
25const WP_LIST_NAME: *u8 = "regen"
26const WP_LIST_SFX: *u8 = ".list"
27const WP_DAY_S: i64 = 86400
28const WP_EXIT_OK: i64 = 0
29const WP_EXIT_USAGE: i64 = 2
30const WP_EXIT_UNOBS: i64 = 3
31
32func wp_w(s: *u8) -> i64 { return sys_write(1, s, ces_slen(s)) }
33func wp_n(v: i64) -> i64 {
34 let b: *u8 = sys_mmap(CES_NUM_CAP + 1)
35 let o: i64 = ces_fmt_int(b, 0, v)
36 return sys_write(1, b, o)
37}
38
39func wp_usage() -> i64 {
40 wp_w("usage: nx_workmix census [days] [ledger]\n" as *u8)
41 wp_w("exit 0 CENSUSED | 2 usage | 3 NO-LEDGER or NO-POPULATION\n" as *u8)
42 return WP_EXIT_USAGE
43}
44
45func wp_span_copy(buf: *u8, off: i64, len: i64) -> *u8 {
46 let d: *u8 = sys_mmap(len + 1)
47 wm_copy_span(d, 0, buf, off, len)
48 return d
49}
50
51// a compare-tree file by name, first published tree then the second: the resolver, never a hand-rolled path
52func wp_read_compare(name: *u8, sfx: *u8, lenp: *i64) -> *u8 {
53 let path: *u8 = sys_mmap(CT_PATH_CAP)
54 lenp[0] = 0
55 ct_build_path(ct_first_published(), name, sfx, path)
56 var b: *u8 = sys_read_file(path, lenp)
57 if lenp[0] <= 0 {
58 ct_build_path(ct_second_published(), name, sfx, path)
59 b = sys_read_file(path, lenp)
60 }
61 return b
62}
63
64func wp_beside(base: *u8, sfx: *u8) -> *u8 {
65 let d: *u8 = sys_mmap(ces_slen(base) + ces_slen(sfx) + 1)
66 let o: i64 = ces_cat(d, 0, base)
67 ces_cat(d, o, sfx)
68 return d
69}
70
71func wp_census(days: i64, ledger: *u8, isdefault: i64) -> i64 {
72 let lenp: *i64 = sys_mmap(WM_I64) as *i64
73 lenp[0] = 0
74 let led: *u8 = sys_read_file(ledger, lenp)
75 let ln: i64 = lenp[0]
76 if ln <= 0 {
77 wp_w("WORKMIX ledger=" as *u8); wp_w(ledger); wp_w(" UNREADABLE: the costcal beat has not written it, so what landed is UNMEASURED verdict=NO-LEDGER\n" as *u8)
78 return WP_EXIT_UNOBS
79 }
80 let st: *i64 = sys_mmap(CES_S_SLOTS * WM_I64) as *i64
81 var ledger_asof: i64 = CES_NONE
82 if ces_cal_parse(led, ln, st) == 1 { ledger_asof = st[CES_S_ASOF] }
83 let cnp: *i64 = sys_mmap(WM_I64) as *i64
84 let conf: *u8 = wp_read_compare(WP_CONF_NAME, WP_CONF_SFX, cnp)
85 var cn: i64 = cnp[0]
86 if cn < 0 { cn = 0 }
87 let lnp: *i64 = sys_mmap(WM_I64) as *i64
88 let lst: *u8 = wp_read_compare(WP_LIST_NAME, WP_LIST_SFX, lnp)
89 let lsn: i64 = lnp[0]
90 if lsn <= 0 { wp_w("WORKMIX regen.list UNREADABLE in both trees verdict=NO-POPULATION\n" as *u8); return WP_EXIT_UNOBS }
91 // the boards: arrays sized from the list itself (one slot per line)
92 var nlines: i64 = 1
93 var c0: i64 = 0
94 while c0 < lsn { if lst[c0] == (CES_CH_NL as u8) { nlines = nlines + 1 } c0 = c0 + 1 }
95 let names: *i64 = sys_mmap(nlines * WM_I64) as *i64
96 let pbuf: *i64 = sys_mmap(nlines * WM_I64) as *i64
97 let plen: *i64 = sys_mmap(nlines * WM_I64) as *i64
98 let which: *i64 = sys_mmap(WM_I64) as *i64
99 var np: i64 = 0
100 var noplan: i64 = 0
101 var ibound: i64 = 1
102 var nclassless: i64 = 0
103 var p: i64 = 0
104 wp_w("WORKMIX-UNCLASSED-BOARDS (no row in the class table; their rungs class only by rungrole):" as *u8)
105 while p < lsn {
106 let e: i64 = ces_line_end(lst, lsn, p)
107 let l: i64 = e - p
108 if l > 0 { if lst[p] != (CES_CH_HASH as u8) {
109 let name: *u8 = wp_span_copy(lst, p, l)
110 if wm_board_class(conf, cn, name) == WM_B_NONE { nclassless = nclassless + 1; wp_w(" " as *u8); wp_w(name) }
111 lenp[0] = 0
112 let plan: *u8 = bf_read_plan(ct_first_published(), ct_second_published(), name, lenp, which)
113 if lenp[0] > 0 {
114 names[np] = name as i64
115 pbuf[np] = plan as i64
116 plen[np] = lenp[0]
117 ibound = ibound + wm_index_bound(lenp[0], name)
118 np = np + 1
119 } else { noplan = noplan + 1 }
120 } }
121 p = e + 1
122 }
123 wp_w("\n" as *u8)
124 // the feature-deps index, built once: which rungs does a FEATURE rung stand on
125 let idx: *u8 = sys_mmap(ibound)
126 var idxn: i64 = 0
127 var b: i64 = 0
128 while b < np {
129 let nm: *u8 = names[b] as *u8
130 idxn = wm_index_board(pbuf[b] as *u8, plen[b], nm, wm_board_class(conf, cn, nm), idx, idxn)
131 b = b + 1
132 }
133 let now: i64 = sys_now_realtime_sec()
134 let acc: *i64 = sys_mmap(WM_A_SLOTS * WM_I64) as *i64
135 wm_mix_census(led, ln, now - days * WP_DAY_S, now + 1, conf, cn, names, pbuf, plen, np, idx, idxn, acc)
136 wp_w("WORKMIX-INPUTS ledger=" as *u8); wp_w(ledger); wp_w(" ledger_bytes=" as *u8); wp_n(ln)
137 wp_w(" ledger_asof=" as *u8); wp_n(ledger_asof)
138 wp_w(" ledger_age_s=" as *u8)
139 if ledger_asof >= 0 { wp_n(now - ledger_asof) } else { wp_n(CES_NONE) }
140 wp_w(" class_table_bytes=" as *u8); wp_n(cn); wp_w(" boards_read=" as *u8); wp_n(np); wp_w(" boards_noplan=" as *u8); wp_n(noplan)
141 wp_w(" boards_without_a_class=" as *u8); wp_n(nclassless); wp_w(" feature_deps_index_bytes=" as *u8); wp_n(idxn); wp_w("\n" as *u8)
142 var k: i64 = 0
143 while k < WM_CLASSES {
144 wp_w(" class=" as *u8); wp_w(wm_class_name(k)); wp_w(" land_rows=" as *u8); wp_n(acc[WM_A_EV + k])
145 wp_w(" deciu=" as *u8); wp_n(acc[WM_A_DECIU + k]); wp_w(" permil_of_rows=" as *u8); wp_n(wm_permil(acc[WM_A_EV + k], acc[WM_A_LAND])); wp_w("\n" as *u8)
146 k = k + 1
147 }
148 let line: *u8 = sys_mmap(wm_line_bound())
149 let lo: i64 = wm_line(line, 0, now, days, np, acc)
150 // publish: the status line truncate-written, the same line appended to the log. A non-default ledger publishes beside itself.
151 var sp: *u8 = WP_STATUS
152 var lp: *u8 = WP_LOG
153 if isdefault == 0 { sp = wp_beside(ledger, WP_STATUS_SFX); lp = wp_beside(ledger, WP_LOG_SFX) }
154 var swrote: i64 = 0
155 let sfd: i64 = sys_openat_wr(sp, MODE_0644)
156 if sfd >= 0 { if sys_write(sfd, line, lo) == lo { swrote = 1 } sys_close(sfd) }
157 var lwrote: i64 = 0
158 let lfd: i64 = sys_openat_append(lp, MODE_0644)
159 if lfd >= 0 { if sys_write(lfd, line, lo) == lo { lwrote = 1 } sys_close(lfd) }
160 wp_w("WORKMIX-PUBLISH status=" as *u8); wp_w(sp); wp_w(" wrote=" as *u8); wp_n(swrote); wp_w(" log=" as *u8); wp_w(lp); wp_w(" appended=" as *u8); wp_n(lwrote); wp_w("\n" as *u8)
161 sys_write(1, line, lo)
162 return WP_EXIT_OK
163}
164
165func main(argc: i64, argv: *i64) -> i64 {
166 if argc < 2 { return wp_usage() }
167 let verb: *u8 = argv[1] as *u8
168 if ces_span_is(verb, 0, ces_slen(verb), "census" as *u8) == 0 { return wp_usage() }
169 var days: i64 = CES_WIP_ACTIVE_S / WP_DAY_S
170 if argc > 2 {
171 let a: *u8 = argv[2] as *u8
172 let d: i64 = ces_parse_int(a, 0, ces_slen(a))
173 if d <= 0 { return wp_usage() }
174 days = d
175 }
176 var ledger: *u8 = WP_LEDGER
177 var isdefault: i64 = 1
178 if argc > 3 { ledger = argv[3] as *u8; isdefault = 0 }
179 return wp_census(days, ledger, isdefault)
180}