code wiki / _hdl_build / nx_asset_dashboard_lib.nx
nx_asset_dashboard_lib.nx source
↩ module page · 183 lines · 10910 B
1// nx_asset_dashboard_lib.nx -- shared dashboard EMIT core (the 3-pillar /wiki/assets.html renderer).
2//
3// Factored out of nx_asset_dashboard_page so BOTH the runnable page emitter AND its gate drive the SAME
4// render path (DRY #15, mirrors nx_asset_ingest_lib). dp_emit(prefix, slug) computes the live stats
5// over an ARBITRARY catalog prefix and renders the 3 awareness pillars through the reusable typed-page
6// generator (ims_page writes web_assets/<slug>.html). Split into per-pillar helpers so no single
7// function trips the fat-function miscompile. NO main(). license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_asset_record.nx"
10import "nx_asset_catalog.nx"
11import "nx_asset_status.nx"
12import "nx_ims_page.nx"
13import "nx_asset_visibility.nx"
14const K_MAGIC_4096: i64 = 4096
15const K_MAGIC_262144: i64 = 262144
16
17func dp_prefix() -> *u8 { return "knowledge/store/asset-catalog-\x00" as *u8 }
18
19func dp_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
20func dp_num(v: i64) -> i64 {
21 let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { sys_write(1, "-\x00" as *u8, 1); m = 0 - m }
22 let t: *u8 = sys_mmap(28); var k: i64 = 0
23 if m == 0 { t[0] = 48 as u8; k = 1 }
24 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
25 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
26 sys_write(1, bb, k); return 0
27}
28func dp_present(v: *u8) -> i64 {
29 if (v as i64) == 0 { return 0 }
30 if v[0] == (0 as u8) { return 0 }
31 return 1
32}
33func dp_streq(a: *u8, b: *u8) -> i64 {
34 var i: i64 = 0
35 while 1 == 1 { if a[i] != b[i] { return 0 } if a[i] == (0 as u8) { return 1 } i = i + 1 }
36 return 1
37}
38
39// one stat-row "<tr><td>label</td><td>N</td></tr>" into dst at off; returns new off.
40func dp_statrow(dst: *u8, off: i64, label: *u8, n: i64) -> i64 {
41 var o: i64 = off
42 o = sh_cat(dst, o, "<tr><td>\x00" as *u8); o = sh_cat(dst, o, label)
43 o = sh_cat(dst, o, "</td><td>\x00" as *u8); o = sh_catn(dst, o, n)
44 o = sh_cat(dst, o, "</td></tr>\n\x00" as *u8)
45 return o
46}
47// one TO-DO signal row only if n>0: "<li><strong>CODE</strong> × N</li>"
48func dp_sigrow(dst: *u8, off: i64, code: *u8, n: i64) -> i64 {
49 if n <= 0 { return off }
50 var o: i64 = off
51 o = sh_cat(dst, o, "<li><strong>\x00" as *u8); o = sh_cat(dst, o, code)
52 o = sh_cat(dst, o, "</strong> × \x00" as *u8); o = sh_catn(dst, o, n)
53 o = sh_cat(dst, o, "</li>\n\x00" as *u8)
54 return o
55}
56
57// the browsable asset list (enumerate the catalog snapshot at `prefix`). returns new off.
58// public_only==1 -> WITHHOLD any asset whose SOURCE flags it non-public (nx_asset_visibility), so the
59// public wiki view never leaks operator-only (e.g. gallery) filenames.
60func dp_asset_list(b: *u8, off: i64, prefix: *u8, public_only: i64) -> i64 {
61 var o: i64 = off
62 let lcap: i64 = K_MAGIC_4096
63 let cids: *i64 = sys_mmap(8 * lcap) as *i64
64 let n: i64 = cat_list(prefix, cids, lcap)
65 let dk: *i64 = sys_mmap(8 * 64) as *i64
66 let dv: *i64 = sys_mmap(8 * 64) as *i64
67 let pp: *i64 = sys_mmap(16) as *i64
68 let ll: *i64 = sys_mmap(16) as *i64
69 var i: i64 = 0
70 while i < n {
71 let cid: *u8 = cids[i] as *u8
72 if cat_get(prefix, cid, pp, ll) == 1 {
73 var show: i64 = 1
74 if public_only == 1 { if vis_is_public(pp[0] as *u8, ll[0]) == 0 { show = 0 } }
75 if show == 1 {
76 let nf: i64 = ar_decode(pp[0] as *u8, ll[0], dk, dv, 64)
77 let typ: *u8 = ar_get(dk, dv, nf, "type\x00" as *u8)
78 let title: *u8 = ar_get(dk, dv, nf, "title\x00" as *u8)
79 let prov: *u8 = ar_get(dk, dv, nf, "prov_class\x00" as *u8)
80 let ident: *u8 = ar_get(dk, dv, nf, "identifier\x00" as *u8)
81 let w: *u8 = ar_get(dk, dv, nf, "width\x00" as *u8)
82 let hgt: *u8 = ar_get(dk, dv, nf, "height\x00" as *u8)
83 o = sh_cat(b, o, "<tr><td>\x00" as *u8)
84 if dp_present(title) == 1 { o = sh_cat(b, o, title) } else { o = sh_cat(b, o, "(untitled)\x00" as *u8) }
85 o = sh_cat(b, o, "</td><td>\x00" as *u8)
86 if dp_present(typ) == 1 { o = sh_cat(b, o, typ) } else { o = sh_cat(b, o, "?\x00" as *u8) }
87 if dp_present(typ) == 1 { if dp_streq(typ, "image\x00" as *u8) == 1 { if dp_present(w) == 1 { if dp_present(hgt) == 1 {
88 o = sh_cat(b, o, " <small>(\x00" as *u8); o = sh_cat(b, o, w); o = sh_cat(b, o, "×\x00" as *u8); o = sh_cat(b, o, hgt); o = sh_cat(b, o, ")</small>\x00" as *u8)
89 } } } }
90 o = sh_cat(b, o, "</td><td>\x00" as *u8)
91 if dp_present(prov) == 1 { o = sh_cat(b, o, prov) } else { o = sh_cat(b, o, "unattributed\x00" as *u8) }
92 o = sh_cat(b, o, "</td><td>\x00" as *u8)
93 if dp_present(typ) == 1 {
94 if dp_streq(typ, "doc\x00" as *u8) == 1 {
95 if dp_present(ident) == 1 {
96 o = sh_cat(b, o, "<a href=\"/wiki/\x00" as *u8); o = sh_cat(b, o, ident); o = sh_cat(b, o, ".html\">/wiki/\x00" as *u8); o = sh_cat(b, o, ident); o = sh_cat(b, o, ".html</a>\x00" as *u8)
97 } else { o = sh_cat(b, o, "—\x00" as *u8) }
98 } else {
99 if dp_present(ident) == 1 { o = sh_cat(b, o, "<code>\x00" as *u8); o = sh_cat(b, o, ident); o = sh_cat(b, o, "</code>\x00" as *u8) } else { o = sh_cat(b, o, "—\x00" as *u8) }
100 }
101 } else { o = sh_cat(b, o, "—\x00" as *u8) }
102 o = sh_cat(b, o, "</td></tr>\n\x00" as *u8)
103 }
104 }
105 i = i + 1
106 }
107 return o
108}
109
110// PILLAR 1: what we have (counts by type + provenance + the browse list).
111func dp_pillar_have(b: *u8, off: i64, prefix: *u8, st: *i64, public_only: i64) -> i64 {
112 var o: i64 = off
113 o = sh_cat(b, o, "<h2 id=\"have\"><a href=\"#have\">What we have</a></h2>\n\x00" as *u8)
114 o = sh_cat(b, o, "<p>Total catalogued assets: <strong>\x00" as *u8); o = sh_catn(b, o, st[ST_TOTAL()])
115 o = sh_cat(b, o, "</strong> (content-addressed; identical bytes collapse to one record).</p>\n\x00" as *u8)
116 o = sh_cat(b, o, "<h3>By type</h3>\n<table><tr><th>Type</th><th>Count</th></tr>\n\x00" as *u8)
117 o = dp_statrow(b, o, "doc\x00" as *u8, st[ST_T_DOC()])
118 o = dp_statrow(b, o, "image\x00" as *u8, st[ST_T_IMAGE()])
119 o = dp_statrow(b, o, "video\x00" as *u8, st[ST_T_VIDEO()])
120 o = dp_statrow(b, o, "audio\x00" as *u8, st[ST_T_AUDIO()])
121 o = dp_statrow(b, o, "dataset\x00" as *u8, st[ST_T_DATASET()])
122 o = dp_statrow(b, o, "product\x00" as *u8, st[ST_T_PRODUCT()])
123 o = sh_cat(b, o, "</table>\n\x00" as *u8)
124 o = sh_cat(b, o, "<h3>By provenance class</h3>\n<table><tr><th>Provenance</th><th>Count</th></tr>\n\x00" as *u8)
125 o = dp_statrow(b, o, "machine-generated\x00" as *u8, st[ST_P_MACHINE()])
126 o = dp_statrow(b, o, "human-authored\x00" as *u8, st[ST_P_HUMAN()])
127 o = dp_statrow(b, o, "downloaded\x00" as *u8, st[ST_P_DOWNLOAD()])
128 o = dp_statrow(b, o, "unattributed\x00" as *u8, st[ST_P_NONE()])
129 o = sh_cat(b, o, "</table>\n\x00" as *u8)
130 o = sh_cat(b, o, "<h3>Browse assets</h3>\n\x00" as *u8)
131 if public_only == 1 { o = sh_cat(b, o, "<p class=\"why\">Public view: assets flagged private/operator-only by their source are withheld here (visible only in the operator view).</p>\n\x00" as *u8) }
132 o = sh_cat(b, o, "<table><tr><th>Title</th><th>Type</th><th>Provenance</th><th>Source</th></tr>\n\x00" as *u8)
133 o = dp_asset_list(b, o, prefix, public_only)
134 o = sh_cat(b, o, "</table>\n\x00" as *u8)
135 return o
136}
137
138// PILLAR 2: what we need to do (derived signals).
139func dp_pillar_todo(b: *u8, off: i64, st: *i64) -> i64 {
140 var o: i64 = off
141 o = sh_cat(b, o, "<h2 id=\"todo\"><a href=\"#todo\">What we need to do</a></h2>\n\x00" as *u8)
142 o = sh_cat(b, o, "<p>Work items are not a hand-kept list — they are <strong>predicates derived from catalog state</strong> by <code>nx_asset_signals</code>. Total signals: <strong>\x00" as *u8)
143 o = sh_catn(b, o, st[ST_SIG_TOTAL()]); o = sh_cat(b, o, "</strong>.</p>\n\x00" as *u8)
144 o = sh_cat(b, o, "<ul>\n\x00" as *u8)
145 o = dp_sigrow(b, o, "MISSING_PROVENANCE\x00" as *u8, st[ST_SIG_PROV()])
146 o = dp_sigrow(b, o, "UNTAGGED\x00" as *u8, st[ST_SIG_UNTAG()])
147 o = dp_sigrow(b, o, "MISSING_METADATA\x00" as *u8, st[ST_SIG_META()])
148 o = dp_sigrow(b, o, "NEAR_DUP\x00" as *u8, st[ST_SIG_NEARDUP()])
149 o = dp_sigrow(b, o, "STALE\x00" as *u8, st[ST_SIG_STALE()])
150 o = dp_sigrow(b, o, "ORPHANED\x00" as *u8, st[ST_SIG_ORPHAN()])
151 o = dp_sigrow(b, o, "UNTRANSCODED\x00" as *u8, st[ST_SIG_UNTRANS()])
152 o = sh_cat(b, o, "</ul>\n\x00" as *u8)
153 o = sh_cat(b, o, "<p class=\"why\">Honest note: <code>MISSING_PROVENANCE</code> fires for every asset because no signed C2PA-style credential is minted yet (deny-by-default), and <code>NEAR_DUP</code> is unevaluated because that needs a pixel decode (the documented R3 boundary). These are genuine next-rung work, not flattering omissions.</p>\n\x00" as *u8)
154 return o
155}
156
157// PILLAR 3: what's going on (freshness/status).
158func dp_pillar_goingon(b: *u8, off: i64, st: *i64) -> i64 {
159 var o: i64 = off
160 o = sh_cat(b, o, "<h2 id=\"going-on\"><a href=\"#going-on\">What's going on</a></h2>\n\x00" as *u8)
161 o = sh_cat(b, o, "<table><tr><th>Status metric</th><th>Value</th></tr>\n\x00" as *u8)
162 o = dp_statrow(b, o, "live / current assets\x00" as *u8, st[ST_CURRENT()])
163 o = dp_statrow(b, o, "soft-retired / not-current\x00" as *u8, st[ST_NOTCURRENT()])
164 o = dp_statrow(b, o, "open work signals\x00" as *u8, st[ST_SIG_TOTAL()])
165 o = dp_statrow(b, o, "total assets\x00" as *u8, st[ST_TOTAL()])
166 o = sh_cat(b, o, "</table>\n\x00" as *u8)
167 o = sh_cat(b, o, "<p>See also the live task board (<a href=\"/wiki/board.html\">/wiki/board.html</a>) and the devlog (<a href=\"/wiki/devlog.html\">/wiki/devlog.html</a>).</p>\n\x00" as *u8)
168 return o
169}
170
171// EMIT the full dashboard for `prefix` to web_assets/<slug>.html. Returns ims_page bytes written (<0 fail).
172func dp_emit(prefix: *u8, slug: *u8, public_only: i64) -> i64 {
173 let st: *i64 = sys_mmap(8 * st_cap()) as *i64
174 st_compute_live(prefix, st)
175 let b: *u8 = sys_mmap(K_MAGIC_262144)
176 var o: i64 = 0
177 o = sh_cat(b, o, "<p class=\"lede\">The <strong>single source of truth</strong> for every Nishi asset — one content-addressed inventory. These numbers are <strong>counted live</strong> from the catalog by <code>nx_asset_status</code>; the work list is <strong>derived</strong> by <code>nx_asset_signals</code>. Nothing here is hand-typed.</p>\n\x00" as *u8)
178 o = dp_pillar_have(b, o, prefix, st, public_only)
179 o = dp_pillar_todo(b, o, st)
180 o = dp_pillar_goingon(b, o, st)
181 b[o] = 0 as u8
182 return ims_page(slug, "reference\x00" as *u8, "Asset Catalog & Awareness Dashboard\x00" as *u8, b)
183}