pi-mega-compact 0.20.69 → 0.20.71

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 (123) hide show
  1. package/dist/config/vector-cortex-enc2c.js +38 -0
  2. package/dist/config/vector-cortex.js +2 -0
  3. package/dist/config.js +1 -1
  4. package/dist/extensions/dashboard-server/api-contracts/setup-cortex-native-ort.js +22 -0
  5. package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +1 -0
  6. package/dist/extensions/dashboard-server/routes-setup-cortex-actions.js +17 -11
  7. package/dist/extensions/dashboard-server/routes-vector-cortex-crystals.js +45 -30
  8. package/dist/extensions/dashboard-server/routes-vector-cortex-diagnostics.js +50 -29
  9. package/dist/extensions/dashboard-server/routes-vector-cortex-economics.js +33 -20
  10. package/dist/extensions/dashboard-server/routes-vector-cortex-helpers.js +54 -0
  11. package/dist/extensions/dashboard-server/routes-vector-cortex-policy.js +33 -16
  12. package/dist/extensions/dashboard-server/setup-cortex-actions-native-ort.js +107 -0
  13. package/dist/extensions/dashboard-server/setup-cortex-actions.js +9 -2
  14. package/dist/src/config/vector-cortex-enc2c.js +38 -0
  15. package/dist/src/config/vector-cortex.js +2 -0
  16. package/dist/src/config.js +1 -1
  17. package/dist/src/vector-cortex/cache/store.js +25 -2
  18. package/dist/src/vector-cortex/encoder/asset.js +34 -2
  19. package/dist/src/vector-cortex/encoder/router.js +31 -3
  20. package/dist/src/vector-cortex/livewire/livewire-live.js +163 -0
  21. package/dist/src/vector-cortex/livewire/livewire-registry.js +73 -0
  22. package/dist/src/vector-cortex/livewire/livewire-runtime.js +107 -0
  23. package/dist/src/vector-cortex/livewire/livewire-snapshot.js +101 -0
  24. package/dist/src/vector-cortex/livewire/livewire-types.js +19 -0
  25. package/dist/src/vector-cortex/provider/registry.js +44 -12
  26. package/dist/src/vector-cortex/setup-cortex-blockers-compute.js +3 -0
  27. package/dist/vector-cortex/cache/store.js +25 -2
  28. package/dist/vector-cortex/encoder/asset.js +34 -2
  29. package/dist/vector-cortex/encoder/router.js +31 -3
  30. package/dist/vector-cortex/provider/registry.js +44 -12
  31. package/dist/vector-cortex/setup-cortex-blockers-compute.js +3 -0
  32. package/extensions/dashboard-client/dist/assets/{AdminTab-BUl1fyQ-.js → AdminTab-ZyVtgYrZ.js} +2 -2
  33. package/extensions/dashboard-client/dist/assets/{AdminTab-BUl1fyQ-.js.map → AdminTab-ZyVtgYrZ.js.map} +1 -1
  34. package/extensions/dashboard-client/dist/assets/{AreaChart-CumzbAON.js → AreaChart-7ms8Hk1m.js} +2 -2
  35. package/extensions/dashboard-client/dist/assets/{AreaChart-CumzbAON.js.map → AreaChart-7ms8Hk1m.js.map} +1 -1
  36. package/extensions/dashboard-client/dist/assets/{BarChart-MvUf2UYv.js → BarChart-DeTE0NXA.js} +2 -2
  37. package/extensions/dashboard-client/dist/assets/{BarChart-MvUf2UYv.js.map → BarChart-DeTE0NXA.js.map} +1 -1
  38. package/extensions/dashboard-client/dist/assets/{CacheTab-CqpJZ5Ok.js → CacheTab-CpIrpr_X.js} +2 -2
  39. package/extensions/dashboard-client/dist/assets/{CacheTab-CqpJZ5Ok.js.map → CacheTab-CpIrpr_X.js.map} +1 -1
  40. package/extensions/dashboard-client/dist/assets/{ConfigTab-Cr0pKYGK.js → ConfigTab-BNMrO7uz.js} +2 -2
  41. package/extensions/dashboard-client/dist/assets/{ConfigTab-Cr0pKYGK.js.map → ConfigTab-BNMrO7uz.js.map} +1 -1
  42. package/extensions/dashboard-client/dist/assets/{EventsTab-FTQ4nJae.js → EventsTab-j42vDTjs.js} +2 -2
  43. package/extensions/dashboard-client/dist/assets/{EventsTab-FTQ4nJae.js.map → EventsTab-j42vDTjs.js.map} +1 -1
  44. package/extensions/dashboard-client/dist/assets/{HealthTab-D7s5lCB0.js → HealthTab-D0Tf8XM_.js} +2 -2
  45. package/extensions/dashboard-client/dist/assets/{HealthTab-D7s5lCB0.js.map → HealthTab-D0Tf8XM_.js.map} +1 -1
  46. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DW5c0ngt.js → MaintenanceTab-CleWX_RM.js} +2 -2
  47. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DW5c0ngt.js.map → MaintenanceTab-CleWX_RM.js.map} +1 -1
  48. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-ocR07fD7.js → MemoryMapTab-LUpPJzNP.js} +2 -2
  49. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-ocR07fD7.js.map → MemoryMapTab-LUpPJzNP.js.map} +1 -1
  50. package/extensions/dashboard-client/dist/assets/{MetricsCards-CNBlWLoU.js → MetricsCards-G4_uynTE.js} +2 -2
  51. package/extensions/dashboard-client/dist/assets/{MetricsCards-CNBlWLoU.js.map → MetricsCards-G4_uynTE.js.map} +1 -1
  52. package/extensions/dashboard-client/dist/assets/MetricsTab-yypKMQXf.js +2 -0
  53. package/extensions/dashboard-client/dist/assets/{MetricsTab-sks9wzZr.js.map → MetricsTab-yypKMQXf.js.map} +1 -1
  54. package/extensions/dashboard-client/dist/assets/{OverviewTab-Duu9zseZ.js → OverviewTab-M47NMRaT.js} +2 -2
  55. package/extensions/dashboard-client/dist/assets/{OverviewTab-Duu9zseZ.js.map → OverviewTab-M47NMRaT.js.map} +1 -1
  56. package/extensions/dashboard-client/dist/assets/{ReposTab-CMd5NYjk.js → ReposTab-BX3ZxrAI.js} +2 -2
  57. package/extensions/dashboard-client/dist/assets/{ReposTab-CMd5NYjk.js.map → ReposTab-BX3ZxrAI.js.map} +1 -1
  58. package/extensions/dashboard-client/dist/assets/{SessionsTab-Ht-k4LKk.js → SessionsTab-CSUmsNeZ.js} +2 -2
  59. package/extensions/dashboard-client/dist/assets/{SessionsTab-Ht-k4LKk.js.map → SessionsTab-CSUmsNeZ.js.map} +1 -1
  60. package/extensions/dashboard-client/dist/assets/{SetupTab-BCfBdL-1.js → SetupTab-jF9BsQjw.js} +3 -3
  61. package/extensions/dashboard-client/dist/assets/SetupTab-jF9BsQjw.js.map +1 -0
  62. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-B3CAK2FZ.js → TimeSavedCard-qfwO1WJ3.js} +2 -2
  63. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-B3CAK2FZ.js.map → TimeSavedCard-qfwO1WJ3.js.map} +1 -1
  64. package/extensions/dashboard-client/dist/assets/{TurnMemoryView-7SRtcvZF.js → TurnMemoryView-C7NQo_xi.js} +2 -2
  65. package/extensions/dashboard-client/dist/assets/{TurnMemoryView-7SRtcvZF.js.map → TurnMemoryView-C7NQo_xi.js.map} +1 -1
  66. package/extensions/dashboard-client/dist/assets/TurnsTab-D-19giqQ.js +2 -0
  67. package/extensions/dashboard-client/dist/assets/{TurnsTab-Djd-nzlT.js.map → TurnsTab-D-19giqQ.js.map} +1 -1
  68. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-BzvdQnVq.js → VcStatusBadge-DTHlwuUJ.js} +2 -2
  69. package/extensions/dashboard-client/dist/assets/{VcStatusBadge-BzvdQnVq.js.map → VcStatusBadge-DTHlwuUJ.js.map} +1 -1
  70. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-qmY0a0E-.js → VectorCortexTab-Dvgdcwvs.js} +2 -2
  71. package/extensions/dashboard-client/dist/assets/{VectorCortexTab-qmY0a0E-.js.map → VectorCortexTab-Dvgdcwvs.js.map} +1 -1
  72. package/extensions/dashboard-client/dist/assets/{WikiTab-DMmc36Xi.js → WikiTab-CYUEAQmZ.js} +2 -2
  73. package/extensions/dashboard-client/dist/assets/{WikiTab-DMmc36Xi.js.map → WikiTab-CYUEAQmZ.js.map} +1 -1
  74. package/extensions/dashboard-client/dist/assets/{button-DcRndiuf.js → button-DPOwTRN8.js} +2 -2
  75. package/extensions/dashboard-client/dist/assets/{button-DcRndiuf.js.map → button-DPOwTRN8.js.map} +1 -1
  76. package/extensions/dashboard-client/dist/assets/{card-CwWLYigw.js → card-CUipkgi9.js} +2 -2
  77. package/extensions/dashboard-client/dist/assets/{card-CwWLYigw.js.map → card-CUipkgi9.js.map} +1 -1
  78. package/extensions/dashboard-client/dist/assets/{client-extra-NQXJNKNj.js → client-extra-9lcKX-iO.js} +2 -2
  79. package/extensions/dashboard-client/dist/assets/{client-extra-NQXJNKNj.js.map → client-extra-9lcKX-iO.js.map} +1 -1
  80. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-BX9n_-am.js → generateCategoricalChart-_WpiJebf.js} +2 -2
  81. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-BX9n_-am.js.map → generateCategoricalChart-_WpiJebf.js.map} +1 -1
  82. package/extensions/dashboard-client/dist/assets/{index-DgKI8jwx.js → index-DlHJ7LBL.js} +3 -3
  83. package/extensions/dashboard-client/dist/assets/{index-DgKI8jwx.js.map → index-DlHJ7LBL.js.map} +1 -1
  84. package/extensions/dashboard-client/dist/assets/{switch-C_xzN77s.js → switch-Cx6-1wnT.js} +2 -2
  85. package/extensions/dashboard-client/dist/assets/{switch-C_xzN77s.js.map → switch-Cx6-1wnT.js.map} +1 -1
  86. package/extensions/dashboard-client/dist/assets/{toggle-807R1-Th.js → toggle-Y3vbE0NG.js} +2 -2
  87. package/extensions/dashboard-client/dist/assets/{toggle-807R1-Th.js.map → toggle-Y3vbE0NG.js.map} +1 -1
  88. package/extensions/dashboard-client/dist/assets/{useSSE-BNG39O7p.js → useSSE-CnJdk56R.js} +2 -2
  89. package/extensions/dashboard-client/dist/assets/{useSSE-BNG39O7p.js.map → useSSE-CnJdk56R.js.map} +1 -1
  90. package/extensions/dashboard-client/dist/index.html +1 -1
  91. package/extensions/dashboard-client/src/tabs/SetupTab/CortexActionsCard.tsx +89 -5
  92. package/extensions/dashboard-client/src/types/setup-cortex.ts +22 -1
  93. package/extensions/dashboard-server/api-contracts/setup-cortex-native-ort.ts +52 -0
  94. package/extensions/dashboard-server/api-contracts/setup-cortex.ts +8 -2
  95. package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +6 -0
  96. package/extensions/dashboard-server/routes-setup-cortex-actions.ts +22 -11
  97. package/extensions/dashboard-server/routes-vector-cortex-crystals.ts +46 -30
  98. package/extensions/dashboard-server/routes-vector-cortex-diagnostics.ts +52 -29
  99. package/extensions/dashboard-server/routes-vector-cortex-economics.ts +35 -20
  100. package/extensions/dashboard-server/routes-vector-cortex-helpers.ts +84 -0
  101. package/extensions/dashboard-server/routes-vector-cortex-policy.ts +35 -16
  102. package/extensions/dashboard-server/setup-cortex-actions-native-ort.ts +121 -0
  103. package/extensions/dashboard-server/setup-cortex-actions.ts +9 -3
  104. package/package.json +1 -1
  105. package/src/config/vector-cortex-enc2c.ts +40 -0
  106. package/src/config/vector-cortex.ts +2 -0
  107. package/src/config.ts +1 -0
  108. package/src/vector-cortex/cache/store.ts +26 -2
  109. package/src/vector-cortex/encoder/asset.ts +46 -3
  110. package/src/vector-cortex/encoder/router.ts +56 -2
  111. package/src/vector-cortex/encoder/types.ts +3 -0
  112. package/src/vector-cortex/livewire/livewire-live.ts +223 -0
  113. package/src/vector-cortex/livewire/livewire-registry.ts +91 -0
  114. package/src/vector-cortex/livewire/livewire-runtime.ts +117 -0
  115. package/src/vector-cortex/livewire/livewire-snapshot.ts +108 -0
  116. package/src/vector-cortex/livewire/livewire-types.ts +84 -0
  117. package/src/vector-cortex/provider/economics.ts +9 -31
  118. package/src/vector-cortex/provider/registry.ts +82 -11
  119. package/src/vector-cortex/provider/types.ts +37 -0
  120. package/src/vector-cortex/setup-cortex-blockers-compute.ts +8 -1
  121. package/extensions/dashboard-client/dist/assets/MetricsTab-sks9wzZr.js +0 -2
  122. package/extensions/dashboard-client/dist/assets/SetupTab-BCfBdL-1.js.map +0 -1
  123. package/extensions/dashboard-client/dist/assets/TurnsTab-Djd-nzlT.js +0 -2
@@ -0,0 +1,107 @@
1
+ /**
2
+ * dashboard-server/setup-cortex-actions-native-ort.ts — ENC-2c native onnxruntime
3
+ * lazy-download INSTALL action driver (actor surface for install-native-ort).
4
+ *
5
+ * Sibling of setup-cortex-actions.ts (which stays under the 300-line source soft
6
+ * cap). Implements the mechanics behind the VC9B `install-native-ort` action:
7
+ *
8
+ * 1. locate the committed scripts/encoder/install-native-ort.mjs by walking up
9
+ * to the repo root (mirroring setup-cortex-actions.ts vc2ScriptDir);
10
+ * 2. spawn `node <script>` locally with a 60s timeout (npm-delegated,
11
+ * sha256-verified install — the registry URL + sha256 live ONLY in
12
+ * src/vector-cortex/encoder/native-install-artifacts.ts, never here);
13
+ * 3. capture output to <stateDir>/logs/vc9b/install-native-ort-<ts>.log;
14
+ * 4. REGARDLESS of the install exit code, re-qualify the binding via the ENC-2b
15
+ * retest path (`runNativeRetest`) and surface the fresh result +
16
+ * effective backend.
17
+ *
18
+ * PREVENT-PI-004 banner: this is an OPT-IN, confirm-gated, npm-delegated local
19
+ * subprocess of a committed repo script. It performs no network I/O in this
20
+ * module and carries NO URL literals (the codebase-wide no-URL-literal scan
21
+ * covers src/ + extensions/).
22
+ *
23
+ * Guardrails: PREVENT-011 (no `any`); the subprocess is a committed local script,
24
+ * never fetched (PREVENT-PI-004, guardrails-allow below).
25
+ */
26
+ import { spawnSync } from "node:child_process"; // guardrails-allow PREVENT-PI-004: opt-in, confirm-gated, npm-delegated install subprocess (local spawn of committed repo script; no URL literals)
27
+ import { mkdirSync, writeFileSync, existsSync } from "node:fs";
28
+ import { join, dirname } from "node:path";
29
+ import { fileURLToPath } from "node:url";
30
+ import { runNativeRetest } from "../../src/vector-cortex/encoder/native-qualify-retest.js";
31
+ /** Locate scripts/encoder/install-native-ort.mjs by walking up to the repo root. */
32
+ export function installScriptPath() {
33
+ let dir = dirname(fileURLToPath(import.meta.url));
34
+ const rel = join("scripts", "encoder", "install-native-ort.mjs");
35
+ for (let i = 0; i < 8; i++) {
36
+ const candidate = join(dir, rel);
37
+ // guardrails-allow PREVENT-PI-004: local repo filesystem read (loopback)
38
+ if (existsSync(candidate))
39
+ return candidate;
40
+ const next = dirname(dir);
41
+ if (next === dir)
42
+ break;
43
+ dir = next;
44
+ }
45
+ return null;
46
+ }
47
+ /** Ensure the vc9b log dir exists (mirrors setup-cortex-actions.ts). */
48
+ function ensureLogDir(stateDir) {
49
+ const dir = join(stateDir, "logs", "vc9b");
50
+ // guardrails-allow PREVENT-PI-004: local state-dir filesystem write (loopback)
51
+ mkdirSync(dir, { recursive: true });
52
+ return dir;
53
+ }
54
+ function writeLog(logPath, body) {
55
+ // guardrails-allow PREVENT-PI-004: local state-dir filesystem write (loopback)
56
+ writeFileSync(logPath, body, "utf8");
57
+ }
58
+ /**
59
+ * Run the ENC-2c lazy-download native onnxruntime INSTALL action. Locates and
60
+ * spawns the committed install script (npm-delegated, sha256-verified), logs the
61
+ * captured output, then ALWAYS runs the ENC-2b retest to re-qualify the binding
62
+ * (regardless of install exit code) and surfaces the fresh result.
63
+ *
64
+ * Never throws: a missing script or non-zero exit is surfaced as ok=false on the
65
+ * result; the retest runs even on install failure so the operator sees the
66
+ * post-install qualification state. Returns a combined SetupCortexActionResult
67
+ * with the ENC-2c additive fields (present only for pendant actions).
68
+ */
69
+ // guardrails-allow PREVENT-PI-004: opt-in, confirm-gated, npm-delegated install action (subprocess of committed repo script; no URL literals)
70
+ export async function runInstallNativeOrt(stateDir) {
71
+ const ts = Date.now();
72
+ const logName = `install-native-ort-${ts}.log`;
73
+ const logPath = join(ensureLogDir(stateDir), logName);
74
+ const scriptPath = installScriptPath();
75
+ if (scriptPath === null) {
76
+ writeLog(logPath, "install-native-ort.mjs not found in this checkout\n");
77
+ return {
78
+ action: "install-native-ort",
79
+ ok: false,
80
+ exitCode: null,
81
+ logPath,
82
+ logName,
83
+ spawned: true,
84
+ };
85
+ }
86
+ // guardrails-allow PREVENT-PI-004: opt-in, confirm-gated, npm-delegated
87
+ // install subprocess (local spawn of committed repo script; no URL literals)
88
+ const result = spawnSync(process.execPath, [scriptPath], {
89
+ encoding: "utf8",
90
+ timeout: 60_000,
91
+ });
92
+ const out = `${result.stdout ?? ""}${result.stderr ?? ""}`;
93
+ writeLog(logPath, out || "(no output)\n");
94
+ // Re-qualify AFTER install regardless of exit code (the retest is the source of
95
+ // truth for whether the binding is actually usable).
96
+ const retest = await runNativeRetest(stateDir);
97
+ return {
98
+ action: "install-native-ort",
99
+ ok: result.status === 0,
100
+ exitCode: result.status === null ? null : result.status,
101
+ logPath,
102
+ logName,
103
+ spawned: true,
104
+ nativeOrtRetestResult: retest,
105
+ nativeOrtBackendEffective: retest !== null && retest.verdict === "qualified" ? "native" : "wasm",
106
+ };
107
+ }
@@ -6,7 +6,9 @@
6
6
  * vc2-model-prep scripts (fetch-model.sh, bench-onnx.mjs), capturing their
7
7
  * output to <stateDir>/logs/vc9b/<action>-<ts>.log, re-running the committed
8
8
  * encoder asset verification seam for verify-asset (NO subprocess), and serving
9
- * a bounded + redacted log tail.
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).
10
12
  *
11
13
  * This module is the ONLY place that touches the filesystem for VC9B actions.
12
14
  * The route file (routes-setup-cortex-actions.ts) carries NO path/script/blocker
@@ -23,6 +25,7 @@ import { fileURLToPath } from "node:url";
23
25
  import { readEncoderManifest, verifyEncoderAsset, detectPlatform, } from "../../src/vector-cortex/encoder/asset.js";
24
26
  import { ENC_0G_ENABLED, ENC_0F_ENABLED } from "../../src/config.js";
25
27
  import { readQualificationRecord, encoderStateDir, } from "./qualification-record.js";
28
+ import { runInstallNativeOrt } from "./setup-cortex-actions-native-ort.js";
26
29
  /** Cap applied to every log tail served by the action-log route. */
27
30
  export const ACTION_LOG_TAIL_BYTES = 8192;
28
31
  /** Locate the commit's vc2-model-prep directory by walking up to the repo root. */
@@ -222,9 +225,13 @@ function writeLog(logPath, body) {
222
225
  * result on success; throws nothing — every failure is surfaced as a result with
223
226
  * ok=false so the route can shape the HTTP response. Never touches the network;
224
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.
225
230
  */
226
- export function runSetupCortexAction(action, stateDir) {
231
+ export async function runSetupCortexAction(action, stateDir) {
227
232
  if (action === "verify-asset")
228
233
  return runVerifyAsset(stateDir);
234
+ if (action === "install-native-ort")
235
+ return runInstallNativeOrt(stateDir);
229
236
  return runSpawnedAction(action, stateDir);
230
237
  }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * config/vector-cortex-enc2c.ts — ENC-2c native onnxruntime lazy-download
3
+ * install-action flag (dashboard-triggered install).
4
+ *
5
+ * Sibling of vector-cortex-enc2a.ts / vector-cortex-enc2b.ts so vector-cortex.ts
6
+ * stays under the 300-line soft limit (soft-as-hard gate). vector-cortex.ts
7
+ * re-exports the flag below and root src/config.ts re-exports it, so no consumer
8
+ * import path changes.
9
+ *
10
+ * ENC-2c turns ENC-2a's operator run-script assist into a dashboard action: the
11
+ * Setup Cortex sub-tab gains an "Install Native ORT" button that, when confirmed
12
+ * by the operator, runs the committed `scripts/encoder/install-native-ort.mjs`
13
+ * subprocess locally (npm-delegated, sha256-verified) and then re-qualifies the
14
+ * binding via the ENC-2b retest path. This is a PREVENT-PI-004 opt-in exemption:
15
+ * it is confirm-gated (never automatic), delegated to a local subprocess of a
16
+ * committed repo script, and carries NO URL literals in src/ or extensions/
17
+ * (the registry URL + sha256 live only in the artifacts-module constants).
18
+ *
19
+ * `MEGACOMPACT_ENC_2C=0` disables: no install action branch, no UI button, no
20
+ * install-related result fields — byte-identical to the ENC-2b predecessor. The
21
+ * flag MUST also be a dashboard SETTINGS toggle (visible in config UI, never in
22
+ * EXCLUDED_SETTINGS — see `feedback_dashboard-flags-toggleable` memory).
23
+ *
24
+ * Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
25
+ *
26
+ * guardrails-allow PREVENT-PI-004: opt-in confirm-gated install action;
27
+ * delegates to local npm install subprocess, no URL literals (registry URL +
28
+ * sha256 live only in native-install-artifacts.ts)
29
+ */
30
+ import { sprintFlag } from "./vector-cortex-flag.js";
31
+ /**
32
+ * ENC-2c — lazy-download native onnxruntime install action (dashboard-triggered,
33
+ * npm-delegated, confirm-gated). Default ON. `MEGACOMPACT_ENC_2C=0` disables and
34
+ * is byte-identical to the ENC-2b predecessor: no install action POST branch, no
35
+ * UI button, no install result fields. This flag MUST also be a dashboard SETTINGS
36
+ * toggle (visible in config UI, never in EXCLUDED_SETTINGS).
37
+ */
38
+ export const ENC_2C_ENABLED = () => sprintFlag("MEGACOMPACT_ENC_2C");
@@ -54,5 +54,7 @@ export { ENC_2BUDGET_ENABLED, ENC_2BUDGET_NATIVE_ORT_BUDGET_ENV, ENC_2BUDGET_MAX
54
54
  export { ENC_2A_ENABLED } from "./vector-cortex-enc2a.js";
55
55
  // ENC-2b native onnxruntime qualification-retest flag extracted to vector-cortex-enc2b.ts.
56
56
  export { ENC_2B_ENABLED } from "./vector-cortex-enc2b.js";
57
+ // ENC-2c native onnxruntime lazy-download install-action flag extracted to vector-cortex-enc2c.ts.
58
+ export { ENC_2C_ENABLED } from "./vector-cortex-enc2c.js";
57
59
  // Breaker constants (TRIAD_RESILIENCE.md §breaker) extracted to vector-cortex-breakers.ts.
58
60
  export { BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./vector-cortex-breakers.js";
@@ -114,4 +114,4 @@ export const NEW_UI = () => ragEnabled("MEGACOMPACT_NEW_UI");
114
114
  // default ON, `=0`/`_DISABLED` off. Re-exported from src/config/vector-cortex.ts
115
115
  // so root consumers share one source of truth.
116
116
  // ---------------------------------------------------------------------------
117
- export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, ML5D_ENABLED, ML5E_ENABLED, DEDUP_ATTR_ENABLED, ENC_0A_ENABLED, ENC_0B_ENABLED, ENC_0C_ENABLED, ENC_0D_ENABLED, ENC_0E_ENABLED, ENC_0F_ENABLED, ENC_0G_ENABLED, ENC_1A_ENABLED, ENC_1B_ENABLED, ENC_2BUDGET_ENABLED, ENC_2BUDGET_NATIVE_ORT_BUDGET_ENV, ENC_2BUDGET_MAX_MIB, ENC_2BUDGET_DEFAULT_MIB, ENC_2A_ENABLED, ENC_2B_ENABLED, COSINE_FP_BENCH_ENABLED, COSINE_FP_REAL_ENABLED, REPO_CORPUS_ENABLED, DASH_0A_ENABLED, DASH_0B_ENABLED, DASH_0C_ENABLED, DASH_0D_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
117
+ export { VC0A_ENABLED, VC0B_ENABLED, VC1A_ENABLED, VC0C_ENABLED, VC1B_ENABLED, VC1C_ENABLED, VC2A_ENABLED, VC2B_ENABLED, VC2C_ENABLED, VC3A_ENABLED, VC3B_ENABLED, VC3C_ENABLED, VC4A_ENABLED, VC4B_ENABLED, VC4C_ENABLED, VC5A_ENABLED, VC5B_ENABLED, VC5C_ENABLED, VC6A_ENABLED, VC6B_ENABLED, VC6C_ENABLED, VC7A_ENABLED, VC7B_ENABLED, VC7C_ENABLED, VC8A_ENABLED, VC8B_ENABLED, VC8C_ENABLED, VC9A_ENABLED, VC9B_ENABLED, VC9C_ENABLED, VC9D_ENABLED, PCC_ENABLED, ML5A_ENABLED, ML5B_ENABLED, ML5C_ENABLED, ML5D_ENABLED, ML5E_ENABLED, DEDUP_ATTR_ENABLED, ENC_0A_ENABLED, ENC_0B_ENABLED, ENC_0C_ENABLED, ENC_0D_ENABLED, ENC_0E_ENABLED, ENC_0F_ENABLED, ENC_0G_ENABLED, ENC_1A_ENABLED, ENC_1B_ENABLED, ENC_2BUDGET_ENABLED, ENC_2BUDGET_NATIVE_ORT_BUDGET_ENV, ENC_2BUDGET_MAX_MIB, ENC_2BUDGET_DEFAULT_MIB, ENC_2A_ENABLED, ENC_2B_ENABLED, ENC_2C_ENABLED, COSINE_FP_BENCH_ENABLED, COSINE_FP_REAL_ENABLED, REPO_CORPUS_ENABLED, DASH_0A_ENABLED, DASH_0B_ENABLED, DASH_0C_ENABLED, DASH_0D_ENABLED, BREAKER_WINDOW_MS, BREAKER_MIN_ATTEMPTS, BREAKER_PERF_FAILURES, BREAKER_PERF_FAILURE_RATE, BREAKER_CORRECTNESS_FAILURES, BREAKER_COOLDOWN_MS, BREAKER_PROBE_COUNT, BREAKER_RETRY_BASE_MS, BREAKER_RETRY_CAP_MS, BREAKER_RETRY_JITTER, BREAKER_HYSTERESIS_FAILURE_RATE, BREAKER_HYSTERESIS_BUDGET_P95_MS, BREAKER_MIN_HEALTHY_RESIDENCE_MS, } from "./config/vector-cortex.js";
@@ -70,6 +70,11 @@ export class CrystalStore {
70
70
  writes = 0;
71
71
  duplicateWrites = 0;
72
72
  collisions = 0;
73
+ /** Restart-survival crystal count/bytes (LIVEWIRE rehydrate). The `committed`
74
+ * map is empty in a fresh process; these offsets carry the persisted totals
75
+ * so the dashboard does not reset to zero on restart. */
76
+ rehydratedCrystalCount = 0;
77
+ rehydratedTotalBytes = 0;
73
78
  /** Freeze a crystal object for a key/bytes pair (digest computed here). */
74
79
  static freeze(keyDigest, bytes, key) {
75
80
  const copy = new Uint8Array(bytes);
@@ -178,12 +183,12 @@ export class CrystalStore {
178
183
  }
179
184
  /** Reader-only aggregate for the dashboard seam — counts and bytes only. */
180
185
  stats() {
181
- let totalBytes = 0;
186
+ let totalBytes = this.rehydratedTotalBytes;
182
187
  for (const c of this.committed.values())
183
188
  totalBytes += c.byteCount;
184
189
  return {
185
190
  mode: this.mode(),
186
- crystalCount: this.committed.size,
191
+ crystalCount: this.rehydratedCrystalCount + this.committed.size,
187
192
  totalBytes,
188
193
  hits: this.hits,
189
194
  misses: this.misses,
@@ -193,4 +198,22 @@ export class CrystalStore {
193
198
  collisions: this.collisions,
194
199
  };
195
200
  }
201
+ /**
202
+ * Restart survival: seed the CUMULATIVE counters from a previously-persisted
203
+ * aggregate (LIVEWIRE). The in-memory `committed` map is naturally empty in a
204
+ * fresh process — this only restores the running totals the dashboard reports,
205
+ * so a process restart does not reset the dashboard to zero. It deliberately
206
+ * does NOT reconstruct crystals: frozen bytes are never persisted to the
207
+ * reader aggregate, only the counts.
208
+ */
209
+ rehydrate(stats) {
210
+ this.rehydratedCrystalCount = stats.crystalCount;
211
+ this.rehydratedTotalBytes = stats.totalBytes;
212
+ this.hits = stats.hits;
213
+ this.misses = stats.misses;
214
+ this.hitBytes = stats.hitBytes;
215
+ this.writes = stats.writes;
216
+ this.duplicateWrites = stats.duplicateWrites;
217
+ this.collisions = stats.collisions;
218
+ }
196
219
  }
@@ -67,7 +67,14 @@ function isManifest(m) {
67
67
  typeof o.onnx.path === "string" &&
68
68
  typeof o.onnx.sha256 === "string" &&
69
69
  typeof o.tokenizer.path === "string" &&
70
- typeof o.tokenizer.sha256 === "string");
70
+ typeof o.tokenizer.sha256 === "string" &&
71
+ // ML5-A (VC2B-2): optional headWeights must, when present, be a valid
72
+ // ManifestAssetFile (path basename + sha256 + bytes).
73
+ (o.headWeights === undefined ||
74
+ (!!o.headWeights &&
75
+ typeof o.headWeights.path === "string" &&
76
+ typeof o.headWeights.sha256 === "string" &&
77
+ typeof o.headWeights.bytes === "number")));
71
78
  }
72
79
  /**
73
80
  * Verify the asset manifest + digest + constraints BEFORE allocation.
@@ -107,6 +114,11 @@ export function verifyEncoderAsset(assetDir, manifest, platform = detectPlatform
107
114
  if (!isBasename(manifest.onnx.path) || !isBasename(manifest.tokenizer.path)) {
108
115
  return { ok: false, code: ENC_FAIL.MANIFEST_INVALID };
109
116
  }
117
+ // ML5-A (VC2B-2): a manifest-declared headWeights path must also be a bare
118
+ // basename (no traversal into arbitrary paths off the asset dir).
119
+ if (manifest.headWeights !== undefined && !isBasename(manifest.headWeights.path)) {
120
+ return { ok: false, code: ENC_FAIL.MANIFEST_INVALID };
121
+ }
110
122
  const onnxPath = join(assetDir, manifest.onnx.path);
111
123
  const onnxDigest = digestFile(onnxPath);
112
124
  if (onnxDigest === null)
@@ -119,6 +131,19 @@ export function verifyEncoderAsset(assetDir, manifest, platform = detectPlatform
119
131
  return { ok: false, code: ENC_FAIL.ASSET_UNREADABLE };
120
132
  if (tokDigest !== manifest.tokenizer.sha256)
121
133
  return { ok: false, code: ENC_FAIL.DIGEST_MISMATCH };
134
+ // ML5-A (VC2B-2): verify the manifest-pinned trained-heads sibling when the
135
+ // manifest declares it. Absent declaration -> headWeightsDigest: null and no
136
+ // failure (committed placeholder bundle ships no trained weights).
137
+ let headWeightsDigest = null;
138
+ if (manifest.headWeights !== undefined) {
139
+ const hwPath = join(assetDir, manifest.headWeights.path);
140
+ const hwDigest = digestFile(hwPath);
141
+ if (hwDigest === null)
142
+ return { ok: false, code: ENC_FAIL.ASSET_UNREADABLE };
143
+ if (hwDigest !== manifest.headWeights.sha256)
144
+ return { ok: false, code: ENC_FAIL.DIGEST_MISMATCH };
145
+ headWeightsDigest = hwDigest;
146
+ }
122
147
  let embeddedBytes = 0;
123
148
  try {
124
149
  embeddedBytes = statSync(onnxPath).size + statSync(tokPath).size;
@@ -126,7 +151,14 @@ export function verifyEncoderAsset(assetDir, manifest, platform = detectPlatform
126
151
  catch {
127
152
  return { ok: false, code: ENC_FAIL.ASSET_UNREADABLE };
128
153
  }
129
- return { ok: true, embeddedBytes, maxTokens: manifest.maxTokens, onnxDigest, tokenizerDigest: tokDigest };
154
+ return {
155
+ ok: true,
156
+ embeddedBytes,
157
+ maxTokens: manifest.maxTokens,
158
+ onnxDigest,
159
+ tokenizerDigest: tokDigest,
160
+ headWeightsDigest,
161
+ };
130
162
  }
131
163
  /**
132
164
  * Read + shape-check a committed ModelManifestV1 from an asset directory.
@@ -25,11 +25,12 @@
25
25
  * Pi-agnostic, zero network (PREVENT-PI-004), no `any` (PREVENT-011).
26
26
  */
27
27
  import { createEncoderRuntime } from "./runtime.js";
28
- import { encodeVectorSet } from "./heads.js";
28
+ import { encodeVectorSet, loadHeadProjections, projectHeadFromTrunk, } from "./heads.js";
29
29
  import { embedTrigram512, selectTrigramBFallback } from "./trigram.js";
30
30
  import { embedLexical, selectLexicalC } from "./lexical.js";
31
31
  import { createEncoderHeadsReporter } from "./emit-vc2b.js";
32
- import { ENC_FAIL, } from "./types.js";
32
+ import { ML5A_ENABLED } from "../../config/vector-cortex.js";
33
+ import { ENC_FAIL, ENCODER_HEAD_ORDER, } from "./types.js";
33
34
  /** Deterministic text derived from an int token sequence so the asset-free
34
35
  * fallback producers operate on the same authority the learned path encoded. */
35
36
  function textFromTokens(tokens) {
@@ -92,9 +93,36 @@ export function encodeOrFallback(input, assetDir, options = {}) {
92
93
  if (!inferred.ok) {
93
94
  return fallbackFromLoad({ ok: false, mode: "B", code: inferred.code }, reporter, tokens);
94
95
  }
95
- const vectorSet = encodeVectorSet(tokens, { reporter, seed: options.seed });
96
+ const vectorSet = produceVectorSet(inferred.semantic, tokens, options, reporter);
96
97
  return { ok: true, mode: "A", vectorSet, code: null };
97
98
  }
99
+ /**
100
+ * Produce a mode-A `VectorSetV1` from the [1,384] trunk embedding (the
101
+ * `runtime.infer` result). VC2B-2 ML5-A: when real trained heads are loaded
102
+ * (`MEGACOMPACT_ML5_A` on + a `trainedHeadsPath` that loads), the multi-head
103
+ * output is projected through the real trained projection matrices via
104
+ * `projectHeadFromTrunk`. Otherwise (flag-off / absent / unloadable artifact)
105
+ * the deterministic LCG placeholder `encodeVectorSet` serves mode A —
106
+ * byte-identical to the VC2B predecessor. Non-fatal: an unloadable artifact
107
+ * degrades to the placeholder, never a throw.
108
+ */
109
+ function produceVectorSet(trunkEmbedding, tokens, options, reporter) {
110
+ const table = ML5A_ENABLED() && options.trainedHeadsPath !== undefined
111
+ ? loadHeadProjections(options.trainedHeadsPath)
112
+ : null;
113
+ if (table !== null) {
114
+ const heads = ENCODER_HEAD_ORDER.map((h) => projectHeadFromTrunk(h, trunkEmbedding, table));
115
+ reporter.headsEmitted({
116
+ heads: heads.length,
117
+ dims: heads.map((h) => h.dim).join("/"),
118
+ normalized: true,
119
+ tokens: tokens.length,
120
+ });
121
+ return { schema: "vector-set-v1", inputTokens: [...tokens], heads, normalized: true };
122
+ }
123
+ // ML5-A placeholder fallback (byte-identical predecessor).
124
+ return encodeVectorSet(tokens, { reporter, seed: options.seed });
125
+ }
98
126
  /**
99
127
  * Catch a (real or forced) A load failure (ok === false only) and select the
100
128
  * B/C fallback that emits `vector_cortex_encoder_fallback_selected` from the
@@ -0,0 +1,163 @@
1
+ /**
2
+ * vector-cortex/livewire/livewire-live.ts — LIVEWIRE in-process live state.
3
+ *
4
+ * Holds the LIVE subsystem objects for ONE stateDir: the VC7A `CrystalStore`,
5
+ * the VC7C cache breaker, the per-miss-class tallies, the VC8B shadow metrics,
6
+ * and the VC7B economics computed bit. This is the object the RUNTIME accumulates
7
+ * into (`recordMiss`, `recordServeBlocked`, `recordShadowRun`, ...) and that the
8
+ * reader-only dashboard routes snapshot out of. Kept separate from the registry
9
+ * (which owns the per-stateDir `Map` + persistence) so neither file crosses the
10
+ * 300-line soft-as-hard gate.
11
+ *
12
+ * AGGREGATE-FIRST, COUNTS ONLY. `snapshotOf` projects the live objects down to
13
+ * the SECURITY_PRIVACY-safe `LivewireSnapshot` (counts + codes + triad mode) that
14
+ * gets persisted and rendered. No session id, digest, range, profile id, bytes,
15
+ * or prompt text can pass through ANY of these fields.
16
+ *
17
+ * PREVENT-PI-004: no network. PREVENT-011: no `any`. Non-fatal: every derive is
18
+ * a pure read.
19
+ */
20
+ import { CrystalStore } from "../cache/store.js";
21
+ import { createCacheBreaker } from "../cache/breaker.js";
22
+ import { validateProfileEconomics } from "../provider/economics.js";
23
+ import { BASE_PROVIDER_PROFILES } from "../provider/registry.js";
24
+ /**
25
+ * Static VC7B economics profile tallies derived from the base provider registry.
26
+ * `profileCount` counts profiles that declare economics; `provenExclusions` /
27
+ * `unprovenExclusions` tally the exclusion sets validated against the fixture
28
+ * rule. This is PURE (no storage/clock/network) and identical regardless of the
29
+ * `MEGACOMPACT_VC7B` flag — only the emission/route seam is flag-gated.
30
+ */
31
+ function baseEconomicsTallies() {
32
+ let profileCount = 0;
33
+ let provenExclusions = 0;
34
+ let unprovenExclusions = 0;
35
+ for (const bundle of BASE_PROVIDER_PROFILES) {
36
+ const econ = bundle.profile.economics;
37
+ if (econ === null)
38
+ continue;
39
+ profileCount += 1;
40
+ const codes = validateProfileEconomics(bundle.profile, econ);
41
+ const failed = new Set(codes);
42
+ for (const _ex of bundle.profile.excludedJsonPointers) {
43
+ if (failed.has("ECON_EXCLUSION_UNPROVEN")) {
44
+ unprovenExclusions += 1;
45
+ }
46
+ else {
47
+ provenExclusions += 1;
48
+ }
49
+ }
50
+ }
51
+ return { profileCount, provenExclusions, unprovenExclusions };
52
+ }
53
+ /** A zeroed per-class tally map. */
54
+ function zeroTallies() {
55
+ return {
56
+ profile: 0,
57
+ range: 0,
58
+ dependency: 0,
59
+ request: 0,
60
+ generation: 0,
61
+ unknown: 0,
62
+ };
63
+ }
64
+ /** Build a fresh (empty) live state with real subsystem objects. */
65
+ export function createLiveState() {
66
+ const econTallies = baseEconomicsTallies();
67
+ return {
68
+ crystalStore: new CrystalStore(),
69
+ breaker: createCacheBreaker(),
70
+ diagnostics: {
71
+ tallies: zeroTallies(),
72
+ serveBlocked: 0,
73
+ breakerState: "CLOSED_A",
74
+ lastFailure: null,
75
+ },
76
+ economics: {
77
+ computed: false,
78
+ profileCount: econTallies.profileCount,
79
+ provenExclusions: econTallies.provenExclusions,
80
+ unprovenExclusions: econTallies.unprovenExclusions,
81
+ lastFailure: null,
82
+ },
83
+ shadow: {
84
+ shadowDecisions: 0,
85
+ clampedDecisions: 0,
86
+ rejectedInputs: 0,
87
+ liveMutations: 0,
88
+ pressureVersion: 1,
89
+ lastFailure: null,
90
+ },
91
+ };
92
+ }
93
+ /** Project the live state down to the persisted, reader-only aggregate. */
94
+ export function snapshotOf(state) {
95
+ const crystals = state.crystalStore.stats();
96
+ const diag = {
97
+ profileMisses: state.diagnostics.tallies.profile,
98
+ rangeMisses: state.diagnostics.tallies.range,
99
+ dependencyMisses: state.diagnostics.tallies.dependency,
100
+ requestMisses: state.diagnostics.tallies.request,
101
+ generationMisses: state.diagnostics.tallies.generation,
102
+ unknownMisses: state.diagnostics.tallies.unknown,
103
+ serveBlocked: state.diagnostics.serveBlocked,
104
+ breakerState: state.diagnostics.breakerState,
105
+ lastFailure: state.diagnostics.lastFailure,
106
+ };
107
+ const econ = {
108
+ profileCount: state.economics.profileCount,
109
+ provenExclusions: state.economics.provenExclusions,
110
+ unprovenExclusions: state.economics.unprovenExclusions,
111
+ computed: state.economics.computed,
112
+ lastFailure: state.economics.lastFailure,
113
+ };
114
+ const policy = {
115
+ shadowDecisions: state.shadow.shadowDecisions,
116
+ clampedDecisions: state.shadow.clampedDecisions,
117
+ rejectedInputs: state.shadow.rejectedInputs,
118
+ liveMutations: state.shadow.liveMutations,
119
+ pressureVersion: state.shadow.pressureVersion,
120
+ lastFailure: state.shadow.lastFailure,
121
+ };
122
+ return {
123
+ schema: "vector-cortex-livewire-v1",
124
+ crystals: {
125
+ mode: crystals.mode,
126
+ crystalCount: crystals.crystalCount,
127
+ totalBytes: crystals.totalBytes,
128
+ hits: crystals.hits,
129
+ misses: crystals.misses,
130
+ hitBytes: crystals.hitBytes,
131
+ writes: crystals.writes,
132
+ duplicateWrites: crystals.duplicateWrites,
133
+ collisions: crystals.collisions,
134
+ },
135
+ diagnostics: diag,
136
+ economics: econ,
137
+ policy,
138
+ };
139
+ }
140
+ /** Seed a fresh live state's CUMULATIVE counters from a persisted snapshot. */
141
+ export function rehydrateLive(state, snap) {
142
+ state.crystalStore.rehydrate(snap.crystals);
143
+ state.diagnostics.tallies.profile = snap.diagnostics.profileMisses;
144
+ state.diagnostics.tallies.range = snap.diagnostics.rangeMisses;
145
+ state.diagnostics.tallies.dependency = snap.diagnostics.dependencyMisses;
146
+ state.diagnostics.tallies.request = snap.diagnostics.requestMisses;
147
+ state.diagnostics.tallies.generation = snap.diagnostics.generationMisses;
148
+ state.diagnostics.tallies.unknown = snap.diagnostics.unknownMisses;
149
+ state.diagnostics.serveBlocked = snap.diagnostics.serveBlocked;
150
+ state.diagnostics.breakerState = snap.diagnostics.breakerState;
151
+ state.diagnostics.lastFailure = snap.diagnostics.lastFailure;
152
+ state.economics.computed = snap.economics.computed;
153
+ state.economics.profileCount = snap.economics.profileCount;
154
+ state.economics.provenExclusions = snap.economics.provenExclusions;
155
+ state.economics.unprovenExclusions = snap.economics.unprovenExclusions;
156
+ state.economics.lastFailure = snap.economics.lastFailure;
157
+ state.shadow.shadowDecisions = snap.policy.shadowDecisions;
158
+ state.shadow.clampedDecisions = snap.policy.clampedDecisions;
159
+ state.shadow.rejectedInputs = snap.policy.rejectedInputs;
160
+ state.shadow.liveMutations = snap.policy.liveMutations;
161
+ state.shadow.pressureVersion = snap.policy.pressureVersion;
162
+ state.shadow.lastFailure = snap.policy.lastFailure;
163
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * vector-cortex/livewire/livewire-registry.ts — per-stateDir LIWIRE registry.
3
+ *
4
+ * The single seam the runtime and the reader-only dashboard routes BOTH access.
5
+ * It owns a `Map<stateDir, LivewireLiveState>` (one live subsystem cluster per
6
+ * repo) and lazily opens a state on first access, rehydrating its cumulative
7
+ * counters from the persisted aggregate snapshot (`livewire-snapshot.ts`) so a
8
+ * freshly-spawned process — e.g. the dashboard server — reports the same counts
9
+ * the runtime has already accumulated.
10
+ *
11
+ * The runtime WRITES through this registry (see `livewire-runtime.ts`): each
12
+ * mutation persists a reduced, count-only snapshot. The routes READ through
13
+ * `livewireOf(stateDir)` and call the pure `snapshotOf`. There is no other path.
14
+ *
15
+ * BEST-EFFORT + NON-FATAL. `openLivewire` never throws: persistence failures are
16
+ * swallowed by the snapshot layer and state is always returned. PREVENT-PI-004
17
+ * (local in-process Map + filesystem only), PREVENT-011 (no `any`).
18
+ */
19
+ import { createLiveState, rehydrateLive, snapshotOf, } from "./livewire-live.js";
20
+ import { loadLivewireSnapshot, saveLivewireSnapshot, } from "./livewire-snapshot.js";
21
+ /** The per-stateDir registry (process-local; a fresh process starts empty). */
22
+ const REGISTRY = new Map();
23
+ let activeLogger;
24
+ /**
25
+ * Bind the structured logger the snapshot layer uses for its non-fatal write
26
+ * failures. The runtime calls this once at startup with its JSON logger.
27
+ */
28
+ export function setLivewireLogger(logger) {
29
+ activeLogger = logger;
30
+ }
31
+ /**
32
+ * Open (or return the cached) live state for a stateDir. Lazy: on first access
33
+ * it rehydrates from the persisted aggregate so a separate dashboard process
34
+ * reflects prior runtime work. Never throws.
35
+ */
36
+ export function livewireOf(stateDir) {
37
+ const cached = REGISTRY.get(stateDir);
38
+ if (cached !== undefined)
39
+ return cached;
40
+ const state = createLiveState();
41
+ const snap = loadLivewireSnapshot(stateDir);
42
+ if (snap !== null)
43
+ rehydrateLive(state, snap);
44
+ REGISTRY.set(stateDir, state);
45
+ return state;
46
+ }
47
+ /**
48
+ * Persist a state's reduced aggregate (counts + codes only). Best-effort and
49
+ * non-fatal. Called by the runtime after every mutation so the snapshot stays
50
+ * fresh for any reader process.
51
+ */
52
+ export function persistLivewire(state, stateDir) {
53
+ saveLivewireSnapshot(stateDir, snapshotOf(state), activeLogger);
54
+ }
55
+ /** Persist the live state for a stateDir (convenience over open + persist). */
56
+ export function flushLivewire(stateDir) {
57
+ const state = REGISTRY.get(stateDir);
58
+ if (state === undefined)
59
+ return;
60
+ persistLivewire(state, stateDir);
61
+ }
62
+ /**
63
+ * Build the reader aggregate for one stateDir WITHOUT persisting — the reader
64
+ * seam the dashboard routes call. Reads the live state (rehydrated from disk on
65
+ * first access) and projects it to the count-only snapshot.
66
+ */
67
+ export function readLivewireSnapshot(stateDir) {
68
+ return snapshotOf(livewireOf(stateDir));
69
+ }
70
+ /** For tests: drop the registry so a fresh stateDir is fully rehydrated. */
71
+ export function _resetLivewireRegistryForTests() {
72
+ REGISTRY.clear();
73
+ }