code wiki / _hdl_build / nx_seat_meter_beat.nx
nx_seat_meter_beat.nx source
↩ module page · 1109 lines · 56340 B
1// nx_seat_meter_beat.nx -- ES1 of /compare/engineshift: THE SCOREBOARD'S PRODUCER (laptop-local, 2026-09-02).
2// nx_seat shift (F831) grades the engine shift from knowledge/status/token_efficiency.log, and every row that log
3// has ever held was appended BY HAND: 16 rows, the last dated 2026-08-05, no hook, clock row or organ names
4// `nx_seat meter`. A gauge whose rows are hand-appended is a diary, not a gauge -- it stops the day the hand
5// stops and reads as "no movement" forever (the local column read ZERO for 44 days and was quoted twice as a
6// finding about the estate). This organ is the producer. It rides the SessionStart hook beside nx_crashwin.
7//
8// WHAT IT MEASURES. Every Claude Code transcript (<sessions>/*.jsonl) carries one line per assistant content
9// block, and EVERY block of one message repeats that message's usage object (measured 2026-09-02: 367 assistant
10// lines for 58 distinct message ids in one transcript). So usage is counted ONCE PER MESSAGE ID, never per line;
11// a naive sum overcounts about six-fold. Per complete UTC day and model family it sums output_tokens,
12// cache_read_input_tokens and cache_creation_input_tokens, counts messages, and counts the transcripts active
13// that day (the row's `sessions` column). A line is an assistant line when it carries a raw "type":"assistant"
14// (tool results are escaped strings and cannot); the message's OWN model, id and usage are the DEPTH-1 children of
15// "message":{ -- a tool_use input is raw JSON and may carry model and id fields of its own, so position on the line
16// decides nothing (neg-controls in the gate). Harness API-error lines (model "<synthetic>") are their own bucket.
17//
18// nx_seat_meter_beat scan <sessions-dir> [--now <epoch>] [--days N]
19// prints one DAY row per (day, family) inside the window and a METERBEAT summary; writes nothing.
20// nx_seat_meter_beat beat <sessions-dir> <state-dir> <mcp-elf> <base-url> <cap-file> [--now <epoch>] [--days N]
21// [--dry] [--json]
22// for every COMPLETE day (strictly before today, UTC) in the window whose (day, family) is not yet in
23// <state-dir>/meterbeat.days, forks <mcp-elf> (nx_mcp_call) to run `nx_seat meter` on the estate and, on
24// the reply "METERED row appended", records the marker -- idempotent by day marker: a second run appends
25// nothing. --dry plans and prints, forks nothing, marks nothing. --json wraps the digest as a SessionStart
26// hook envelope and exits 0 (the hook framework parses stdout only on exit 0).
27// Today is NEVER pushed: an incomplete day would be re-summed tomorrow and the marker would make it final.
28// Window: --days N (default MB_DAYS_DEFAULT) complete days; transcripts whose mtime predates the window start
29// are not read (they cannot carry a newer day), so a session-start run touches only recent files.
30// A transcript whose last line has no newline is counted PARTIAL: its complete lines count, the tail does not,
31// and the summary says so -- a truncated file is never read as zero.
32// Exit: 0 GREEN | 1 RED (a push was refused or answered without the METERED receipt) | 2 usage |
33// 3 UNOBSERVABLE (the sessions dir cannot be opened). verdict= is the LAST token of the last line.
34// license_tier: ORIGINAL. Writes only <state-dir>/meterbeat.days. No hw writes (Rule 26).
35import "nx_syscalls.nx"
36import "nx_memplane_lib.nx"
37import "nx_tool_run.nx"
38
39const MB_DAYS_DEFAULT: i64 = 3 // a hook run owes yesterday and the day before; older days were owed earlier
40const MB_DAYS_MAX: i64 = 400 // distinct days one run can hold; reaching it announces days_floor=1
41const MB_FAM_MAX: i64 = 8 // model families per run (fable, opus, sonnet, haiku, ...)
42const MB_FAM_CAP: i64 = 32 // one family token cell
43const MB_SLOT: i64 = 256 // one transcript name cell (names measured 42 B)
44const MB_FILES_MAX: i64 = 4096 // 220 transcripts on 2026-09-02; reaching the cap announces files_floor=1
45const MB_PATH: i64 = 4096 // PATH_MAX
46const MB_DENTBUF: i64 = 262144 // getdents64 batch buffer, LOOPED to completion
47const MB_STATBUF: i64 = 256 // struct stat is 144 B on x86_64
48const MB_STAT_MTIME_SLOT: i64 = 11 // st_mtim.tv_sec at byte 88 = i64[11]
49const MB_DOT: i64 = 46
50const MB_QUOTE: i64 = 34
51const MB_NL: i64 = 10
52const MB_DASH: i64 = 45
53const MB_ID_CAP: i64 = 64 // msg_ ids measured 30 B
54const MB_ID_RING: i64 = 8 // blocks of one message are consecutive; a ring of 8 absorbs interleaving
55const MB_OUT: i64 = 262144 // report buffer (400 days x 8 families x ~120 B fits 4x over)
56const MB_DAY_LEN: i64 = 10 // YYYY-MM-DD
57const MB_SEC_PER_DAY: i64 = 86400
58const MB_EXIT_OK: i64 = 0
59const MB_EXIT_RED: i64 = 1
60const MB_EXIT_USAGE: i64 = 2
61const MB_EXIT_UNOBS: i64 = 3
62const MB_FORK_TIMEOUT_MS: i64 = 60000 // the estate appends one row; 60 s covers a saturated box
63const MB_RESP_CAP: i64 = 65536
64const MB_READ_SLACK: i64 = 16 // sys_read_file maps size+16; released with the same arithmetic
65const MB_MARK_CAP: i64 = 1048576 // marker file window; 400 days x 8 families x ~64 B is 200 KB
66const MB_ARGV_MAX: i64 = 8
67const MB_FRAG_CAP: i64 = 1024
68const MB_NOTE_CAP: i64 = 256
69const MB_DIGITS_MAX: i64 = 18 // an i64 holds 18 full decimal digits; longer runs are malformed
70const MB_HINNANT_OFFSET: i64 = 719468 // days_from_civil: 1970-01-01 is day 719468 of the proleptic era count
71const MB_ERA_DAYS: i64 = 146097
72const MB_ERA_YEARS: i64 = 400
73const MB_DOY_MUL: i64 = 153
74const MB_DOY_ADD: i64 = 2
75const MB_DOY_DIV: i64 = 5
76const MB_YEAR_DAYS: i64 = 365
77const MB_KEY_YEAR_MUL: i64 = 10000 // day key = y*10000 + m*100 + d, printable back with dashes
78const MB_KEY_MON_MUL: i64 = 100
79const MB_CELLS: i64 = 3200 // MB_DAYS_MAX * MB_FAM_MAX
80const MB_I64: i64 = 8
81
82// ---- small helpers --------------------------------------------------------------------------------------
83func mb_slot(base: *u8, k: i64) -> *u8 { return ((base as i64) + k * MB_SLOT) as *u8 }
84func mb_famslot(base: *u8, k: i64) -> *u8 { return ((base as i64) + k * MB_FAM_CAP) as *u8 }
85
86func mb_copy(dst: *u8, src: *u8, cap: i64) -> i64 {
87 var i: i64 = 0
88 while i < cap - 1 {
89 if src[i] == (0 as u8) { dst[i] = 0 as u8; return i }
90 dst[i] = src[i]
91 i = i + 1
92 }
93 dst[i] = 0 as u8
94 return i
95}
96
97func mb_ends_with(name: *u8, ext: *u8) -> i64 {
98 let nl: i64 = mp_len(name)
99 let el: i64 = mp_len(ext)
100 if nl < el { return 0 }
101 var i: i64 = 0
102 while i < el { if name[nl - el + i] != ext[i] { return 0 } i = i + 1 }
103 return 1
104}
105
106func mb_atoi(s: *u8) -> i64 {
107 var v: i64 = 0
108 var i: i64 = 0
109 while s[i] != (0 as u8) {
110 let c: i64 = s[i] as i64
111 if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } }
112 i = i + 1
113 }
114 return v
115}
116
117// find literal `lit` in buf[s..e) scanning FORWARD; returns the offset of its first byte or -1
118func mb_find(buf: *u8, s: i64, e: i64, lit: *u8) -> i64 {
119 let ll: i64 = mp_len(lit)
120 if ll == 0 { return 0 - 1 }
121 var i: i64 = s
122 while i + ll <= e {
123 var j: i64 = 0
124 var same: i64 = 1
125 var scan: i64 = 1
126 while scan == 1 {
127 if j >= ll { scan = 0 } else {
128 if buf[i + j] != lit[j] { same = 0; scan = 0 } else { j = j + 1 }
129 }
130 }
131 if same == 1 { return i }
132 i = i + 1
133 }
134 return 0 - 1
135}
136
137// find the LAST occurrence of `lit` in buf[s..e); returns its offset or -1
138func mb_rfind(buf: *u8, s: i64, e: i64, lit: *u8) -> i64 {
139 let ll: i64 = mp_len(lit)
140 if ll == 0 { return 0 - 1 }
141 var i: i64 = e - ll
142 while i >= s {
143 var j: i64 = 0
144 var same: i64 = 1
145 var scan: i64 = 1
146 while scan == 1 {
147 if j >= ll { scan = 0 } else {
148 if buf[i + j] != lit[j] { same = 0; scan = 0 } else { j = j + 1 }
149 }
150 }
151 if same == 1 { return i }
152 i = i - 1
153 }
154 return 0 - 1
155}
156
157// parse the decimal integer that starts at buf[i] and ends before e or a non-digit; -1 when no digit is there
158func mb_int_at(buf: *u8, i0: i64, e: i64) -> i64 {
159 var i: i64 = i0
160 var v: i64 = 0
161 var digits: i64 = 0
162 var scan: i64 = 1
163 while scan == 1 {
164 if i >= e { scan = 0 } else {
165 let c: i64 = buf[i] as i64
166 if c < 48 { scan = 0 } else { if c > 57 { scan = 0 } else {
167 if digits >= MB_DIGITS_MAX { return 0 - 1 }
168 v = v * 10 + (c - 48); digits = digits + 1; i = i + 1
169 } }
170 }
171 }
172 if digits == 0 { return 0 - 1 }
173 return v
174}
175
176// the integer after `key` within buf[s..e), FIRST occurrence; -1 when absent or unparseable
177func mb_int_after(buf: *u8, s: i64, e: i64, key: *u8) -> i64 {
178 let p: i64 = mb_find(buf, s, e, key)
179 if p < 0 { return 0 - 1 }
180 return mb_int_at(buf, p + mp_len(key), e)
181}
182
183// Hinnant days_from_civil, valid for every civil date after 0000-03-01; integer arithmetic only
184func mb_days_from_civil(y0: i64, m: i64, d: i64) -> i64 {
185 var y: i64 = y0
186 if m <= 2 { y = y - 1 }
187 let era: i64 = y / MB_ERA_YEARS
188 let yoe: i64 = y - era * MB_ERA_YEARS
189 var mm: i64 = m + 9
190 if m > 2 { mm = m - 3 }
191 let doy: i64 = (MB_DOY_MUL * mm + MB_DOY_ADD) / MB_DOY_DIV + d - 1
192 let doe: i64 = yoe * MB_YEAR_DAYS + yoe / 4 - yoe / 100 + doy
193 return era * MB_ERA_DAYS + doe - MB_HINNANT_OFFSET
194}
195
196// YYYY-MM-DD at buf[i..i+10) -> day key y*10000+m*100+d, or -1 when the shape is wrong
197func mb_daykey_at(buf: *u8, i: i64, e: i64) -> i64 {
198 if i + MB_DAY_LEN > e { return 0 - 1 }
199 if (buf[i + 4] as i64) != MB_DASH { return 0 - 1 }
200 if (buf[i + 7] as i64) != MB_DASH { return 0 - 1 }
201 let y: i64 = mb_int_at(buf, i, i + 4)
202 let m: i64 = mb_int_at(buf, i + 5, i + 7)
203 let d: i64 = mb_int_at(buf, i + 8, i + 10)
204 if y < 0 { return 0 - 1 }
205 if m < 1 { return 0 - 1 }
206 if m > 12 { return 0 - 1 }
207 if d < 1 { return 0 - 1 }
208 if d > 31 { return 0 - 1 }
209 return y * MB_KEY_YEAR_MUL + m * MB_KEY_MON_MUL + d
210}
211
212func mb_key_daynum(key: i64) -> i64 {
213 let y: i64 = key / MB_KEY_YEAR_MUL
214 let m: i64 = (key / MB_KEY_MON_MUL) % MB_KEY_MON_MUL
215 let d: i64 = key % MB_KEY_MON_MUL
216 return mb_days_from_civil(y, m, d)
217}
218
219// print a day key as YYYY-MM-DD into out at off
220func mb_cat_key(out: *u8, off: i64, key: i64) -> i64 {
221 var o: i64 = off
222 o = mp_catn(out, o, key / MB_KEY_YEAR_MUL)
223 out[o] = MB_DASH as u8; o = o + 1
224 let m: i64 = (key / MB_KEY_MON_MUL) % MB_KEY_MON_MUL
225 if m < 10 { out[o] = 48 as u8; o = o + 1 }
226 o = mp_catn(out, o, m)
227 out[o] = MB_DASH as u8; o = o + 1
228 let d: i64 = key % MB_KEY_MON_MUL
229 if d < 10 { out[o] = 48 as u8; o = o + 1 }
230 o = mp_catn(out, o, d)
231 return o
232}
233
234func mb_mtime(path: *u8) -> i64 {
235 let sb: *u8 = sys_mmap(MB_STATBUF)
236 let r: i64 = sys_fstatat(path, sb)
237 if r < 0 { sys_munmap(sb, MB_STATBUF); return 0 - 1 }
238 let sw: *i64 = sb as *i64
239 let mt: i64 = sw[MB_STAT_MTIME_SLOT]
240 sys_munmap(sb, MB_STATBUF)
241 return mt
242}
243
244// ---- the per-run tables ---------------------------------------------------------------------------------
245// keys[d] day key; fams[f] family token; cell c = d*MB_FAM_MAX + f; per cell: msgs, out, cread, ccre, files.
246// ctr slots: 0 files_seen 1 files_read 2 files_skipped_mtime 3 lines 4 assistant 5 msgs 6 dup_blocks
247// 7 malformed 8 partial_files 9 days 10 fams 11 days_floor 12 files_floor 13 statfail 14 outside_window
248const MB_C_FILES: i64 = 0
249const MB_C_READ: i64 = 1
250const MB_C_SKIPPED: i64 = 2
251const MB_C_LINES: i64 = 3
252const MB_C_ASSIST: i64 = 4
253const MB_C_MSGS: i64 = 5
254const MB_C_DUP: i64 = 6
255const MB_C_MALFORMED: i64 = 7
256const MB_C_PARTIAL: i64 = 8
257const MB_C_DAYS: i64 = 9
258const MB_C_FAMS: i64 = 10
259const MB_C_DAYSFLOOR: i64 = 11
260const MB_C_FILESFLOOR: i64 = 12
261const MB_C_STATFAIL: i64 = 13
262const MB_C_OUTSIDE: i64 = 14
263const MB_C_SYNTH: i64 = 15 // harness-written API-error lines: model "<synthetic>", no msg_ id, nothing to meter
264const MB_C_RECOVERED: i64 = 16 // rows the estate log already held that the local marker had lost (a dropped receipt)
265const MB_C_DEFERRED: i64 = 17 // rows NOT pushed because the estate log could not be read first
266const MB_C_SLOTS: i64 = 24
267const MB_LOG_CAP: i64 = 262144 // one meterlog fetch: 400 rows x ~120 B escaped fits 5x over
268const MB_LOG_ROWS: *u8 = "400" // tail rows to read back; 40 days x 2 families x 2 retries is 160
269const MB_ROW_BACK: i64 = 200 // a log row is epoch TAB seat TAB 4 numbers TAB note: the seat sits within 200 B before its note
270
271func mb_day_index(keys: *i64, ctr: *i64, key: i64) -> i64 {
272 var i: i64 = 0
273 let n: i64 = ctr[MB_C_DAYS]
274 while i < n { if keys[i] == key { return i } i = i + 1 }
275 if n >= MB_DAYS_MAX { ctr[MB_C_DAYSFLOOR] = 1; return 0 - 1 }
276 keys[n] = key
277 ctr[MB_C_DAYS] = n + 1
278 return n
279}
280
281// find `key` where it starts a DEPTH-1 field of the object whose body begins at s (just past its '{'). Strings
282// are skipped with their escapes and nested objects and arrays are skipped whole, so a tool_use input that
283// carries its own "model" or "id" (raw JSON inside content) can never be mistaken for the message's field.
284// Returns the key's offset, or -1 when the object closes first or the key is absent.
285func mb_depth1_find(buf: *u8, s: i64, e: i64, key: *u8) -> i64 {
286 let kl: i64 = mp_len(key)
287 var depth: i64 = 1
288 var instr: i64 = 0
289 var i: i64 = s
290 while i < e {
291 let c: i64 = buf[i] as i64
292 if instr == 1 {
293 if c == 92 { i = i + 1 } else { if c == MB_QUOTE { instr = 0 } }
294 } else {
295 if c == MB_QUOTE {
296 if depth == 1 { if i + kl <= e { if mb_find(buf, i, i + kl, key) == i { return i } } }
297 instr = 1
298 } else {
299 if c == 123 { depth = depth + 1 } else { if c == 91 { depth = depth + 1 } else {
300 if c == 125 { depth = depth - 1 } else { if c == 93 { depth = depth - 1 } }
301 } }
302 if depth <= 0 { return 0 - 1 }
303 }
304 }
305 i = i + 1
306 }
307 return 0 - 1
308}
309
310// family token = the run between "claude-" and the next '-' in the model id at offset p (the message's OWN
311// model field, found at depth 1 by the caller); p < 0 files as "other"
312func mb_fam_index(fams: *u8, ctr: *i64, buf: *u8, p: i64, e: i64) -> i64 {
313 let tok: *u8 = sys_mmap(MB_FAM_CAP)
314 var tl: i64 = 0
315 if p < 0 { tl = mp_cat(tok, 0, "other" as *u8) } else {
316 var i: i64 = p + mp_len("\"model\":\"claude-" as *u8)
317 var scan: i64 = 1
318 while scan == 1 {
319 if i >= e { scan = 0 } else {
320 let c: i64 = buf[i] as i64
321 if c == MB_DASH { scan = 0 } else { if c == MB_QUOTE { scan = 0 } else {
322 if tl < MB_FAM_CAP - 1 { tok[tl] = c as u8; tl = tl + 1 }
323 i = i + 1
324 } }
325 }
326 }
327 if tl == 0 { tl = mp_cat(tok, 0, "other" as *u8) }
328 }
329 tok[tl] = 0 as u8
330 var f: i64 = 0
331 let n: i64 = ctr[MB_C_FAMS]
332 while f < n { if mp_streq(mb_famslot(fams, f), tok) == 1 { sys_munmap(tok, MB_FAM_CAP); return f } f = f + 1 }
333 if n >= MB_FAM_MAX { sys_munmap(tok, MB_FAM_CAP); return 0 - 1 }
334 mb_copy(mb_famslot(fams, n), tok, MB_FAM_CAP)
335 ctr[MB_C_FAMS] = n + 1
336 sys_munmap(tok, MB_FAM_CAP)
337 return n
338}
339
340// scan ONE transcript into the tables. ring/ringn: the last MB_ID_RING message ids seen in this file (per-file dedupe).
341// fileday[f]: the last day key this file was counted as active for family f (per-file session counting).
342func mb_scan_file(path: *u8, keys: *i64, fams: *u8, msgs: *i64, outt: *i64, cread: *i64, ccre: *i64, files: *i64,
343 ctr: *i64, lo_day: i64, hi_day: i64) -> i64 {
344 let lenp: *i64 = sys_mmap(MB_I64) as *i64
345 let buf: *u8 = sys_read_file(path, lenp)
346 let n: i64 = lenp[0]
347 if (buf as i64) == 0 { sys_munmap(lenp as *u8, MB_I64); return 0 - 1 }
348 let ring: *u8 = sys_mmap(MB_ID_RING * MB_ID_CAP)
349 var ringn: i64 = 0
350 var ringw: i64 = 0
351 let fileday: *i64 = sys_mmap(MB_FAM_MAX * MB_I64) as *i64
352 var f0: i64 = 0
353 while f0 < MB_FAM_MAX { fileday[f0] = 0 - 1; f0 = f0 + 1 }
354 var i: i64 = 0
355 var partial: i64 = 0
356 while i < n {
357 var e: i64 = i
358 var scan: i64 = 1
359 while scan == 1 { if e >= n { scan = 0 } else { if (buf[e] as i64) == MB_NL { scan = 0 } else { e = e + 1 } } }
360 if e >= n { partial = 1 } else {
361 ctr[MB_C_LINES] = ctr[MB_C_LINES] + 1
362 // a raw "type":"assistant" is written only by the harness at top level or inside an assistant
363 // tool_use input (tool results are escaped strings), so its presence classifies the line
364 var isasst: i64 = 0
365 if mb_find(buf, i, e, "\"type\":\"assistant\"" as *u8) >= 0 { isasst = 1 }
366 if isasst == 1 {
367 ctr[MB_C_ASSIST] = ctr[MB_C_ASSIST] + 1
368 // the message's OWN fields are the depth-1 children of "message":{ -- a tool_use input inside
369 // content is raw JSON too and may carry "model":"..." or "id":"..." of its own (MEASURED: two
370 // messages on 2026-09-01 carried five raw model fields each, and position on the line filed
371 // them under the wrong family), so depth decides, never position
372 let mp: i64 = mb_find(buf, i, e, "\"message\":{" as *u8)
373 var ms: i64 = 0 - 1
374 if mp >= 0 { ms = mp + mp_len("\"message\":{" as *u8) }
375 var up: i64 = 0 - 1
376 var idp: i64 = 0 - 1
377 var modp: i64 = 0 - 1
378 if ms >= 0 {
379 up = mb_depth1_find(buf, ms, e, "\"usage\":{" as *u8)
380 idp = mb_depth1_find(buf, ms, e, "\"id\":\"msg_" as *u8)
381 modp = mb_depth1_find(buf, ms, e, "\"model\":\"claude-" as *u8)
382 }
383 let tsp: i64 = mb_rfind(buf, i, e, "\"timestamp\":\"" as *u8)
384 var ok: i64 = 1
385 if up < 0 { ok = 0 }
386 if tsp < 0 { ok = 0 }
387 if idp < 0 { ok = 0 }
388 var key: i64 = 0 - 1
389 var outv: i64 = 0 - 1
390 var crv: i64 = 0 - 1
391 var ccv: i64 = 0 - 1
392 if ok == 1 {
393 key = mb_daykey_at(buf, tsp + mp_len("\"timestamp\":\"" as *u8), e)
394 outv = mb_int_after(buf, up, e, "\"output_tokens\":" as *u8)
395 crv = mb_int_after(buf, up, e, "\"cache_read_input_tokens\":" as *u8)
396 ccv = mb_int_after(buf, up, e, "\"cache_creation_input_tokens\":" as *u8)
397 if key < 0 { ok = 0 }
398 if outv < 0 { ok = 0 }
399 if crv < 0 { ok = 0 }
400 if ccv < 0 { ok = 0 }
401 }
402 // an API-error line is written by the harness with model "<synthetic>" and no msg_ id (MEASURED
403 // 2026-09-02: 15 of them in two days); it is a named bucket, never MALFORMED and never a message
404 if ok == 0 { if mb_find(buf, i, e, "\"model\":\"<synthetic>\"" as *u8) >= 0 { ctr[MB_C_SYNTH] = ctr[MB_C_SYNTH] + 1 } else { ctr[MB_C_MALFORMED] = ctr[MB_C_MALFORMED] + 1 } } else {
405 // per-file dedupe: the id span "msg_..." up to the closing quote
406 let ids: i64 = idp + mp_len("\"id\":\"" as *u8)
407 var ide: i64 = ids
408 var s2: i64 = 1
409 while s2 == 1 { if ide >= e { s2 = 0 } else { if (buf[ide] as i64) == MB_QUOTE { s2 = 0 } else { ide = ide + 1 } } }
410 var idl: i64 = ide - ids
411 if idl > MB_ID_CAP - 1 { idl = MB_ID_CAP - 1 }
412 var dup: i64 = 0
413 var r: i64 = 0
414 while r < ringn {
415 let rs: *u8 = ((ring as i64) + r * MB_ID_CAP) as *u8
416 var same: i64 = 1
417 var k: i64 = 0
418 while k < idl { if rs[k] != buf[ids + k] { same = 0 } k = k + 1 }
419 if rs[idl] != (0 as u8) { same = 0 }
420 if same == 1 { dup = 1 }
421 r = r + 1
422 }
423 if dup == 1 { ctr[MB_C_DUP] = ctr[MB_C_DUP] + 1 } else {
424 let ws: *u8 = ((ring as i64) + ringw * MB_ID_CAP) as *u8
425 var k2: i64 = 0
426 while k2 < idl { ws[k2] = buf[ids + k2]; k2 = k2 + 1 }
427 ws[idl] = 0 as u8
428 ringw = (ringw + 1) % MB_ID_RING
429 if ringn < MB_ID_RING { ringn = ringn + 1 }
430 let dn: i64 = mb_key_daynum(key)
431 var inwin: i64 = 1
432 if dn < lo_day { inwin = 0 }
433 if dn > hi_day { inwin = 0 }
434 if inwin == 0 { ctr[MB_C_OUTSIDE] = ctr[MB_C_OUTSIDE] + 1 } else {
435 let d: i64 = mb_day_index(keys, ctr, key)
436 let f: i64 = mb_fam_index(fams, ctr, buf, modp, e)
437 if d < 0 { ctr[MB_C_MALFORMED] = ctr[MB_C_MALFORMED] + 1 } else { if f < 0 { ctr[MB_C_MALFORMED] = ctr[MB_C_MALFORMED] + 1 } else {
438 let c: i64 = d * MB_FAM_MAX + f
439 msgs[c] = msgs[c] + 1
440 outt[c] = outt[c] + outv
441 cread[c] = cread[c] + crv
442 ccre[c] = ccre[c] + ccv
443 ctr[MB_C_MSGS] = ctr[MB_C_MSGS] + 1
444 if fileday[f] != key { files[c] = files[c] + 1; fileday[f] = key }
445 } }
446 }
447 }
448 }
449 }
450 }
451 i = e + 1
452 }
453 if partial == 1 { ctr[MB_C_PARTIAL] = ctr[MB_C_PARTIAL] + 1 }
454 sys_munmap(ring, MB_ID_RING * MB_ID_CAP)
455 sys_munmap(fileday as *u8, MB_FAM_MAX * MB_I64)
456 sys_munmap(buf, n + MB_READ_SLACK)
457 sys_munmap(lenp as *u8, MB_I64)
458 return 0
459}
460
461// ---- RESIDUE (ES11 sm_residue): which bytes of a session were REASONING and which were MECHANICAL --------------
462// The 2026-07-21 hand measurement (92.9 percent mechanical, 7.1 percent reasoning over 222 transcripts) as a standing
463// organ. Four buckets partition every content byte a line carries, measured as stored (escaped JSON string bytes):
464// reasoning assistant text and thinking blocks -- the residue only a frontier seat produces today
465// authored tool_use input objects -- code and commands the seat wrote (the local maker's target)
466// mechanical tool_result content on user lines -- what tools returned and the context re-reads every turn
467// prompt plain user text -- the operator
468// Per transcript in the window one RESIDUE row (a session's own permil), then the window total. A byte that fits no
469// bucket is counted as OTHER so the partition still sums.
470const MB_R_REASON: i64 = 0
471const MB_R_AUTHORED: i64 = 1
472const MB_R_MECH: i64 = 2
473const MB_R_PROMPT: i64 = 3
474const MB_R_OTHER: i64 = 4
475const MB_R_LINES: i64 = 5
476const MB_R_SLOTS: i64 = 8
477const MB_LBRACE: i64 = 123
478const MB_RBRACE: i64 = 125
479const MB_LBRACK: i64 = 91
480const MB_RBRACK: i64 = 93
481const MB_COMMA: i64 = 44
482const MB_PERMIL: i64 = 1000
483
484// index of the closing unescaped quote of the string whose first byte is buf[s]; e when unterminated
485func mb_str_end(buf: *u8, s: i64, e: i64) -> i64 {
486 var i: i64 = s
487 while i < e {
488 let c: i64 = buf[i] as i64
489 if c == 92 { i = i + 2 } else { if c == MB_QUOTE { return i } else { i = i + 1 } }
490 }
491 return e
492}
493// index just past the value that starts at buf[s] (object, array, string, or a bare scalar up to , ] })
494func mb_skip_value(buf: *u8, s: i64, e: i64) -> i64 {
495 if s >= e { return e }
496 let c0: i64 = buf[s] as i64
497 if c0 == MB_QUOTE { let q: i64 = mb_str_end(buf, s + 1, e); if q >= e { return e } return q + 1 }
498 if c0 == MB_LBRACE { } else { if c0 == MB_LBRACK { } else {
499 var j: i64 = s
500 var go: i64 = 1
501 while go == 1 { if j >= e { go = 0 } else { let c: i64 = buf[j] as i64; if c == MB_COMMA { go = 0 } else { if c == MB_RBRACE { go = 0 } else { if c == MB_RBRACK { go = 0 } else { j = j + 1 } } } } }
502 return j
503 } }
504 var depth: i64 = 0
505 var instr: i64 = 0
506 var i: i64 = s
507 while i < e {
508 let c: i64 = buf[i] as i64
509 if instr == 1 {
510 if c == 92 { i = i + 1 } else { if c == MB_QUOTE { instr = 0 } }
511 } else {
512 if c == MB_QUOTE { instr = 1 } else {
513 if c == MB_LBRACE { depth = depth + 1 } else { if c == MB_LBRACK { depth = depth + 1 } else {
514 if c == MB_RBRACE { depth = depth - 1 } else { if c == MB_RBRACK { depth = depth - 1 } }
515 } }
516 if depth == 0 { return i + 1 }
517 }
518 }
519 i = i + 1
520 }
521 return e
522}
523// byte length of the string value of depth-1 key `key` inside the object body starting at s; 0 when absent
524func mb_strlen_of(buf: *u8, s: i64, e: i64, key: *u8) -> i64 {
525 let p: i64 = mb_depth1_find(buf, s, e, key)
526 if p < 0 { return 0 }
527 let vs: i64 = p + mp_len(key)
528 return mb_str_end(buf, vs, e) - vs
529}
530// byte length of the object value of depth-1 key `key` (key literal ends with :{ ), 0 when absent
531func mb_objlen_of(buf: *u8, s: i64, e: i64, key: *u8) -> i64 {
532 let p: i64 = mb_depth1_find(buf, s, e, key)
533 if p < 0 { return 0 }
534 let os: i64 = p + mp_len(key) - 1
535 return mb_skip_value(buf, os, e) - os
536}
537// walk the content ARRAY whose '[' is at buf[a]; per element object, add its bytes to the right bucket by "type"
538func mb_residue_content(buf: *u8, a: i64, e: i64, isasst: i64, acc: *i64) -> i64 {
539 var i: i64 = a + 1
540 var go: i64 = 1
541 while go == 1 {
542 if i >= e { go = 0 } else {
543 let c: i64 = buf[i] as i64
544 if c == MB_RBRACK { go = 0 } else { if c == MB_LBRACE {
545 let es: i64 = i + 1
546 let ee: i64 = mb_skip_value(buf, i, e)
547 let tp: i64 = mb_depth1_find(buf, es, ee, "\"type\":\"" as *u8)
548 var kind: i64 = MB_R_OTHER
549 var bytes: i64 = ee - i
550 if tp >= 0 {
551 let ts: i64 = tp + mp_len("\"type\":\"" as *u8)
552 if mb_find(buf, ts, ee, "text\"" as *u8) == ts { if isasst == 1 { kind = MB_R_REASON } else { kind = MB_R_PROMPT } bytes = mb_strlen_of(buf, es, ee, "\"text\":\"" as *u8) }
553 if mb_find(buf, ts, ee, "thinking\"" as *u8) == ts { kind = MB_R_REASON; bytes = mb_strlen_of(buf, es, ee, "\"thinking\":\"" as *u8) }
554 if mb_find(buf, ts, ee, "tool_use\"" as *u8) == ts { kind = MB_R_AUTHORED; bytes = mb_objlen_of(buf, es, ee, "\"input\":{" as *u8) }
555 if mb_find(buf, ts, ee, "tool_result\"" as *u8) == ts {
556 kind = MB_R_MECH
557 let cp: i64 = mb_depth1_find(buf, es, ee, "\"content\":" as *u8)
558 if cp < 0 { bytes = 0 } else {
559 let vs: i64 = cp + mp_len("\"content\":" as *u8)
560 if (buf[vs] as i64) == MB_QUOTE { bytes = mb_str_end(buf, vs + 1, ee) - (vs + 1) } else {
561 bytes = mb_skip_value(buf, vs, ee) - vs
562 }
563 }
564 }
565 }
566 acc[kind] = acc[kind] + bytes
567 i = ee
568 } else { i = i + 1 } }
569 }
570 }
571 return 0
572}
573// one line: classify its message content into the buckets (only lines with a "message":{ object carry content)
574func mb_residue_line(buf: *u8, i: i64, e: i64, acc: *i64) -> i64 {
575 acc[MB_R_LINES] = acc[MB_R_LINES] + 1
576 let mp: i64 = mb_find(buf, i, e, "\"message\":{" as *u8)
577 if mp < 0 { return 0 }
578 let ms: i64 = mp + mp_len("\"message\":{" as *u8)
579 var isasst: i64 = 0
580 if mb_find(buf, i, e, "\"type\":\"assistant\"" as *u8) >= 0 { isasst = 1 }
581 let cp: i64 = mb_depth1_find(buf, ms, e, "\"content\":" as *u8)
582 if cp < 0 { return 0 }
583 let vs: i64 = cp + mp_len("\"content\":" as *u8)
584 let c0: i64 = buf[vs] as i64
585 if c0 == MB_QUOTE {
586 let n: i64 = mb_str_end(buf, vs + 1, e) - (vs + 1)
587 if isasst == 1 { acc[MB_R_REASON] = acc[MB_R_REASON] + n } else { acc[MB_R_PROMPT] = acc[MB_R_PROMPT] + n }
588 return 0
589 }
590 if c0 == MB_LBRACK { mb_residue_content(buf, vs, e, isasst, acc) }
591 return 0
592}
593// per transcript: sum the buckets; write ONE RESIDUE row; add to the window accumulator
594func mb_residue_file(path: *u8, name: *u8, ob: *u8, op: *i64, win: *i64) -> i64 {
595 let lenp: *i64 = sys_mmap(MB_I64) as *i64
596 let buf: *u8 = sys_read_file(path, lenp)
597 let n: i64 = lenp[0]
598 if (buf as i64) == 0 { sys_munmap(lenp as *u8, MB_I64); return 0 - 1 }
599 let acc: *i64 = sys_mmap(MB_R_SLOTS * MB_I64) as *i64
600 var k: i64 = 0
601 while k < MB_R_SLOTS { acc[k] = 0; k = k + 1 }
602 var i: i64 = 0
603 while i < n {
604 var e: i64 = i
605 var scan: i64 = 1
606 while scan == 1 { if e >= n { scan = 0 } else { if (buf[e] as i64) == MB_NL { scan = 0 } else { e = e + 1 } } }
607 if e < n { mb_residue_line(buf, i, e, acc) }
608 i = e + 1
609 }
610 let total: i64 = acc[MB_R_REASON] + acc[MB_R_AUTHORED] + acc[MB_R_MECH] + acc[MB_R_PROMPT] + acc[MB_R_OTHER]
611 var o: i64 = op[0]
612 o = mp_cat(ob, o, "RESIDUE file=" as *u8); o = mp_cat(ob, o, name)
613 o = mp_cat(ob, o, " lines=" as *u8); o = mp_catn(ob, o, acc[MB_R_LINES])
614 o = mp_cat(ob, o, " reasoning=" as *u8); o = mp_catn(ob, o, acc[MB_R_REASON])
615 o = mp_cat(ob, o, " authored=" as *u8); o = mp_catn(ob, o, acc[MB_R_AUTHORED])
616 o = mp_cat(ob, o, " mechanical=" as *u8); o = mp_catn(ob, o, acc[MB_R_MECH])
617 o = mp_cat(ob, o, " prompt=" as *u8); o = mp_catn(ob, o, acc[MB_R_PROMPT])
618 o = mp_cat(ob, o, " other=" as *u8); o = mp_catn(ob, o, acc[MB_R_OTHER])
619 o = mp_cat(ob, o, " total=" as *u8); o = mp_catn(ob, o, total)
620 o = mp_cat(ob, o, " reasoning_permil=" as *u8)
621 if total > 0 { o = mp_catn(ob, o, (acc[MB_R_REASON] * MB_PERMIL) / total) } else { o = mp_cat(ob, o, "UNMEASURED" as *u8) }
622 o = mp_cat(ob, o, "\n" as *u8)
623 op[0] = o
624 k = 0
625 while k < MB_R_SLOTS { win[k] = win[k] + acc[k]; k = k + 1 }
626 sys_munmap(acc as *u8, MB_R_SLOTS * MB_I64)
627 sys_munmap(buf, n + MB_READ_SLACK)
628 sys_munmap(lenp as *u8, MB_I64)
629 return 0
630}
631
632// walk <dir> for *.jsonl newer than min_mtime and scan each. Returns 0, or -1 when the dir cannot be opened.
633// mode 0 = the meter tables; mode 1 = RESIDUE rows into ob/op with the window accumulator win.
634func mb_scan_dir(dir: *u8, min_mtime: i64, keys: *i64, fams: *u8, msgs: *i64, outt: *i64, cread: *i64, ccre: *i64,
635 files: *i64, ctr: *i64, lo_day: i64, hi_day: i64, mode: i64, ob: *u8, op: *i64, win: *i64) -> i64 {
636 let fd: i64 = sys_openat_rd(dir)
637 if fd < 0 { return 0 - 1 }
638 let dbuf: *u8 = sys_mmap(MB_DENTBUF)
639 let path: *u8 = sys_mmap(MB_PATH)
640 var run: i64 = 1
641 while run == 1 {
642 let got: i64 = sys_getdents64(fd, dbuf, MB_DENTBUF)
643 if got <= 0 { run = 0 } else {
644 var off: i64 = 0
645 var inner: i64 = 1
646 while inner == 1 {
647 if off >= got { inner = 0 } else {
648 let rec: *u8 = ((dbuf as i64) + off) as *u8
649 let reclen: i64 = dirent_reclen(rec)
650 if reclen <= 0 { inner = 0 } else {
651 let name: *u8 = dirent_name(rec)
652 var take: i64 = 1
653 if (name[0] as i64) == MB_DOT { take = 0 }
654 if take == 1 { if mb_ends_with(name, ".jsonl" as *u8) == 0 { take = 0 } }
655 if take == 1 {
656 ctr[MB_C_FILES] = ctr[MB_C_FILES] + 1
657 if ctr[MB_C_FILES] > MB_FILES_MAX { ctr[MB_C_FILESFLOOR] = 1 } else {
658 mp_join(path, dir, name)
659 let mt: i64 = mb_mtime(path)
660 if mt < 0 { ctr[MB_C_STATFAIL] = ctr[MB_C_STATFAIL] + 1 } else {
661 if mt < min_mtime { ctr[MB_C_SKIPPED] = ctr[MB_C_SKIPPED] + 1 } else {
662 var r: i64 = 0
663 if mode == 1 { r = mb_residue_file(path, name, ob, op, win) } else { r = mb_scan_file(path, keys, fams, msgs, outt, cread, ccre, files, ctr, lo_day, hi_day) }
664 if r < 0 { ctr[MB_C_STATFAIL] = ctr[MB_C_STATFAIL] + 1 } else { ctr[MB_C_READ] = ctr[MB_C_READ] + 1 }
665 }
666 }
667 }
668 }
669 off = off + reclen
670 }
671 }
672 }
673 }
674 }
675 sys_close(fd)
676 sys_munmap(dbuf, MB_DENTBUF)
677 sys_munmap(path, MB_PATH)
678 return 0
679}
680
681// ---- marker file: one line per pushed (day, family): YYYY-MM-DD\tfamily\tepoch\tsessions\tout\tcread\tccreate ----
682func mb_marked(mark: *u8, mn: i64, key: i64, fam: *u8) -> i64 {
683 let probe: *u8 = sys_mmap(MB_NOTE_CAP)
684 var o: i64 = mb_cat_key(probe, 0, key)
685 probe[o] = 9 as u8; o = o + 1
686 o = mp_cat(probe, o, fam)
687 probe[o] = 9 as u8; o = o + 1
688 probe[o] = 0 as u8
689 var found: i64 = 0
690 // a marker line starts the file or follows a newline -- an anchored match, never a substring of a note
691 var i: i64 = 0
692 while i < mn {
693 var at: i64 = 0
694 if i == 0 { at = 1 } else { if (mark[i - 1] as i64) == MB_NL { at = 1 } }
695 if at == 1 { if mb_find(mark, i, mn, probe) == i { found = 1 } }
696 i = i + 1
697 }
698 sys_munmap(probe, MB_NOTE_CAP)
699 return found
700}
701
702func mb_mark_append(markpath: *u8, key: i64, fam: *u8, now: i64, sess: i64, ov: i64, cr: i64, cc: i64) -> i64 {
703 let ln: *u8 = sys_mmap(MB_NOTE_CAP)
704 var o: i64 = mb_cat_key(ln, 0, key)
705 ln[o] = 9 as u8; o = o + 1
706 o = mp_cat(ln, o, fam)
707 ln[o] = 9 as u8; o = o + 1
708 o = mp_catn(ln, o, now)
709 ln[o] = 9 as u8; o = o + 1
710 o = mp_catn(ln, o, sess)
711 ln[o] = 9 as u8; o = o + 1
712 o = mp_catn(ln, o, ov)
713 ln[o] = 9 as u8; o = o + 1
714 o = mp_catn(ln, o, cr)
715 ln[o] = 9 as u8; o = o + 1
716 o = mp_catn(ln, o, cc)
717 ln[o] = MB_NL as u8; o = o + 1
718 let fd: i64 = sys_openat_append(markpath, 420)
719 if fd < 0 { sys_munmap(ln, MB_NOTE_CAP); return 0 - 1 }
720 let w: i64 = sys_write(fd, ln, o)
721 sys_close(fd)
722 sys_munmap(ln, MB_NOTE_CAP)
723 if w != o { return 0 - 1 }
724 return 0
725}
726
727// push ONE row through the sovereign MCP client: nx_mcp_call <base_url> nx_seat <cap_file> "argv":[meter ...]
728func mb_push(mcp: *u8, base: *u8, cap: *u8, key: i64, fam: *u8, sess: i64, ov: i64, cr: i64, cc: i64, msgs: i64, resp: *u8) -> i64 {
729 let frag: *u8 = sys_mmap(MB_FRAG_CAP)
730 var o: i64 = mp_cat(frag, 0, "\"argv\":[\"meter\",\"claude-" as *u8)
731 o = mp_cat(frag, o, fam)
732 o = mp_cat(frag, o, "-daily\",\"" as *u8)
733 o = mp_catn(frag, o, sess)
734 o = mp_cat(frag, o, "\",\"" as *u8)
735 o = mp_catn(frag, o, ov)
736 o = mp_cat(frag, o, "\",\"" as *u8)
737 o = mp_catn(frag, o, cr)
738 o = mp_cat(frag, o, "\",\"" as *u8)
739 o = mp_catn(frag, o, cc)
740 o = mp_cat(frag, o, "\",\"beat-" as *u8)
741 o = mb_cat_key(frag, o, key)
742 o = mp_cat(frag, o, "-msgs=" as *u8)
743 o = mp_catn(frag, o, msgs)
744 o = mp_cat(frag, o, "-files=" as *u8)
745 o = mp_catn(frag, o, sess)
746 o = mp_cat(frag, o, "-src=nx_seat_meter_beat\"]" as *u8)
747 frag[o] = 0 as u8
748 let av: *i64 = sys_mmap(MB_ARGV_MAX * MB_I64) as *i64
749 av[0] = mcp as i64; av[1] = base as i64; av[2] = "nx_seat" as i64; av[3] = cap as i64; av[4] = frag as i64; av[5] = 0
750 let rl: *i64 = sys_mmap(MB_I64) as *i64
751 let rc: i64 = tr_run_capture_to(mcp, av, resp, MB_RESP_CAP, rl, MB_FORK_TIMEOUT_MS)
752 let n: i64 = rl[0]
753 if n >= 0 { if n < MB_RESP_CAP { resp[n] = 0 as u8 } else { resp[MB_RESP_CAP - 1] = 0 as u8 } } else { resp[0] = 0 as u8 }
754 var ok: i64 = 0
755 if n > 0 { if mb_find(resp, 0, n, "METERED row appended" as *u8) >= 0 { ok = 1 } }
756 sys_munmap(frag, MB_FRAG_CAP)
757 sys_munmap(av as *u8, MB_ARGV_MAX * MB_I64)
758 sys_munmap(rl as *u8, MB_I64)
759 if rc < 0 { return 0 - 1 }
760 if ok == 0 { return 0 - 2 }
761 return 0
762}
763
764// read the estate's meter log tail ONCE per run: nx_mcp_call <base_url> nx_seat <cap_file> "argv":["meterlog","400"].
765// Returns the captured byte count, or -1 when the transport failed or the reply carries no METERLOG header.
766func mb_fetch_meterlog(mcp: *u8, base: *u8, capf: *u8, log: *u8) -> i64 {
767 let frag: *u8 = sys_mmap(MB_FRAG_CAP)
768 var o: i64 = mp_cat(frag, 0, "\"argv\":[\"meterlog\",\"" as *u8)
769 o = mp_cat(frag, o, MB_LOG_ROWS)
770 o = mp_cat(frag, o, "\"]" as *u8)
771 frag[o] = 0 as u8
772 let av: *i64 = sys_mmap(MB_ARGV_MAX * MB_I64) as *i64
773 av[0] = mcp as i64; av[1] = base as i64; av[2] = "nx_seat" as i64; av[3] = capf as i64; av[4] = frag as i64; av[5] = 0
774 let rl: *i64 = sys_mmap(MB_I64) as *i64
775 let rc: i64 = tr_run_capture_to(mcp, av, log, MB_LOG_CAP, rl, MB_FORK_TIMEOUT_MS)
776 var n: i64 = rl[0]
777 if n < 0 { n = 0 }
778 if n >= MB_LOG_CAP { n = MB_LOG_CAP - 1 }
779 log[n] = 0 as u8
780 sys_munmap(frag, MB_FRAG_CAP)
781 sys_munmap(av as *u8, MB_ARGV_MAX * MB_I64)
782 sys_munmap(rl as *u8, MB_I64)
783 if rc < 0 { return 0 - 1 }
784 if mb_find(log, 0, n, "METERLOG file_bytes=" as *u8) < 0 { return 0 - 1 }
785 return n
786}
787
788// does the fetched log (JSON-escaped, so TAB reads as backslash-t) already carry this beat's row for (day, family)?
789// A row is epoch TAB claude-<fam>-daily TAB ... TAB beat-<day>-msgs=... so the seat token must sit within
790// MB_ROW_BACK bytes BEFORE the note; every occurrence of the note is checked, never only the first.
791func mb_remote_has(log: *u8, n: i64, key: i64, fam: *u8) -> i64 {
792 let note: *u8 = sys_mmap(MB_NOTE_CAP)
793 var o: i64 = mp_cat(note, 0, "beat-" as *u8)
794 o = mb_cat_key(note, o, key)
795 o = mp_cat(note, o, "-msgs=" as *u8)
796 note[o] = 0 as u8
797 let seat: *u8 = sys_mmap(MB_NOTE_CAP)
798 var so: i64 = mp_cat(seat, 0, "claude-" as *u8)
799 so = mp_cat(seat, so, fam)
800 so = mp_cat(seat, so, "-daily" as *u8)
801 seat[so] = 0 as u8
802 var found: i64 = 0
803 var from: i64 = 0
804 var scan: i64 = 1
805 while scan == 1 {
806 let p: i64 = mb_find(log, from, n, note)
807 if p < 0 { scan = 0 } else {
808 // the seat token must sit in the SAME row: a row starts after the previous separator, which in the
809 // escaped reply is the two bytes backslash-n and in a raw capture is byte 10 -- take the nearer one.
810 // Without this anchor the previous row's seat (families alternate day by day) reads as this row's.
811 var lo: i64 = p - MB_ROW_BACK
812 if lo < 0 { lo = 0 }
813 var rs: i64 = lo
814 let esc: i64 = mb_rfind(log, lo, p, "\\n" as *u8)
815 if esc >= 0 { rs = esc + 2 }
816 var q: i64 = p - 1
817 var back: i64 = 1
818 while back == 1 { if q < rs { back = 0 } else { if (log[q] as i64) == MB_NL { rs = q + 1; back = 0 } else { q = q - 1 } } }
819 if mb_find(log, rs, p, seat) >= 0 { found = 1; scan = 0 } else { from = p + 1 }
820 }
821 }
822 sys_munmap(note, MB_NOTE_CAP)
823 sys_munmap(seat, MB_NOTE_CAP)
824 return found
825}
826
827const SM_PUSHED: i64 = 0
828const SM_ALREADY: i64 = 1
829const SM_WOULD: i64 = 2
830const SM_TRANSPORT: i64 = 3
831const SM_REFUSED: i64 = 4
832const SM_UNMARKED: i64 = 5
833const SM_RECOVERED: i64 = 6
834const SM_DEFERRED: i64 = 7
835// THE BEAT DECISION for one (day, family) row -- the ES1 contract sm_beat: the local marker first, then the estate's
836// own log (a dropped receipt is a row that LANDED without a marker -- MEASURED on this organ's first live run, where
837// one push was reported failed and the estate log held it), then the push through the sovereign MCP client, then the
838// marker append. With the estate log unreadable NOTHING is pushed: an insert is not idempotent and a blind retry
839// double-applies. Every outcome is a NAMED state, never a bare bit.
840func sm_beat(mcp: *u8, base: *u8, capf: *u8, markpath: *u8, mark: *u8, mn: i64, log: *u8, ln: i64, key: i64, fam: *u8, sess: i64, ov: i64, cr: i64, cc: i64, nmsgs: i64, dry: i64, now: i64, resp: *u8) -> i64 {
841 if mb_marked(mark, mn, key, fam) == 1 { return SM_ALREADY }
842 if dry == 1 { return SM_WOULD }
843 if ln < 0 { return SM_DEFERRED }
844 if mb_remote_has(log, ln, key, fam) == 1 {
845 mb_mark_append(markpath, key, fam, now, sess, ov, cr, cc)
846 return SM_RECOVERED
847 }
848 let pr: i64 = mb_push(mcp, base, capf, key, fam, sess, ov, cr, cc, nmsgs, resp)
849 if pr == 0 - 1 { return SM_TRANSPORT }
850 if pr != 0 { return SM_REFUSED }
851 if mb_mark_append(markpath, key, fam, now, sess, ov, cr, cc) != 0 { return SM_UNMARKED }
852 return SM_PUSHED
853}
854
855func mb_usage() -> i64 {
856 let m: *u8 = "usage: nx_seat_meter_beat scan <sessions-dir> [--now <epoch>] [--days N] | beat <sessions-dir> <state-dir> <mcp-elf> <base-url> <cap-file> [--now <epoch>] [--days N] [--dry] [--json] | remotecheck <meterlog-capture> <YYYY-MM-DD> <family> | residue <sessions-dir> [--now <epoch>] [--days N]\n" as *u8
857 mp_write_all(2, m, mp_len(m))
858 return MB_EXIT_USAGE
859}
860
861// THE RESIDUE VERB -- ES11 contract sm_residue: every transcript touched inside the window gets one RESIDUE row and
862// the window total closes with the partition printed; exit 0 GREEN, 3 UNOBSERVABLE (dir unreadable or zero bytes)
863func sm_residue(dir: *u8, now: i64, days: i64) -> i64 {
864 let today: i64 = now / MB_SEC_PER_DAY
865 let lo_day: i64 = today - days
866 let min_mtime: i64 = lo_day * MB_SEC_PER_DAY
867 let ctr: *i64 = sys_mmap(MB_C_SLOTS * MB_I64) as *i64
868 let ob: *u8 = sys_mmap(MB_OUT)
869 let op: *i64 = sys_mmap(MB_I64) as *i64
870 op[0] = 0
871 let win: *i64 = sys_mmap(MB_R_SLOTS * MB_I64) as *i64
872 var k: i64 = 0
873 while k < MB_R_SLOTS { win[k] = 0; k = k + 1 }
874 let sr: i64 = mb_scan_dir(dir, min_mtime, 0 as *i64, 0 as *u8, 0 as *i64, 0 as *i64, 0 as *i64, 0 as *i64, 0 as *i64, ctr, lo_day, today, 1, ob, op, win)
875 var o: i64 = op[0]
876 if sr < 0 {
877 o = mp_cat(ob, o, "RESIDUE-TOTAL sessions_dir_unreadable=1 verdict=UNOBSERVABLE\n" as *u8)
878 mp_write_all(1, ob, o)
879 return MB_EXIT_UNOBS
880 }
881 let total: i64 = win[MB_R_REASON] + win[MB_R_AUTHORED] + win[MB_R_MECH] + win[MB_R_PROMPT] + win[MB_R_OTHER]
882 o = mp_cat(ob, o, "RESIDUE-TOTAL window_days=" as *u8); o = mp_catn(ob, o, days)
883 o = mp_cat(ob, o, " files_seen=" as *u8); o = mp_catn(ob, o, ctr[MB_C_FILES])
884 o = mp_cat(ob, o, " files_read=" as *u8); o = mp_catn(ob, o, ctr[MB_C_READ])
885 o = mp_cat(ob, o, " files_skipped_mtime=" as *u8); o = mp_catn(ob, o, ctr[MB_C_SKIPPED])
886 o = mp_cat(ob, o, " lines=" as *u8); o = mp_catn(ob, o, win[MB_R_LINES])
887 o = mp_cat(ob, o, " reasoning=" as *u8); o = mp_catn(ob, o, win[MB_R_REASON])
888 o = mp_cat(ob, o, " authored=" as *u8); o = mp_catn(ob, o, win[MB_R_AUTHORED])
889 o = mp_cat(ob, o, " mechanical=" as *u8); o = mp_catn(ob, o, win[MB_R_MECH])
890 o = mp_cat(ob, o, " prompt=" as *u8); o = mp_catn(ob, o, win[MB_R_PROMPT])
891 o = mp_cat(ob, o, " other=" as *u8); o = mp_catn(ob, o, win[MB_R_OTHER])
892 o = mp_cat(ob, o, " total=" as *u8); o = mp_catn(ob, o, total)
893 o = mp_cat(ob, o, " partition=" as *u8); o = mp_catn(ob, o, win[MB_R_REASON] + win[MB_R_AUTHORED] + win[MB_R_MECH] + win[MB_R_PROMPT] + win[MB_R_OTHER])
894 if total > 0 {
895 o = mp_cat(ob, o, " reasoning_permil=" as *u8); o = mp_catn(ob, o, (win[MB_R_REASON] * MB_PERMIL) / total)
896 o = mp_cat(ob, o, " authored_permil=" as *u8); o = mp_catn(ob, o, (win[MB_R_AUTHORED] * MB_PERMIL) / total)
897 o = mp_cat(ob, o, " mechanical_permil=" as *u8); o = mp_catn(ob, o, (win[MB_R_MECH] * MB_PERMIL) / total)
898 o = mp_cat(ob, o, " verdict=GREEN\n" as *u8)
899 mp_write_all(1, ob, o)
900 return MB_EXIT_OK
901 }
902 o = mp_cat(ob, o, " reasoning_permil=UNMEASURED verdict=UNOBSERVABLE\n" as *u8)
903 mp_write_all(1, ob, o)
904 return MB_EXIT_UNOBS
905}
906
907func main(argc: i64, argv: *i64) -> i64 {
908 if argc < 3 { sys_exit(mb_usage()); return MB_EXIT_USAGE }
909 let verb: *u8 = argv[1] as *u8
910 // remotecheck: the read-back ruler on a captured meterlog reply, exposed so the gate can drive it
911 if mp_streq(verb, "remotecheck" as *u8) == 1 {
912 if argc < 5 { sys_exit(mb_usage()); return MB_EXIT_USAGE }
913 let lp: *i64 = sys_mmap(MB_I64) as *i64
914 let lg: *u8 = sys_read_file(argv[2] as *u8, lp)
915 let ln0: i64 = lp[0]
916 if (lg as i64) == 0 { let um: *u8 = "REMOTECHECK verdict=UNOBSERVABLE (capture unreadable)\n" as *u8; mp_write_all(1, um, mp_len(um)); sys_exit(MB_EXIT_UNOBS); return MB_EXIT_UNOBS }
917 let dk: i64 = mb_daykey_at(argv[3] as *u8, 0, MB_DAY_LEN)
918 if dk < 0 { sys_exit(mb_usage()); return MB_EXIT_USAGE }
919 let hit: i64 = mb_remote_has(lg, ln0, dk, argv[4] as *u8)
920 if hit == 1 { let ym: *u8 = "REMOTECHECK verdict=REMOTE-MARKED\n" as *u8; mp_write_all(1, ym, mp_len(ym)) } else { let nm: *u8 = "REMOTECHECK verdict=REMOTE-ABSENT\n" as *u8; mp_write_all(1, nm, mp_len(nm)) }
921 sys_exit(MB_EXIT_OK)
922 return MB_EXIT_OK
923 }
924 // residue <sessions-dir> [--now <epoch>] [--days N]: the ES11 contract sm_residue, one row per transcript
925 if mp_streq(verb, "residue" as *u8) == 1 {
926 let rdir: *u8 = argv[2] as *u8
927 var rnow: i64 = sys_now_realtime_sec()
928 var rdays: i64 = MB_DAYS_DEFAULT
929 var ri: i64 = 3
930 while ri < argc {
931 let ra: *u8 = argv[ri] as *u8
932 var rused: i64 = 0
933 if mp_streq(ra, "--now" as *u8) == 1 { if ri + 1 < argc { rnow = mb_atoi(argv[ri + 1] as *u8); ri = ri + 1 } rused = 1 }
934 if mp_streq(ra, "--days" as *u8) == 1 { if ri + 1 < argc { rdays = mb_atoi(argv[ri + 1] as *u8); ri = ri + 1 } rused = 1 }
935 if rused == 0 { sys_exit(mb_usage()); return MB_EXIT_USAGE }
936 ri = ri + 1
937 }
938 if rdays < 1 { rdays = 1 }
939 sys_exit(sm_residue(rdir, rnow, rdays))
940 return 0
941 }
942 var isbeat: i64 = 0
943 if mp_streq(verb, "beat" as *u8) == 1 { isbeat = 1 } else { if mp_streq(verb, "scan" as *u8) == 0 { sys_exit(mb_usage()); return MB_EXIT_USAGE } }
944 if isbeat == 1 { if argc < 7 { sys_exit(mb_usage()); return MB_EXIT_USAGE } }
945 let sessdir: *u8 = argv[2] as *u8
946 var statedir: *u8 = "" as *u8
947 var mcp: *u8 = "" as *u8
948 var base: *u8 = "" as *u8
949 var capf: *u8 = "" as *u8
950 var ai: i64 = 3
951 if isbeat == 1 { statedir = argv[3] as *u8; mcp = argv[4] as *u8; base = argv[5] as *u8; capf = argv[6] as *u8; ai = 7 }
952 var now: i64 = sys_now_realtime_sec()
953 var days: i64 = MB_DAYS_DEFAULT
954 var dry: i64 = 0
955 var jsonf: i64 = 0
956 while ai < argc {
957 let a: *u8 = argv[ai] as *u8
958 var used: i64 = 0
959 if mp_streq(a, "--dry" as *u8) == 1 { dry = 1; used = 1 }
960 if mp_streq(a, "--json" as *u8) == 1 { jsonf = 1; used = 1 }
961 if mp_streq(a, "--now" as *u8) == 1 { if ai + 1 < argc { now = mb_atoi(argv[ai + 1] as *u8); ai = ai + 1 } used = 1 }
962 if mp_streq(a, "--days" as *u8) == 1 { if ai + 1 < argc { days = mb_atoi(argv[ai + 1] as *u8); ai = ai + 1 } used = 1 }
963 if used == 0 { sys_exit(mb_usage()); return MB_EXIT_USAGE }
964 ai = ai + 1
965 }
966 if days < 1 { days = 1 }
967 if days > MB_DAYS_MAX - 1 { days = MB_DAYS_MAX - 1 }
968 let today: i64 = now / MB_SEC_PER_DAY
969 let hi_day: i64 = today - 1 // the newest COMPLETE day
970 let lo_day: i64 = today - days
971 let min_mtime: i64 = (lo_day) * MB_SEC_PER_DAY // a file last written before the window start carries no in-window day
972
973 let keys: *i64 = sys_mmap(MB_DAYS_MAX * MB_I64) as *i64
974 let fams: *u8 = sys_mmap(MB_FAM_MAX * MB_FAM_CAP)
975 let msgs: *i64 = sys_mmap(MB_CELLS * MB_I64) as *i64
976 let outt: *i64 = sys_mmap(MB_CELLS * MB_I64) as *i64
977 let cread: *i64 = sys_mmap(MB_CELLS * MB_I64) as *i64
978 let ccre: *i64 = sys_mmap(MB_CELLS * MB_I64) as *i64
979 let files: *i64 = sys_mmap(MB_CELLS * MB_I64) as *i64
980 let ctr: *i64 = sys_mmap(MB_C_SLOTS * MB_I64) as *i64
981 let ob: *u8 = sys_mmap(MB_OUT)
982 var o: i64 = 0
983
984 let sr: i64 = mb_scan_dir(sessdir, min_mtime, keys, fams, msgs, outt, cread, ccre, files, ctr, lo_day, hi_day, 0, ob, 0 as *i64, 0 as *i64)
985 if sr < 0 {
986 o = mp_cat(ob, o, "METERBEAT sessions_dir_unreadable=1 dir=" as *u8)
987 o = mp_cat(ob, o, sessdir)
988 o = mp_cat(ob, o, " verdict=UNOBSERVABLE\n" as *u8)
989 if jsonf == 1 { mp_hook_json("SessionStart" as *u8, ob, o); sys_exit(MB_EXIT_OK); return MB_EXIT_OK }
990 mp_write_all(1, ob, o)
991 sys_exit(MB_EXIT_UNOBS)
992 return MB_EXIT_UNOBS
993 }
994
995 // marker file (beat only)
996 let markpath: *u8 = sys_mmap(MB_PATH)
997 var mark: *u8 = 0 as *u8
998 var mn: i64 = 0
999 if isbeat == 1 {
1000 mp_join(markpath, statedir, "meterbeat.days" as *u8)
1001 let ml: *i64 = sys_mmap(MB_I64) as *i64
1002 mark = sys_read_file(markpath, ml)
1003 mn = ml[0]
1004 if (mark as i64) == 0 { mn = 0 }
1005 sys_munmap(ml as *u8, MB_I64)
1006 }
1007 // the estate's own log, read ONCE before any push (dry runs fork nothing)
1008 let log: *u8 = sys_mmap(MB_LOG_CAP)
1009 var ln: i64 = 0 - 1
1010 if isbeat == 1 { if dry == 0 { ln = mb_fetch_meterlog(mcp, base, capf, log) } }
1011
1012 // rows, oldest day first (the table is in first-seen order; sort by key with a simple selection order)
1013 var pushed: i64 = 0
1014 var planned: i64 = 0
1015 var already: i64 = 0
1016 var failed: i64 = 0
1017 var sumout: i64 = 0
1018 var sumcr: i64 = 0
1019 let resp: *u8 = sys_mmap(MB_RESP_CAP)
1020 let nd: i64 = ctr[MB_C_DAYS]
1021 let nf: i64 = ctr[MB_C_FAMS]
1022 let done: *i64 = sys_mmap(MB_DAYS_MAX * MB_I64) as *i64
1023 var emitted: i64 = 0
1024 while emitted < nd {
1025 // pick the smallest not-yet-emitted key
1026 var best: i64 = 0 - 1
1027 var di: i64 = 0
1028 while di < nd { if done[di] == 0 { if best < 0 { best = di } else { if keys[di] < keys[best] { best = di } } } di = di + 1 }
1029 done[best] = 1
1030 emitted = emitted + 1
1031 var f: i64 = 0
1032 while f < nf {
1033 let c: i64 = best * MB_FAM_MAX + f
1034 if msgs[c] > 0 {
1035 let fam: *u8 = mb_famslot(fams, f)
1036 o = mp_cat(ob, o, "DAY " as *u8)
1037 o = mb_cat_key(ob, o, keys[best])
1038 o = mp_cat(ob, o, " fam=" as *u8); o = mp_cat(ob, o, fam)
1039 o = mp_cat(ob, o, " sessions=" as *u8); o = mp_catn(ob, o, files[c])
1040 o = mp_cat(ob, o, " msgs=" as *u8); o = mp_catn(ob, o, msgs[c])
1041 o = mp_cat(ob, o, " out=" as *u8); o = mp_catn(ob, o, outt[c])
1042 o = mp_cat(ob, o, " cread=" as *u8); o = mp_catn(ob, o, cread[c])
1043 o = mp_cat(ob, o, " ccreate=" as *u8); o = mp_catn(ob, o, ccre[c])
1044 sumout = sumout + outt[c]
1045 sumcr = sumcr + cread[c]
1046 if isbeat == 1 {
1047 let st: i64 = sm_beat(mcp, base, capf, markpath, mark, mn, log, ln, keys[best], fam, files[c], outt[c], cread[c], ccre[c], msgs[c], dry, now, resp)
1048 if st == SM_ALREADY { already = already + 1; o = mp_cat(ob, o, " status=ALREADY-MARKED" as *u8) } else { planned = planned + 1 }
1049 if st == SM_WOULD { o = mp_cat(ob, o, " status=WOULD-PUSH" as *u8) }
1050 if st == SM_RECOVERED { ctr[MB_C_RECOVERED] = ctr[MB_C_RECOVERED] + 1; o = mp_cat(ob, o, " status=RECOVERED-estate-log-already-held-it" as *u8) }
1051 if st == SM_DEFERRED { ctr[MB_C_DEFERRED] = ctr[MB_C_DEFERRED] + 1; o = mp_cat(ob, o, " status=DEFERRED-estate-log-unreadable" as *u8) }
1052 if st == SM_PUSHED { pushed = pushed + 1; o = mp_cat(ob, o, " status=PUSHED" as *u8) }
1053 if st == SM_UNMARKED { failed = failed + 1; o = mp_cat(ob, o, " status=PUSHED-BUT-UNMARKED" as *u8) }
1054 if st == SM_TRANSPORT { failed = failed + 1; o = mp_cat(ob, o, " status=PUSH-FAILED-transport" as *u8) }
1055 if st == SM_REFUSED { failed = failed + 1; o = mp_cat(ob, o, " status=PUSH-REFUSED-no-METERED-receipt" as *u8) }
1056 }
1057 o = mp_cat(ob, o, "\n" as *u8)
1058 }
1059 f = f + 1
1060 }
1061 }
1062 o = mp_cat(ob, o, "METERBEAT window_days=" as *u8); o = mp_catn(ob, o, days)
1063 o = mp_cat(ob, o, " today_daynum=" as *u8); o = mp_catn(ob, o, today)
1064 o = mp_cat(ob, o, " files_seen=" as *u8); o = mp_catn(ob, o, ctr[MB_C_FILES])
1065 o = mp_cat(ob, o, " files_read=" as *u8); o = mp_catn(ob, o, ctr[MB_C_READ])
1066 o = mp_cat(ob, o, " files_skipped_mtime=" as *u8); o = mp_catn(ob, o, ctr[MB_C_SKIPPED])
1067 o = mp_cat(ob, o, " statfail=" as *u8); o = mp_catn(ob, o, ctr[MB_C_STATFAIL])
1068 o = mp_cat(ob, o, " lines=" as *u8); o = mp_catn(ob, o, ctr[MB_C_LINES])
1069 o = mp_cat(ob, o, " assistant_lines=" as *u8); o = mp_catn(ob, o, ctr[MB_C_ASSIST])
1070 o = mp_cat(ob, o, " msgs=" as *u8); o = mp_catn(ob, o, ctr[MB_C_MSGS])
1071 o = mp_cat(ob, o, " dup_blocks=" as *u8); o = mp_catn(ob, o, ctr[MB_C_DUP])
1072 o = mp_cat(ob, o, " outside_window=" as *u8); o = mp_catn(ob, o, ctr[MB_C_OUTSIDE])
1073 o = mp_cat(ob, o, " malformed=" as *u8); o = mp_catn(ob, o, ctr[MB_C_MALFORMED])
1074 o = mp_cat(ob, o, " synthetic=" as *u8); o = mp_catn(ob, o, ctr[MB_C_SYNTH])
1075 o = mp_cat(ob, o, " partial_files=" as *u8); o = mp_catn(ob, o, ctr[MB_C_PARTIAL])
1076 o = mp_cat(ob, o, " days=" as *u8); o = mp_catn(ob, o, nd)
1077 o = mp_cat(ob, o, " fams=" as *u8); o = mp_catn(ob, o, nf)
1078 o = mp_cat(ob, o, " days_floor=" as *u8); o = mp_catn(ob, o, ctr[MB_C_DAYSFLOOR])
1079 o = mp_cat(ob, o, " files_floor=" as *u8); o = mp_catn(ob, o, ctr[MB_C_FILESFLOOR])
1080 o = mp_cat(ob, o, " window_out=" as *u8); o = mp_catn(ob, o, sumout)
1081 o = mp_cat(ob, o, " window_cread=" as *u8); o = mp_catn(ob, o, sumcr)
1082 // partition: assistant_lines = msgs + dup_blocks + outside_window + malformed + synthetic (printed so a reader can check it)
1083 o = mp_cat(ob, o, " partition=" as *u8); o = mp_catn(ob, o, ctr[MB_C_MSGS] + ctr[MB_C_DUP] + ctr[MB_C_OUTSIDE] + ctr[MB_C_MALFORMED] + ctr[MB_C_SYNTH])
1084 if isbeat == 1 {
1085 o = mp_cat(ob, o, " planned=" as *u8); o = mp_catn(ob, o, planned)
1086 o = mp_cat(ob, o, " pushed=" as *u8); o = mp_catn(ob, o, pushed)
1087 o = mp_cat(ob, o, " already=" as *u8); o = mp_catn(ob, o, already)
1088 o = mp_cat(ob, o, " failed=" as *u8); o = mp_catn(ob, o, failed)
1089 o = mp_cat(ob, o, " recovered=" as *u8); o = mp_catn(ob, o, ctr[MB_C_RECOVERED])
1090 o = mp_cat(ob, o, " deferred=" as *u8); o = mp_catn(ob, o, ctr[MB_C_DEFERRED])
1091 if dry == 1 { o = mp_cat(ob, o, " remote_log=NOT-READ-dry" as *u8) } else { if ln < 0 { o = mp_cat(ob, o, " remote_log=UNREADABLE" as *u8) } else { o = mp_cat(ob, o, " remote_log=READ" as *u8) } }
1092 o = mp_cat(ob, o, " dry=" as *u8); o = mp_catn(ob, o, dry)
1093 }
1094 var rc: i64 = MB_EXIT_OK
1095 if failed > 0 { rc = MB_EXIT_RED }
1096 if rc == MB_EXIT_OK { o = mp_cat(ob, o, " verdict=GREEN\n" as *u8) } else { o = mp_cat(ob, o, " verdict=RED\n" as *u8) }
1097 if jsonf == 1 {
1098 // the hook envelope carries ONE line: the summary; the DAY rows stay in plain mode
1099 let sp: i64 = mb_rfind(ob, 0, o, "METERBEAT " as *u8)
1100 var s0: i64 = 0
1101 if sp >= 0 { s0 = sp }
1102 mp_hook_json("SessionStart" as *u8, ((ob as i64) + s0) as *u8, o - s0)
1103 sys_exit(MB_EXIT_OK)
1104 return MB_EXIT_OK
1105 }
1106 mp_write_all(1, ob, o)
1107 sys_exit(rc)
1108 return rc
1109}