pi-mega-compact 0.20.76 → 0.20.78

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/config/vector-cortex-vc9b.js +4 -3
  2. package/dist/extensions/dashboard-server/api-contracts/endpoints/registry-ext.js +1 -1
  3. package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +1 -1
  4. package/dist/extensions/dashboard-server/routes-setup-cortex-actions.js +6 -5
  5. package/dist/extensions/dashboard-server/setup-cortex-actions-vc2.js +334 -0
  6. package/dist/extensions/dashboard-server/setup-cortex-actions.js +18 -69
  7. package/dist/src/config/vector-cortex-vc9b.js +4 -3
  8. package/extensions/dashboard-client/dist/assets/{AdminTab-B8JqsA41.js → AdminTab-BsA8-_bX.js} +2 -2
  9. package/extensions/dashboard-client/dist/assets/{AdminTab-B8JqsA41.js.map → AdminTab-BsA8-_bX.js.map} +1 -1
  10. package/extensions/dashboard-client/dist/assets/{AreaChart-CeaexvWO.js → AreaChart-BRHEfWhc.js} +2 -2
  11. package/extensions/dashboard-client/dist/assets/{AreaChart-CeaexvWO.js.map → AreaChart-BRHEfWhc.js.map} +1 -1
  12. package/extensions/dashboard-client/dist/assets/{BarChart-Bhyviy7_.js → BarChart-C-M0LaFc.js} +2 -2
  13. package/extensions/dashboard-client/dist/assets/{BarChart-Bhyviy7_.js.map → BarChart-C-M0LaFc.js.map} +1 -1
  14. package/extensions/dashboard-client/dist/assets/{CacheTab-C6bFdEHq.js → CacheTab-Cj3n59U3.js} +2 -2
  15. package/extensions/dashboard-client/dist/assets/{CacheTab-C6bFdEHq.js.map → CacheTab-Cj3n59U3.js.map} +1 -1
  16. package/extensions/dashboard-client/dist/assets/{ConfigTab-CbsdI5yj.js → ConfigTab-C016XTNC.js} +2 -2
  17. package/extensions/dashboard-client/dist/assets/{ConfigTab-CbsdI5yj.js.map → ConfigTab-C016XTNC.js.map} +1 -1
  18. package/extensions/dashboard-client/dist/assets/{EventsTab-kvB5Znx2.js → EventsTab-DE29fuqe.js} +2 -2
  19. package/extensions/dashboard-client/dist/assets/{EventsTab-kvB5Znx2.js.map → EventsTab-DE29fuqe.js.map} +1 -1
  20. package/extensions/dashboard-client/dist/assets/{HealthTab-DqEUk5LW.js → HealthTab-D4eVI8ar.js} +2 -2
  21. package/extensions/dashboard-client/dist/assets/{HealthTab-DqEUk5LW.js.map → HealthTab-D4eVI8ar.js.map} +1 -1
  22. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CS5HqDkY.js → MaintenanceTab-4fJ7M4S4.js} +2 -2
  23. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CS5HqDkY.js.map → MaintenanceTab-4fJ7M4S4.js.map} +1 -1
  24. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-Oq-iqvUq.js → MemoryMapTab-CDbcK9e4.js} +2 -2
  25. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-Oq-iqvUq.js.map → MemoryMapTab-CDbcK9e4.js.map} +1 -1
  26. package/extensions/dashboard-client/dist/assets/{MetricsCards-36RVmtPj.js → MetricsCards-VUEcgGzo.js} +2 -2
  27. package/extensions/dashboard-client/dist/assets/{MetricsCards-36RVmtPj.js.map → MetricsCards-VUEcgGzo.js.map} +1 -1
  28. package/extensions/dashboard-client/dist/assets/MetricsTab-CKqJ0Zl-.js +2 -0
  29. package/extensions/dashboard-client/dist/assets/{MetricsTab-Clkcniuo.js.map → MetricsTab-CKqJ0Zl-.js.map} +1 -1
  30. package/extensions/dashboard-client/dist/assets/{OverviewTab-Cl2Zx7r1.js → OverviewTab-9Kxo79mi.js} +2 -2
  31. package/extensions/dashboard-client/dist/assets/{OverviewTab-Cl2Zx7r1.js.map → OverviewTab-9Kxo79mi.js.map} +1 -1
  32. package/extensions/dashboard-client/dist/assets/{ReposTab-DUoDgjk-.js → ReposTab-C4iveqrP.js} +2 -2
  33. package/extensions/dashboard-client/dist/assets/{ReposTab-DUoDgjk-.js.map → ReposTab-C4iveqrP.js.map} +1 -1
  34. package/extensions/dashboard-client/dist/assets/{SessionsTab-hEQ_OAfB.js → SessionsTab-DSEwkMQm.js} +2 -2
  35. package/extensions/dashboard-client/dist/assets/{SessionsTab-hEQ_OAfB.js.map → SessionsTab-DSEwkMQm.js.map} +1 -1
  36. package/extensions/dashboard-client/dist/assets/{SetupTab-Bqibg0cD.js → SetupTab-CCyWgy4O.js} +2 -2
  37. package/extensions/dashboard-client/dist/assets/{SetupTab-Bqibg0cD.js.map → SetupTab-CCyWgy4O.js.map} +1 -1
  38. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-9QMQUc7L.js → TimeSavedCard-CyD8e_e_.js} +2 -2
  39. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-9QMQUc7L.js.map → TimeSavedCard-CyD8e_e_.js.map} +1 -1
  40. package/extensions/dashboard-client/dist/assets/{TurnMemoryView-DAfqhJqd.js → TurnMemoryView-5tLbWkRv.js} +2 -2
  41. package/extensions/dashboard-client/dist/assets/{TurnMemoryView-DAfqhJqd.js.map → TurnMemoryView-5tLbWkRv.js.map} +1 -1
  42. package/extensions/dashboard-client/dist/assets/TurnsTab-C7pm92Hg.js +2 -0
  43. package/extensions/dashboard-client/dist/assets/{TurnsTab-C-uZNH2F.js.map → TurnsTab-C7pm92Hg.js.map} +1 -1
  44. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-DyOagOVb.js → VcStatusBadge-ObhcIyfN.js} +2 -2
  45. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-DyOagOVb.js.map → VcStatusBadge-ObhcIyfN.js.map} +1 -1
  46. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BxsbSUGv.js → VectorCortexTab-BtHZb7o7.js} +2 -2
  47. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BxsbSUGv.js.map → VectorCortexTab-BtHZb7o7.js.map} +1 -1
  48. package/extensions/dashboard-client/dist/assets/{WikiTab-CjefloQb.js → WikiTab-lQ4l3QIK.js} +2 -2
  49. package/extensions/dashboard-client/dist/assets/{WikiTab-CjefloQb.js.map → WikiTab-lQ4l3QIK.js.map} +1 -1
  50. package/extensions/dashboard-client/dist/assets/{button-D-9nb4Bw.js → button-DhQQAJGm.js} +2 -2
  51. package/extensions/dashboard-client/dist/assets/{button-D-9nb4Bw.js.map → button-DhQQAJGm.js.map} +1 -1
  52. package/extensions/dashboard-client/dist/assets/{card-Dvl16_R5.js → card-Cfhz9X31.js} +2 -2
  53. package/extensions/dashboard-client/dist/assets/{card-Dvl16_R5.js.map → card-Cfhz9X31.js.map} +1 -1
  54. package/extensions/dashboard-client/dist/assets/{client-extra-BShDrG99.js → client-extra-CKNOGEz_.js} +2 -2
  55. package/extensions/dashboard-client/dist/assets/{client-extra-BShDrG99.js.map → client-extra-CKNOGEz_.js.map} +1 -1
  56. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Q_V4fqVi.js → generateCategoricalChart-JKjK9_cB.js} +2 -2
  57. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Q_V4fqVi.js.map → generateCategoricalChart-JKjK9_cB.js.map} +1 -1
  58. package/extensions/dashboard-client/dist/assets/{index-CL6Af_JZ.js → index-iuxgtzEW.js} +4 -4
  59. package/extensions/dashboard-client/dist/assets/{index-CL6Af_JZ.js.map → index-iuxgtzEW.js.map} +1 -1
  60. package/extensions/dashboard-client/dist/assets/{switch-0MNUTR9I.js → switch-7EHEQMSP.js} +2 -2
  61. package/extensions/dashboard-client/dist/assets/{switch-0MNUTR9I.js.map → switch-7EHEQMSP.js.map} +1 -1
  62. package/extensions/dashboard-client/dist/assets/{toggle-DHbWo-CW.js → toggle-z1lWY4UM.js} +2 -2
  63. package/extensions/dashboard-client/dist/assets/{toggle-DHbWo-CW.js.map → toggle-z1lWY4UM.js.map} +1 -1
  64. package/extensions/dashboard-client/dist/assets/{useSSE-DcBpzKtI.js → useSSE-sctOZuRM.js} +2 -2
  65. package/extensions/dashboard-client/dist/assets/{useSSE-DcBpzKtI.js.map → useSSE-sctOZuRM.js.map} +1 -1
  66. package/extensions/dashboard-client/dist/index.html +1 -1
  67. package/extensions/dashboard-server/api-contracts/endpoints/registry-ext.ts +1 -1
  68. package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +1 -1
  69. package/extensions/dashboard-server/routes-setup-cortex-actions.ts +6 -5
  70. package/extensions/dashboard-server/setup-cortex-actions-vc2.ts +400 -0
  71. package/extensions/dashboard-server/setup-cortex-actions.ts +18 -71
  72. package/package.json +1 -1
  73. package/src/config/vector-cortex-vc9b.ts +4 -3
  74. package/extensions/dashboard-client/dist/assets/MetricsTab-Clkcniuo.js +0 -2
  75. package/extensions/dashboard-client/dist/assets/TurnsTab-C-uZNH2F.js +0 -2
@@ -0,0 +1,400 @@
1
+ /**
2
+ * dashboard-server/setup-cortex-actions-vc2.ts — VC2 model-prep action driver
3
+ * (fetch-model + bench), ported in-process.
4
+ *
5
+ * Sibling of setup-cortex-actions.ts (the vc9b actor surface). Implements the
6
+ * mechanics behind the VC9B `fetch-model` and `bench` actions, replacing the
7
+ * previous spawn-of-scripts approach: the npm package's `files` allowlist does
8
+ * NOT include scripts/, so scripts/vc2-model-prep/* is absent on installed
9
+ * devices and the spawn path 500s with "not found in this checkout".
10
+ *
11
+ * fetch-model: downloads the candidate encoder (model.onnx + tokenizer.json)
12
+ * from HuggingFace via node:https and verifies sha256 against pinned digests.
13
+ * PREVENT-PI-004 opt-in: user-triggered, confirm-gated download of ML model
14
+ * assets from HuggingFace (same exemption class as install-native-ort).
15
+ *
16
+ * bench: loads onnxruntime-node via createRequire, runs warm-up + timed
17
+ * inference iterations, computes p50/p95/p99 latency, samples RSS, and runs a
18
+ * determinism check (identical outputs within 1e-6 across repeats).
19
+ *
20
+ * Never throws: every failure is returned as { ok: false, ... } with a log.
21
+ * Guardrails: PREVENT-011 (no `any`); PREVENT-PI-004 (guardrails-allow below).
22
+ */
23
+
24
+ // guardrails-allow PREVENT-PI-004: opt-in, confirm-gated download of ML model
25
+ // assets from HuggingFace (user-triggered from dashboard)
26
+ import { get as httpsGet } from "node:https";
27
+
28
+ import { createHash } from "node:crypto";
29
+ import { createRequire } from "node:module";
30
+ import {
31
+ mkdirSync,
32
+ writeFileSync,
33
+ existsSync,
34
+ statSync,
35
+ rmSync,
36
+ } from "node:fs";
37
+ import { join, dirname } from "node:path";
38
+ import { fileURLToPath } from "node:url";
39
+ import type {
40
+ SetupCortexActionKind,
41
+ SetupCortexActionResult,
42
+ } from "./api-contracts/setup-cortex.js";
43
+ import { writeLogName, writeLog } from "./setup-cortex-actions.js";
44
+
45
+ // ─── fetch-model constants ─────────────────────────────────────────────────
46
+
47
+ const HF_BASE =
48
+ // guardrails-allow PREVENT-PI-004: opt-in, confirm-gated download of ML model
49
+ // assets from HuggingFace (user-triggered from dashboard)
50
+ "https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2/resolve/main";
51
+ const MODEL_URL = `${HF_BASE}/onnx/model_qint8_avx512_vnni.onnx`;
52
+ const TOKENIZER_URL = `${HF_BASE}/tokenizer.json`;
53
+ const MODEL_SHA256 =
54
+ "4278337fd0ff3c68bfb6291042cad8ab363e1d9fbc43dcb499fe91c871902474";
55
+ const TOKENIZER_SHA256 =
56
+ "be50c3628f2bf5bb5e3a7f17b1f74611b2561a3a27eeab05e5aa30f411572037";
57
+
58
+ // ─── bench constants ───────────────────────────────────────────────────────
59
+
60
+ const LATENCY_BUDGET_MS = 40;
61
+ const RSS_BUDGET_MIB = 150;
62
+ const DETERMINISM_EPSILON = 1e-6;
63
+ const BENCH_TOKENS = 512;
64
+ const BENCH_ITERS = 300;
65
+ const BENCH_THREADS = 4;
66
+ const BENCH_REPEATS = 200;
67
+
68
+ // ─── shared helpers ────────────────────────────────────────────────────────
69
+
70
+ function sha256Hex(buf: Buffer): string {
71
+ return createHash("sha256").update(buf).digest("hex");
72
+ }
73
+
74
+ function mib(bytes: number): number {
75
+ return +(bytes / 1048576).toFixed(1);
76
+ }
77
+
78
+ function percentile(sorted: number[], p: number): number {
79
+ const i = Math.min(sorted.length - 1, Math.floor(sorted.length * p));
80
+ return +sorted[i].toFixed(2);
81
+ }
82
+
83
+ // ─── fetch helpers ─────────────────────────────────────────────────────────
84
+
85
+ /** Download a URL to a Buffer via node:https (follows one redirect). */
86
+ function download(url: string): Promise<Buffer> {
87
+ return new Promise((resolve, reject) => {
88
+ // guardrails-allow PREVENT-PI-004: opt-in, confirm-gated download of ML
89
+ // model assets from HuggingFace (user-triggered from dashboard)
90
+ httpsGet(url, (res) => {
91
+ if (
92
+ res.statusCode !== undefined &&
93
+ res.statusCode >= 300 &&
94
+ res.statusCode < 400 &&
95
+ res.headers.location
96
+ ) {
97
+ res.resume();
98
+ // Follow a single redirect (HuggingFace CDN redirects). The Location
99
+ // header may be a RELATIVE path (e.g. /api/resolve-cache/...) — resolve
100
+ // it against the original URL so httpsGet never receives a bare path.
101
+ const redirected = new URL(res.headers.location, url).toString();
102
+ download(redirected).then(resolve, reject);
103
+ return;
104
+ }
105
+ if (res.statusCode !== 200) {
106
+ res.resume();
107
+ reject(new Error(`HTTP ${res.statusCode} for ${url}`));
108
+ return;
109
+ }
110
+ const chunks: Buffer[] = [];
111
+ res.on("data", (chunk: Buffer) => chunks.push(chunk));
112
+ res.on("end", () => resolve(Buffer.concat(chunks)));
113
+ res.on("error", reject);
114
+ }).on("error", reject);
115
+ });
116
+ }
117
+
118
+ /** Fetch one asset: download, verify sha256, write to disk. */
119
+ async function fetchAsset(
120
+ url: string,
121
+ outPath: string,
122
+ wantSha: string,
123
+ logLines: string[],
124
+ ): Promise<boolean> {
125
+ const label = outPath.split("/").pop() ?? outPath;
126
+ logLines.push(`fetching ${label}`);
127
+ let buf: Buffer;
128
+ try {
129
+ buf = await download(url);
130
+ } catch (err) {
131
+ const msg = err instanceof Error ? err.message : String(err);
132
+ logLines.push(`FAIL download ${label}: ${msg}`);
133
+ return false;
134
+ }
135
+ const got = sha256Hex(buf);
136
+ if (got !== wantSha) {
137
+ logLines.push(`DIGEST MISMATCH for ${label}`);
138
+ logLines.push(` expected: ${wantSha}`);
139
+ logLines.push(` actual: ${got}`);
140
+ return false;
141
+ }
142
+ // guardrails-allow PREVENT-PI-004: local state-dir filesystem write (loopback)
143
+ writeFileSync(outPath, buf);
144
+ logLines.push(` ok sha256=${got} bytes=${buf.length}`);
145
+ return true;
146
+ }
147
+
148
+ // ─── fetch-model implementation ────────────────────────────────────────────
149
+
150
+ async function runFetchModel(
151
+ stateDir: string,
152
+ ): Promise<SetupCortexActionResult> {
153
+ const action: SetupCortexActionKind = "fetch-model";
154
+ const { name, logPath } = writeLogName(action, stateDir);
155
+ const outdir = join(stateDir, "vc2-model-prep");
156
+ // guardrails-allow PREVENT-PI-004: local state-dir filesystem write (loopback)
157
+ mkdirSync(outdir, { recursive: true });
158
+
159
+ const logLines: string[] = [];
160
+ let ok = true;
161
+
162
+ // Model
163
+ const modelPath = join(outdir, "model.onnx");
164
+ if (!(await fetchAsset(MODEL_URL, modelPath, MODEL_SHA256, logLines))) {
165
+ ok = false;
166
+ // Clean up partial download
167
+ // guardrails-allow PREVENT-PI-004: removing file we just wrote (local FS)
168
+ rmSync(modelPath, { force: true });
169
+ }
170
+
171
+ // Tokenizer
172
+ const tokPath = join(outdir, "tokenizer.json");
173
+ if (!(await fetchAsset(TOKENIZER_URL, tokPath, TOKENIZER_SHA256, logLines))) {
174
+ ok = false;
175
+ // guardrails-allow PREVENT-PI-004: removing file we just wrote (local FS)
176
+ rmSync(tokPath, { force: true });
177
+ }
178
+
179
+ logLines.push("");
180
+ logLines.push(`Staged in ${outdir}.`);
181
+ logLines.push(
182
+ "NOTE: this export is opset 14, NOT the opset 17 required by MODEL_ASSET.md.",
183
+ );
184
+ logLines.push(
185
+ "See docs/vector-cortex/vc2-model-prep.md (Opset gap) before committing.",
186
+ );
187
+
188
+ writeLog(logPath, logLines.join("\n") + "\n");
189
+ return {
190
+ action,
191
+ ok,
192
+ exitCode: ok ? 0 : 1,
193
+ logPath,
194
+ logName: name,
195
+ spawned: false,
196
+ };
197
+ }
198
+
199
+ // ─── bench implementation ──────────────────────────────────────────────────
200
+
201
+ /** Locate model.onnx: stateDir first, then walk up from module for dev. */
202
+ function findModelPath(stateDir: string): string | null {
203
+ // Check stateDir first (installed-device path).
204
+ const fromState = join(stateDir, "vc2-model-prep", "model.onnx");
205
+ // guardrails-allow PREVENT-PI-004: local state-dir filesystem read (loopback)
206
+ if (existsSync(fromState)) return fromState;
207
+
208
+ // Walk up from module for repo-checkout dev mode.
209
+ let dir = dirname(fileURLToPath(import.meta.url));
210
+ const rel = join("scripts", "vc2-model-prep", "model.onnx");
211
+ for (let i = 0; i < 8; i++) {
212
+ const candidate = join(dir, rel);
213
+ // guardrails-allow PREVENT-PI-004: local repo filesystem read (loopback)
214
+ if (existsSync(candidate)) return candidate;
215
+ const next = dirname(dir);
216
+ if (next === dir) break;
217
+ dir = next;
218
+ }
219
+ return null;
220
+ }
221
+
222
+ /** Run the ONNX bench: latency + RSS + determinism gates. */
223
+ async function runBench(
224
+ stateDir: string,
225
+ ): Promise<SetupCortexActionResult> {
226
+ const action: SetupCortexActionKind = "bench";
227
+ const { name, logPath } = writeLogName(action, stateDir);
228
+ const logLines: string[] = [];
229
+
230
+ const modelPath = findModelPath(stateDir);
231
+ if (modelPath === null) {
232
+ logLines.push("bench: model.onnx not found (run fetch-model first)");
233
+ writeLog(logPath, logLines.join("\n") + "\n");
234
+ return { action, ok: false, exitCode: 2, logPath, logName: name, spawned: false };
235
+ }
236
+
237
+ // Load onnxruntime-node via createRequire — the binding may be at the
238
+ // ENC-2a native-ort root or in the package's node_modules.
239
+ let ort;
240
+ try {
241
+ const req = createRequire(import.meta.url);
242
+ ort = req("onnxruntime-node");
243
+ } catch {
244
+ logLines.push(
245
+ "onnxruntime-node is not installed. See docs/vector-cortex/vc2-model-prep.md.",
246
+ );
247
+ writeLog(logPath, logLines.join("\n") + "\n");
248
+ return { action, ok: false, exitCode: 2, logPath, logName: name, spawned: false };
249
+ }
250
+
251
+ const tokens = BENCH_TOKENS;
252
+ const iters = BENCH_ITERS;
253
+ const threads = BENCH_THREADS;
254
+ const repeats = BENCH_REPEATS;
255
+
256
+ const rssBefore = process.memoryUsage().rss;
257
+ const loadStart = Date.now();
258
+ const session = await ort.InferenceSession.create(modelPath, {
259
+ executionProviders: ["cpu"],
260
+ intraOpNumThreads: threads,
261
+ graphOptimizationLevel: "all",
262
+ });
263
+ const loadMs = Date.now() - loadStart;
264
+
265
+ const dims = [1, tokens];
266
+ const ids = BigInt64Array.from({ length: tokens }, (_: unknown, i: number) =>
267
+ BigInt(i === 0 ? 101 : i === tokens - 1 ? 102 : 2000 + (i % 500)),
268
+ );
269
+ const mask = BigInt64Array.from({ length: tokens }, () => 1n);
270
+ const types = new BigInt64Array(tokens);
271
+
272
+ interface Feeds { [key: string]: unknown }
273
+ const feeds = (): Feeds => {
274
+ const f: Feeds = {};
275
+ if (session.inputNames.includes("input_ids"))
276
+ f.input_ids = new ort.Tensor("int64", ids, dims);
277
+ if (session.inputNames.includes("attention_mask"))
278
+ f.attention_mask = new ort.Tensor("int64", mask, dims);
279
+ if (session.inputNames.includes("token_type_ids"))
280
+ f.token_type_ids = new ort.Tensor("int64", types, dims);
281
+ return f;
282
+ };
283
+
284
+ // Warm-up
285
+ for (let i = 0; i < 5; i++) await session.run(feeds());
286
+
287
+ // Latency measurement — do NOT retain outputs (measures working set, not GC).
288
+ const lat: number[] = [];
289
+ for (let i = 0; i < iters; i++) {
290
+ const t = process.hrtime.bigint();
291
+ await session.run(feeds());
292
+ lat.push(Number(process.hrtime.bigint() - t) / 1e6);
293
+ }
294
+
295
+ // GC + steady-state RSS
296
+ let gcRan = false;
297
+ if (typeof global.gc === "function") {
298
+ global.gc();
299
+ global.gc();
300
+ await new Promise((r) => setTimeout(r, 200));
301
+ global.gc();
302
+ gcRan = true;
303
+ } else {
304
+ logLines.push(
305
+ "WARNING: global.gc not available (run under node --expose-gc);" +
306
+ " RSS figure is unreliable without it.",
307
+ );
308
+ }
309
+ const steadyRss = mib(process.memoryUsage().rss - rssBefore);
310
+ lat.sort((a, b) => a - b);
311
+
312
+ // Determinism: identical inputs must yield bit-stable outputs.
313
+ let ref: Float32Array | null = null;
314
+ let maxDelta = 0;
315
+ const digests = new Set<string>();
316
+ for (let i = 0; i < repeats; i++) {
317
+ const out = (await session.run(feeds())) as Record<string, { data: Float32Array }>;
318
+ const d = out[session.outputNames[0]].data;
319
+ digests.add(
320
+ createHash("sha256")
321
+ .update(Buffer.from(d.buffer, d.byteOffset, d.byteLength))
322
+ .digest("hex"),
323
+ );
324
+ if (!ref) ref = Float32Array.from(d);
325
+ else
326
+ for (let k = 0; k < d.length; k++) {
327
+ const delta = Math.abs(d[k] - ref[k]);
328
+ if (delta > maxDelta) maxDelta = delta;
329
+ }
330
+ }
331
+
332
+ const p95 = percentile(lat, 0.95);
333
+ const report = {
334
+ model: modelPath,
335
+ // guardrails-allow PREVENT-PI-004: local file stat (loopback)
336
+ modelBytes: statSync(modelPath).size,
337
+ backend: "onnxruntime-node",
338
+ ortVersion: (() => {
339
+ try {
340
+ return createRequire(import.meta.url)("onnxruntime-node/package.json").version as string;
341
+ } catch {
342
+ return "unknown";
343
+ }
344
+ })(),
345
+ platform: `${process.platform}-${process.arch}`,
346
+ threads,
347
+ tokens,
348
+ iters,
349
+ loadMs,
350
+ p50: percentile(lat, 0.5),
351
+ p95,
352
+ p99: percentile(lat, 0.99),
353
+ steadyRssMiB: steadyRss,
354
+ gcRan,
355
+ determinism: {
356
+ repeats,
357
+ distinctDigests: digests.size,
358
+ maxAbsDelta: maxDelta,
359
+ },
360
+ gates: {
361
+ latency: p95 <= LATENCY_BUDGET_MS,
362
+ rss: steadyRss <= RSS_BUDGET_MIB,
363
+ determinism: digests.size === 1 && maxDelta <= DETERMINISM_EPSILON,
364
+ },
365
+ };
366
+ const allPass =
367
+ report.gates.latency && report.gates.rss && report.gates.determinism;
368
+
369
+ logLines.push(JSON.stringify({ ...report, gates: { ...report.gates, all: allPass } }, null, 2));
370
+ writeLog(logPath, logLines.join("\n") + "\n");
371
+ return {
372
+ action,
373
+ ok: allPass,
374
+ exitCode: allPass ? 0 : 1,
375
+ logPath,
376
+ logName: name,
377
+ spawned: false,
378
+ };
379
+ }
380
+
381
+ // ─── public entry point ────────────────────────────────────────────────────
382
+
383
+ /**
384
+ * Run one VC2 model-prep action (fetch-model or bench) in-process.
385
+ * Never throws — every failure surfaces as { ok: false, ... } with a log.
386
+ */
387
+ export async function runVc2Action(
388
+ action: Extract<SetupCortexActionKind, "fetch-model" | "bench">,
389
+ stateDir: string,
390
+ ): Promise<SetupCortexActionResult> {
391
+ try {
392
+ if (action === "fetch-model") return await runFetchModel(stateDir);
393
+ return await runBench(stateDir);
394
+ } catch (err) {
395
+ const msg = err instanceof Error ? err.message : String(err);
396
+ const { name, logPath } = writeLogName(action, stateDir);
397
+ writeLog(logPath, `${action} failed: ${msg}\n`);
398
+ return { action, ok: false, exitCode: 1, logPath, logName: name, spawned: false };
399
+ }
400
+ }
@@ -2,24 +2,20 @@
2
2
  * dashboard-server/setup-cortex-actions.ts — VC9B action driver (actor surface).
3
3
  *
4
4
  * Implements the actual mechanics behind POST /api/setup-cortex-action and
5
- * GET /api/setup-cortex-action-log: locating + spawning ONLY the committed local
6
- * vc2-model-prep scripts (fetch-model.sh, bench-onnx.mjs), capturing their
7
- * output to <stateDir>/logs/vc9b/<action>-<ts>.log, re-running the committed
8
- * encoder asset verification seam for verify-asset (NO subprocess), and serving
9
- * a bounded + redacted log tail. ENC-2c adds the `install-native-ort` action,
10
- * delegated to the sibling setup-cortex-actions-native-ort.ts (the confirm-gated,
11
- * npm-delegated local install + ENC-2b re-qualification).
5
+ * GET /api/setup-cortex-action-log: in-process HTTPS download for fetch-model
6
+ * and in-process ONNX bench (delegated to setup-cortex-actions-vc2.ts), re-running
7
+ * the committed encoder asset verification seam for verify-asset (NO subprocess),
8
+ * and serving a bounded + redacted log tail. ENC-2c adds the `install-native-ort`
9
+ * action, delegated to the sibling setup-cortex-actions-native-ort.ts (the
10
+ * confirm-gated, npm-delegated local install + ENC-2b re-qualification).
12
11
  *
13
12
  * This module is the ONLY place that touches the filesystem for VC9B actions.
14
13
  * The route file (routes-setup-cortex-actions.ts) carries NO path/script/blocker
15
- * string literals — it delegates here. Guardrails: the spawned scripts are the
16
- * existing committed local developer-tooling scripts (never fetched, no network,
17
- * PREVENT-PI-004); the log tail is bounded at 8 KiB and redacted (digest
18
- * prefixes + codes only, never payload bytes — EVAL-REDACT-002); PREVENT-011
19
- * (no `any`).
14
+ * string literals — it delegates here. Guardrails: the log tail is bounded at
15
+ * 8 KiB and redacted (digest prefixes + codes only, never payload bytes —
16
+ * EVAL-REDACT-002); PREVENT-011 (no `any`).
20
17
  */
21
18
 
22
- import { spawnSync } from "node:child_process"; // guardrails-allow PREVENT-PI-004: local subprocess spawn of committed repo script (loopback)
23
19
  import {
24
20
  mkdirSync,
25
21
  readFileSync,
@@ -44,24 +40,11 @@ import {
44
40
  encoderStateDir,
45
41
  } from "./qualification-record.js";
46
42
  import { runInstallNativeOrt } from "./setup-cortex-actions-native-ort.js";
43
+ import { runVc2Action } from "./setup-cortex-actions-vc2.js";
47
44
 
48
45
  /** Cap applied to every log tail served by the action-log route. */
49
46
  export const ACTION_LOG_TAIL_BYTES = 8192;
50
47
 
51
- /** Locate the commit's vc2-model-prep directory by walking up to the repo root. */
52
- function vc2ScriptDir(): string | null {
53
- let dir = dirname(fileURLToPath(import.meta.url));
54
- const rel = join("scripts", "vc2-model-prep");
55
- for (let i = 0; i < 8; i++) {
56
- const candidate = join(dir, rel);
57
- if (existsSync(join(candidate, "fetch-model.sh"))) return candidate;
58
- const next = dirname(dir);
59
- if (next === dir) break;
60
- dir = next;
61
- }
62
- return null;
63
- }
64
-
65
48
  /** Absolute dir holding this repo's <stateDir>/logs/vc9b/ action logs. */
66
49
  export function vc9bLogDir(stateDir: string): string {
67
50
  return join(stateDir, "logs", "vc9b");
@@ -125,43 +108,6 @@ export function readActionLogTail(
125
108
  };
126
109
  }
127
110
 
128
- /** Run a vc2-model-prep subprocess and capture its output to a vc9b log file. */
129
- function runSpawnedAction(
130
- action: Extract<SetupCortexActionKind, "fetch-model" | "bench">,
131
- stateDir: string,
132
- ): SetupCortexActionResult {
133
- const dir = vc2ScriptDir();
134
- const { name, logPath } = writeLogName(action, stateDir);
135
- if (dir === null) {
136
- writeLog(logPath, "vc2-model-prep scripts not found in this checkout\n");
137
- return { action, ok: false, exitCode: null, logPath, logName: name, spawned: true };
138
- }
139
- let result;
140
- if (action === "fetch-model") {
141
- // guardrails-allow PREVENT-PI-004: local subprocess spawn of committed repo script (loopback)
142
- result = spawnSync("bash", [join(dir, "fetch-model.sh"), join(stateDir, "vc2-model-prep")], {
143
- encoding: "utf8",
144
- timeout: 60_000,
145
- });
146
- } else {
147
- // guardrails-allow PREVENT-PI-004: local subprocess spawn of committed repo script (loopback)
148
- result = spawnSync(process.execPath, [join(dir, "bench-onnx.mjs")], {
149
- encoding: "utf8",
150
- timeout: 60_000,
151
- });
152
- }
153
- const out = `${result.stdout ?? ""}${result.stderr ?? ""}`;
154
- writeLog(logPath, out || "(no output)\n");
155
- return {
156
- action,
157
- ok: result.status === 0,
158
- exitCode: result.status === null ? null : result.status,
159
- logPath,
160
- logName: name,
161
- spawned: true,
162
- };
163
- }
164
-
165
111
  /**
166
112
  * Re-run the committed encoder asset verification seam (readEncoderManifest +
167
113
  * verifyEncoderAsset + detectPlatform) WITHOUT any subprocess, and log a
@@ -236,7 +182,7 @@ interface LogFileRef {
236
182
  }
237
183
 
238
184
  /** Unique <action>-<ts>.log name + absolute path under the vc9b log dir. */
239
- function writeLogName(action: SetupCortexActionKind, stateDir: string): LogFileRef {
185
+ export function writeLogName(action: SetupCortexActionKind, stateDir: string): LogFileRef {
240
186
  let ts = Date.now();
241
187
  const existing = new Set(readdirSync(ensureLogDir(stateDir)));
242
188
  while (existing.has(`${action}-${ts}.log`)) ts++;
@@ -244,7 +190,8 @@ function writeLogName(action: SetupCortexActionKind, stateDir: string): LogFileR
244
190
  return { name, logPath: join(vc9bLogDir(stateDir), name) };
245
191
  }
246
192
 
247
- function writeLog(logPath: string, body: string): void {
193
+ /** Write a vc9b action log file. Exported for the VC2 sibling. */
194
+ export function writeLog(logPath: string, body: string): void {
248
195
  // guardrails-allow PREVENT-PI-004: local state-dir filesystem write (loopback)
249
196
  writeFileSync(logPath, body, "utf8");
250
197
  }
@@ -252,10 +199,10 @@ function writeLog(logPath: string, body: string): void {
252
199
  /**
253
200
  * Run one Setup Cortex action against the given stateDir. Returns the action
254
201
  * result on success; throws nothing — every failure is surfaced as a result with
255
- * ok=false so the route can shape the HTTP response. Never touches the network;
256
- * the subprocesses it may spawn are the committed local vc2-model-prep scripts.
257
- * Async (ENC-2c): install-native-ort runs the npm-delegated local install then
258
- * re-qualifies via the ENC-2b retest path.
202
+ * ok=false so the route can shape the HTTP response. fetch-model/bench run
203
+ * in-process via the VC2 sibling (HTTPS download + ONNX bench); install-native-ort
204
+ * (ENC-2c) runs the npm-delegated local install then re-qualifies via the ENC-2b
205
+ * retest path.
259
206
  */
260
207
  export async function runSetupCortexAction(
261
208
  action: SetupCortexActionKind,
@@ -263,5 +210,5 @@ export async function runSetupCortexAction(
263
210
  ): Promise<SetupCortexActionResult> {
264
211
  if (action === "verify-asset") return runVerifyAsset(stateDir);
265
212
  if (action === "install-native-ort") return runInstallNativeOrt(stateDir);
266
- return runSpawnedAction(action, stateDir);
213
+ return runVc2Action(action, stateDir);
267
214
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mega-compact",
3
- "version": "0.20.76",
3
+ "version": "0.20.78",
4
4
  "description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
5
5
  "type": "module",
6
6
  "license": "BSD-3-Clause",
@@ -22,9 +22,10 @@ import { sprintFlag } from "./vector-cortex-flag.js";
22
22
  * GET /api/setup-cortex-action-log). Default ON. `MEGACOMPACT_VC9B=0` disables
23
23
  * and is byte-identical to the predecessor (VC9A-era): the action POST returns
24
24
  * the disabled shape (404/disabled) and flag-off bytes are unchanged. The
25
- * actions only spawn the existing committed local scripts
26
- * (scripts/vc2-model-prep/fetch-model.sh / bench-onnx.mjs) or re-read the
27
- * committed encoder assets never payload bytes, no network (PREVENT-PI-004).
25
+ * actions run in-process: fetch-model downloads via HTTPS (opt-in, confirm-gated)
26
+ * and bench runs ONNX inference directly — no subprocess spawns. verify-asset
27
+ * re-reads the committed encoder assets; install-native-ort uses the npm-delegated
28
+ * install (PREVENT-PI-004 opt-in). Never payload bytes.
28
29
  * This flag MUST also be a dashboard SETTINGS toggle (visible in config UI,
29
30
  * never in EXCLUDED_SETTINGS), mirroring VC9A.
30
31
  */
@@ -1,2 +0,0 @@
1
- import{j as r}from"./index-CL6Af_JZ.js";import{M as t}from"./MetricsCards-36RVmtPj.js";import"./card-Dvl16_R5.js";import"./generateCategoricalChart-Q_V4fqVi.js";import"./BarChart-Bhyviy7_.js";import"./AreaChart-CeaexvWO.js";function e(){return r.jsx(t,{})}export{e as default};
2
- //# sourceMappingURL=MetricsTab-Clkcniuo.js.map
@@ -1,2 +0,0 @@
1
- import{j as r}from"./index-CL6Af_JZ.js";import{T as o}from"./TurnMemoryView-DAfqhJqd.js";import"./card-Dvl16_R5.js";import"./button-D-9nb4Bw.js";function e(){return r.jsx(o,{})}export{e as default};
2
- //# sourceMappingURL=TurnsTab-C-uZNH2F.js.map