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
@@ -20,9 +20,10 @@ import { sprintFlag } from "./vector-cortex-flag.js";
20
20
  * GET /api/setup-cortex-action-log). Default ON. `MEGACOMPACT_VC9B=0` disables
21
21
  * and is byte-identical to the predecessor (VC9A-era): the action POST returns
22
22
  * the disabled shape (404/disabled) and flag-off bytes are unchanged. The
23
- * actions only spawn the existing committed local scripts
24
- * (scripts/vc2-model-prep/fetch-model.sh / bench-onnx.mjs) or re-read the
25
- * committed encoder assets never payload bytes, no network (PREVENT-PI-004).
23
+ * actions run in-process: fetch-model downloads via HTTPS (opt-in, confirm-gated)
24
+ * and bench runs ONNX inference directly — no subprocess spawns. verify-asset
25
+ * re-reads the committed encoder assets; install-native-ort uses the npm-delegated
26
+ * install (PREVENT-PI-004 opt-in). Never payload bytes.
26
27
  * This flag MUST also be a dashboard SETTINGS toggle (visible in config UI,
27
28
  * never in EXCLUDED_SETTINGS), mirroring VC9A.
28
29
  */
@@ -39,7 +39,7 @@ export const EXTRA_ENDPOINTS = {
39
39
  setupCortexAction: {
40
40
  method: "POST",
41
41
  path: "/api/setup-cortex-action",
42
- description: "Confirmation-gated driver: fetch-model / bench / verify-asset. Executes only the committed local scripts (scripts/vc2-model-prep/*) or re-reads the committed encoder assets; an OPEN hard-gate item returns action_blocked_by_open_item and does NOT spawn. Never payload bytes; confirm:true required.",
42
+ description: "Confirmation-gated driver: fetch-model / bench / verify-asset. Runs in-process model fetch (HTTPS) + ONNX bench or re-reads the committed encoder assets; an OPEN hard-gate item returns action_blocked_by_open_item and does NOT execute. Never payload bytes; confirm:true required.",
43
43
  },
44
44
  /** GET /api/setup-cortex-action-log — bounded, redacted action log tail. */
45
45
  setupCortexActionLog: {
@@ -49,7 +49,7 @@ export const VECTOR_CORTEX_SETTINGS = {
49
49
  boolDirect("MEGACOMPACT_VC8B", "VC8B Shadow Adaptive Policy", "Bounded shadow adaptive policy + M7 pressure-v2 migration. Policy actions are from a finite set (admit/dampen/defer/escalate/reject) chosen deterministically by the canonical pressure level; token budgets are clamped into a configured window after the pressure factor. Unknown pressure labels are rejected as POL_PRESSURE_UNKNOWN, never coerced to a neighbour. The shadow engine is structurally incapable of affecting the live path: inputs are deep-copied, the canonical prompt digest is pinned before and after to prove non-mutation, and liveMutations is always zero. M7 migrates legacy pressure labels to the v2 canonical five by copy/validate/switch; an unknown label blocks the switch and keeps the legacy pointer (M7_PRESSURE_UNKNOWN). A shadow decision is mode A, static calibrated policy is mode B (forced by invalid A), and fixed legacy thresholds is mode C (forced by M7 or B failure). OFF = byte-identical predecessor (VC8A); the policy/shadow/migration arithmetic still runs, only the reporter + dashboard seam is suppressed.", true),
50
50
  boolDirect("MEGACOMPACT_VC8C", "VC8C Canary Platform + Rust Parity", "Canary selection and external Rust parity. The selector admits a qualified external Rust artifact only when ABI version, URL metadata, commit, Cargo.lock digest, and platform all match evidence; a Cargo.lock digest mismatch rejects the artifact (RUST_CARGO_DIGEST_MISMATCH). The cross-conformance runner exchanges length-framed neutral records over a local stdin/stdout channel — a subprocess, never a URL (PREVENT-PI-004). A parity mismatch selects TS mode B. A qualified external artifact is mode A, TS reference is mode B, legacy path is mode C. OFF = byte-identical predecessor (VC8B); the selector and cross-conformance arithmetic still run, only the reporter + dashboard seam is suppressed.", true),
51
51
  boolDirect("MEGACOMPACT_VC9A", "VC9A Setup Cortex Status", "Reader-only Setup Cortex status read path (GET /api/setup-cortex-status): surfaces the vector-cortex encoder gate — mode A/B/C, qualification verdict, open blockers, encoder health — to the dashboard Setup tab without closing the ML gate. OFF = byte-identical predecessor (VC8C-era): returns enabled:false / mode:C / status:off.", true),
52
- boolDirect("MEGACOMPACT_VC9B", "VC9B Setup Cortex Actions", "Setup Cortex action drivers (POST /api/setup-cortex-action + GET /api/setup-cortex-action-log): confirmation-gated wrappers that fetch-model / bench / verify-asset by spawning only the committed local scripts (scripts/vc2-model-prep/fetch-model.sh, bench-onnx.mjs) or re-reading the committed encoder assets — never payload bytes, no network. Actions gated by an OPEN hard-gate item (HG-1/HG-3) return action_blocked_by_open_item and do NOT spawn. OFF = byte-identical predecessor (VC9A-era): the action POST returns a disabled/404 shape and flag-off bytes are unchanged.", true),
52
+ boolDirect("MEGACOMPACT_VC9B", "VC9B Setup Cortex Actions", "Setup Cortex action drivers (POST /api/setup-cortex-action + GET /api/setup-cortex-action-log): confirmation-gated wrappers that fetch-model / bench / verify-asset using in-process model fetch (HTTPS download from HuggingFace) and in-process ONNX bench — never payload bytes. Actions gated by an OPEN hard-gate item (HG-1/HG-3) return action_blocked_by_open_item and do NOT execute. OFF = byte-identical predecessor (VC9A-era): the action POST returns a disabled/404 shape and flag-off bytes are unchanged.", true),
53
53
  boolDirect("MEGACOMPACT_VC9C", "VC9C SetupTab Cortex Sub-tab", "SetupTab Cortex sub-tab (client UI): a Cortex sub-tab inside SetupTab that consumes the VC9A status endpoint (GET /api/setup-cortex-status) + the VC9B action endpoints. It surfaces the encoder mode A/B/C, asset digest prefix, qualification verdict + threshold failures, the open hard-gate blockers, and the confirmation-gated fetch/bench/verify actions. OFF = byte-identical predecessor (VC9B-era): the Cortex sub-tab is filtered from SUB_TABS and the Setup tab renders exactly as before.", true),
54
54
  boolDirect("MEGACOMPACT_VC9D", "VC9D Embedder Detect Consolidation", "Embedder-detect consolidation + VC9 workstream roll-up: memoizes /api/setup-detect against the mutable input (resolved binary path + mtime) so consecutive requests reuse the result without re-spawning, and unifies the embedder + cortex sub-tabs' 5s poll contract. OFF = byte-identical predecessor (VC9C-era): detect spawns fresh per request and the embedder poll keeps its previous cadence.", true),
55
55
  boolDirect("MEGACOMPACT_PC_C", "PC-C Dashboard Cache Visibility", "Dashboard per-turn prompt-cache visibility: surfaces the per-turn stable-prefix ratio trend (GET /api/prefix-stability) in the CacheTab PrefixStabilityCard. Reads aggregate ratios/counts from the local monitoring events log only — no payload bytes. OFF = byte-identical predecessor (PC-B-era): /api/prefix-stability returns 404 and the CacheTab omits the PrefixStabilityCard.", true),
@@ -5,12 +5,13 @@
5
5
  * GET /api/setup-cortex-action-log — bounded, redacted log tail
6
6
  *
7
7
  * Reader/actor-only: NEVER exposes payload bytes, prompts, or ledger. Actions
8
- * only spawn the committed local vc2-model-prep scripts, re-read the committed
8
+ * run in-process (fetch-model via HTTPS, bench via ONNX), re-read the committed
9
9
  * encoder assets (verify-asset), or — ENC-2c — run the confirm-gated npm-delegated
10
- * native onnxruntime install (install-native-ort) + re-qualify — no network in
11
- * this layer (PREVENT-PI-004). A hard gate (HG-1/HG-3) blocking the requested
12
- * action yields 423 action_blocked_by_open_item with the blocker ids and NO
13
- * subprocess is spawned. Missing confirm:true yields 400 confirmation_required.
10
+ * native onnxruntime install (install-native-ort) + re-qualify — no subprocess
11
+ * spawn for fetch-model/bench (PREVENT-PI-004 opt-in for fetch-model HTTPS).
12
+ * A hard gate (HG-1/HG-3) blocking the requested
13
+ * action yields 423 action_blocked_by_open_item with the blocker ids and the
14
+ * action does NOT execute. Missing confirm:true yields 400 confirmation_required.
14
15
  * Flag-off (MEGACOMPACT_VC9B=0) is byte-identical to the VC9A-era predecessor:
15
16
  * the routes are absent, so they return the 404 disabled shape and no action runs.
16
17
  *
@@ -0,0 +1,334 @@
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
+ // guardrails-allow PREVENT-PI-004: opt-in, confirm-gated download of ML model
24
+ // assets from HuggingFace (user-triggered from dashboard)
25
+ import { get as httpsGet } from "node:https";
26
+ import { createHash } from "node:crypto";
27
+ import { createRequire } from "node:module";
28
+ import { mkdirSync, writeFileSync, existsSync, statSync, rmSync, } from "node:fs";
29
+ import { join, dirname } from "node:path";
30
+ import { fileURLToPath } from "node:url";
31
+ import { writeLogName, writeLog } from "./setup-cortex-actions.js";
32
+ // ─── fetch-model constants ─────────────────────────────────────────────────
33
+ const HF_BASE =
34
+ // guardrails-allow PREVENT-PI-004: opt-in, confirm-gated download of ML model
35
+ // assets from HuggingFace (user-triggered from dashboard)
36
+ "https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2/resolve/main";
37
+ const MODEL_URL = `${HF_BASE}/onnx/model_qint8_avx512_vnni.onnx`;
38
+ const TOKENIZER_URL = `${HF_BASE}/tokenizer.json`;
39
+ const MODEL_SHA256 = "4278337fd0ff3c68bfb6291042cad8ab363e1d9fbc43dcb499fe91c871902474";
40
+ const TOKENIZER_SHA256 = "be50c3628f2bf5bb5e3a7f17b1f74611b2561a3a27eeab05e5aa30f411572037";
41
+ // ─── bench constants ───────────────────────────────────────────────────────
42
+ const LATENCY_BUDGET_MS = 40;
43
+ const RSS_BUDGET_MIB = 150;
44
+ const DETERMINISM_EPSILON = 1e-6;
45
+ const BENCH_TOKENS = 512;
46
+ const BENCH_ITERS = 300;
47
+ const BENCH_THREADS = 4;
48
+ const BENCH_REPEATS = 200;
49
+ // ─── shared helpers ────────────────────────────────────────────────────────
50
+ function sha256Hex(buf) {
51
+ return createHash("sha256").update(buf).digest("hex");
52
+ }
53
+ function mib(bytes) {
54
+ return +(bytes / 1048576).toFixed(1);
55
+ }
56
+ function percentile(sorted, p) {
57
+ const i = Math.min(sorted.length - 1, Math.floor(sorted.length * p));
58
+ return +sorted[i].toFixed(2);
59
+ }
60
+ // ─── fetch helpers ─────────────────────────────────────────────────────────
61
+ /** Download a URL to a Buffer via node:https (follows one redirect). */
62
+ function download(url) {
63
+ return new Promise((resolve, reject) => {
64
+ // guardrails-allow PREVENT-PI-004: opt-in, confirm-gated download of ML
65
+ // model assets from HuggingFace (user-triggered from dashboard)
66
+ httpsGet(url, (res) => {
67
+ if (res.statusCode !== undefined &&
68
+ res.statusCode >= 300 &&
69
+ res.statusCode < 400 &&
70
+ res.headers.location) {
71
+ res.resume();
72
+ // Follow a single redirect (HuggingFace CDN redirects). The Location
73
+ // header may be a RELATIVE path (e.g. /api/resolve-cache/...) — resolve
74
+ // it against the original URL so httpsGet never receives a bare path.
75
+ const redirected = new URL(res.headers.location, url).toString();
76
+ download(redirected).then(resolve, reject);
77
+ return;
78
+ }
79
+ if (res.statusCode !== 200) {
80
+ res.resume();
81
+ reject(new Error(`HTTP ${res.statusCode} for ${url}`));
82
+ return;
83
+ }
84
+ const chunks = [];
85
+ res.on("data", (chunk) => chunks.push(chunk));
86
+ res.on("end", () => resolve(Buffer.concat(chunks)));
87
+ res.on("error", reject);
88
+ }).on("error", reject);
89
+ });
90
+ }
91
+ /** Fetch one asset: download, verify sha256, write to disk. */
92
+ async function fetchAsset(url, outPath, wantSha, logLines) {
93
+ const label = outPath.split("/").pop() ?? outPath;
94
+ logLines.push(`fetching ${label}`);
95
+ let buf;
96
+ try {
97
+ buf = await download(url);
98
+ }
99
+ catch (err) {
100
+ const msg = err instanceof Error ? err.message : String(err);
101
+ logLines.push(`FAIL download ${label}: ${msg}`);
102
+ return false;
103
+ }
104
+ const got = sha256Hex(buf);
105
+ if (got !== wantSha) {
106
+ logLines.push(`DIGEST MISMATCH for ${label}`);
107
+ logLines.push(` expected: ${wantSha}`);
108
+ logLines.push(` actual: ${got}`);
109
+ return false;
110
+ }
111
+ // guardrails-allow PREVENT-PI-004: local state-dir filesystem write (loopback)
112
+ writeFileSync(outPath, buf);
113
+ logLines.push(` ok sha256=${got} bytes=${buf.length}`);
114
+ return true;
115
+ }
116
+ // ─── fetch-model implementation ────────────────────────────────────────────
117
+ async function runFetchModel(stateDir) {
118
+ const action = "fetch-model";
119
+ const { name, logPath } = writeLogName(action, stateDir);
120
+ const outdir = join(stateDir, "vc2-model-prep");
121
+ // guardrails-allow PREVENT-PI-004: local state-dir filesystem write (loopback)
122
+ mkdirSync(outdir, { recursive: true });
123
+ const logLines = [];
124
+ let ok = true;
125
+ // Model
126
+ const modelPath = join(outdir, "model.onnx");
127
+ if (!(await fetchAsset(MODEL_URL, modelPath, MODEL_SHA256, logLines))) {
128
+ ok = false;
129
+ // Clean up partial download
130
+ // guardrails-allow PREVENT-PI-004: removing file we just wrote (local FS)
131
+ rmSync(modelPath, { force: true });
132
+ }
133
+ // Tokenizer
134
+ const tokPath = join(outdir, "tokenizer.json");
135
+ if (!(await fetchAsset(TOKENIZER_URL, tokPath, TOKENIZER_SHA256, logLines))) {
136
+ ok = false;
137
+ // guardrails-allow PREVENT-PI-004: removing file we just wrote (local FS)
138
+ rmSync(tokPath, { force: true });
139
+ }
140
+ logLines.push("");
141
+ logLines.push(`Staged in ${outdir}.`);
142
+ logLines.push("NOTE: this export is opset 14, NOT the opset 17 required by MODEL_ASSET.md.");
143
+ logLines.push("See docs/vector-cortex/vc2-model-prep.md (Opset gap) before committing.");
144
+ writeLog(logPath, logLines.join("\n") + "\n");
145
+ return {
146
+ action,
147
+ ok,
148
+ exitCode: ok ? 0 : 1,
149
+ logPath,
150
+ logName: name,
151
+ spawned: false,
152
+ };
153
+ }
154
+ // ─── bench implementation ──────────────────────────────────────────────────
155
+ /** Locate model.onnx: stateDir first, then walk up from module for dev. */
156
+ function findModelPath(stateDir) {
157
+ // Check stateDir first (installed-device path).
158
+ const fromState = join(stateDir, "vc2-model-prep", "model.onnx");
159
+ // guardrails-allow PREVENT-PI-004: local state-dir filesystem read (loopback)
160
+ if (existsSync(fromState))
161
+ return fromState;
162
+ // Walk up from module for repo-checkout dev mode.
163
+ let dir = dirname(fileURLToPath(import.meta.url));
164
+ const rel = join("scripts", "vc2-model-prep", "model.onnx");
165
+ for (let i = 0; i < 8; i++) {
166
+ const candidate = join(dir, rel);
167
+ // guardrails-allow PREVENT-PI-004: local repo filesystem read (loopback)
168
+ if (existsSync(candidate))
169
+ return candidate;
170
+ const next = dirname(dir);
171
+ if (next === dir)
172
+ break;
173
+ dir = next;
174
+ }
175
+ return null;
176
+ }
177
+ /** Run the ONNX bench: latency + RSS + determinism gates. */
178
+ async function runBench(stateDir) {
179
+ const action = "bench";
180
+ const { name, logPath } = writeLogName(action, stateDir);
181
+ const logLines = [];
182
+ const modelPath = findModelPath(stateDir);
183
+ if (modelPath === null) {
184
+ logLines.push("bench: model.onnx not found (run fetch-model first)");
185
+ writeLog(logPath, logLines.join("\n") + "\n");
186
+ return { action, ok: false, exitCode: 2, logPath, logName: name, spawned: false };
187
+ }
188
+ // Load onnxruntime-node via createRequire — the binding may be at the
189
+ // ENC-2a native-ort root or in the package's node_modules.
190
+ let ort;
191
+ try {
192
+ const req = createRequire(import.meta.url);
193
+ ort = req("onnxruntime-node");
194
+ }
195
+ catch {
196
+ logLines.push("onnxruntime-node is not installed. See docs/vector-cortex/vc2-model-prep.md.");
197
+ writeLog(logPath, logLines.join("\n") + "\n");
198
+ return { action, ok: false, exitCode: 2, logPath, logName: name, spawned: false };
199
+ }
200
+ const tokens = BENCH_TOKENS;
201
+ const iters = BENCH_ITERS;
202
+ const threads = BENCH_THREADS;
203
+ const repeats = BENCH_REPEATS;
204
+ const rssBefore = process.memoryUsage().rss;
205
+ const loadStart = Date.now();
206
+ const session = await ort.InferenceSession.create(modelPath, {
207
+ executionProviders: ["cpu"],
208
+ intraOpNumThreads: threads,
209
+ graphOptimizationLevel: "all",
210
+ });
211
+ const loadMs = Date.now() - loadStart;
212
+ const dims = [1, tokens];
213
+ const ids = BigInt64Array.from({ length: tokens }, (_, i) => BigInt(i === 0 ? 101 : i === tokens - 1 ? 102 : 2000 + (i % 500)));
214
+ const mask = BigInt64Array.from({ length: tokens }, () => 1n);
215
+ const types = new BigInt64Array(tokens);
216
+ const feeds = () => {
217
+ const f = {};
218
+ if (session.inputNames.includes("input_ids"))
219
+ f.input_ids = new ort.Tensor("int64", ids, dims);
220
+ if (session.inputNames.includes("attention_mask"))
221
+ f.attention_mask = new ort.Tensor("int64", mask, dims);
222
+ if (session.inputNames.includes("token_type_ids"))
223
+ f.token_type_ids = new ort.Tensor("int64", types, dims);
224
+ return f;
225
+ };
226
+ // Warm-up
227
+ for (let i = 0; i < 5; i++)
228
+ await session.run(feeds());
229
+ // Latency measurement — do NOT retain outputs (measures working set, not GC).
230
+ const lat = [];
231
+ for (let i = 0; i < iters; i++) {
232
+ const t = process.hrtime.bigint();
233
+ await session.run(feeds());
234
+ lat.push(Number(process.hrtime.bigint() - t) / 1e6);
235
+ }
236
+ // GC + steady-state RSS
237
+ let gcRan = false;
238
+ if (typeof global.gc === "function") {
239
+ global.gc();
240
+ global.gc();
241
+ await new Promise((r) => setTimeout(r, 200));
242
+ global.gc();
243
+ gcRan = true;
244
+ }
245
+ else {
246
+ logLines.push("WARNING: global.gc not available (run under node --expose-gc);" +
247
+ " RSS figure is unreliable without it.");
248
+ }
249
+ const steadyRss = mib(process.memoryUsage().rss - rssBefore);
250
+ lat.sort((a, b) => a - b);
251
+ // Determinism: identical inputs must yield bit-stable outputs.
252
+ let ref = null;
253
+ let maxDelta = 0;
254
+ const digests = new Set();
255
+ for (let i = 0; i < repeats; i++) {
256
+ const out = (await session.run(feeds()));
257
+ const d = out[session.outputNames[0]].data;
258
+ digests.add(createHash("sha256")
259
+ .update(Buffer.from(d.buffer, d.byteOffset, d.byteLength))
260
+ .digest("hex"));
261
+ if (!ref)
262
+ ref = Float32Array.from(d);
263
+ else
264
+ for (let k = 0; k < d.length; k++) {
265
+ const delta = Math.abs(d[k] - ref[k]);
266
+ if (delta > maxDelta)
267
+ maxDelta = delta;
268
+ }
269
+ }
270
+ const p95 = percentile(lat, 0.95);
271
+ const report = {
272
+ model: modelPath,
273
+ // guardrails-allow PREVENT-PI-004: local file stat (loopback)
274
+ modelBytes: statSync(modelPath).size,
275
+ backend: "onnxruntime-node",
276
+ ortVersion: (() => {
277
+ try {
278
+ return createRequire(import.meta.url)("onnxruntime-node/package.json").version;
279
+ }
280
+ catch {
281
+ return "unknown";
282
+ }
283
+ })(),
284
+ platform: `${process.platform}-${process.arch}`,
285
+ threads,
286
+ tokens,
287
+ iters,
288
+ loadMs,
289
+ p50: percentile(lat, 0.5),
290
+ p95,
291
+ p99: percentile(lat, 0.99),
292
+ steadyRssMiB: steadyRss,
293
+ gcRan,
294
+ determinism: {
295
+ repeats,
296
+ distinctDigests: digests.size,
297
+ maxAbsDelta: maxDelta,
298
+ },
299
+ gates: {
300
+ latency: p95 <= LATENCY_BUDGET_MS,
301
+ rss: steadyRss <= RSS_BUDGET_MIB,
302
+ determinism: digests.size === 1 && maxDelta <= DETERMINISM_EPSILON,
303
+ },
304
+ };
305
+ const allPass = report.gates.latency && report.gates.rss && report.gates.determinism;
306
+ logLines.push(JSON.stringify({ ...report, gates: { ...report.gates, all: allPass } }, null, 2));
307
+ writeLog(logPath, logLines.join("\n") + "\n");
308
+ return {
309
+ action,
310
+ ok: allPass,
311
+ exitCode: allPass ? 0 : 1,
312
+ logPath,
313
+ logName: name,
314
+ spawned: false,
315
+ };
316
+ }
317
+ // ─── public entry point ────────────────────────────────────────────────────
318
+ /**
319
+ * Run one VC2 model-prep action (fetch-model or bench) in-process.
320
+ * Never throws — every failure surfaces as { ok: false, ... } with a log.
321
+ */
322
+ export async function runVc2Action(action, stateDir) {
323
+ try {
324
+ if (action === "fetch-model")
325
+ return await runFetchModel(stateDir);
326
+ return await runBench(stateDir);
327
+ }
328
+ catch (err) {
329
+ const msg = err instanceof Error ? err.message : String(err);
330
+ const { name, logPath } = writeLogName(action, stateDir);
331
+ writeLog(logPath, `${action} failed: ${msg}\n`);
332
+ return { action, ok: false, exitCode: 1, logPath, logName: name, spawned: false };
333
+ }
334
+ }
@@ -2,23 +2,19 @@
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
- import { spawnSync } from "node:child_process"; // guardrails-allow PREVENT-PI-004: local subprocess spawn of committed repo script (loopback)
22
18
  import { mkdirSync, readFileSync, writeFileSync, existsSync, readdirSync, } from "node:fs";
23
19
  import { join, dirname, basename } from "node:path";
24
20
  import { fileURLToPath } from "node:url";
@@ -26,23 +22,9 @@ import { readEncoderManifest, verifyEncoderAsset, detectPlatform, } from "../../
26
22
  import { ENC_0G_ENABLED, ENC_0F_ENABLED } from "../../src/config.js";
27
23
  import { readQualificationRecord, encoderStateDir, } from "./qualification-record.js";
28
24
  import { runInstallNativeOrt } from "./setup-cortex-actions-native-ort.js";
25
+ import { runVc2Action } from "./setup-cortex-actions-vc2.js";
29
26
  /** Cap applied to every log tail served by the action-log route. */
30
27
  export const ACTION_LOG_TAIL_BYTES = 8192;
31
- /** Locate the commit's vc2-model-prep directory by walking up to the repo root. */
32
- function vc2ScriptDir() {
33
- let dir = dirname(fileURLToPath(import.meta.url));
34
- const rel = join("scripts", "vc2-model-prep");
35
- for (let i = 0; i < 8; i++) {
36
- const candidate = join(dir, rel);
37
- if (existsSync(join(candidate, "fetch-model.sh")))
38
- return candidate;
39
- const next = dirname(dir);
40
- if (next === dir)
41
- break;
42
- dir = next;
43
- }
44
- return null;
45
- }
46
28
  /** Absolute dir holding this repo's <stateDir>/logs/vc9b/ action logs. */
47
29
  export function vc9bLogDir(stateDir) {
48
30
  return join(stateDir, "logs", "vc9b");
@@ -105,40 +87,6 @@ export function readActionLogTail(stateDir, name) {
105
87
  complete: raw.length <= ACTION_LOG_TAIL_BYTES,
106
88
  };
107
89
  }
108
- /** Run a vc2-model-prep subprocess and capture its output to a vc9b log file. */
109
- function runSpawnedAction(action, stateDir) {
110
- const dir = vc2ScriptDir();
111
- const { name, logPath } = writeLogName(action, stateDir);
112
- if (dir === null) {
113
- writeLog(logPath, "vc2-model-prep scripts not found in this checkout\n");
114
- return { action, ok: false, exitCode: null, logPath, logName: name, spawned: true };
115
- }
116
- let result;
117
- if (action === "fetch-model") {
118
- // guardrails-allow PREVENT-PI-004: local subprocess spawn of committed repo script (loopback)
119
- result = spawnSync("bash", [join(dir, "fetch-model.sh"), join(stateDir, "vc2-model-prep")], {
120
- encoding: "utf8",
121
- timeout: 60_000,
122
- });
123
- }
124
- else {
125
- // guardrails-allow PREVENT-PI-004: local subprocess spawn of committed repo script (loopback)
126
- result = spawnSync(process.execPath, [join(dir, "bench-onnx.mjs")], {
127
- encoding: "utf8",
128
- timeout: 60_000,
129
- });
130
- }
131
- const out = `${result.stdout ?? ""}${result.stderr ?? ""}`;
132
- writeLog(logPath, out || "(no output)\n");
133
- return {
134
- action,
135
- ok: result.status === 0,
136
- exitCode: result.status === null ? null : result.status,
137
- logPath,
138
- logName: name,
139
- spawned: true,
140
- };
141
- }
142
90
  /**
143
91
  * Re-run the committed encoder asset verification seam (readEncoderManifest +
144
92
  * verifyEncoderAsset + detectPlatform) WITHOUT any subprocess, and log a
@@ -208,7 +156,7 @@ function encoderAssetDir() {
208
156
  return null;
209
157
  }
210
158
  /** Unique <action>-<ts>.log name + absolute path under the vc9b log dir. */
211
- function writeLogName(action, stateDir) {
159
+ export function writeLogName(action, stateDir) {
212
160
  let ts = Date.now();
213
161
  const existing = new Set(readdirSync(ensureLogDir(stateDir)));
214
162
  while (existing.has(`${action}-${ts}.log`))
@@ -216,22 +164,23 @@ function writeLogName(action, stateDir) {
216
164
  const name = `${action}-${ts}.log`;
217
165
  return { name, logPath: join(vc9bLogDir(stateDir), name) };
218
166
  }
219
- function writeLog(logPath, body) {
167
+ /** Write a vc9b action log file. Exported for the VC2 sibling. */
168
+ export function writeLog(logPath, body) {
220
169
  // guardrails-allow PREVENT-PI-004: local state-dir filesystem write (loopback)
221
170
  writeFileSync(logPath, body, "utf8");
222
171
  }
223
172
  /**
224
173
  * Run one Setup Cortex action against the given stateDir. Returns the action
225
174
  * result on success; throws nothing — every failure is surfaced as a result with
226
- * ok=false so the route can shape the HTTP response. Never touches the network;
227
- * the subprocesses it may spawn are the committed local vc2-model-prep scripts.
228
- * Async (ENC-2c): install-native-ort runs the npm-delegated local install then
229
- * re-qualifies via the ENC-2b retest path.
175
+ * ok=false so the route can shape the HTTP response. fetch-model/bench run
176
+ * in-process via the VC2 sibling (HTTPS download + ONNX bench); install-native-ort
177
+ * (ENC-2c) runs the npm-delegated local install then re-qualifies via the ENC-2b
178
+ * retest path.
230
179
  */
231
180
  export async function runSetupCortexAction(action, stateDir) {
232
181
  if (action === "verify-asset")
233
182
  return runVerifyAsset(stateDir);
234
183
  if (action === "install-native-ort")
235
184
  return runInstallNativeOrt(stateDir);
236
- return runSpawnedAction(action, stateDir);
185
+ return runVc2Action(action, stateDir);
237
186
  }
@@ -20,9 +20,10 @@ import { sprintFlag } from "./vector-cortex-flag.js";
20
20
  * GET /api/setup-cortex-action-log). Default ON. `MEGACOMPACT_VC9B=0` disables
21
21
  * and is byte-identical to the predecessor (VC9A-era): the action POST returns
22
22
  * the disabled shape (404/disabled) and flag-off bytes are unchanged. The
23
- * actions only spawn the existing committed local scripts
24
- * (scripts/vc2-model-prep/fetch-model.sh / bench-onnx.mjs) or re-read the
25
- * committed encoder assets never payload bytes, no network (PREVENT-PI-004).
23
+ * actions run in-process: fetch-model downloads via HTTPS (opt-in, confirm-gated)
24
+ * and bench runs ONNX inference directly — no subprocess spawns. verify-asset
25
+ * re-reads the committed encoder assets; install-native-ort uses the npm-delegated
26
+ * install (PREVENT-PI-004 opt-in). Never payload bytes.
26
27
  * This flag MUST also be a dashboard SETTINGS toggle (visible in config UI,
27
28
  * never in EXCLUDED_SETTINGS), mirroring VC9A.
28
29
  */
@@ -1,2 +1,2 @@
1
- import{r as s,u as o,e as c,j as e}from"./index-CL6Af_JZ.js";import{T as i}from"./toggle-DHbWo-CW.js";import r from"./MaintenanceTab-CS5HqDkY.js";import{C as l}from"./ConfigTab-CbsdI5yj.js";import"./card-Dvl16_R5.js";import"./button-D-9nb4Bw.js";import"./switch-0MNUTR9I.js";const f="MEGACOMPACT_DASH_0C";function m(n){if(!n)return!1;for(const t of n.categories)for(const a of t.settings)if(a.key===f&&a.type==="boolean")return a.value===!0;return!1}function h(){const[n,t]=s.useState("maintenance"),{data:a}=o(s.useCallback(()=>c(),[]),{pollInterval:0,maxRetries:0});return m(a)?e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",role:"tablist","aria-label":"Admin views",children:[e.jsx(i,{pressed:n==="maintenance",onClick:()=>t("maintenance"),children:"Maintenance"}),e.jsx(i,{pressed:n==="config",onClick:()=>t("config"),children:"Config"})]}),n==="maintenance"?e.jsx(r,{}):e.jsx(l,{})]}):e.jsx(r,{})}export{h as default};
2
- //# sourceMappingURL=AdminTab-B8JqsA41.js.map
1
+ import{r as s,u as o,e as c,j as e}from"./index-iuxgtzEW.js";import{T as i}from"./toggle-z1lWY4UM.js";import r from"./MaintenanceTab-4fJ7M4S4.js";import{C as l}from"./ConfigTab-C016XTNC.js";import"./card-Cfhz9X31.js";import"./button-DhQQAJGm.js";import"./switch-7EHEQMSP.js";const f="MEGACOMPACT_DASH_0C";function m(n){if(!n)return!1;for(const t of n.categories)for(const a of t.settings)if(a.key===f&&a.type==="boolean")return a.value===!0;return!1}function h(){const[n,t]=s.useState("maintenance"),{data:a}=o(s.useCallback(()=>c(),[]),{pollInterval:0,maxRetries:0});return m(a)?e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",role:"tablist","aria-label":"Admin views",children:[e.jsx(i,{pressed:n==="maintenance",onClick:()=>t("maintenance"),children:"Maintenance"}),e.jsx(i,{pressed:n==="config",onClick:()=>t("config"),children:"Config"})]}),n==="maintenance"?e.jsx(r,{}):e.jsx(l,{})]}):e.jsx(r,{})}export{h as default};
2
+ //# sourceMappingURL=AdminTab-BsA8-_bX.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdminTab-B8JqsA41.js","sources":["../../src/tabs/AdminTab.tsx"],"sourcesContent":["/**\n * dashboard-client/src/tabs/AdminTab.tsx — Admin tab (DASH-0c delegate-shell).\n *\n * DASH-0c: the Admin surface combines the maintenance actions with the config\n * editor. A `AdminViews` toggle (\"maintenance\" / \"config\") switches between\n * `MaintenanceTab` (the maintenance shell over MaintenanceTab/*) and `ConfigTab`\n * (the config editor). Both bodies are UNCHANGED — only their hosting changes to\n * this new delegate-shell. `MaintenanceTab.tsx` and `ConfigTab.tsx` stay importable\n * from their original hosts (`ConfigTab` also stays wired into SetupTab per the\n * dual-host note). Flag-ON renders the toggle + both views; flag-OFF renders only\n * the maintenance view (the predecessor's `admin → MaintenanceTab` mapping),\n * and App.tsx keeps its current TabId routing this sprint (DASH-0d rewires).\n *\n * Flag: `MEGACOMPACT_DASH_0C` default ON. The dashboard client is a browser\n * bundle with NO `process` global, so the positive sprint flag cannot be read\n * server-side-style (`process.env`) inside the client. Instead the flag is read\n * from the server-authoritative `/api/rag-settings` state: the server resolves\n * `process.env[\"MEGACOMPACT_DASH_0C\"] ?? default` into the `SettingState.value`\n * boolean.\n */\n\nimport type React from \"react\";\nimport { useCallback, useState } from \"react\";\nimport type { SettingsResponse } from \"@contracts\";\nimport { useApi } from \"../hooks/useApi\";\nimport { fetchSettings } from \"../api/client\";\nimport { Toggle } from \"../components/ui/toggle\";\nimport MaintenanceTab from \"./MaintenanceTab\";\nimport ConfigTab from \"./ConfigTab\";\n\nconst DASH_0C_KEY = \"MEGACOMPACT_DASH_0C\";\n\n/** Resolve the DASH-0c consolidation flag from the server settings state.\n * Absent/not-yet-loaded => false (flag-off posture), so flag-off users never\n * see the toggle flash; the toggle appears only once settings confirm it is ON. */\nfunction dash0cEnabled(settings: SettingsResponse | null): boolean {\n\tif (!settings) return false;\n\tfor (const cat of settings.categories) {\n\t\tfor (const s of cat.settings) {\n\t\t\tif (s.key === DASH_0C_KEY && s.type === \"boolean\") return s.value === true;\n\t\t}\n\t}\n\treturn false;\n}\n\ntype AdminViews = \"maintenance\" | \"config\";\n\nexport default function AdminTab(): React.ReactElement {\n\tconst [view, setView] = useState<AdminViews>(\"maintenance\");\n\n\tconst { data: settingsData } = useApi<SettingsResponse>(\n\t\tuseCallback(() => fetchSettings(), []),\n\t\t{ pollInterval: 0, maxRetries: 0 },\n\t);\n\tconst dash0cOn = dash0cEnabled(settingsData);\n\n\tif (!dash0cOn) {\n\t\treturn <MaintenanceTab />;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div\n\t\t\t\tclassName=\"flex items-center gap-2\"\n\t\t\t\trole=\"tablist\"\n\t\t\t\taria-label=\"Admin views\"\n\t\t\t>\n\t\t\t\t<Toggle\n\t\t\t\t\tpressed={view === \"maintenance\"}\n\t\t\t\t\tonClick={() => setView(\"maintenance\")}\n\t\t\t\t>\n\t\t\t\t\tMaintenance\n\t\t\t\t</Toggle>\n\t\t\t\t<Toggle pressed={view === \"config\"} onClick={() => setView(\"config\")}>\n\t\t\t\t\tConfig\n\t\t\t\t</Toggle>\n\t\t\t</div>\n\t\t\t{view === \"maintenance\" ? <MaintenanceTab /> : <ConfigTab />}\n\t\t</div>\n\t);\n}\n"],"names":["DASH_0C_KEY","dash0cEnabled","settings","cat","s","AdminTab","view","setView","useState","settingsData","useApi","useCallback","fetchSettings","jsxs","jsx","Toggle","MaintenanceTab","ConfigTab"],"mappings":"mRA8BA,MAAMA,EAAc,sBAKpB,SAASC,EAAcC,EAA4C,CAClE,GAAI,CAACA,EAAU,MAAO,GACtB,UAAWC,KAAOD,EAAS,WAC1B,UAAWE,KAAKD,EAAI,SACnB,GAAIC,EAAE,MAAQJ,GAAeI,EAAE,OAAS,UAAW,OAAOA,EAAE,QAAU,GAGxE,MAAO,EACR,CAIA,SAAwBC,GAA+B,CACtD,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAqB,aAAa,EAEpD,CAAE,KAAMC,CAAA,EAAiBC,EAC9BC,cAAY,IAAMC,EAAA,EAAiB,EAAE,EACrC,CAAE,aAAc,EAAG,WAAY,CAAA,CAAE,EAIlC,OAFiBX,EAAcQ,CAAY,EAO1CI,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAA,EAAAA,KAAC,MAAA,CACA,UAAU,0BACV,KAAK,UACL,aAAW,cAEX,SAAA,CAAAC,EAAAA,IAACC,EAAA,CACA,QAAST,IAAS,cAClB,QAAS,IAAMC,EAAQ,aAAa,EACpC,SAAA,aAAA,CAAA,EAGDO,EAAAA,IAACC,EAAA,CAAO,QAAST,IAAS,SAAU,QAAS,IAAMC,EAAQ,QAAQ,EAAG,SAAA,QAAA,CAEtE,CAAA,CAAA,CAAA,EAEAD,IAAS,cAAgBQ,MAACE,EAAA,CAAA,CAAe,QAAMC,EAAA,CAAA,CAAU,CAAA,EAC3D,QArBQD,EAAA,EAAe,CAuBzB"}
1
+ {"version":3,"file":"AdminTab-BsA8-_bX.js","sources":["../../src/tabs/AdminTab.tsx"],"sourcesContent":["/**\n * dashboard-client/src/tabs/AdminTab.tsx — Admin tab (DASH-0c delegate-shell).\n *\n * DASH-0c: the Admin surface combines the maintenance actions with the config\n * editor. A `AdminViews` toggle (\"maintenance\" / \"config\") switches between\n * `MaintenanceTab` (the maintenance shell over MaintenanceTab/*) and `ConfigTab`\n * (the config editor). Both bodies are UNCHANGED — only their hosting changes to\n * this new delegate-shell. `MaintenanceTab.tsx` and `ConfigTab.tsx` stay importable\n * from their original hosts (`ConfigTab` also stays wired into SetupTab per the\n * dual-host note). Flag-ON renders the toggle + both views; flag-OFF renders only\n * the maintenance view (the predecessor's `admin → MaintenanceTab` mapping),\n * and App.tsx keeps its current TabId routing this sprint (DASH-0d rewires).\n *\n * Flag: `MEGACOMPACT_DASH_0C` default ON. The dashboard client is a browser\n * bundle with NO `process` global, so the positive sprint flag cannot be read\n * server-side-style (`process.env`) inside the client. Instead the flag is read\n * from the server-authoritative `/api/rag-settings` state: the server resolves\n * `process.env[\"MEGACOMPACT_DASH_0C\"] ?? default` into the `SettingState.value`\n * boolean.\n */\n\nimport type React from \"react\";\nimport { useCallback, useState } from \"react\";\nimport type { SettingsResponse } from \"@contracts\";\nimport { useApi } from \"../hooks/useApi\";\nimport { fetchSettings } from \"../api/client\";\nimport { Toggle } from \"../components/ui/toggle\";\nimport MaintenanceTab from \"./MaintenanceTab\";\nimport ConfigTab from \"./ConfigTab\";\n\nconst DASH_0C_KEY = \"MEGACOMPACT_DASH_0C\";\n\n/** Resolve the DASH-0c consolidation flag from the server settings state.\n * Absent/not-yet-loaded => false (flag-off posture), so flag-off users never\n * see the toggle flash; the toggle appears only once settings confirm it is ON. */\nfunction dash0cEnabled(settings: SettingsResponse | null): boolean {\n\tif (!settings) return false;\n\tfor (const cat of settings.categories) {\n\t\tfor (const s of cat.settings) {\n\t\t\tif (s.key === DASH_0C_KEY && s.type === \"boolean\") return s.value === true;\n\t\t}\n\t}\n\treturn false;\n}\n\ntype AdminViews = \"maintenance\" | \"config\";\n\nexport default function AdminTab(): React.ReactElement {\n\tconst [view, setView] = useState<AdminViews>(\"maintenance\");\n\n\tconst { data: settingsData } = useApi<SettingsResponse>(\n\t\tuseCallback(() => fetchSettings(), []),\n\t\t{ pollInterval: 0, maxRetries: 0 },\n\t);\n\tconst dash0cOn = dash0cEnabled(settingsData);\n\n\tif (!dash0cOn) {\n\t\treturn <MaintenanceTab />;\n\t}\n\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div\n\t\t\t\tclassName=\"flex items-center gap-2\"\n\t\t\t\trole=\"tablist\"\n\t\t\t\taria-label=\"Admin views\"\n\t\t\t>\n\t\t\t\t<Toggle\n\t\t\t\t\tpressed={view === \"maintenance\"}\n\t\t\t\t\tonClick={() => setView(\"maintenance\")}\n\t\t\t\t>\n\t\t\t\t\tMaintenance\n\t\t\t\t</Toggle>\n\t\t\t\t<Toggle pressed={view === \"config\"} onClick={() => setView(\"config\")}>\n\t\t\t\t\tConfig\n\t\t\t\t</Toggle>\n\t\t\t</div>\n\t\t\t{view === \"maintenance\" ? <MaintenanceTab /> : <ConfigTab />}\n\t\t</div>\n\t);\n}\n"],"names":["DASH_0C_KEY","dash0cEnabled","settings","cat","s","AdminTab","view","setView","useState","settingsData","useApi","useCallback","fetchSettings","jsxs","jsx","Toggle","MaintenanceTab","ConfigTab"],"mappings":"mRA8BA,MAAMA,EAAc,sBAKpB,SAASC,EAAcC,EAA4C,CAClE,GAAI,CAACA,EAAU,MAAO,GACtB,UAAWC,KAAOD,EAAS,WAC1B,UAAWE,KAAKD,EAAI,SACnB,GAAIC,EAAE,MAAQJ,GAAeI,EAAE,OAAS,UAAW,OAAOA,EAAE,QAAU,GAGxE,MAAO,EACR,CAIA,SAAwBC,GAA+B,CACtD,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAqB,aAAa,EAEpD,CAAE,KAAMC,CAAA,EAAiBC,EAC9BC,cAAY,IAAMC,EAAA,EAAiB,EAAE,EACrC,CAAE,aAAc,EAAG,WAAY,CAAA,CAAE,EAIlC,OAFiBX,EAAcQ,CAAY,EAO1CI,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACd,SAAA,CAAAA,EAAAA,KAAC,MAAA,CACA,UAAU,0BACV,KAAK,UACL,aAAW,cAEX,SAAA,CAAAC,EAAAA,IAACC,EAAA,CACA,QAAST,IAAS,cAClB,QAAS,IAAMC,EAAQ,aAAa,EACpC,SAAA,aAAA,CAAA,EAGDO,EAAAA,IAACC,EAAA,CAAO,QAAST,IAAS,SAAU,QAAS,IAAMC,EAAQ,QAAQ,EAAG,SAAA,QAAA,CAEtE,CAAA,CAAA,CAAA,EAEAD,IAAS,cAAgBQ,MAACE,EAAA,CAAA,CAAe,QAAMC,EAAA,CAAA,CAAU,CAAA,EAC3D,QArBQD,EAAA,EAAe,CAuBzB"}