pi-mega-compact 0.17.0 → 0.17.1

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 (99) hide show
  1. package/dist/config/vector-cortex.js +10 -0
  2. package/dist/dedup/digest.js +30 -0
  3. package/dist/dedup/l1-lsh-v2.js +60 -0
  4. package/dist/dedup/l1-lsh.js +52 -0
  5. package/dist/dedup/l1-minhash-v2.js +193 -0
  6. package/dist/dedup/l1-minhash.js +91 -0
  7. package/dist/dedup/l1-verify.js +54 -0
  8. package/dist/dedup/mmr.js +45 -0
  9. package/dist/dedup/normalize.js +39 -0
  10. package/dist/dedup/raptor/buildHistory.js +164 -0
  11. package/dist/dedup/raptor/guardrails.js +83 -0
  12. package/dist/dedup/raptor/incremental.js +304 -0
  13. package/dist/dedup/raptor/index.js +190 -0
  14. package/dist/dedup/raptor/kmeans.js +152 -0
  15. package/dist/dedup/raptor/multilevel.js +184 -0
  16. package/dist/dedup/raptor/retrieval.js +93 -0
  17. package/dist/dedup/raptor/summarizer.js +86 -0
  18. package/dist/dedup/raptor/tree.js +202 -0
  19. package/dist/dedup/topk.js +60 -0
  20. package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +1 -0
  21. package/dist/src/config/vector-cortex.js +10 -0
  22. package/dist/src/config.js +1 -1
  23. package/dist/src/dedup/l1-lsh-v2.js +60 -0
  24. package/dist/src/dedup/l1-minhash-v2.js +193 -0
  25. package/dist/src/dedup/normalize.js +1 -1
  26. package/dist/src/vector-cortex/conformance/emit.js +46 -0
  27. package/dist/src/vector-cortex/conformance/manifest.js +235 -0
  28. package/dist/src/vector-cortex/conformance/runner.js +111 -0
  29. package/dist/src/vector-cortex/conformance/triadB-reader.js +95 -0
  30. package/dist/src/vector-cortex/migrations/minhash-v2.js +209 -0
  31. package/dist/vector-cortex/conformance/emit.js +46 -0
  32. package/dist/vector-cortex/conformance/manifest.js +235 -0
  33. package/dist/vector-cortex/conformance/runner.js +111 -0
  34. package/dist/vector-cortex/conformance/triadB-reader.js +95 -0
  35. package/dist/vector-cortex/migrations/minhash-v2.js +209 -0
  36. package/extensions/dashboard-client/dist/assets/{AreaChart-CAnWomhw.js → AreaChart-BQXFF7UI.js} +2 -2
  37. package/extensions/dashboard-client/dist/assets/{AreaChart-CAnWomhw.js.map → AreaChart-BQXFF7UI.js.map} +1 -1
  38. package/extensions/dashboard-client/dist/assets/{BarChart-lZ2-s71k.js → BarChart-BVtoz9Eg.js} +2 -2
  39. package/extensions/dashboard-client/dist/assets/{BarChart-lZ2-s71k.js.map → BarChart-BVtoz9Eg.js.map} +1 -1
  40. package/extensions/dashboard-client/dist/assets/{CacheTab-BL2Thh66.js → CacheTab-trI2TIGy.js} +2 -2
  41. package/extensions/dashboard-client/dist/assets/{CacheTab-BL2Thh66.js.map → CacheTab-trI2TIGy.js.map} +1 -1
  42. package/extensions/dashboard-client/dist/assets/{EventsTab-DEh2Z9fp.js → EventsTab-CNUbk9__.js} +2 -2
  43. package/extensions/dashboard-client/dist/assets/{EventsTab-DEh2Z9fp.js.map → EventsTab-CNUbk9__.js.map} +1 -1
  44. package/extensions/dashboard-client/dist/assets/{HealthTab-DTwKclxk.js → HealthTab-K-bd_CM-.js} +2 -2
  45. package/extensions/dashboard-client/dist/assets/{HealthTab-DTwKclxk.js.map → HealthTab-K-bd_CM-.js.map} +1 -1
  46. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DDfBEdbX.js → MaintenanceTab-CoEioKzx.js} +2 -2
  47. package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DDfBEdbX.js.map → MaintenanceTab-CoEioKzx.js.map} +1 -1
  48. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-Dgfmg-0Q.js → MemoryMapTab-CJo24ulv.js} +2 -2
  49. package/extensions/dashboard-client/dist/assets/{MemoryMapTab-Dgfmg-0Q.js.map → MemoryMapTab-CJo24ulv.js.map} +1 -1
  50. package/extensions/dashboard-client/dist/assets/{MetricsTab-DOcMm0Tx.js → MetricsTab-DCNlQWWP.js} +2 -2
  51. package/extensions/dashboard-client/dist/assets/{MetricsTab-DOcMm0Tx.js.map → MetricsTab-DCNlQWWP.js.map} +1 -1
  52. package/extensions/dashboard-client/dist/assets/{OverviewTab-DHT5aoHg.js → OverviewTab-CQQlyIQ6.js} +2 -2
  53. package/extensions/dashboard-client/dist/assets/{OverviewTab-DHT5aoHg.js.map → OverviewTab-CQQlyIQ6.js.map} +1 -1
  54. package/extensions/dashboard-client/dist/assets/{ReposTab-CGAmtR_c.js → ReposTab-Cqm82_yn.js} +2 -2
  55. package/extensions/dashboard-client/dist/assets/{ReposTab-CGAmtR_c.js.map → ReposTab-Cqm82_yn.js.map} +1 -1
  56. package/extensions/dashboard-client/dist/assets/{SessionsTab-BIgx6iKT.js → SessionsTab-A8xTAdET.js} +2 -2
  57. package/extensions/dashboard-client/dist/assets/{SessionsTab-BIgx6iKT.js.map → SessionsTab-A8xTAdET.js.map} +1 -1
  58. package/extensions/dashboard-client/dist/assets/{SetupTab-ADghKuEI.js → SetupTab-CqaSgaZl.js} +2 -2
  59. package/extensions/dashboard-client/dist/assets/{SetupTab-ADghKuEI.js.map → SetupTab-CqaSgaZl.js.map} +1 -1
  60. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-C33UiiOM.js → TimeSavedCard-C_f3q8GR.js} +2 -2
  61. package/extensions/dashboard-client/dist/assets/{TimeSavedCard-C33UiiOM.js.map → TimeSavedCard-C_f3q8GR.js.map} +1 -1
  62. package/extensions/dashboard-client/dist/assets/{TurnsTab-DdbL9wPN.js → TurnsTab-BEsafACo.js} +2 -2
  63. package/extensions/dashboard-client/dist/assets/{TurnsTab-DdbL9wPN.js.map → TurnsTab-BEsafACo.js.map} +1 -1
  64. package/extensions/dashboard-client/dist/assets/VectorCortexTab-DD1CMK80.js +2 -0
  65. package/extensions/dashboard-client/dist/assets/VectorCortexTab-DD1CMK80.js.map +1 -0
  66. package/extensions/dashboard-client/dist/assets/{WikiTab-Ch00OFKs.js → WikiTab-Bf01M2_Z.js} +2 -2
  67. package/extensions/dashboard-client/dist/assets/{WikiTab-Ch00OFKs.js.map → WikiTab-Bf01M2_Z.js.map} +1 -1
  68. package/extensions/dashboard-client/dist/assets/{button-ByeEdo2g.js → button-BEJPTk_E.js} +2 -2
  69. package/extensions/dashboard-client/dist/assets/{button-ByeEdo2g.js.map → button-BEJPTk_E.js.map} +1 -1
  70. package/extensions/dashboard-client/dist/assets/{card-DesoLXvc.js → card-DK1V382s.js} +2 -2
  71. package/extensions/dashboard-client/dist/assets/{card-DesoLXvc.js.map → card-DK1V382s.js.map} +1 -1
  72. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-CCAB7Iz4.js → generateCategoricalChart-CRtaPphL.js} +2 -2
  73. package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-CCAB7Iz4.js.map → generateCategoricalChart-CRtaPphL.js.map} +1 -1
  74. package/extensions/dashboard-client/dist/assets/{index-B6cgyAPr.js → index-CB6BslE4.js} +3 -3
  75. package/extensions/dashboard-client/dist/assets/{index-B6cgyAPr.js.map → index-CB6BslE4.js.map} +1 -1
  76. package/extensions/dashboard-client/dist/assets/{switch-DIZC-oe-.js → switch-C4FV6B9k.js} +2 -2
  77. package/extensions/dashboard-client/dist/assets/{switch-DIZC-oe-.js.map → switch-C4FV6B9k.js.map} +1 -1
  78. package/extensions/dashboard-client/dist/assets/{toggle-CIoWaH2e.js → toggle-GBmeENMd.js} +2 -2
  79. package/extensions/dashboard-client/dist/assets/{toggle-CIoWaH2e.js.map → toggle-GBmeENMd.js.map} +1 -1
  80. package/extensions/dashboard-client/dist/assets/{useSSE-Bv4943l1.js → useSSE-BOKZGSn1.js} +2 -2
  81. package/extensions/dashboard-client/dist/assets/{useSSE-Bv4943l1.js.map → useSSE-BOKZGSn1.js.map} +1 -1
  82. package/extensions/dashboard-client/dist/index.html +1 -1
  83. package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +1 -1
  84. package/extensions/dashboard-client/tsconfig.json +1 -1
  85. package/extensions/dashboard-server/routes-rag-settings-helpers.ts +6 -0
  86. package/package.json +1 -1
  87. package/src/config/vector-cortex.ts +11 -0
  88. package/src/config.ts +1 -0
  89. package/src/dedup/l1-lsh-v2.ts +78 -0
  90. package/src/dedup/l1-minhash-v2.ts +221 -0
  91. package/src/dedup/normalize.ts +1 -1
  92. package/src/store/sqlite/game-scores.ts +2 -1
  93. package/src/vector-cortex/conformance/emit.ts +56 -0
  94. package/src/vector-cortex/conformance/manifest.ts +298 -0
  95. package/src/vector-cortex/conformance/runner.ts +165 -0
  96. package/src/vector-cortex/conformance/triadB-reader.ts +110 -0
  97. package/src/vector-cortex/migrations/minhash-v2.ts +263 -0
  98. package/extensions/dashboard-client/dist/assets/VectorCortexTab-Cl1pbEdR.js +0 -2
  99. package/extensions/dashboard-client/dist/assets/VectorCortexTab-Cl1pbEdR.js.map +0 -1
@@ -0,0 +1,165 @@
1
+ /**
2
+ * vector-cortex/conformance/runner.ts — v2 conformance runner (VC1C).
3
+ *
4
+ * Dispatches a conformance case STRICTLY by domain/version (no inference, no
5
+ * partial output on unknown) and compares both the canonical success bytes and
6
+ * the expected failure code. Owns `DowngradeReport`.
7
+ *
8
+ * The runner is triad-shaped (mode A client):
9
+ * A = this manifest runner over the real algorithms;
10
+ * B = an independent exact fixture reader (invertible digest recheck);
11
+ * C = reject any unknown domain/version WITHOUT partial output.
12
+ *
13
+ * Downgrade export: `exporter` produces a new legacy copy that never edits
14
+ * authority data; the resulting `DowngradeReport` is deterministic — a second
15
+ * run yields a byte-identical report digest (CONF-DOWN-003).
16
+ *
17
+ * No network, no side effects on authority (PREVENT-PI-004 / PREVENT-011).
18
+ */
19
+
20
+ import { CONF_FAIL, type FixtureManifestEntry } from "./manifest.js";
21
+ import {
22
+ createConformanceReporter,
23
+ type ConformanceReporter,
24
+ } from "./emit.js";
25
+
26
+ /** A registered conformance algorithm handler for a (domain, tuple) key. */
27
+ export interface ConformanceHandler {
28
+ /**
29
+ * Run the case. `fixture` is the raw parsed fixture object. Returns ok with a
30
+ * canonical output digest (the success bytes), or a failure code.
31
+ */
32
+ run(
33
+ entry: FixtureManifestEntry,
34
+ fixture: unknown,
35
+ ): { ok: true; outputBytes: Uint8Array; outputDigest: string } | { ok: false; code: string };
36
+ }
37
+
38
+ /**
39
+ * The deterministic downgrade-export report. `reportDigest` is a SHA-256 over
40
+ * the canonical JSON of the report body, so a repeated export is byte-identical.
41
+ */
42
+ export interface DowngradeReport {
43
+ readonly schema: "downgrade-report-v1";
44
+ readonly exportedCopyId: string;
45
+ readonly copiedCount: number;
46
+ readonly unrepresentableIds: readonly string[];
47
+ readonly reportDigest: string;
48
+ }
49
+
50
+ /** A minimal exporter: produces a new legacy copy and its deterministic report. */
51
+ export interface DowngradeExporter {
52
+ /** Run the export once. Must never edit the authority data it reads. */
53
+ exportOnce(): DowngradeReport;
54
+ }
55
+
56
+ /**
57
+ * Result of dispatching a conformance case: success bytes (mode A/B) or the
58
+ * exact expected failure code (mode C rejects unknown without partial output).
59
+ */
60
+ export type CaseResult =
61
+ | { ok: true; outputDigest: string; algorithm: string }
62
+ | { ok: false; code: string; algorithm: string };
63
+
64
+ const UNKNOWN_DOMAIN = "CONF_UNKNOWN_DOMAIN";
65
+ const UNKNOWN_VERSION = "CONF_UNKNOWN_VERSION";
66
+ /**
67
+ * The runner-pinned expectation mismatch code: a dispatched handler returned an
68
+ * outcome that contradicts the manifest entry's frozen expectation (the wrong
69
+ * failure code, or a success/failure parity error). This is the runner's own
70
+ * cross-check (task 5: "compare both success bytes and expected failure code"),
71
+ * distinct from the domain's own failure codes.
72
+ */
73
+ const EXPECTATION_MISMATCH = "CONF_EXPECTATION_MISMATCH";
74
+
75
+ export { UNKNOWN_DOMAIN, UNKNOWN_VERSION, EXPECTATION_MISMATCH };
76
+
77
+ /**
78
+ * Run one conformance case by dispatching strictly on `(domain, algorithmTuple)`.
79
+ * If no handler is registered for the exact domain/algorithms, returns
80
+ * `CONF_UNKNOWN_DOMAIN`/`CONF_UNKNOWN_VERSION` WITHOUT partial output.
81
+ *
82
+ * After dispatch the runner cross-checks the handler's outcome against the
83
+ * manifest entry's frozen expectation (task 5):
84
+ * - failure expected (`entry.failureCode` set): the handler must return
85
+ * `ok:false` with that exact code, else `CONF_EXPECTATION_MISMATCH`;
86
+ * - success expected (`entry.expected === "ok"`): the handler must return
87
+ * `ok:true`, and when the manifest pins an `expectedOutputDigest` the
88
+ * handler's `outputDigest` must match it, else `CONF_DIGEST_DRIFT`.
89
+ */
90
+ export function runConformanceCase(
91
+ entry: FixtureManifestEntry,
92
+ handlers: ReadonlyMap<string, ConformanceHandler>,
93
+ fixture: unknown,
94
+ reporter: ConformanceReporter = createConformanceReporter(),
95
+ ): CaseResult {
96
+ const key = `${entry.domain}::${entry.algorithmTuple.join(";")}`;
97
+ const handler = handlers.get(key);
98
+ let result: CaseResult;
99
+ if (!handler) {
100
+ if (entry.domain === "") {
101
+ result = { ok: false, code: UNKNOWN_DOMAIN, algorithm: entry.algorithm };
102
+ } else {
103
+ result = { ok: false, code: UNKNOWN_VERSION, algorithm: entry.algorithm };
104
+ }
105
+ } else {
106
+ const out = handler.run(entry, fixture);
107
+ if (out.ok) {
108
+ // Success expected? The manifest entry pins the expected success bytes.
109
+ if (entry.expected !== "ok") {
110
+ result = { ok: false, code: EXPECTATION_MISMATCH, algorithm: entry.algorithm };
111
+ } else if (
112
+ entry.expectedOutputDigest !== undefined &&
113
+ out.outputDigest !== entry.expectedOutputDigest
114
+ ) {
115
+ result = { ok: false, code: CONF_FAIL.DIGEST_DRIFT, algorithm: entry.algorithm };
116
+ } else {
117
+ result = { ok: true, outputDigest: out.outputDigest, algorithm: entry.algorithm };
118
+ }
119
+ } else {
120
+ // Failure expected? The manifest entry pins the exact failure code.
121
+ if (entry.failureCode !== undefined && out.code === entry.failureCode) {
122
+ result = { ok: false, code: out.code, algorithm: entry.algorithm };
123
+ } else {
124
+ result = { ok: false, code: EXPECTATION_MISMATCH, algorithm: entry.algorithm };
125
+ }
126
+ }
127
+ }
128
+ reporter.caseChecked({
129
+ id: entry.id,
130
+ domain: entry.domain,
131
+ algorithm: entry.algorithm,
132
+ ok: result.ok,
133
+ ...(result.ok ? { outputDigest: result.outputDigest } : { code: result.code }),
134
+ });
135
+ return result;
136
+ }
137
+
138
+ /**
139
+ * Build a dispatch key for a (domain, algorithmTuple) pair. Callers register
140
+ * handlers under this key.
141
+ */
142
+ export function handlerKey(
143
+ domain: string,
144
+ algorithmTuple: readonly string[],
145
+ ): string {
146
+ return `${domain}::${algorithmTuple.join(";")}`;
147
+ }
148
+
149
+ /**
150
+ * Run a downgrade export and recompute its report digest deterministically.
151
+ * A second invocation produces a byte-identical report (CONF-DOWN-003).
152
+ */
153
+ export function runDowngradeExport(
154
+ exporter: DowngradeExporter,
155
+ reporter: ConformanceReporter = createConformanceReporter(),
156
+ ): DowngradeReport {
157
+ const report = exporter.exportOnce();
158
+ reporter.downgradeWritten({
159
+ exportedCopyId: report.exportedCopyId,
160
+ copiedCount: report.copiedCount,
161
+ unrepresentableIds: report.unrepresentableIds,
162
+ reportDigest: report.reportDigest,
163
+ });
164
+ return report;
165
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * conformance/triadB-reader.ts — TRIAD-B independent exact reader (VC1C).
3
+ *
4
+ * Deliberately shares NO code and NO cached-seed instance with the runner
5
+ * modules (l1-minhash-v2.ts / l1-lsh-v2.ts). It re-derives the minhash-v2
6
+ * signature and 64 bucket keys from first principles, using only the PUBLISHED
7
+ * (a,b) seed pairs passed in (read by the caller from
8
+ * conformance/.../minhash/seeds-v2.json — the table authored independently by
9
+ * scripts/gen-fixtures/minhash.mjs, the same process that produced the frozen
10
+ * fixture bytes). Because B shares no subroutine with the runner, a systematic
11
+ * error in the runner's splitmix64 / seed-derivation / signature arithmetic
12
+ * cannot satisfy both triad A and triad B.
13
+ *
14
+ * Pure compute, no deps, no storage, no network (PREVENT-PI-004 / PREVENT-011).
15
+ */
16
+
17
+ import { createHash } from "node:crypto";
18
+
19
+ const MASK64 = 0xffffffffffffffffn;
20
+ const P = (1n << 61n) - 1n; // 2^61 - 1
21
+ const SLOTS = 256;
22
+ const U64 = 8;
23
+ const BANDS = 64;
24
+
25
+ /** A published (a, b) seed pair as decimal strings (exactness beyond 2^53). */
26
+ export interface PublishedSeedPair {
27
+ readonly a: string;
28
+ readonly b: string;
29
+ }
30
+
31
+ /** 64-bit FNV-1a over UTF-8 bytes or a raw byte buffer (own, independent loop). */
32
+ function fnv1a64(input: string | Uint8Array): bigint {
33
+ let h = 0xcbf29ce484222325n;
34
+ for (const b of Buffer.from(input)) {
35
+ h = ((h ^ BigInt(b)) * 0x100000001b3n) & MASK64;
36
+ }
37
+ return h;
38
+ }
39
+
40
+ /**
41
+ * Re-derive the 2048-byte minhash-v2 signature and (optionally) the 64 LSH
42
+ * bucket keys for `text` within `session`, from published seed pairs only —
43
+ * never the runner module.
44
+ */
45
+ export function independentReaderV2(
46
+ text: string,
47
+ session: string,
48
+ seedPairs: readonly PublishedSeedPair[],
49
+ withBuckets: boolean,
50
+ ): { bytes: Uint8Array; digest: string; buckets: string[] } {
51
+ // Normalization: ANSI-strip, NFC, case-fold, CRLF->LF, whitespace collapse,
52
+ // 32K cap — mirrored from the frozen VC1C spec.
53
+ let norm = (text || "")
54
+ .replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "")
55
+ .normalize("NFC")
56
+ .toLowerCase()
57
+ .replace(/\r\n?/g, "\n")
58
+ .replace(/\s+/g, " ")
59
+ .trim();
60
+ if (norm.length > 32768) norm = norm.slice(0, 32768);
61
+
62
+ // Five-code-point shingles (deduped, capped at 50_000).
63
+ const grams: bigint[] = [];
64
+ if (norm.length > 0) {
65
+ const cps = Array.from(norm);
66
+ const seen = new Set<bigint>();
67
+ const short = cps.length < 5;
68
+ for (let i = 0; i < (short ? 1 : cps.length - 4); i++) {
69
+ const h = short ? fnv1a64(norm) : fnv1a64(cps.slice(i, i + 5).join(""));
70
+ if (!seen.has(h)) {
71
+ seen.add(h);
72
+ grams.push(h);
73
+ }
74
+ if (!short && seen.size >= 50000) break;
75
+ }
76
+ }
77
+
78
+ // Signature: slot i = min over shingles of (a_i*x + b_i) mod p (exact BigInt).
79
+ const sig = new Array<bigint>(SLOTS).fill(P);
80
+ for (let i = 0; i < SLOTS && grams.length > 0; i++) {
81
+ const pair = seedPairs[i] as PublishedSeedPair;
82
+ const a = BigInt(pair.a);
83
+ const b = BigInt(pair.b);
84
+ let min = P;
85
+ for (const x of grams) {
86
+ const h = (a * x + b) % P;
87
+ if (h < min) min = h;
88
+ }
89
+ sig[i] = min;
90
+ }
91
+
92
+ // Own 256 x u64 little-endian encoder.
93
+ const buf = Buffer.allocUnsafe(SLOTS * U64);
94
+ for (let i = 0; i < SLOTS; i++) buf.writeBigUInt64LE(sig[i] as bigint, i * U64);
95
+ const bytes = new Uint8Array(buf);
96
+ const digest = createHash("sha256").update(bytes).digest("hex");
97
+
98
+ // 64 buckets: FNV-1a over `<session>|v2|` + each 32-byte band (LE hex).
99
+ const buckets: string[] = [];
100
+ if (withBuckets) {
101
+ const prefix = Buffer.from(`${session}|v2|`, "utf8");
102
+ for (let band = 0; band < BANDS; band++) {
103
+ const bandBytes = Buffer.from(bytes.slice(band * 32, band * 32 + 32));
104
+ const out = Buffer.allocUnsafe(U64);
105
+ out.writeBigUInt64LE(fnv1a64(Buffer.concat([prefix, bandBytes])), 0);
106
+ buckets.push(`b${band}:${out.toString("hex")}`);
107
+ }
108
+ }
109
+ return { bytes, digest, buckets };
110
+ }
@@ -0,0 +1,263 @@
1
+ /**
2
+ * vector-cortex/migrations/minhash-v2.ts — M4 MinHashV2 copy/validate/switch
3
+ * migration (VC1C).
4
+ *
5
+ * M4 versions the L1 dedup signature store: v2 signatures/buckets are written
6
+ * BESIDE v1, backfilled by checkpoint id, verified, and only then switched as
7
+ * the active version. It follows the same copy/validate/switch + resume
8
+ * contract as M2 but for the minhash index:
9
+ *
10
+ * - batch: writes v2 signatures + buckets for a set of checkpoint IDs, each
11
+ * tagged with the frozen version 2; never touches v1 rows.
12
+ * - backfill: resumable by checkpoint id — an interrupted run resumes without
13
+ * duplicate v2 signatures or active-pointer drift.
14
+ * - verify: counts per checkpoint match v1 and every v2 digest re-hashes.
15
+ * - switch: atomically flips the ACTIVE VERSION pointer from v1 to v2; until
16
+ * a verified switch, v1 remains active (interruption keeps old authority).
17
+ *
18
+ * Cross-version compare is REJECTED: a mixed v1-v2 similarity/bucket query
19
+ * returns `MINHASH_VERSION_MISMATCH` (never compares v1/v2 signatures).
20
+ *
21
+ * Pure logic over an injected M4Host (deterministic + testable; no console).
22
+ * PREVENT-002/011/PI-004 honored.
23
+ */
24
+
25
+ import { createHash } from "node:crypto";
26
+ import {
27
+ MINHASH_VERSION,
28
+ minhashV2Signature,
29
+ encodeSignatureV2,
30
+ } from "../../dedup/l1-minhash-v2.js";
31
+ import {
32
+ lshBandsV2,
33
+ BANDS_V2,
34
+ SIGNATURE_BYTES_EXPECTED_V2,
35
+ } from "../../dedup/l1-lsh-v2.js";
36
+ import {
37
+ createConformanceReporter,
38
+ type ConformanceReporter,
39
+ } from "../conformance/emit.js";
40
+
41
+ /** M4 failure codes. */
42
+ export const M4_FAIL = {
43
+ VERSION_MISMATCH: "MINHASH_VERSION_MISMATCH",
44
+ BACKFILL_PARTIAL: "M4_BACKFILL_PARTIAL",
45
+ COUNT_MISMATCH: "M4_COUNT_MISMATCH",
46
+ DIGEST_MISMATCH: "M4_DIGEST_MISMATCH",
47
+ } as const;
48
+ export type M4MigrationCode = (typeof M4_FAIL)[keyof typeof M4_FAIL];
49
+
50
+ /** A v2 signature row stored beside v1 (keyed by checkpoint id). */
51
+ export interface V2SignatureRow {
52
+ readonly checkpointId: string;
53
+ readonly sessionId: string;
54
+ readonly version: number; // MINHASH_VERSION
55
+ readonly signatureBytes: Uint8Array; // 2048 LE bytes
56
+ readonly digest: string; // sha256: over signatureBytes
57
+ readonly buckets: readonly string[]; // 64 band keys
58
+ }
59
+
60
+ /** The host the migration reads from / writes to (capability-shaped). */
61
+ export interface M4Host {
62
+ /** Full set of v1 checkpoint ids the index should cover. */
63
+ readonly v1CheckpointIds: () => readonly string[];
64
+ /** Session id a checkpoint belongs to (for bucket scoping). */
65
+ readonly sessionOf: (checkpointId: string) => string;
66
+ /** The raw source text for a checkpoint (to recompute a v2 signature). */
67
+ readonly sourceOf: (checkpointId: string) => string;
68
+ /** Persisted v2 rows already written (for resume/dedup + active pointer). */
69
+ readonly storedV2: () => readonly V2SignatureRow[];
70
+ /** The currently ACTIVE version (1 until a verified switch). */
71
+ readonly activeVersion: () => number;
72
+ /** Idempotent write of v2 rows (never mutates v1 rows). */
73
+ readonly putV2: (rows: readonly V2SignatureRow[]) => void;
74
+ /** Atomically switch the active version pointer to v2. */
75
+ readonly switchToV2: () => void;
76
+ }
77
+
78
+ /** An M4 migration failure result. */
79
+ export interface M4ValidateResult {
80
+ readonly ok: boolean;
81
+ readonly codes: readonly M4MigrationCode[];
82
+ }
83
+
84
+ /** Reject a cross-version compare. Returns the frozen mismatch code. */
85
+ export function crossVersionError(): M4MigrationCode {
86
+ return M4_FAIL.VERSION_MISMATCH;
87
+ }
88
+
89
+ /**
90
+ * Compute v2 signature + buckets for one checkpoint (the authoritative bytes).
91
+ * Pure and cross-language deterministic.
92
+ */
93
+ export function computeV2Row(host: M4Host, checkpointId: string): V2SignatureRow {
94
+ const sessionId = host.sessionOf(checkpointId);
95
+ const source = host.sourceOf(checkpointId);
96
+ const sig = minhashV2Signature(source);
97
+ const bytes = encodeSignatureV2(sig);
98
+ const buckets = lshBandsV2(new Uint8Array(bytes), sessionId);
99
+ return {
100
+ checkpointId,
101
+ sessionId,
102
+ version: MINHASH_VERSION,
103
+ signatureBytes: new Uint8Array(bytes),
104
+ digest: `sha256:${sha256Hex(bytes)}`,
105
+ buckets,
106
+ };
107
+ }
108
+
109
+ function sha256Hex(bytes: Uint8Array): string {
110
+ return createHash("sha256").update(bytes).digest("hex");
111
+ }
112
+
113
+ /**
114
+ * Backfill v2 signatures/buckets for all v1 checkpoint ids (resumable): rows
115
+ * already persisted with matching v2 digest/version are left untouched (no
116
+ * duplicates), and the active pointer stays at v1 until a verified switch.
117
+ * Returns the rows written this call (delta), never duplicates.
118
+ *
119
+ * An EXISTING row is re-computed and digest-verified before it is skipped; if
120
+ * the persisted row is corrupt (wrong version, wrong length, or a digest that
121
+ * no longer re-hashes its signatureBytes — e.g. a crash mid-write that left a
122
+ * truncated/bad row for an already-present id), it is recomputed and rewritten
123
+ * so corruption self-heals instead of being frozen by a later `m4Verify` failure.
124
+ */
125
+ export function m4Backfill(
126
+ host: M4Host,
127
+ reporter: ConformanceReporter = createConformanceReporter(),
128
+ ): readonly V2SignatureRow[] {
129
+ const wanted = host.v1CheckpointIds();
130
+ const existing = new Map(host.storedV2().map((r) => [r.checkpointId, r]));
131
+ const writes: V2SignatureRow[] = [];
132
+ for (const id of wanted) {
133
+ const row = computeV2Row(host, id);
134
+ const stored = existing.get(id);
135
+ if (stored !== undefined && v2RowMatches(stored, row)) continue; // healthy, no dup
136
+ writes.push(row); // absent, or stored row is corrupt -> (re)compute authoritative bytes
137
+ }
138
+ if (writes.length > 0) {
139
+ host.putV2(writes);
140
+ reporter.backfilled({
141
+ written: writes.length,
142
+ checkpointIds: writes.map((r) => r.checkpointId),
143
+ });
144
+ }
145
+ return writes;
146
+ }
147
+
148
+ /** True when a persisted row already matches the authoritative recompute. */
149
+ function v2RowMatches(stored: V2SignatureRow, fresh: V2SignatureRow): boolean {
150
+ return (
151
+ stored.version === MINHASH_VERSION &&
152
+ stored.checkpointId === fresh.checkpointId &&
153
+ stored.sessionId === fresh.sessionId &&
154
+ stored.signatureBytes.length === fresh.signatureBytes.length &&
155
+ stored.digest === fresh.digest &&
156
+ bucketsMatch(stored)
157
+ );
158
+ }
159
+
160
+ /**
161
+ * Re-derive the 64 bucket keys from the row's signatureBytes + sessionId and
162
+ * compare every value to the stored buckets. This closes a defensive
163
+ * verification gap: a persisted row whose signatureBytes + digest are correct
164
+ * but whose bucket VALUES were written wrong (a writer defect, or a partial
165
+ * bucket write that still held 64 entries) would otherwise pass digest+count
166
+ * checks and be treated as healthy — yet the buckets are exactly the data the
167
+ * live LSH-dedup path queries. Buckets are deterministic from sigBytes +
168
+ * sessionId, so a mismatch is always a real storage/author defect.
169
+ */
170
+ function bucketsMatch(row: V2SignatureRow): boolean {
171
+ // A wrong-length signature can't be banded (lshBandsV2 throws); the caller
172
+ // already reports it as a count/version mismatch, so fail closed here too.
173
+ if (row.signatureBytes.length !== SIGNATURE_BYTES_EXPECTED_V2) return false;
174
+ if (row.buckets.length !== BANDS_V2) return false;
175
+ const expected = lshBandsV2(new Uint8Array(row.signatureBytes), row.sessionId);
176
+ for (let i = 0; i < BANDS_V2; i++) {
177
+ if ((expected[i] as string) !== (row.buckets[i] as string)) return false;
178
+ }
179
+ return true;
180
+ }
181
+
182
+ /**
183
+ * Verify the backfilled v2 index: every v1 checkpoint has exactly one v2 row
184
+ * (reset -> resumable partial counts), each stored row's digest re-hashes, and
185
+ * each row has all 64 buckets. Never mutates.
186
+ */
187
+ export function m4Verify(host: M4Host): M4ValidateResult {
188
+ const codes: M4MigrationCode[] = [];
189
+ const wanted = new Set(host.v1CheckpointIds());
190
+ const stored = host.storedV2();
191
+ const counts = new Map<string, number>();
192
+ for (const r of stored) {
193
+ counts.set(r.checkpointId, (counts.get(r.checkpointId) ?? 0) + 1);
194
+ if (r.version !== MINHASH_VERSION) codes.push(M4_FAIL.VERSION_MISMATCH);
195
+ if (r.signatureBytes.length !== 2048) codes.push(M4_FAIL.COUNT_MISMATCH);
196
+ if (r.buckets.length !== BANDS_V2) codes.push(M4_FAIL.COUNT_MISMATCH);
197
+ if (r.digest !== `sha256:${sha256Hex(r.signatureBytes)}`) {
198
+ codes.push(M4_FAIL.DIGEST_MISMATCH);
199
+ }
200
+ // Bucket VALUE verification: re-derive all 64 keys from signatureBytes +
201
+ // sessionId and compare them. Digest + count alone would let a row with
202
+ // correct sigBytes/digest but wrong bucket values pass; the buckets are the
203
+ // data the live LSH-dedup path queries, so a drifts here is a real defect.
204
+ if (!bucketsMatch(r)) codes.push(M4_FAIL.COUNT_MISMATCH);
205
+ }
206
+ // Every v1 checkpoint backfilled exactly once (count parity, no dup rows).
207
+ for (const id of wanted) {
208
+ const c = counts.get(id) ?? 0;
209
+ if (c === 0) codes.push(M4_FAIL.BACKFILL_PARTIAL);
210
+ if (c > 1) codes.push(M4_FAIL.COUNT_MISMATCH);
211
+ }
212
+ // No orphan v2 rows without a v1 checkpoint.
213
+ for (const id of counts.keys()) {
214
+ if (!wanted.has(id)) codes.push(M4_FAIL.COUNT_MISMATCH);
215
+ }
216
+ const ok = codes.length === 0;
217
+ return { ok, codes: dedupe(codes) };
218
+ }
219
+
220
+ /**
221
+ * Switch the active version to v2. Only call after `m4Verify` reports ok; a
222
+ * crash/return before switch leaves v1 active (interruption keeps old
223
+ * authority, resumable idempotently).
224
+ */
225
+ export function m4Switch(host: M4Host): void {
226
+ host.switchToV2();
227
+ }
228
+
229
+ /** Full M4 lifecycle: backfill -> verify -> switch; returns verify result. */
230
+ export function migrateMinhashV2(
231
+ host: M4Host,
232
+ reporter: ConformanceReporter = createConformanceReporter(),
233
+ ): M4ValidateResult {
234
+ m4Backfill(host, reporter);
235
+ const v = m4Verify(host);
236
+ if (v.ok) m4Switch(host);
237
+ return v;
238
+ }
239
+
240
+ /** Registered M4 conformance ID range (M4-001..008 + named M4-*). */
241
+ export const M4_IDS = [
242
+ "M4-001",
243
+ "M4-002",
244
+ "M4-003",
245
+ "M4-004",
246
+ "M4-005",
247
+ "M4-006",
248
+ "M4-007",
249
+ "M4-008",
250
+ ] as const;
251
+
252
+ /** Registered named M4 conformance IDs. */
253
+ export const M4_NAMED = [
254
+ "M4-HIGHBIT-001",
255
+ "M4-VERSION-002",
256
+ "M4-RESUME-003",
257
+ ] as const;
258
+
259
+ function dedupe(codes: M4MigrationCode[]): M4MigrationCode[] {
260
+ const out: M4MigrationCode[] = [];
261
+ for (const c of codes) if (!out.includes(c)) out.push(c);
262
+ return out;
263
+ }
@@ -1,2 +0,0 @@
1
- import{r as n,j as e,B as o}from"./index-B6cgyAPr.js";import{C as d,a as i,b as x,c as h}from"./card-DesoLXvc.js";async function k(){const s=await fetch("/api/vector-cortex/evaluation");if(!s.ok)throw new Error(`vector-cortex evaluation: ${s.status}`);return s.json()}async function N(){const s=await fetch("/api/vector-cortex/health");if(!s.ok)throw new Error(`vector-cortex health: ${s.status}`);return s.json()}async function $(s="default"){const r=await fetch(`/api/vector-cortex/ledger?session=${encodeURIComponent(s)}`);if(!r.ok)throw new Error(`vector-cortex ledger: ${r.status}`);return r.json()}async function V(s){const r=await fetch("/api/vector-cortex/breakers/reset",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({subsystem:s})});if(!r.ok)throw new Error(`vector-cortex reset: ${r.status}`);return r.json()}function u({mode:s,count:r}){return e.jsxs("div",{className:"flex items-center justify-between border-b border-border/50 py-1 text-sm",children:[e.jsxs("span",{className:"text-muted-foreground",children:["Mode ",s]}),e.jsx("span",{className:"font-mono",children:r})]})}function l({label:s,value:r}){return e.jsxs("div",{children:[e.jsx("div",{className:"text-xs text-muted-foreground",children:s}),e.jsx("div",{className:"font-mono text-sm",children:r})]})}function I(){const[s,r]=n.useState(null),[j,y]=n.useState(null),[C,w]=n.useState(!0),[a,f]=n.useState(null),[v,g]=n.useState(null),[c,E]=n.useState(null),m=n.useCallback(()=>{k().then(r).catch(t=>y(t instanceof Error?t.message:String(t))).finally(()=>w(!1)),N().then(f).catch(()=>{}),$().then(E).catch(()=>{})},[]);n.useEffect(()=>{m();const t=setInterval(m,5e3);return()=>clearInterval(t)},[m]);const S=()=>{V("provider").then(t=>(g(`Breaker "${t.subsystem}" ${t.state}; evidence retained: ${t.failures} failures / ${t.attempts} attempts`),N())).then(f).catch(t=>g(t instanceof Error?t.message:String(t)))};if(C&&!s)return e.jsx("div",{className:"vc-loading",children:"Loading vector-cortex evaluation…"});if(j&&!s)return e.jsxs("div",{className:"vc-error",children:["Error: ",j]});if(!s)return e.jsx("div",{className:"vc-empty",children:"No evaluation data available."});const p=Math.max(1,...s.histogram.cells,s.histogram.overflow);return e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h2",{className:"text-lg font-semibold",children:"Vector Cortex Evaluation"}),s.enabled?e.jsx(o,{variant:"success",children:"OBSERVER ACTIVE (A)"}):e.jsx(o,{variant:"danger",children:"MODE C (OFF)"})]}),e.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-3",children:[e.jsxs(d,{children:[e.jsx(i,{children:e.jsx(x,{children:"Samples"})}),e.jsxs(h,{children:[e.jsx("div",{className:"text-3xl font-bold",children:s.samples}),e.jsxs("div",{className:"mt-2 flex flex-col",children:[e.jsx(u,{mode:"A",count:s.byMode.A}),e.jsx(u,{mode:"B",count:s.byMode.B}),e.jsx(u,{mode:"C",count:s.byMode.C})]})]})]}),e.jsxs(d,{className:"md:col-span-2",children:[e.jsx(i,{children:e.jsx(x,{children:"Latency Histogram (ms, inclusive edges)"})}),e.jsxs(h,{children:[e.jsxs("div",{className:"flex items-end gap-2",style:{height:160},children:[s.histogram.edges.map((t,b)=>{const M=s.histogram.cells[b]/p*140;return e.jsxs("div",{className:"flex flex-1 flex-col items-center gap-1",children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:s.histogram.cells[b]}),e.jsx("div",{className:"w-full rounded-t",style:{height:Math.max(2,M),background:"#6366f1"}}),e.jsxs("span",{className:"text-[10px] text-muted-foreground",children:["≤",t]})]},t)}),e.jsxs("div",{className:"flex flex-1 flex-col items-center gap-1",children:[e.jsx("span",{className:"text-xs text-muted-foreground",children:s.histogram.overflow}),e.jsx("div",{className:"w-full rounded-t",style:{height:Math.max(2,s.histogram.overflow/p*140),background:"#f87171"}}),e.jsx("span",{className:"text-[10px] text-muted-foreground",children:">250"})]})]}),e.jsxs("div",{className:"mt-1 text-xs text-muted-foreground",children:["Total: ",s.histogram.total," · Rejects: ",s.rejects.length]})]})]})]}),e.jsxs(d,{children:[e.jsx(i,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(x,{children:"Live Safety Envelope (VC0C)"}),e.jsxs("div",{className:"flex items-center gap-2",children:[a?.stateSource==="ephemeral"&&e.jsx(o,{variant:"outline",children:"EPHEMERAL (non-live)"}),e.jsx("button",{onClick:S,disabled:!a?.enabled,className:"rounded border border-border px-2 py-1 text-xs disabled:opacity-50",children:"Reset Cooldown"})]})]})}),e.jsxs(h,{children:[v&&e.jsx("div",{className:"mb-2 text-xs text-muted-foreground",children:v}),a?e.jsxs("div",{className:"grid grid-cols-2 gap-4 md:grid-cols-4",children:[e.jsx(l,{label:"State",value:a.state}),e.jsx(l,{label:"Mode",value:a.mode}),e.jsx(l,{label:"Window",value:`${a.windowMs}ms`}),e.jsx(l,{label:"Probes",value:String(a.probeCount)}),e.jsx(l,{label:"Backoff",value:`${a.backoffDelayMs}ms`}),e.jsx(l,{label:"Failures",value:`${a.failures}/${a.attempts}`}),e.jsx(l,{label:"Frontier",value:a.stateSource==="ephemeral"?"non-live":a.frontierFrozen?"FROZEN":"LIVE"}),e.jsx(l,{label:"Spool lag",value:String(a.spoolLag)})]}):e.jsx("div",{className:"vc-empty",children:"Health unavailable (VC0C off)."})]})]}),e.jsxs(d,{children:[e.jsx(i,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(x,{children:"Occurrence Ledger (VC1B)"}),c?.enabled?e.jsx(o,{variant:"success",children:"ACTIVE"}):e.jsx(o,{variant:"danger",children:"OFF"})]})}),e.jsx(h,{children:c?.enabled?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-3 grid grid-cols-2 gap-4 md:grid-cols-3",children:[e.jsx(l,{label:"Session",value:c.session}),e.jsx(l,{label:"High-water",value:c.highWater}),e.jsx(l,{label:"Occurrences",value:String(c.count)})]}),c.occurrences.length===0?e.jsx("div",{className:"vc-empty",children:"No occurrences recorded."}):e.jsx("div",{className:"max-h-64 overflow-y-auto",children:e.jsxs("table",{className:"w-full text-left text-xs",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-border/50 text-muted-foreground",children:[e.jsx("th",{className:"py-1 pr-2",children:"seq"}),e.jsx("th",{className:"py-1 pr-2",children:"eventId"}),e.jsx("th",{className:"py-1 pr-2",children:"kind"}),e.jsx("th",{className:"py-1 pr-2",children:"toolCall"}),e.jsx("th",{className:"py-1",children:"digest"})]})}),e.jsx("tbody",{children:c.occurrences.map(t=>e.jsxs("tr",{className:"border-b border-border/30",children:[e.jsx("td",{className:"py-1 pr-2 font-mono",children:t.seq}),e.jsx("td",{className:"py-1 pr-2 font-mono",children:t.eventId}),e.jsx("td",{className:"py-1 pr-2",children:t.kind}),e.jsx("td",{className:"py-1 pr-2 font-mono",children:t.toolCallId??"—"}),e.jsx("td",{className:"max-w-[180px] truncate font-mono text-muted-foreground",children:t.digest})]},`${t.seq}-${t.eventId}`))})]})})]}):e.jsx("div",{className:"vc-empty",children:"Ledger disabled (VC1B off)."})})]})]})}export{I as default};
2
- //# sourceMappingURL=VectorCortexTab-Cl1pbEdR.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"VectorCortexTab-Cl1pbEdR.js","sources":["../../src/api/vector-cortex.ts","../../src/tabs/VectorCortexTab.tsx"],"sourcesContent":["/**\n * dashboard-client/src/api/vector-cortex.ts — vector-cortex API client.\n * PREVENT-PI-004: relative path only (loopback dashboard).\n */\n\nimport type {\n\tVectorCortexEvaluationSummary,\n\tVectorCortexHealthCard,\n\tVectorCortexLedgerView,\n\tVectorCortexResetResult,\n} from \"../types/vector-cortex\";\n\nexport type {\n\tVectorCortexEvaluationSummary,\n\tVectorCortexHealthCard,\n\tVectorCortexLedgerView,\n\tVectorCortexResetResult,\n};\n\nexport async function fetchVectorCortexEvaluation(): Promise<VectorCortexEvaluationSummary> {\n\tconst r = await fetch(\"/api/vector-cortex/evaluation\");\n\tif (!r.ok) throw new Error(`vector-cortex evaluation: ${r.status}`);\n\treturn r.json() as Promise<VectorCortexEvaluationSummary>;\n}\n\nexport async function fetchVectorCortexHealth(): Promise<VectorCortexHealthCard> {\n\tconst r = await fetch(\"/api/vector-cortex/health\");\n\tif (!r.ok) throw new Error(`vector-cortex health: ${r.status}`);\n\treturn r.json() as Promise<VectorCortexHealthCard>;\n}\n\n/** Reader-only occurrence-ledger identity view (VC1B). */\nexport async function fetchVectorCortexLedger(\n\tsession = \"default\",\n): Promise<VectorCortexLedgerView> {\n\tconst r = await fetch(\n\t\t`/api/vector-cortex/ledger?session=${encodeURIComponent(session)}`,\n\t);\n\tif (!r.ok) throw new Error(`vector-cortex ledger: ${r.status}`);\n\treturn r.json() as Promise<VectorCortexLedgerView>;\n}\n\n/** Admin capability: reset a breaker's cooldown (never evidence). */\nexport async function resetVectorCortexBreaker(\n\tsubsystem: string,\n): Promise<VectorCortexResetResult> {\n\tconst r = await fetch(\"/api/vector-cortex/breakers/reset\", {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\tbody: JSON.stringify({ subsystem }),\n\t});\n\tif (!r.ok) throw new Error(`vector-cortex reset: ${r.status}`);\n\treturn r.json() as Promise<VectorCortexResetResult>;\n}\n","/**\n * VectorCortexTab.tsx — vector-cortex dashboard tab.\n * VC0A: reader-only aggregate latency histogram + per-mode sample counts from\n * GET /api/vector-cortex/evaluation. VC0C (task 5): live safety envelope health\n * card (breaker state, window/probe/backoff, durable spool frontier/lag) from\n * GET /api/vector-cortex/health plus an admin \"reset cooldown\" action. Polls\n * every 5s.\n */\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport {\n\tfetchVectorCortexEvaluation,\n\tfetchVectorCortexHealth,\n\tfetchVectorCortexLedger,\n\tresetVectorCortexBreaker,\n\ttype VectorCortexEvaluationSummary,\n\ttype VectorCortexHealthCard,\n\ttype VectorCortexLedgerView,\n} from \"../api/vector-cortex\";\nimport { Card, CardContent, CardHeader, CardTitle } from \"../components/ui/card\";\nimport { Badge } from \"../components/ui/badge\";\n\nfunction ModeChip({ mode, count }: { mode: string; count: number }): React.ReactElement {\n\treturn (\n\t\t<div className=\"flex items-center justify-between border-b border-border/50 py-1 text-sm\">\n\t\t\t<span className=\"text-muted-foreground\">Mode {mode}</span>\n\t\t\t<span className=\"font-mono\">{count}</span>\n\t\t</div>\n\t);\n}\n\nfunction Metric({ label, value }: { label: string; value: string }): React.ReactElement {\n\treturn (\n\t\t<div>\n\t\t\t<div className=\"text-xs text-muted-foreground\">{label}</div>\n\t\t\t<div className=\"font-mono text-sm\">{value}</div>\n\t\t</div>\n\t);\n}\n\nexport default function VectorCortexTab(): React.ReactElement {\n\tconst [data, setData] = useState<VectorCortexEvaluationSummary | null>(null);\n\tconst [err, setError] = useState<string | null>(null);\n\tconst [loading, setLoading] = useState(true);\n\tconst [health, setHealth] = useState<VectorCortexHealthCard | null>(null);\n\tconst [resetMsg, setResetMsg] = useState<string | null>(null);\n\tconst [ledger, setLedger] = useState<VectorCortexLedgerView | null>(null);\n\n\tconst poll = useCallback(() => {\n\t\tfetchVectorCortexEvaluation()\n\t\t\t.then(setData)\n\t\t\t.catch((e: unknown) =>\n\t\t\t\tsetError(e instanceof Error ? e.message : String(e)),\n\t\t\t)\n\t\t\t.finally(() => setLoading(false));\n\t\tfetchVectorCortexHealth().then(setHealth).catch(() => {\n\t\t\t/* health card is best-effort (VC0C) */\n\t\t});\n\t\tfetchVectorCortexLedger().then(setLedger).catch(() => {\n\t\t\t/* ledger card is best-effort (VC1B) */\n\t\t});\n\t}, []);\n\n\tuseEffect(() => {\n\t\tpoll();\n\t\tconst id = setInterval(poll, 5000);\n\t\treturn () => clearInterval(id);\n\t}, [poll]);\n\n\tconst onReset = () => {\n\t\tresetVectorCortexBreaker(\"provider\")\n\t\t\t.then((r) => {\n\t\t\t\tsetResetMsg(\n\t\t\t\t\t`Breaker \"${r.subsystem}\" ${r.state}; evidence retained: ${r.failures} failures / ${r.attempts} attempts`,\n\t\t\t\t);\n\t\t\t\treturn fetchVectorCortexHealth();\n\t\t\t})\n\t\t\t.then(setHealth)\n\t\t\t.catch((e: unknown) =>\n\t\t\t\tsetResetMsg(e instanceof Error ? e.message : String(e)),\n\t\t\t);\n\t};\n\n\tif (loading && !data)\n\t\treturn <div className=\"vc-loading\">Loading vector-cortex evaluation…</div>;\n\tif (err && !data)\n\t\treturn <div className=\"vc-error\">Error: {err}</div>;\n\tif (!data)\n\t\treturn <div className=\"vc-empty\">No evaluation data available.</div>;\n\n\tconst max = Math.max(1, ...data.histogram.cells, data.histogram.overflow);\n\treturn (\n\t\t<div className=\"flex flex-col gap-4\">\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<h2 className=\"text-lg font-semibold\">Vector Cortex Evaluation</h2>\n\t\t\t\t{data.enabled ? (\n\t\t\t\t\t<Badge variant=\"success\">OBSERVER ACTIVE (A)</Badge>\n\t\t\t\t) : (\n\t\t\t\t\t<Badge variant=\"danger\">MODE C (OFF)</Badge>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t<div className=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n\t\t\t\t<Card>\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<CardTitle>Samples</CardTitle>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<CardContent>\n\t\t\t\t\t\t<div className=\"text-3xl font-bold\">{data.samples}</div>\n\t\t\t\t\t\t<div className=\"mt-2 flex flex-col\">\n\t\t\t\t\t\t\t<ModeChip mode=\"A\" count={data.byMode.A} />\n\t\t\t\t\t\t\t<ModeChip mode=\"B\" count={data.byMode.B} />\n\t\t\t\t\t\t\t<ModeChip mode=\"C\" count={data.byMode.C} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardContent>\n\t\t\t\t</Card>\n\n\t\t\t\t<Card className=\"md:col-span-2\">\n\t\t\t\t\t<CardHeader>\n\t\t\t\t\t\t<CardTitle>Latency Histogram (ms, inclusive edges)</CardTitle>\n\t\t\t\t\t</CardHeader>\n\t\t\t\t\t<CardContent>\n\t\t\t\t\t\t<div className=\"flex items-end gap-2\" style={{ height: 160 }}>\n\t\t\t\t\t\t\t{data.histogram.edges.map((edge, i) => {\n\t\t\t\t\t\t\t\tconst h = (data.histogram.cells[i] / max) * 140;\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div key={edge} className=\"flex flex-1 flex-col items-center gap-1\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t{data.histogram.cells[i]}\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"w-full rounded-t\"\n\t\t\t\t\t\t\t\t\t\t\tstyle={{ height: Math.max(2, h), background: \"#6366f1\" }}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t<span className=\"text-[10px] text-muted-foreground\">&le;{edge}</span>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t<div className=\"flex flex-1 flex-col items-center gap-1\">\n\t\t\t\t\t\t\t\t<span className=\"text-xs text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{data.histogram.overflow}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclassName=\"w-full rounded-t\"\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\theight: Math.max(2, (data.histogram.overflow / max) * 140),\n\t\t\t\t\t\t\t\t\t\tbackground: \"#f87171\",\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<span className=\"text-[10px] text-muted-foreground\">&gt;250</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"mt-1 text-xs text-muted-foreground\">\n\t\t\t\t\t\t\tTotal: {data.histogram.total} · Rejects: {data.rejects.length}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</CardContent>\n\t\t\t\t</Card>\n\t\t\t</div>\n\n\t\t\t<Card>\n\t\t\t\t<CardHeader>\n\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t<CardTitle>Live Safety Envelope (VC0C)</CardTitle>\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t{health?.stateSource === \"ephemeral\" && (\n\t\t\t\t\t\t\t\t<Badge variant=\"outline\">EPHEMERAL (non-live)</Badge>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tonClick={onReset}\n\t\t\t\t\t\t\t\tdisabled={!health?.enabled}\n\t\t\t\t\t\t\t\tclassName=\"rounded border border-border px-2 py-1 text-xs disabled:opacity-50\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tReset Cooldown\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</CardHeader>\n\t\t\t\t<CardContent>\n\t\t\t\t\t{resetMsg && (\n\t\t\t\t\t\t<div className=\"mb-2 text-xs text-muted-foreground\">{resetMsg}</div>\n\t\t\t\t\t)}\n\t\t\t\t\t{!health ? (\n\t\t\t\t\t\t<div className=\"vc-empty\">Health unavailable (VC0C off).</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"grid grid-cols-2 gap-4 md:grid-cols-4\">\n\t\t\t\t\t\t\t<Metric label=\"State\" value={health.state} />\n\t\t\t\t\t\t\t<Metric label=\"Mode\" value={health.mode} />\n\t\t\t\t\t\t\t<Metric label=\"Window\" value={`${health.windowMs}ms`} />\n\t\t\t\t\t\t\t<Metric label=\"Probes\" value={String(health.probeCount)} />\n\t\t\t\t\t\t\t<Metric label=\"Backoff\" value={`${health.backoffDelayMs}ms`} />\n\t\t\t\t\t\t\t<Metric\n\t\t\t\t\t\t\t\tlabel=\"Failures\"\n\t\t\t\t\t\t\t\tvalue={`${health.failures}/${health.attempts}`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Metric\n\t\t\t\t\t\t\t\tlabel=\"Frontier\"\n\t\t\t\t\t\t\t\tvalue={\n\t\t\t\t\t\t\t\t\thealth.stateSource === \"ephemeral\"\n\t\t\t\t\t\t\t\t\t\t? \"non-live\"\n\t\t\t\t\t\t\t\t\t\t: health.frontierFrozen\n\t\t\t\t\t\t\t\t\t\t\t? \"FROZEN\"\n\t\t\t\t\t\t\t\t\t\t\t: \"LIVE\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Metric label=\"Spool lag\" value={String(health.spoolLag)} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</CardContent>\n\t\t\t</Card>\n\t\t\t<Card>\n\t\t\t\t<CardHeader>\n\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t<CardTitle>Occurrence Ledger (VC1B)</CardTitle>\n\t\t\t\t\t\t{ledger?.enabled ? (\n\t\t\t\t\t\t\t<Badge variant=\"success\">ACTIVE</Badge>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Badge variant=\"danger\">OFF</Badge>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t</CardHeader>\n\t\t\t\t<CardContent>\n\t\t\t\t\t{!ledger?.enabled ? (\n\t\t\t\t\t\t<div className=\"vc-empty\">Ledger disabled (VC1B off).</div>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div className=\"mb-3 grid grid-cols-2 gap-4 md:grid-cols-3\">\n\t\t\t\t\t\t\t\t<Metric label=\"Session\" value={ledger.session} />\n\t\t\t\t\t\t\t\t<Metric label=\"High-water\" value={ledger.highWater} />\n\t\t\t\t\t\t\t\t<Metric label=\"Occurrences\" value={String(ledger.count)} />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{ledger.occurrences.length === 0 ? (\n\t\t\t\t\t\t\t\t<div className=\"vc-empty\">No occurrences recorded.</div>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<div className=\"max-h-64 overflow-y-auto\">\n\t\t\t\t\t\t\t\t\t<table className=\"w-full text-left text-xs\">\n\t\t\t\t\t\t\t\t\t\t<thead>\n\t\t\t\t\t\t\t\t\t\t\t<tr className=\"border-b border-border/50 text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t<th className=\"py-1 pr-2\">seq</th>\n\t\t\t\t\t\t\t\t\t\t\t\t<th className=\"py-1 pr-2\">eventId</th>\n\t\t\t\t\t\t\t\t\t\t\t\t<th className=\"py-1 pr-2\">kind</th>\n\t\t\t\t\t\t\t\t\t\t\t\t<th className=\"py-1 pr-2\">toolCall</th>\n\t\t\t\t\t\t\t\t\t\t\t\t<th className=\"py-1\">digest</th>\n\t\t\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t\t\t</thead>\n\t\t\t\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t\t\t\t{ledger.occurrences.map((o) => (\n\t\t\t\t\t\t\t\t\t\t\t\t<tr\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={`${o.seq}-${o.eventId}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"border-b border-border/30\"\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<td className=\"py-1 pr-2 font-mono\">{o.seq}</td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<td className=\"py-1 pr-2 font-mono\">{o.eventId}</td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<td className=\"py-1 pr-2\">{o.kind}</td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<td className=\"py-1 pr-2 font-mono\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{o.toolCallId ?? \"\\u2014\"}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<td className=\"max-w-[180px] truncate font-mono text-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{o.digest}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</CardContent>\n\t\t\t</Card>\n\t\t</div>\n\t);\n}\n"],"names":["fetchVectorCortexEvaluation","r","fetchVectorCortexHealth","fetchVectorCortexLedger","session","resetVectorCortexBreaker","subsystem","ModeChip","mode","count","jsxs","jsx","Metric","label","value","VectorCortexTab","data","setData","useState","err","setError","loading","setLoading","health","setHealth","resetMsg","setResetMsg","ledger","setLedger","poll","useCallback","e","useEffect","id","onReset","max","Badge","Card","CardHeader","CardTitle","CardContent","edge","i","h","Fragment","o"],"mappings":"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"}