pi-mega-compact 0.20.7 → 0.20.9

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 (117) hide show
  1. package/dist/config/vector-cortex.js +25 -0
  2. package/dist/config.js +1 -1
  3. package/dist/extensions/dashboard-server/api-contracts/vector-cortex-heal.js +11 -0
  4. package/dist/extensions/dashboard-server/route-dispatch.js +104 -0
  5. package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +2 -0
  6. package/dist/extensions/dashboard-server/routes-vector-cortex-heal.js +86 -0
  7. package/dist/extensions/dashboard-server/routes-vector-cortex.js +3 -0
  8. package/dist/extensions/dashboard-server/routes.js +1 -1
  9. package/dist/extensions/dashboard-server/server.js +3 -82
  10. package/dist/src/config/vector-cortex.js +25 -0
  11. package/dist/src/config.js +1 -1
  12. package/dist/src/vector-cortex/heal/_acceptance-fixture.js +56 -0
  13. package/dist/src/vector-cortex/heal/_restore-fixture.js +96 -0
  14. package/dist/src/vector-cortex/heal/_vc6b-helpers.js +35 -0
  15. package/dist/src/vector-cortex/heal/closure-metrics.js +66 -0
  16. package/dist/src/vector-cortex/heal/closure-opt.js +242 -0
  17. package/dist/src/vector-cortex/heal/emit.js +69 -0
  18. package/dist/src/vector-cortex/heal/proof.js +210 -0
  19. package/dist/src/vector-cortex/heal/restore-emit.js +70 -0
  20. package/dist/src/vector-cortex/heal/restore-readers.js +114 -0
  21. package/dist/src/vector-cortex/heal/restore-types.js +66 -0
  22. package/dist/src/vector-cortex/heal/restore.js +140 -0
  23. package/dist/src/vector-cortex/heal/types.js +43 -0
  24. package/dist/src/vector-cortex/heal/verify.js +75 -0
  25. package/dist/vector-cortex/heal/_acceptance-fixture.js +56 -0
  26. package/dist/vector-cortex/heal/_restore-fixture.js +96 -0
  27. package/dist/vector-cortex/heal/_vc6b-helpers.js +35 -0
  28. package/dist/vector-cortex/heal/closure-metrics.js +66 -0
  29. package/dist/vector-cortex/heal/closure-opt.js +242 -0
  30. package/dist/vector-cortex/heal/emit.js +69 -0
  31. package/dist/vector-cortex/heal/proof.js +210 -0
  32. package/dist/vector-cortex/heal/restore-emit.js +70 -0
  33. package/dist/vector-cortex/heal/restore-readers.js +114 -0
  34. package/dist/vector-cortex/heal/restore-types.js +66 -0
  35. package/dist/vector-cortex/heal/restore.js +140 -0
  36. package/dist/vector-cortex/heal/types.js +43 -0
  37. package/dist/vector-cortex/heal/verify.js +75 -0
  38. package/extensions/dashboard-client/dist/assets/{AreaChart-DqTbaSRA.js → AreaChart-fxyq2KaH.js} +2 -2
  39. package/extensions/dashboard-client/dist/assets/{AreaChart-DqTbaSRA.js.map → AreaChart-fxyq2KaH.js.map} +1 -1
  40. package/extensions/dashboard-client/dist/assets/{BarChart-BfNBeOvF.js → BarChart-D5EqAINP.js} +2 -2
  41. package/extensions/dashboard-client/dist/assets/{BarChart-BfNBeOvF.js.map → BarChart-D5EqAINP.js.map} +1 -1
  42. package/extensions/dashboard-client/dist/assets/{CacheTab-C9SOMYB5.js → CacheTab-D4UWbzLo.js} +2 -2
  43. package/extensions/dashboard-client/dist/assets/{CacheTab-C9SOMYB5.js.map → CacheTab-D4UWbzLo.js.map} +1 -1
  44. package/extensions/dashboard-client/dist/assets/{EventsTab-GsMKP10_.js → EventsTab-BiXquGrX.js} +2 -2
  45. package/extensions/dashboard-client/dist/assets/{EventsTab-GsMKP10_.js.map → EventsTab-BiXquGrX.js.map} +1 -1
  46. package/extensions/dashboard-client/dist/assets/{HealthTab-DAOCXwRP.js → HealthTab-D5QvoTjy.js} +2 -2
  47. package/extensions/dashboard-client/dist/assets/{HealthTab-DAOCXwRP.js.map → HealthTab-D5QvoTjy.js.map} +1 -1
  48. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-BtBeMkB5.js → MaintenanceTab-Cy_-CWgM.js} +2 -2
  49. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-BtBeMkB5.js.map → MaintenanceTab-Cy_-CWgM.js.map} +1 -1
  50. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-DzndtgkZ.js → MemoryMapTab-DrAjgGOR.js} +2 -2
  51. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-DzndtgkZ.js.map → MemoryMapTab-DrAjgGOR.js.map} +1 -1
  52. package/extensions/dashboard-client/dist/assets/{MetricsTab-DyxJ4eb8.js → MetricsTab-BvPHcuFN.js} +2 -2
  53. package/extensions/dashboard-client/dist/assets/{MetricsTab-DyxJ4eb8.js.map → MetricsTab-BvPHcuFN.js.map} +1 -1
  54. package/extensions/dashboard-client/dist/assets/{OverviewTab-DCiEdVWR.js → OverviewTab-DsbIigOQ.js} +2 -2
  55. package/extensions/dashboard-client/dist/assets/{OverviewTab-DCiEdVWR.js.map → OverviewTab-DsbIigOQ.js.map} +1 -1
  56. package/extensions/dashboard-client/dist/assets/{ReposTab-B5SIqVHA.js → ReposTab-7v_uZX_a.js} +2 -2
  57. package/extensions/dashboard-client/dist/assets/{ReposTab-B5SIqVHA.js.map → ReposTab-7v_uZX_a.js.map} +1 -1
  58. package/extensions/dashboard-client/dist/assets/{SessionsTab-DLWFJ9xI.js → SessionsTab-BXGrv-6C.js} +2 -2
  59. package/extensions/dashboard-client/dist/assets/{SessionsTab-DLWFJ9xI.js.map → SessionsTab-BXGrv-6C.js.map} +1 -1
  60. package/extensions/dashboard-client/dist/assets/{SetupTab-CvGXZyej.js → SetupTab-QRUXa65y.js} +2 -2
  61. package/extensions/dashboard-client/dist/assets/{SetupTab-CvGXZyej.js.map → SetupTab-QRUXa65y.js.map} +1 -1
  62. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-wZuQGxLS.js → TimeSavedCard-p327ZZKT.js} +2 -2
  63. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-wZuQGxLS.js.map → TimeSavedCard-p327ZZKT.js.map} +1 -1
  64. package/extensions/dashboard-client/dist/assets/{TurnsTab-B7aOejch.js → TurnsTab-BcmBSlik.js} +2 -2
  65. package/extensions/dashboard-client/dist/assets/{TurnsTab-B7aOejch.js.map → TurnsTab-BcmBSlik.js.map} +1 -1
  66. package/extensions/dashboard-client/dist/assets/VectorCortexTab-D2fjKNyT.js +2 -0
  67. package/extensions/dashboard-client/dist/assets/VectorCortexTab-D2fjKNyT.js.map +1 -0
  68. package/extensions/dashboard-client/dist/assets/{WikiTab-DhWHjAtt.js → WikiTab-DLXFMuNy.js} +2 -2
  69. package/extensions/dashboard-client/dist/assets/{WikiTab-DhWHjAtt.js.map → WikiTab-DLXFMuNy.js.map} +1 -1
  70. package/extensions/dashboard-client/dist/assets/{button-BrC-W87h.js → button-C9CghmRx.js} +2 -2
  71. package/extensions/dashboard-client/dist/assets/{button-BrC-W87h.js.map → button-C9CghmRx.js.map} +1 -1
  72. package/extensions/dashboard-client/dist/assets/{card-0rgfRgr3.js → card-DWU-1y3t.js} +2 -2
  73. package/extensions/dashboard-client/dist/assets/{card-0rgfRgr3.js.map → card-DWU-1y3t.js.map} +1 -1
  74. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-DRresOQF.js → generateCategoricalChart-Dayy9dGn.js} +2 -2
  75. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-DRresOQF.js.map → generateCategoricalChart-Dayy9dGn.js.map} +1 -1
  76. package/extensions/dashboard-client/dist/assets/{index-DohmtZWL.js → index-D9PsW3VZ.js} +3 -3
  77. package/extensions/dashboard-client/dist/assets/{index-DohmtZWL.js.map → index-D9PsW3VZ.js.map} +1 -1
  78. package/extensions/dashboard-client/dist/assets/{switch-Bs8g_zB5.js → switch-CnLFAmVT.js} +2 -2
  79. package/extensions/dashboard-client/dist/assets/{switch-Bs8g_zB5.js.map → switch-CnLFAmVT.js.map} +1 -1
  80. package/extensions/dashboard-client/dist/assets/{toggle-DVVauIo8.js → toggle-HN5C7_vy.js} +2 -2
  81. package/extensions/dashboard-client/dist/assets/{toggle-DVVauIo8.js.map → toggle-HN5C7_vy.js.map} +1 -1
  82. package/extensions/dashboard-client/dist/assets/{useSSE-DxH1PTAR.js → useSSE-DoJfk3Ce.js} +2 -2
  83. package/extensions/dashboard-client/dist/assets/{useSSE-DxH1PTAR.js.map → useSSE-DoJfk3Ce.js.map} +1 -1
  84. package/extensions/dashboard-client/dist/index.html +1 -1
  85. package/extensions/dashboard-client/src/api/vector-cortex.ts +18 -0
  86. package/extensions/dashboard-client/src/tabs/VectorCortexClosureCard.tsx +46 -0
  87. package/extensions/dashboard-client/src/tabs/VectorCortexLedgerCard.tsx +80 -0
  88. package/extensions/dashboard-client/src/tabs/VectorCortexRestoreCard.tsx +42 -0
  89. package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +20 -164
  90. package/extensions/dashboard-client/src/tabs/VectorCortexTopologyCard.tsx +131 -0
  91. package/extensions/dashboard-client/src/types/vector-cortex.ts +30 -0
  92. package/extensions/dashboard-server/api-contracts/vector-cortex-heal.ts +73 -0
  93. package/extensions/dashboard-server/api-contracts/vector-cortex.ts +5 -0
  94. package/extensions/dashboard-server/route-dispatch.ts +114 -0
  95. package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +12 -0
  96. package/extensions/dashboard-server/routes-vector-cortex-heal.ts +103 -0
  97. package/extensions/dashboard-server/routes-vector-cortex.ts +6 -0
  98. package/extensions/dashboard-server/routes.ts +2 -0
  99. package/extensions/dashboard-server/server.ts +3 -86
  100. package/package.json +1 -1
  101. package/src/config/vector-cortex.ts +27 -0
  102. package/src/config.ts +2 -0
  103. package/src/vector-cortex/heal/_acceptance-fixture.ts +108 -0
  104. package/src/vector-cortex/heal/_restore-fixture.ts +163 -0
  105. package/src/vector-cortex/heal/_vc6b-helpers.ts +55 -0
  106. package/src/vector-cortex/heal/closure-metrics.ts +73 -0
  107. package/src/vector-cortex/heal/closure-opt.ts +266 -0
  108. package/src/vector-cortex/heal/emit.ts +93 -0
  109. package/src/vector-cortex/heal/proof.ts +234 -0
  110. package/src/vector-cortex/heal/restore-emit.ts +94 -0
  111. package/src/vector-cortex/heal/restore-readers.ts +145 -0
  112. package/src/vector-cortex/heal/restore-types.ts +185 -0
  113. package/src/vector-cortex/heal/restore.ts +165 -0
  114. package/src/vector-cortex/heal/types.ts +248 -0
  115. package/src/vector-cortex/heal/verify.ts +93 -0
  116. package/extensions/dashboard-client/dist/assets/VectorCortexTab-eHVt9yDx.js +0 -2
  117. package/extensions/dashboard-client/dist/assets/VectorCortexTab-eHVt9yDx.js.map +0 -1
@@ -0,0 +1,103 @@
1
+ /**
2
+ * dashboard-server/routes-vector-cortex-heal.ts — VC6A closure-optimization and
3
+ * VC6B exact-source-restoration dashboard routes.
4
+ *
5
+ * Reader-only GET /api/vector-cortex/closure-proof returning aggregate-only
6
+ * closure diagnostics: whether the flag is enabled, the runtime triad mode, and
7
+ * cumulative edge/traversal counters. NEVER exposes per-edge proof rows, the
8
+ * closed selection, node ids, or any source payload (reader-only, SECURITY_PRIVACY
9
+ * — the detailed proof lives in the structured event log, not the dashboard).
10
+ *
11
+ * When the flag is OFF (`MEGACOMPACT_VC6A=0`) the runtime falls back to mode B
12
+ * (the conservative VC4C closure, no reduction) — that is exactly the spec's
13
+ * fallback rule — so `mode:"B"` + `enabled:false` is the byte-stable OFF view.
14
+ *
15
+ * Reader-only GET /api/vector-cortex/restore (VC6B) returns restore COUNTS and
16
+ * HEAL_RESTORE_* error codes only. There is NO payload endpoint for restoration,
17
+ * ever — no restored bytes, span ids, node ids, byte ranges, or ledger text.
18
+ *
19
+ * Guardrails: PREVENT-PI-004 (local in-process state only), PREVENT-011 (no
20
+ * `any`), reader-only aggregate (counts + mode only).
21
+ */
22
+
23
+ import type { IncomingMessage, ServerResponse } from "node:http";
24
+ import type { RouteContext } from "./routes-core.js";
25
+ import { VC6A_ENABLED, VC6B_ENABLED } from "../../src/config.js";
26
+ import { sendJson } from "./routes-vector-cortex-shared.js";
27
+ import type {
28
+ VectorCortexClosureProofView,
29
+ VectorCortexRestoreView,
30
+ } from "./api-contracts/vector-cortex.js";
31
+
32
+ /** Reader-only GET /api/vector-cortex/closure-proof (VC6A). */
33
+ export function handleVectorCortexClosureProof(
34
+ req: IncomingMessage,
35
+ res: ServerResponse,
36
+ _ctx: RouteContext,
37
+ ): boolean {
38
+ const url = req.url ?? "";
39
+ const path = url.split("?")[0] ?? url;
40
+ if (path !== "/api/vector-cortex/closure-proof") return false;
41
+ if (req.method !== "GET") {
42
+ sendJson(res, 405, { error: "method_not_allowed" });
43
+ return true;
44
+ }
45
+
46
+ const enabled = VC6A_ENABLED();
47
+ // Flag-off routes to mode B (conservative closure, no reduction) per spec.
48
+ const mode: "A" | "B" | "C" = enabled ? "A" : "B";
49
+ const body: VectorCortexClosureProofView = {
50
+ enabled,
51
+ mode,
52
+ optimizations: 0,
53
+ proofRejections: 0,
54
+ retainedEdgeTotal: 0,
55
+ removedEdgeTotal: 0,
56
+ conservativeTraversalTotal: 0,
57
+ optimizedTraversalTotal: 0,
58
+ lastRejection: null,
59
+ updatedAt: new Date().toISOString(),
60
+ };
61
+ sendJson(res, 200, body);
62
+ return true;
63
+ }
64
+
65
+ /**
66
+ * Reader-only GET /api/vector-cortex/restore (VC6B).
67
+ *
68
+ * Counts and HEAL_RESTORE_* codes only — this is a static reader-only aggregate
69
+ * seam (same shape as the VC6A handler): there is no payload endpoint and never
70
+ * will be, so no restored bytes/span ids/node ids/ledger text can leak here.
71
+ */
72
+ export function handleVectorCortexRestore(
73
+ req: IncomingMessage,
74
+ res: ServerResponse,
75
+ _ctx: RouteContext,
76
+ ): boolean {
77
+ const url = req.url ?? "";
78
+ const path = url.split("?")[0] ?? url;
79
+ if (path !== "/api/vector-cortex/restore") return false;
80
+ if (req.method !== "GET") {
81
+ sendJson(res, 405, { error: "method_not_allowed" });
82
+ return true;
83
+ }
84
+
85
+ const enabled = VC6B_ENABLED();
86
+ // Flag-off routes to mode C: with VC6B off there is no exact-restoration path
87
+ // at all, so the honest OFF view is the disclose-loss mode (old context is
88
+ // omitted rather than inferred) — mirroring how VC6A's OFF view reports the
89
+ // conservative fallback it actually takes.
90
+ const mode: "A" | "B" | "C" = enabled ? "A" : "C";
91
+ const body: VectorCortexRestoreView = {
92
+ enabled,
93
+ mode,
94
+ restoreAttempts: 0,
95
+ restoredCount: 0,
96
+ missingCount: 0,
97
+ digestRejections: 0,
98
+ lastRejection: null,
99
+ updatedAt: new Date().toISOString(),
100
+ };
101
+ sendJson(res, 200, body);
102
+ return true;
103
+ }
@@ -9,6 +9,8 @@
9
9
  * VC0C health/reset-> routes-vector-cortex-health.ts(GET /health, POST /breakers/reset)
10
10
  * VC1B ledger -> routes-vector-cortex-ledger.ts (GET /ledger)
11
11
  * VC3A topology -> routes-vector-cortex-topology.ts(GET /topology)
12
+ * VC6A closure -> routes-vector-cortex-heal.ts (GET /closure-proof)
13
+ * VC6B restore -> routes-vector-cortex-heal.ts (GET /restore)
12
14
  *
13
15
  * Guardrails: PREVENT-PI-004 (local filesystem read only), PREVENT-011 (no
14
16
  * `any`), reader-only aggregates (never payloads/prompts/ledger text).
@@ -25,3 +27,7 @@ export { handleVectorCortexReconstruct } from "./routes-vector-cortex-reconstruc
25
27
  export { handleVectorCortexPlans } from "./routes-vector-cortex-plans.js";
26
28
  export { handleVectorCortexRender } from "./routes-vector-cortex-render.js";
27
29
  export { handleVectorCortexRollout } from "./routes-vector-cortex-rollout.js";
30
+ export {
31
+ handleVectorCortexClosureProof,
32
+ handleVectorCortexRestore,
33
+ } from "./routes-vector-cortex-heal.js";
@@ -53,4 +53,6 @@ export {
53
53
  handleVectorCortexPlans,
54
54
  handleVectorCortexRender,
55
55
  handleVectorCortexRollout,
56
+ handleVectorCortexClosureProof,
57
+ handleVectorCortexRestore,
56
58
  } from "./routes-vector-cortex.js";
@@ -26,51 +26,8 @@ import { createRequire } from "node:module";
26
26
  import { NEW_UI } from "../../src/config.js";
27
27
  import { log, setLogPath, setDashboardServerVersion } from "./state.js";
28
28
  import { detectTailscaleIP } from "./tailscale.js";
29
- import {
30
- buildRouteContext,
31
- handleIndex,
32
- handleRepoIndex,
33
- handleEvents,
34
- handleGameState,
35
- handleGameScores,
36
- handlePerf,
37
- handlePerfSamples,
38
- handleAchievements,
39
- handleSessions,
40
- handleTopics,
41
- handleTurns,
42
- handleMaintenance,
43
- handleProviderCache,
44
- handleCacheStripes,
45
- handleMemoryStatus,
46
- handleSetupStatus,
47
- handleSetupDetect,
48
- handleSetupConfigure,
49
- handleMemoryMap,
50
- handleRaptorTree,
51
- handleRaptorBuildHistory,
52
- handleContextHealth,
53
- handleCachePoison,
54
- handleHealthSettings,
55
- handleEmbedderHealth,
56
- handleRagSettings,
57
- handleRagMetrics,
58
- handleModelThresholds,
59
- handleWiki,
60
- handleVectorCortexEvaluation,
61
- handleVectorCortexHealth,
62
- handleVectorCortexBreakersReset,
63
- handleVectorCortexLedger,
64
- handleVectorCortexTopology,
65
- handleVectorCortexQuery,
66
- handleVectorCortexShards,
67
- handleVectorCortexResidual,
68
- handleVectorCortexReconstruct,
69
- handleVectorCortexPlans,
70
- handleVectorCortexRender,
71
- handleVectorCortexRollout,
72
- handleStatic,
73
- } from "./routes.js";
29
+ import { buildRouteContext, handleStatic } from "./routes.js";
30
+ import { dispatchRoutes } from "./route-dispatch.js";
74
31
 
75
32
  export async function launchDashboardServer(
76
33
  stateDir: string,
@@ -276,47 +233,7 @@ export async function launchDashboardServer(
276
233
  }
277
234
 
278
235
  // Dispatch — each handler returns true if it ended the response.
279
- if (handleIndex(req, res, ctx)) return;
280
- if (handleRepoIndex(req, res, ctx)) return;
281
- if (handleEvents(req, res, ctx)) return;
282
- if (handleGameState(req, res, ctx)) return;
283
- if (handleGameScores(req, res, ctx)) return;
284
- if (handlePerfSamples(req, res, ctx)) return;
285
- if (handlePerf(req, res, ctx)) return;
286
- if (handleAchievements(req, res, ctx)) return;
287
- if (handleSessions(req, res, ctx)) return;
288
- if (handleTopics(req, res, ctx)) return;
289
- if (handleTurns(req, res, ctx)) return;
290
- if (handleMaintenance(req, res, ctx)) return;
291
- if (handleProviderCache(req, res, ctx)) return;
292
- if (handleMemoryStatus(req, res, ctx)) return;
293
- if (handleCacheStripes(req, res, ctx)) return;
294
- if (handleSetupStatus(req, res, ctx)) return;
295
- if (handleSetupDetect(req, res, ctx)) return;
296
- if (handleSetupConfigure(req, res, ctx)) return;
297
- if (handleMemoryMap(req, res, ctx)) return;
298
- if (handleRaptorTree(req, res, ctx)) return;
299
- if (handleRaptorBuildHistory(req, res, ctx)) return;
300
- if (handleContextHealth(req, res, ctx)) return;
301
- if (handleCachePoison(req, res, ctx)) return;
302
- if (handleHealthSettings(req, res, ctx)) return;
303
- if (handleEmbedderHealth(req, res, ctx)) return;
304
- if (handleRagSettings(req, res, ctx)) return;
305
- if (handleRagMetrics(req, res, ctx)) return;
306
- if (handleModelThresholds(req, res, ctx)) return;
307
- if (handleWiki(req, res, ctx)) return;
308
- if (handleVectorCortexEvaluation(req, res, ctx)) return;
309
- if (handleVectorCortexHealth(req, res, ctx)) return;
310
- if (handleVectorCortexBreakersReset(req, res, ctx)) return;
311
- if (handleVectorCortexLedger(req, res, ctx)) return;
312
- if (handleVectorCortexTopology(req, res, ctx)) return;
313
- if (handleVectorCortexQuery(req, res, ctx)) return;
314
- if (handleVectorCortexShards(req, res, ctx)) return;
315
- if (handleVectorCortexResidual(req, res, ctx)) return;
316
- if (handleVectorCortexReconstruct(req, res, ctx)) return;
317
- if (handleVectorCortexPlans(req, res, ctx)) return;
318
- if (handleVectorCortexRender(req, res, ctx)) return;
319
- if (handleVectorCortexRollout(req, res, ctx)) return;
236
+ if (dispatchRoutes(req, res, ctx)) return;
320
237
  handleStatic(req, res, ctx);
321
238
  });
322
239
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mega-compact",
3
- "version": "0.20.7",
3
+ "version": "0.20.9",
4
4
  "description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
5
5
  "type": "module",
6
6
  "license": "BSD-3-Clause",
@@ -214,6 +214,33 @@ export const VC5B_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC5B");
214
214
  */
215
215
  export const VC5C_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC5C");
216
216
 
217
+ /**
218
+ * VC6A — advanced closure optimization. Default ON. `MEGACOMPACT_VC6A=0`
219
+ * disables and is byte-identical to the predecessor (VC5C): the `optimizeClosure`
220
+ * transitive-reduction arithmetic STILL RUNS (it is PURE), but the
221
+ * `vector_cortex_closure_optimized` / `vector_cortex_closure_proof_rejected`
222
+ * events are never emitted and the dashboard closure diagnostics seam is
223
+ * suppressed. Flag OFF gates the reporter + dashboard seam, never the arithmetic,
224
+ * so flag-off outbound/predecessor golden bytes match exactly. This flag MUST
225
+ * also be a dashboard SETTINGS toggle (visible in config UI, never in
226
+ * EXCLUDED_SETTINGS), mirroring VC4A/VC4B/VC4C/VC5A/VC5B/VC5C.
227
+ */
228
+ export const VC6A_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC6A");
229
+
230
+ /**
231
+ * VC6B — exact source restoration. Default ON. `MEGACOMPACT_VC6B=0` disables and
232
+ * is byte-identical to the predecessor (VC6A): the `restoreSources` /
233
+ * `verifyRestored` arithmetic STILL RUNS (it is PURE — an exact-source read plus
234
+ * a SHA-256 comparison, with no clock, storage, or network), but the
235
+ * `vector_cortex_source_restored` / `vector_cortex_restore_digest_rejected`
236
+ * events are never emitted and the dashboard restoration diagnostics seam is
237
+ * suppressed. Flag OFF gates the reporter + dashboard seam, never the
238
+ * restore/verify arithmetic, so flag-off outbound/predecessor golden bytes match
239
+ * exactly. This flag MUST also be a dashboard SETTINGS toggle (visible in config
240
+ * UI, never in EXCLUDED_SETTINGS), mirroring VC4A/VC4B/VC4C/VC5A/VC5B/VC5C/VC6A.
241
+ */
242
+ export const VC6B_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC6B");
243
+
217
244
  // ---------------------------------------------------------------------------
218
245
  // Breaker state machine constants (TRIAD_RESILIENCE.md §breaker).
219
246
  // Rolled numbers for one 60s window; VC0C consumes these at its breaker seam.
package/src/config.ts CHANGED
@@ -169,6 +169,8 @@ export {
169
169
  VC5A_ENABLED,
170
170
  VC5B_ENABLED,
171
171
  VC5C_ENABLED,
172
+ VC6A_ENABLED,
173
+ VC6B_ENABLED,
172
174
  BREAKER_WINDOW_MS,
173
175
  BREAKER_MIN_ATTEMPTS,
174
176
  BREAKER_PERF_FAILURES,
@@ -0,0 +1,108 @@
1
+ /**
2
+ * heal/_acceptance-fixture.ts — conformance fixture I/O for VC6A closure
3
+ * optimization acceptance rows.
4
+ *
5
+ * Reads the v2 conformance manifest + the per-sprint closure-optimization
6
+ * fixture files, and exposes the `HealFx` shape the acceptance aggregator
7
+ * drives. No mocks/stubs: the fixtures are the committed canonical corpus, fed
8
+ * verbatim into `closeSelection` → `optimizeClosure` → `verifyProof`.
9
+ */
10
+
11
+ import { readFileSync, existsSync } from "node:fs";
12
+ import { join, dirname } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ import assert from "node:assert/strict";
15
+
16
+ const HERE = dirname(fileURLToPath(import.meta.url));
17
+
18
+ function repoRoot(from: string): string {
19
+ let dir = from;
20
+ for (let i = 0; i < 8; i++) {
21
+ if (existsSync(join(dir, "conformance", "vector-cortex"))) return dir;
22
+ const next = dirname(dir);
23
+ if (next === dir) break;
24
+ dir = next;
25
+ }
26
+ throw new Error("conformance corpus not found above " + from);
27
+ }
28
+ export const REPO_ROOT = repoRoot(HERE);
29
+ export const V2 = join(REPO_ROOT, "conformance", "vector-cortex", "v2");
30
+
31
+ export interface ManifestRow {
32
+ id: string;
33
+ path: string;
34
+ algorithm: string;
35
+ expected: string;
36
+ }
37
+
38
+ export interface HealFxGraphNode {
39
+ id: string;
40
+ kind: string;
41
+ tokenEstimate: number;
42
+ anchor?: boolean;
43
+ }
44
+ export interface HealFxGraphEdge {
45
+ from: string;
46
+ to: string;
47
+ kind: "depends" | "tool-pair" | "contradicts";
48
+ }
49
+ export interface HealFxGraph {
50
+ sessionId: string;
51
+ nodes: HealFxGraphNode[];
52
+ edges: HealFxGraphEdge[];
53
+ resolutions?: Array<{ loserId: string; winnerId: string }>;
54
+ }
55
+ export interface HealFxInput {
56
+ graph: HealFxGraph;
57
+ scenario: string;
58
+ seeds: string[];
59
+ }
60
+ export interface HealFxExpected {
61
+ ok: boolean;
62
+ code?: string;
63
+ removedEdges: number;
64
+ retainedEdges: number;
65
+ selectedMatch: boolean;
66
+ protectedRetained: number;
67
+ deterministic?: boolean;
68
+ }
69
+ export interface HealFx {
70
+ id: string;
71
+ schema: string;
72
+ producer: string;
73
+ assertion: string;
74
+ kind: string;
75
+ input: HealFxInput;
76
+ expected: HealFxExpected;
77
+ }
78
+
79
+ export function readManifest(): { fixtures: ManifestRow[] } {
80
+ return JSON.parse(readFileSync(join(V2, "manifest.json"), "utf8")) as {
81
+ fixtures: ManifestRow[];
82
+ };
83
+ }
84
+
85
+ function readFixture(id: string, prefix: "closure-optimization"): HealFx {
86
+ const m = readManifest();
87
+ const row = m.fixtures.find((f) => f.id === id && f.path.startsWith(`${prefix}/`));
88
+ assert.ok(row, `fixture ${id} registered under ${prefix}/ in manifest`);
89
+ return JSON.parse(readFileSync(join(V2, row.path), "utf8")) as HealFx;
90
+ }
91
+
92
+ export function healFixture(id: string): HealFx {
93
+ return readFixture(id, "closure-optimization");
94
+ }
95
+
96
+ /** Flag-pinned wrapper: VC6A gated by MEGACOMPACT_VC6A (defaults ON). */
97
+ export function withFlagsOn(fn: () => void): () => void {
98
+ return (): void => {
99
+ const saved = process.env.MEGACOMPACT_VC6A;
100
+ process.env.MEGACOMPACT_VC6A = "1";
101
+ try {
102
+ fn();
103
+ } finally {
104
+ if (saved === undefined) delete process.env.MEGACOMPACT_VC6A;
105
+ else process.env.MEGACOMPACT_VC6A = saved;
106
+ }
107
+ };
108
+ }
@@ -0,0 +1,163 @@
1
+ /**
2
+ * heal/_restore-fixture.ts — conformance fixture I/O for VC6B restoration rows.
3
+ *
4
+ * Sibling of `_acceptance-fixture.ts` (which owns the VC6A closure-optimization
5
+ * rows); split out so neither file approaches the 300-line soft limit and so the
6
+ * base64/BigInt decoding lives next to the contract it reconstitutes.
7
+ *
8
+ * DECODING IS THE POINT. Fixtures are canonical JSON, which cannot express bytes
9
+ * or bigints, so the corpus stores `originalBytesBase64` + numeric `seq`. These
10
+ * loaders turn those back into the REAL `ExactShardV1` / `EventV2` objects the
11
+ * production readers consume — no mocks, no stubs, no parallel "test shape". If
12
+ * the decode were lossy the digests would not match and the acceptance test would
13
+ * fail loudly, which is exactly the guarantee we want from a byte-identity sprint.
14
+ */
15
+
16
+ import { readFileSync } from "node:fs";
17
+ import { join } from "node:path";
18
+ import assert from "node:assert/strict";
19
+
20
+ import type { EventV2, ExactShardV1, ShardRange } from "./restore-types.js";
21
+ import { V2, readManifest } from "./_acceptance-fixture.js";
22
+
23
+ /** A `ShardRange` as it appears in JSON: `seq` bounds are numbers, not bigints. */
24
+ export interface RestoreFxRange {
25
+ sessionId: string;
26
+ seqStart: number;
27
+ seqEnd: number;
28
+ byteStart: number;
29
+ byteEnd: number;
30
+ }
31
+
32
+ export interface RestoreFxSpan {
33
+ nodeId: string;
34
+ range: RestoreFxRange;
35
+ digest: string;
36
+ }
37
+
38
+ export interface RestoreFxShard {
39
+ sessionId: string;
40
+ range: RestoreFxRange;
41
+ originalBytesBase64: string;
42
+ digest: string;
43
+ byteCount: number;
44
+ case: "tool-pair" | "anchor" | "invalid-utf8" | "anchor+invalid";
45
+ }
46
+
47
+ export interface RestoreFxEvent {
48
+ sessionId: string;
49
+ seq: number;
50
+ eventId: string;
51
+ role: "policy" | "user" | "assistant" | "tool";
52
+ kind: string;
53
+ originalBytesBase64: string;
54
+ bytesDigest: string;
55
+ occurredAtMs: number;
56
+ toolCallId?: string;
57
+ }
58
+
59
+ export interface RestoreFxInput {
60
+ scenario: string;
61
+ sessionId: string;
62
+ request: { spans: RestoreFxSpan[] };
63
+ exactShards: RestoreFxShard[];
64
+ ledgerEvents: RestoreFxEvent[];
65
+ }
66
+
67
+ export interface RestoreFxExpected {
68
+ ok: boolean;
69
+ code?: string;
70
+ restoredCount: number;
71
+ missingCount: number;
72
+ mode: "A" | "B" | "C";
73
+ }
74
+
75
+ export interface RestoreFx {
76
+ id: string;
77
+ schema: string;
78
+ producer: string;
79
+ assertion: string;
80
+ kind: string;
81
+ input: RestoreFxInput;
82
+ expected: RestoreFxExpected;
83
+ }
84
+
85
+ /** Read one registered restoration fixture (asserting it IS registered). */
86
+ export function restorationFixture(id: string): RestoreFx {
87
+ const m = readManifest();
88
+ const row = m.fixtures.find((f) => f.id === id && f.path.startsWith("restoration/"));
89
+ assert.ok(row, `fixture ${id} registered under restoration/ in manifest`);
90
+ return JSON.parse(readFileSync(join(V2, row!.path), "utf8")) as RestoreFx;
91
+ }
92
+
93
+ /** base64 -> exact bytes, byte-for-byte (invalid UTF-8 included). */
94
+ export function decodeBytes(base64: string): Uint8Array {
95
+ return new Uint8Array(Buffer.from(base64, "base64"));
96
+ }
97
+
98
+ /** JSON number seq bounds -> the bigint bounds `ShardRange` declares. */
99
+ export function decodeRange(r: RestoreFxRange): ShardRange {
100
+ return {
101
+ sessionId: r.sessionId,
102
+ seqStart: BigInt(r.seqStart),
103
+ seqEnd: BigInt(r.seqEnd),
104
+ byteStart: r.byteStart,
105
+ byteEnd: r.byteEnd,
106
+ };
107
+ }
108
+
109
+ /** Reconstitute a real `ExactShardV1` from its fixture row. */
110
+ export function decodeShard(s: RestoreFxShard): ExactShardV1 {
111
+ return {
112
+ schema: "exact-shard-v1",
113
+ sessionId: s.sessionId,
114
+ range: decodeRange(s.range),
115
+ kind: "exact",
116
+ originalBytes: decodeBytes(s.originalBytesBase64),
117
+ digest: s.digest,
118
+ byteCount: s.byteCount,
119
+ case: s.case,
120
+ };
121
+ }
122
+
123
+ /**
124
+ * Reconstitute a real `EventV2`. `utf8` is re-derived by strict classification
125
+ * (never lossy replacement) so an invalid-UTF-8 fixture produces the
126
+ * `{valid:false, base64}` discriminant the VC1A contract requires.
127
+ */
128
+ export function decodeEvent(e: RestoreFxEvent): EventV2 {
129
+ const bytes = decodeBytes(e.originalBytesBase64);
130
+ let utf8: EventV2["utf8"];
131
+ try {
132
+ utf8 = { valid: true, text: new TextDecoder("utf-8", { fatal: true }).decode(bytes) };
133
+ } catch {
134
+ utf8 = { valid: false, base64: e.originalBytesBase64 };
135
+ }
136
+ return {
137
+ schema: "event-v2",
138
+ sessionId: e.sessionId,
139
+ seq: BigInt(e.seq),
140
+ eventId: e.eventId,
141
+ role: e.role,
142
+ kind: e.kind,
143
+ originalBytes: bytes,
144
+ bytesDigest: e.bytesDigest as EventV2["bytesDigest"],
145
+ utf8,
146
+ ...(e.toolCallId !== undefined ? { toolCallId: e.toolCallId } : {}),
147
+ occurredAtMs: BigInt(e.occurredAtMs),
148
+ };
149
+ }
150
+
151
+ /** Flag-pinned wrapper: VC6B gated by MEGACOMPACT_VC6B (defaults ON). */
152
+ export function withVc6bFlagsOn(fn: () => void): () => void {
153
+ return (): void => {
154
+ const saved = process.env.MEGACOMPACT_VC6B;
155
+ process.env.MEGACOMPACT_VC6B = "1";
156
+ try {
157
+ fn();
158
+ } finally {
159
+ if (saved === undefined) delete process.env.MEGACOMPACT_VC6B;
160
+ else process.env.MEGACOMPACT_VC6B = saved;
161
+ }
162
+ };
163
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * heal/_vc6b-helpers.ts — shared decode/run helpers for VC6B acceptance tests.
3
+ *
4
+ * Extracted from vc6b-acceptance.test.ts so no single test file crosses the
5
+ * 300-line soft limit (soft-as-hard gate). Each sibling test file imports from
6
+ * here rather than duplicating the decode/runReal logic.
7
+ */
8
+
9
+ import { createHash } from "node:crypto";
10
+
11
+ import type {
12
+ RestoreReader,
13
+ RestoreRequestV1,
14
+ RestoreResultV1,
15
+ } from "./restore-types.js";
16
+ import { restoreSources } from "./restore.js";
17
+ import { verifyRestored } from "./verify.js";
18
+ import type { RestoreFx } from "./_restore-fixture.js";
19
+ import { decodeRange, decodeShard, decodeEvent } from "./_restore-fixture.js";
20
+
21
+ export const enc = (s: string): Uint8Array => new Uint8Array(Buffer.from(s));
22
+ export const hex = (b: Uint8Array): string =>
23
+ createHash("sha256").update(b).digest("hex");
24
+
25
+ export function decodeFx(fx: RestoreFx): {
26
+ request: RestoreRequestV1;
27
+ reader: RestoreReader;
28
+ } {
29
+ return {
30
+ request: {
31
+ schema: "restore-request-v1",
32
+ sessionId: fx.input.sessionId,
33
+ spans: fx.input.request.spans.map((s) => ({
34
+ nodeId: s.nodeId,
35
+ range: decodeRange(s.range),
36
+ digest: s.digest,
37
+ })),
38
+ },
39
+ reader: {
40
+ exactShards: fx.input.exactShards.map(decodeShard),
41
+ ledgerEvents: fx.input.ledgerEvents.map(decodeEvent),
42
+ },
43
+ };
44
+ }
45
+
46
+ export function runReal(fx: RestoreFx): {
47
+ request: RestoreRequestV1;
48
+ reader: RestoreReader;
49
+ result: RestoreResultV1;
50
+ verification: ReturnType<typeof verifyRestored>;
51
+ } {
52
+ const { request, reader } = decodeFx(fx);
53
+ const result = restoreSources(request, reader);
54
+ return { request, reader, result, verification: verifyRestored(result, request) };
55
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * vector-cortex/heal/closure-metrics.ts — VC6A closure proof metrics + handoff.
3
+ *
4
+ * Pure read-only derivations over a `ClosureProofV2`: traversal savings (the
5
+ * sprint's >=20% median acceptance bar) and the `RestoreHintV1` list VC6B
6
+ * consumes. Extracted from `closure-opt.ts` (delegate-shell) to keep the core
7
+ * reduction algorithm under the 300-line soft limit.
8
+ *
9
+ * PURE / DETERMINISTIC / LOCAL: no storage, no clock, no network (PREVENT-PI-004
10
+ * / PREVENT-011). Identity only — never source bytes or prompt text
11
+ * (SECURITY_PRIVACY).
12
+ */
13
+
14
+ import type { ClosureGraph } from "../reconstruct/types.js";
15
+ import type { ClosureProofV2, RestoreHintV1, RetainReason } from "./types.js";
16
+
17
+ /** Bytewise id comparator — matches `closure-opt.ts` / `reconstruct/closure.ts`. */
18
+ function byBytes(a: string, b: string): number {
19
+ return a < b ? -1 : a > b ? 1 : 0;
20
+ }
21
+
22
+ /** Anchor id set from a graph (matches `closure-opt.ts`). */
23
+ function anchorIds(graph: ClosureGraph): Set<string> {
24
+ return new Set(graph.nodes.filter((n) => n.anchor === true).map((n) => n.id));
25
+ }
26
+
27
+ /**
28
+ * Traversal savings as a fraction in [0,1]: how much of the conservative edge
29
+ * walk the optimized plan avoids. A plan with nothing to remove scores 0 (not a
30
+ * failure — a chain graph is already minimal). The sprint's acceptance bar is a
31
+ * >=20% MEDIAN over the corpus, never a per-graph floor.
32
+ */
33
+ export function traversalSavings(proof: ClosureProofV2): number {
34
+ if (proof.conservativeTraversals === 0) return 0;
35
+ const saved = proof.conservativeTraversals - proof.optimizedTraversals;
36
+ return saved / proof.conservativeTraversals;
37
+ }
38
+
39
+ /**
40
+ * Derive the `RestoreHintV1` list VC6B consumes (the sprint's declared handoff:
41
+ * "VC6B receives missing-source hints and proof").
42
+ *
43
+ * One hint per selected node that a RETAINED edge reaches, naming the cheapest
44
+ * (bytewise-first) retained prerequisite and whether the node is protected.
45
+ * Identity only — never source bytes or prompt text (SECURITY_PRIVACY).
46
+ */
47
+ export function restoreHints(proof: ClosureProofV2, graph: ClosureGraph): readonly RestoreHintV1[] {
48
+ const anchors = anchorIds(graph);
49
+ const best = new Map<string, { from: string; reason: RetainReason }>();
50
+ for (const row of proof.rows) {
51
+ if (row.decision !== "retained") continue;
52
+ const reason = row.reason as RetainReason;
53
+ const existing = best.get(row.to);
54
+ if (existing === undefined || byBytes(row.from, existing.from) < 0) {
55
+ best.set(row.to, { from: row.from, reason });
56
+ }
57
+ }
58
+ const hints: RestoreHintV1[] = [];
59
+ for (const nodeId of [...proof.selected].sort(byBytes)) {
60
+ const hit = best.get(nodeId);
61
+ const isToolPair = proof.retainedEdges.some(
62
+ (e) => e.kind === "tool-pair" && (e.from === nodeId || e.to === nodeId),
63
+ );
64
+ hints.push({
65
+ schema: "restore-hint-v1",
66
+ nodeId,
67
+ viaEdgeFrom: hit?.from,
68
+ protectedNode: anchors.has(nodeId) || isToolPair,
69
+ reason: hit?.reason ?? (anchors.has(nodeId) ? "anchor" : "no-alternate-path"),
70
+ });
71
+ }
72
+ return hints;
73
+ }