pi-mega-compact 0.16.2 → 0.17.0
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.
- package/dist/config/vector-cortex.js +81 -0
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry-ext.js +30 -0
- package/dist/extensions/dashboard-server/api-contracts/endpoints/registry.js +4 -14
- package/dist/extensions/dashboard-server/api-contracts/vector-cortex.js +12 -0
- package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +10 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex.js +292 -0
- package/dist/extensions/dashboard-server/routes.js +1 -0
- package/dist/extensions/dashboard-server/server.js +9 -1
- package/dist/extensions/mega-events/context-handler.js +11 -0
- package/dist/extensions/mega-runtime/vector-cortex-ledger.js +131 -0
- package/dist/extensions/mega-runtime/vector-cortex-safety.js +100 -0
- package/dist/src/config/vector-cortex.js +81 -0
- package/dist/src/config.js +6 -0
- package/dist/src/httpEmbedder.js +136 -1
- package/dist/src/vector-cortex/eval/annotations.js +41 -0
- package/dist/src/vector-cortex/eval/metrics.js +86 -0
- package/dist/src/vector-cortex/eval/observer.js +61 -0
- package/dist/src/vector-cortex/eval/persist.js +67 -0
- package/dist/src/vector-cortex/eval/reader.js +29 -0
- package/dist/src/vector-cortex/eval/types.js +33 -0
- package/dist/src/vector-cortex/ledger/adapter.js +55 -0
- package/dist/src/vector-cortex/ledger/compat-journal.js +206 -0
- package/dist/src/vector-cortex/ledger/emit.js +53 -0
- package/dist/src/vector-cortex/ledger/event-codec.js +72 -0
- package/dist/src/vector-cortex/ledger/event-codecB.js +76 -0
- package/dist/src/vector-cortex/ledger/sqlite.js +200 -0
- package/dist/src/vector-cortex/ledger/store.js +184 -0
- package/dist/src/vector-cortex/ledger/types.js +52 -0
- package/dist/src/vector-cortex/ledger/validator.js +117 -0
- package/dist/src/vector-cortex/migrations/effective-cut-v2.js +103 -0
- package/dist/src/vector-cortex/migrations/occurrence-v2.js +139 -0
- package/dist/src/vector-cortex/replay/cut.js +123 -0
- package/dist/src/vector-cortex/replay/emit.js +58 -0
- package/dist/src/vector-cortex/replay/replay.js +260 -0
- package/dist/src/vector-cortex/replay/replayB.js +73 -0
- package/dist/src/vector-cortex/replay/types.js +52 -0
- package/dist/src/vector-cortex/resilience/breaker-core.js +359 -0
- package/dist/src/vector-cortex/resilience/breaker.js +12 -0
- package/dist/src/vector-cortex/resilience/emit.js +56 -0
- package/dist/src/vector-cortex/resilience/spool-core.js +347 -0
- package/dist/src/vector-cortex/resilience/spool.js +12 -0
- package/dist/src/vector-cortex/resilience/types.js +32 -0
- package/dist/vector-cortex/eval/annotations.js +41 -0
- package/dist/vector-cortex/eval/metrics.js +86 -0
- package/dist/vector-cortex/eval/observer.js +61 -0
- package/dist/vector-cortex/eval/persist.js +67 -0
- package/dist/vector-cortex/eval/reader.js +29 -0
- package/dist/vector-cortex/eval/types.js +33 -0
- package/dist/vector-cortex/ledger/adapter.js +55 -0
- package/dist/vector-cortex/ledger/compat-journal.js +206 -0
- package/dist/vector-cortex/ledger/emit.js +53 -0
- package/dist/vector-cortex/ledger/event-codec.js +72 -0
- package/dist/vector-cortex/ledger/event-codecB.js +76 -0
- package/dist/vector-cortex/ledger/sqlite.js +200 -0
- package/dist/vector-cortex/ledger/store.js +184 -0
- package/dist/vector-cortex/ledger/types.js +52 -0
- package/dist/vector-cortex/ledger/validator.js +117 -0
- package/dist/vector-cortex/migrations/effective-cut-v2.js +103 -0
- package/dist/vector-cortex/migrations/occurrence-v2.js +139 -0
- package/dist/vector-cortex/replay/cut.js +123 -0
- package/dist/vector-cortex/replay/emit.js +58 -0
- package/dist/vector-cortex/replay/replay.js +260 -0
- package/dist/vector-cortex/replay/replayB.js +73 -0
- package/dist/vector-cortex/replay/types.js +52 -0
- package/dist/vector-cortex/resilience/breaker-core.js +359 -0
- package/dist/vector-cortex/resilience/breaker.js +12 -0
- package/dist/vector-cortex/resilience/emit.js +56 -0
- package/dist/vector-cortex/resilience/spool-core.js +347 -0
- package/dist/vector-cortex/resilience/spool.js +12 -0
- package/dist/vector-cortex/resilience/types.js +32 -0
- package/extensions/dashboard-client/dist/assets/{AreaChart-Y_X0Bbjd.js → AreaChart-CAnWomhw.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-Y_X0Bbjd.js.map → AreaChart-CAnWomhw.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-B9XDb-Ob.js → BarChart-lZ2-s71k.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-B9XDb-Ob.js.map → BarChart-lZ2-s71k.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-BUGVb1G1.js → CacheTab-BL2Thh66.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-BUGVb1G1.js.map → CacheTab-BL2Thh66.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-dOqLYTsy.js → EventsTab-DEh2Z9fp.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-dOqLYTsy.js.map → EventsTab-DEh2Z9fp.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-c2vezKg1.js → HealthTab-DTwKclxk.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-c2vezKg1.js.map → HealthTab-DTwKclxk.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-bQYHIcdx.js → MaintenanceTab-DDfBEdbX.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-bQYHIcdx.js.map → MaintenanceTab-DDfBEdbX.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-2L8pH6y2.js → MemoryMapTab-Dgfmg-0Q.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-2L8pH6y2.js.map → MemoryMapTab-Dgfmg-0Q.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-CzUx1jpo.js → MetricsTab-DOcMm0Tx.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-CzUx1jpo.js.map → MetricsTab-DOcMm0Tx.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-eCNoaclv.js → OverviewTab-DHT5aoHg.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-eCNoaclv.js.map → OverviewTab-DHT5aoHg.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-tb0IW3NF.js → ReposTab-CGAmtR_c.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-tb0IW3NF.js.map → ReposTab-CGAmtR_c.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-C-IoLw5h.js → SessionsTab-BIgx6iKT.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-C-IoLw5h.js.map → SessionsTab-BIgx6iKT.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-BvmFi8gf.js → SetupTab-ADghKuEI.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-BvmFi8gf.js.map → SetupTab-ADghKuEI.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-DBH-cOlA.js → TimeSavedCard-C33UiiOM.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-DBH-cOlA.js.map → TimeSavedCard-C33UiiOM.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-DBMgmvnX.js → TurnsTab-DdbL9wPN.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-DBMgmvnX.js.map → TurnsTab-DdbL9wPN.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-Cl1pbEdR.js +2 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-Cl1pbEdR.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{WikiTab-1LcQrXk3.js → WikiTab-Ch00OFKs.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-1LcQrXk3.js.map → WikiTab-Ch00OFKs.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-DtEsZTUE.js → button-ByeEdo2g.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-DtEsZTUE.js.map → button-ByeEdo2g.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-DcfTmw-4.js → card-DesoLXvc.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-DcfTmw-4.js.map → card-DesoLXvc.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-BsIxUDyw.js → generateCategoricalChart-CCAB7Iz4.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-BsIxUDyw.js.map → generateCategoricalChart-CCAB7Iz4.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-B93cewiX.js → index-B6cgyAPr.js} +34 -29
- package/extensions/dashboard-client/dist/assets/index-B6cgyAPr.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/index-CfvziyBi.css +1 -0
- package/extensions/dashboard-client/dist/assets/{switch-Bowd7jCD.js → switch-DIZC-oe-.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-Bowd7jCD.js.map → switch-DIZC-oe-.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-Bo7kJZ4u.js → toggle-CIoWaH2e.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-Bo7kJZ4u.js.map → toggle-CIoWaH2e.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-zNhb0c3u.js → useSSE-Bv4943l1.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-zNhb0c3u.js.map → useSSE-Bv4943l1.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +2 -2
- package/extensions/dashboard-client/src/App.tsx +2 -0
- package/extensions/dashboard-client/src/api/vector-cortex.ts +54 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +272 -0
- package/extensions/dashboard-client/src/tabs/registry.ts +4 -1
- package/extensions/dashboard-client/src/types/vector-cortex.ts +84 -0
- package/extensions/dashboard-server/api-contracts/endpoints/registry-ext.ts +67 -0
- package/extensions/dashboard-server/api-contracts/endpoints/registry.ts +4 -21
- package/extensions/dashboard-server/api-contracts/index.ts +3 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex.ts +136 -0
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +35 -0
- package/extensions/dashboard-server/routes-vector-cortex.ts +332 -0
- package/extensions/dashboard-server/routes.ts +6 -0
- package/extensions/dashboard-server/server.ts +8 -0
- package/extensions/mega-events/context-handler.ts +16 -0
- package/extensions/mega-runtime/vector-cortex-ledger.ts +165 -0
- package/extensions/mega-runtime/vector-cortex-safety.ts +181 -0
- package/package.json +2 -1
- package/src/config/vector-cortex.ts +87 -0
- package/src/config.ts +27 -0
- package/src/httpEmbedder.ts +134 -1
- package/src/vector-cortex/eval/annotations.ts +70 -0
- package/src/vector-cortex/eval/metrics.ts +113 -0
- package/src/vector-cortex/eval/observer.ts +86 -0
- package/src/vector-cortex/eval/persist.ts +73 -0
- package/src/vector-cortex/eval/reader.ts +45 -0
- package/src/vector-cortex/eval/types.ts +89 -0
- package/src/vector-cortex/ledger/adapter.ts +71 -0
- package/src/vector-cortex/ledger/compat-journal.ts +234 -0
- package/src/vector-cortex/ledger/emit.ts +86 -0
- package/src/vector-cortex/ledger/event-codec.ts +79 -0
- package/src/vector-cortex/ledger/event-codecB.ts +87 -0
- package/src/vector-cortex/ledger/sqlite.ts +265 -0
- package/src/vector-cortex/ledger/store.ts +380 -0
- package/src/vector-cortex/ledger/types.ts +141 -0
- package/src/vector-cortex/ledger/validator.ts +124 -0
- package/src/vector-cortex/migrations/effective-cut-v2.ts +149 -0
- package/src/vector-cortex/migrations/occurrence-v2.ts +192 -0
- package/src/vector-cortex/replay/cut.ts +169 -0
- package/src/vector-cortex/replay/emit.ts +89 -0
- package/src/vector-cortex/replay/replay.ts +308 -0
- package/src/vector-cortex/replay/replayB.ts +97 -0
- package/src/vector-cortex/replay/types.ts +145 -0
- package/src/vector-cortex/resilience/breaker-core.ts +444 -0
- package/src/vector-cortex/resilience/breaker.ts +22 -0
- package/src/vector-cortex/resilience/emit.ts +99 -0
- package/src/vector-cortex/resilience/spool-core.ts +411 -0
- package/src/vector-cortex/resilience/spool.ts +22 -0
- package/src/vector-cortex/resilience/types.ts +158 -0
- package/extensions/dashboard-client/dist/assets/index-B93cewiX.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-C_tCbOI0.css +0 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/vector-cortex.ts — vector-cortex feature flags + breaker/triad constants.
|
|
3
|
+
*
|
|
4
|
+
* Every sprint ships one positive `MEGACOMPACT_<SPRINT>` flag, default ON and
|
|
5
|
+
* `=0`/`_DISABLED` off. Flag-OFF is byte-identical to the predecessor sprint's
|
|
6
|
+
* behavior (for VC0A: mode C — observer absent, zero evaluation writes).
|
|
7
|
+
*
|
|
8
|
+
* The breaker/triad constants (TRIAD_RESILIENCE.md) live here so VC0C consumes
|
|
9
|
+
* them without re-declaring the ownership boundary. Pi-agnostic, dependency-free.
|
|
10
|
+
*/
|
|
11
|
+
/** Positive sprint flag: `=0` or `_DISABLED=true` disables (default ON). */
|
|
12
|
+
function sprintFlag(name) {
|
|
13
|
+
const v = process.env[name];
|
|
14
|
+
if (v === "0" || v === "false")
|
|
15
|
+
return false;
|
|
16
|
+
const disabled = process.env[name + "_DISABLED"];
|
|
17
|
+
if (disabled === "true" || disabled === "1")
|
|
18
|
+
return false;
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
/** VC0A — baseline observability (MetricEventV1 / AnnotationV1). Default ON. */
|
|
22
|
+
export const VC0A_ENABLED = () => sprintFlag("MEGACOMPACT_VC0A");
|
|
23
|
+
/**
|
|
24
|
+
* VC0B — replay correctness (ReplayCutV2 / ReplayReportV2, M3 effective-cut-v2).
|
|
25
|
+
* Default ON. `MEGACOMPACT_VC0B=0` disables and is byte-identical to the
|
|
26
|
+
* predecessor (legacy capped-replay behavior preserved; the v2 cut/replay is
|
|
27
|
+
* only consulted on the vector-cortex path).
|
|
28
|
+
*/
|
|
29
|
+
export const VC0B_ENABLED = () => sprintFlag("MEGACOMPACT_VC0B");
|
|
30
|
+
/**
|
|
31
|
+
* VC1A — canonical byte events (EventV2 / EventCodec).
|
|
32
|
+
* Default ON. `MEGACOMPACT_VC1A=0` disables and is byte-identical to the
|
|
33
|
+
* predecessor (mode C: ledger absent, current transcript codec unchanged).
|
|
34
|
+
* The single real consumer is the ledger emit seam (`ledger/emit.ts`): flag OFF
|
|
35
|
+
* gates zero observability writes.
|
|
36
|
+
*/
|
|
37
|
+
export const VC1A_ENABLED = () => sprintFlag("MEGACOMPACT_VC1A");
|
|
38
|
+
/**
|
|
39
|
+
* VC1B — occurrence ledger + tool identity + compat journal (LedgerReader/
|
|
40
|
+
* Writer/Admin, CompatJournalV1, M2 occurrence-v2 migration).
|
|
41
|
+
* Default ON. `MEGACOMPACT_VC1B=0` disables and is byte-identical to the
|
|
42
|
+
* predecessor (mode C: the neutral occurrence ledger is not written, no
|
|
43
|
+
* journal rows, zero `vector_cortex_occurrence_appended` emissions). The real
|
|
44
|
+
* consumers are the ledger write integration seam and the compat-journal
|
|
45
|
+
* switch seam.
|
|
46
|
+
*/
|
|
47
|
+
export const VC1B_ENABLED = () => sprintFlag("MEGACOMPACT_VC1B");
|
|
48
|
+
/**
|
|
49
|
+
* VC0C — live safety envelope (TriadResult / Breaker / KillDecision + durable
|
|
50
|
+
* spool). Default ON. `MEGACOMPACT_VC0C=0` disables and is byte-identical to
|
|
51
|
+
* the predecessor (mode C: selected before provider invocation, unchanged host
|
|
52
|
+
* transcript, breaker/spool idle and emitting nothing). The single real
|
|
53
|
+
* consumer is the resilience emit seam + the safety adapter's triad selection.
|
|
54
|
+
*/
|
|
55
|
+
export const VC0C_ENABLED = () => sprintFlag("MEGACOMPACT_VC0C");
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Breaker state machine constants (TRIAD_RESILIENCE.md §breaker).
|
|
58
|
+
// Rolled numbers for one 60s window; VC0C consumes these at its breaker seam.
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
/** Rolling eligibility window (milliseconds). */
|
|
61
|
+
export const BREAKER_WINDOW_MS = 60_000;
|
|
62
|
+
/** Minimum attempts before a breaker may trip or promote. */
|
|
63
|
+
export const BREAKER_MIN_ATTEMPTS = 20;
|
|
64
|
+
/** Performance trip: ≥ this many failures in window, or ≥ this fraction. */
|
|
65
|
+
export const BREAKER_PERF_FAILURES = 5;
|
|
66
|
+
export const BREAKER_PERF_FAILURE_RATE = 0.1;
|
|
67
|
+
/** Correctness trip trips on the first correctness failure. */
|
|
68
|
+
export const BREAKER_CORRECTNESS_FAILURES = 1;
|
|
69
|
+
/** Cooldown before an open breaker may probe (milliseconds). */
|
|
70
|
+
export const BREAKER_COOLDOWN_MS = 30_000;
|
|
71
|
+
/** Consecutive successful probes required to advance a state. */
|
|
72
|
+
export const BREAKER_PROBE_COUNT = 3;
|
|
73
|
+
/** Exponential retry base: 30s * 2^attempt, capped, ±10% jitter. */
|
|
74
|
+
export const BREAKER_RETRY_BASE_MS = 30_000;
|
|
75
|
+
export const BREAKER_RETRY_CAP_MS = 15 * 60_000;
|
|
76
|
+
export const BREAKER_RETRY_JITTER = 0.1;
|
|
77
|
+
/** Promotion hysteresis: failure rate must be < this and p95 within budget. */
|
|
78
|
+
export const BREAKER_HYSTERESIS_FAILURE_RATE = 0.02;
|
|
79
|
+
export const BREAKER_HYSTERESIS_BUDGET_P95_MS = 50;
|
|
80
|
+
/** Minimum healthy residence before a further promotion (milliseconds). */
|
|
81
|
+
export const BREAKER_MIN_HEALTHY_RESIDENCE_MS = 5 * 60_000;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Additive endpoint entries spread into the ENDPOINTS registry. */
|
|
2
|
+
export const EXTRA_ENDPOINTS = {
|
|
3
|
+
// ─── Per-model compaction thresholds (S52 / v0.16.1) ───────────────
|
|
4
|
+
/** GET /api/model-thresholds — List known models + their thresholds. */
|
|
5
|
+
modelThresholds: {
|
|
6
|
+
method: "GET",
|
|
7
|
+
path: "/api/model-thresholds",
|
|
8
|
+
description: "Every known model (from model_snapshots) with its per-model threshold override (or defaults).",
|
|
9
|
+
},
|
|
10
|
+
// ─── RAG Metrics (Sprint H2) ──────────────────────────────────────
|
|
11
|
+
/** GET /api/rag-metrics — HyDE + recall-quality telemetry aggregates. */
|
|
12
|
+
ragMetrics: {
|
|
13
|
+
method: "GET",
|
|
14
|
+
path: "/api/rag-metrics",
|
|
15
|
+
description: "HyDE invocation + recall-quality telemetry: flags, totals, recent turns, and daily series.",
|
|
16
|
+
},
|
|
17
|
+
// ─── Vector Cortex (VC0A) ────────────────────────────────────────
|
|
18
|
+
/** GET /api/vector-cortex/evaluation — reader-only eval aggregate (VC0A). */
|
|
19
|
+
vectorCortexEvaluation: {
|
|
20
|
+
method: "GET",
|
|
21
|
+
path: "/api/vector-cortex/evaluation",
|
|
22
|
+
description: "Reader-only vector-cortex evaluation summary: latency histogram + per-mode sample counts (never payloads).",
|
|
23
|
+
},
|
|
24
|
+
/** GET /api/vector-cortex/ledger — reader-only occurrence ledger view (VC1B). */
|
|
25
|
+
vectorCortexLedger: {
|
|
26
|
+
method: "GET",
|
|
27
|
+
path: "/api/vector-cortex/ledger",
|
|
28
|
+
description: "Reader-only occurrence-ledger identity view: seq/eventId/kind/digest + high-water (never source payloads).",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EXTRA_ENDPOINTS } from "./registry-ext.js";
|
|
1
2
|
// ─── ENDPOINTS Registry ─────────────────────────────────────────────────────
|
|
2
3
|
/**
|
|
3
4
|
* Central registry of all 14 dashboard API endpoints. Each entry is an
|
|
@@ -290,18 +291,7 @@ export const ENDPOINTS = {
|
|
|
290
291
|
path: "/api/rag-settings",
|
|
291
292
|
description: "Update RAG feature flag states by writing _DISABLED env vars to .mega-compact.env.",
|
|
292
293
|
},
|
|
293
|
-
// ───
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
method: "GET",
|
|
297
|
-
path: "/api/rag-metrics",
|
|
298
|
-
description: "HyDE invocation + recall-quality telemetry: flags, totals, recent turns, and daily series.",
|
|
299
|
-
},
|
|
300
|
-
// ─── Per-model compaction thresholds (S52 / v0.16.1) ───────────────
|
|
301
|
-
/** GET /api/model-thresholds — List known models + their thresholds. */
|
|
302
|
-
modelThresholds: {
|
|
303
|
-
method: "GET",
|
|
304
|
-
path: "/api/model-thresholds",
|
|
305
|
-
description: "Every known model (from model_snapshots) with its per-model threshold override (or defaults).",
|
|
306
|
-
},
|
|
294
|
+
// ─── Additive groups (rag-metrics, thresholds, vector-cortex) live in
|
|
295
|
+
// ─── registry-ext.ts so this registry stays under the 500-line limit.
|
|
296
|
+
...EXTRA_ENDPOINTS,
|
|
307
297
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api-contracts/vector-cortex.ts — vector-cortex dashboard API contracts.
|
|
3
|
+
*
|
|
4
|
+
* Owned by the vector-cortex sprints. VC0A ships only the reader-only aggregate
|
|
5
|
+
* `GET /api/vector-cortex/evaluation`. VC0C adds the breaker health endpoint
|
|
6
|
+
* and reset mutation into this SAME file — keep entries small and additive so
|
|
7
|
+
* the file stays within extension limits (400 soft / 500 hard).
|
|
8
|
+
*
|
|
9
|
+
* PREVENT-PI-004: type definitions only, no network code.
|
|
10
|
+
* PREVENT-011: no `any` type.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
@@ -129,6 +129,16 @@ export const SETTINGS = [
|
|
|
129
129
|
num("MEGACOMPACT_EMBED_CACHE", "Embed Cache Size", "Embedding cache entries (0 = disabled)", 256, 0, 10000),
|
|
130
130
|
],
|
|
131
131
|
},
|
|
132
|
+
{
|
|
133
|
+
name: "Vector Cortex",
|
|
134
|
+
settings: [
|
|
135
|
+
boolDirect("MEGACOMPACT_VC0A", "VC0A Baseline Observability", "Structured evaluation observer (MetricEventV1 + latency histogram). OFF = mode C, byte-identical to predecessor.", true),
|
|
136
|
+
boolDirect("MEGACOMPACT_VC0B", "VC0B Replay Correctness", "ReplayCutV2 effective-cut (min of boundary-safe/commit/capture high-water + pair retreat + anchor floor) and M3 effective-cut-v2 migration. OFF = legacy capped replay, byte-identical.", true),
|
|
137
|
+
boolDirect("MEGACOMPACT_VC1A", "VC1A Canonical Byte Events", "EventV2 byte-authority ledger codec (original bytes + SHA-256, strict UTF-8, derived NFC) and canonical validator (EVT_DIGEST_MISMATCH / EVT_UTF8_TAG_INVALID / EVT_DUPLICATE_ID). OFF = mode C, transcript codec unchanged, byte-identical.", true),
|
|
138
|
+
boolDirect("MEGACOMPACT_VC1B", "VC1B Occurrence Ledger + Tool Identity", "Neutral occurrence ledger (LedgerReader/Writer/Admin + CompatJournalV1): per-session monotonic seq, tool result references one earlier call, uniqueness by (eventId,digest) only, and the M2 copy-validate-switch downgrade journal. OFF = mode C, ledger unwritten, byte-identical.", true),
|
|
139
|
+
boolDirect("MEGACOMPACT_VC0C", "VC0C Live Safety Envelope", "TriadResult/Breaker live circuit breaker (60s window, 20 attempts, 30s cooldown, 3 probes, 5min healthy residence) + durable spool before provider invocation; manual reset clears cooldown but never evidence. OFF = mode C, unchanged transcript, byte-identical.", true),
|
|
140
|
+
],
|
|
141
|
+
},
|
|
132
142
|
{
|
|
133
143
|
name: "Cost API",
|
|
134
144
|
settings: [
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/routes-vector-cortex.ts — vector-cortex dashboard routes.
|
|
3
|
+
*
|
|
4
|
+
* VC0A ships a single reader-only GET /api/vector-cortex/evaluation that
|
|
5
|
+
* aggregates redacted evaluation rows (persisted JSONL under the state dir)
|
|
6
|
+
* via the reader. No writable capability — no reset/mutation here; VC0C adds
|
|
7
|
+
* breaker health + reset endpoints into this same file, keeping it additive
|
|
8
|
+
* and within extension limits.
|
|
9
|
+
*
|
|
10
|
+
* VC0C (task 5) adds:
|
|
11
|
+
* GET /api/vector-cortex/health — reader-only aggregate health card
|
|
12
|
+
* POST /api/vector-cortex/breakers/reset — explicit admin capability
|
|
13
|
+
*
|
|
14
|
+
* Guardrails: PREVENT-PI-004 (local filesystem read only), PREVENT-011 (no
|
|
15
|
+
* `any`), reader-only aggregate (never payloads/prompts/ledger — EVAL-REDACT-002).
|
|
16
|
+
*/
|
|
17
|
+
import { VC0A_ENABLED, VC0C_ENABLED, VC1B_ENABLED } from "../../src/config.js";
|
|
18
|
+
import { readEvalRows } from "../../src/vector-cortex/eval/persist.js";
|
|
19
|
+
import { summarizeEvalRows } from "../../src/vector-cortex/eval/reader.js";
|
|
20
|
+
import { createVectorCortexSafety } from "../mega-runtime/vector-cortex-safety.js";
|
|
21
|
+
import { createLedgerStore } from "../../src/vector-cortex/ledger/store.js";
|
|
22
|
+
/** Admin capability: an actor-supplied subsystem selector for breaker reset. */
|
|
23
|
+
function readJsonBody(req, cb) {
|
|
24
|
+
let body = "";
|
|
25
|
+
let tooBig = false;
|
|
26
|
+
req.on("data", (chunk) => {
|
|
27
|
+
if (body.length > 65536) {
|
|
28
|
+
tooBig = true;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
body += chunk.toString();
|
|
32
|
+
});
|
|
33
|
+
req.on("end", () => {
|
|
34
|
+
if (tooBig)
|
|
35
|
+
return cb({ ok: false, error: "body_too_large" });
|
|
36
|
+
try {
|
|
37
|
+
const v = body ? JSON.parse(body) : {};
|
|
38
|
+
if (typeof v !== "object" || v === null || Array.isArray(v)) {
|
|
39
|
+
return cb({ ok: false, error: "invalid_object" });
|
|
40
|
+
}
|
|
41
|
+
cb({ ok: true, value: v });
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
cb({ ok: false, error: "invalid_json" });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function sendJson(res, status, body) {
|
|
49
|
+
// guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
50
|
+
res.writeHead(status, { "Content-Type": "application/json" });
|
|
51
|
+
res.end(JSON.stringify(body));
|
|
52
|
+
}
|
|
53
|
+
/** Reader-only aggregate GET /api/vector-cortex/evaluation. */
|
|
54
|
+
export function handleVectorCortexEvaluation(req, res, ctx) {
|
|
55
|
+
const url = req.url ?? "";
|
|
56
|
+
if (url !== "/api/vector-cortex/evaluation")
|
|
57
|
+
return false;
|
|
58
|
+
if (req.method !== "GET") {
|
|
59
|
+
// Reader-only: no mutation endpoints exist on this path.
|
|
60
|
+
// guardrails-allow PREVENT-PI-004: loopback dashboard response (local)
|
|
61
|
+
res.writeHead(405, { "Content-Type": "application/json" });
|
|
62
|
+
res.end(JSON.stringify({ error: "method_not_allowed" }));
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
const enabled = VC0A_ENABLED();
|
|
66
|
+
const rows = enabled ? readEvalRows(ctx.stateDir) : [];
|
|
67
|
+
const summary = summarizeEvalRows(rows);
|
|
68
|
+
const body = {
|
|
69
|
+
enabled,
|
|
70
|
+
mode: enabled ? "A" : "C",
|
|
71
|
+
samples: summary.samples,
|
|
72
|
+
byMode: {
|
|
73
|
+
A: summary.byMode.A,
|
|
74
|
+
B: summary.byMode.B,
|
|
75
|
+
C: summary.byMode.C,
|
|
76
|
+
},
|
|
77
|
+
histogram: {
|
|
78
|
+
edges: [...summary.histogram.edges],
|
|
79
|
+
cells: [...summary.histogram.cells],
|
|
80
|
+
overflow: summary.histogram.overflow,
|
|
81
|
+
total: summary.histogram.total,
|
|
82
|
+
},
|
|
83
|
+
rejects: [], // VC0C wires live breaker/reject telemetry here
|
|
84
|
+
updatedAt: new Date().toISOString(),
|
|
85
|
+
};
|
|
86
|
+
sendJson(res, 200, body);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Reader-only GET /api/vector-cortex/health (VC0C).
|
|
91
|
+
*
|
|
92
|
+
* Aggregate health card: breaker state (window/probe/backoff), durable spool
|
|
93
|
+
* frontier/authority/lag, and a worst-state aggregate. Constructs the safety
|
|
94
|
+
* adapter over the state dir — durable spool state (frontier-frozen, lag) is
|
|
95
|
+
* read from disk, so it reflects restart. Purely read: no mutation, never
|
|
96
|
+
* payloads/prompts/ledger.
|
|
97
|
+
*/
|
|
98
|
+
export function handleVectorCortexHealth(req, res, ctx) {
|
|
99
|
+
const url = req.url ?? "";
|
|
100
|
+
if (url !== "/api/vector-cortex/health")
|
|
101
|
+
return false;
|
|
102
|
+
if (req.method !== "GET") {
|
|
103
|
+
// Reader-only path: no mutation endpoint lives at /health.
|
|
104
|
+
sendJson(res, 405, { error: "method_not_allowed" });
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
const enabled = VC0C_ENABLED();
|
|
108
|
+
const safety = enabled ? createVectorCortexSafety({ stateDir: ctx.stateDir }) : null;
|
|
109
|
+
const card = safety ? safety.health() : null;
|
|
110
|
+
const fallback = {
|
|
111
|
+
enabled: false,
|
|
112
|
+
mode: "C",
|
|
113
|
+
state: "CLOSED_A",
|
|
114
|
+
subsystem: "provider",
|
|
115
|
+
sinceMs: 0,
|
|
116
|
+
windowMs: 0,
|
|
117
|
+
probeCount: 0,
|
|
118
|
+
backoffDelayMs: 0,
|
|
119
|
+
frontierFrozen: false,
|
|
120
|
+
authorityOutage: false,
|
|
121
|
+
spoolLag: 0,
|
|
122
|
+
attempts: 0,
|
|
123
|
+
failures: 0,
|
|
124
|
+
p95Ms: 0,
|
|
125
|
+
failureRate: 0,
|
|
126
|
+
updatedAt: new Date().toISOString(),
|
|
127
|
+
aggregate: "CLOSED_A",
|
|
128
|
+
stateSource: "ephemeral",
|
|
129
|
+
};
|
|
130
|
+
if (!card) {
|
|
131
|
+
sendJson(res, 200, fallback);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
const mode = card.state === "CLOSED_A" ? "A" : card.state === "MANUAL_HALT" ? "C" : "B";
|
|
135
|
+
const aggregate = card.state === "MANUAL_HALT"
|
|
136
|
+
? "MANUAL_HALT"
|
|
137
|
+
: card.state === "OPEN_C"
|
|
138
|
+
? "OPEN_C"
|
|
139
|
+
: card.state === "OPEN_B"
|
|
140
|
+
? "OPEN_B"
|
|
141
|
+
: card.state === "PROBE_B" || card.state === "PROBE_A"
|
|
142
|
+
? "PROBE"
|
|
143
|
+
: "CLOSED_A";
|
|
144
|
+
const body = {
|
|
145
|
+
enabled,
|
|
146
|
+
mode,
|
|
147
|
+
state: card.state,
|
|
148
|
+
subsystem: card.subsystem,
|
|
149
|
+
sinceMs: card.sinceMs,
|
|
150
|
+
reason: card.reason,
|
|
151
|
+
windowMs: card.windowMs,
|
|
152
|
+
probeCount: card.probeCount,
|
|
153
|
+
backoffDelayMs: card.backoffDelayMs,
|
|
154
|
+
frontierFrozen: card.frontierFrozen,
|
|
155
|
+
authorityOutage: card.authorityOutage,
|
|
156
|
+
spoolLag: card.spoolLag,
|
|
157
|
+
attempts: card.attempts,
|
|
158
|
+
failures: card.failures,
|
|
159
|
+
p95Ms: card.p95Ms,
|
|
160
|
+
failureRate: card.failureRate,
|
|
161
|
+
updatedAt: new Date().toISOString(),
|
|
162
|
+
aggregate,
|
|
163
|
+
stateSource: card.stateSource,
|
|
164
|
+
};
|
|
165
|
+
sendJson(res, 200, body);
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Admin POST /api/vector-cortex/breakers/reset (VC0C).
|
|
170
|
+
*
|
|
171
|
+
* Explicit admin capability (separate from the reader GET). Clears a breaker's
|
|
172
|
+
* cooldown — or unwires a MANUAL_HALT — but NEVER evidence (attempts/failures
|
|
173
|
+
* are retained, per TRIAD_RESILIENCE). The subsystem is actor-supplied via the
|
|
174
|
+
* JSON body `{ subsystem }`. Every reset is documented in the returned record
|
|
175
|
+
* (state, retained evidence, updatedAt) — an auditable mutation surface; the
|
|
176
|
+
* GET path can never mutate.
|
|
177
|
+
*/
|
|
178
|
+
export function handleVectorCortexBreakersReset(req, res, ctx) {
|
|
179
|
+
const url = req.url ?? "";
|
|
180
|
+
if (url !== "/api/vector-cortex/breakers/reset")
|
|
181
|
+
return false;
|
|
182
|
+
if (req.method !== "POST") {
|
|
183
|
+
sendJson(res, 405, { error: "method_not_allowed" });
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
if (!VC0C_ENABLED()) {
|
|
187
|
+
sendJson(res, 409, { error: "vco_c_disabled" });
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
readJsonBody(req, (parsed) => {
|
|
191
|
+
if (!parsed.ok) {
|
|
192
|
+
sendJson(res, 400, { error: parsed.error });
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const subsystem = parsed.value.subsystem;
|
|
196
|
+
if (typeof subsystem !== "string" || subsystem.length === 0) {
|
|
197
|
+
sendJson(res, 400, { error: "subsystem_required" });
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
const safety = createVectorCortexSafety({ stateDir: ctx.stateDir });
|
|
202
|
+
const rec = safety.reset(subsystem);
|
|
203
|
+
const body = {
|
|
204
|
+
subsystem: rec.subsystem,
|
|
205
|
+
state: rec.state,
|
|
206
|
+
cooldownCleared: true,
|
|
207
|
+
attempts: rec.attempts,
|
|
208
|
+
failures: rec.failures,
|
|
209
|
+
probeCount: rec.probeCount,
|
|
210
|
+
manualReason: rec.manualReason,
|
|
211
|
+
updatedAt: rec.updatedAt,
|
|
212
|
+
};
|
|
213
|
+
sendJson(res, 200, body);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
sendJson(res, 500, { error: "reset_failed" });
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Reader-only GET /api/vector-cortex/ledger (VC1B).
|
|
223
|
+
*
|
|
224
|
+
* Built on the LedgerReader capability: opens the occurrence-v2 ledger for this
|
|
225
|
+
* repo's state dir and returns the session's occurrence IDENTITY rows
|
|
226
|
+
* (seq/eventId/kind/digest/toolCallId) plus high-water/count. NEVER ships
|
|
227
|
+
* sourceBytes or prompt text (reader-only no-ledger-text rule). Optional
|
|
228
|
+
* `?session=<id>` query selects the session (default "default").
|
|
229
|
+
*/
|
|
230
|
+
export function handleVectorCortexLedger(req, res, ctx) {
|
|
231
|
+
const url = req.url ?? "";
|
|
232
|
+
const path = url.split("?")[0] ?? url;
|
|
233
|
+
if (path !== "/api/vector-cortex/ledger")
|
|
234
|
+
return false;
|
|
235
|
+
if (req.method !== "GET") {
|
|
236
|
+
// Reader-only path: no mutation endpoint lives at /ledger.
|
|
237
|
+
sendJson(res, 405, { error: "method_not_allowed" });
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
// Parse the optional session query parameter.
|
|
241
|
+
let session = "default";
|
|
242
|
+
const qs = url.split("?")[1];
|
|
243
|
+
if (qs !== undefined) {
|
|
244
|
+
for (const pair of qs.split("&")) {
|
|
245
|
+
const [k, v] = pair.split("=");
|
|
246
|
+
if (k === "session" && v !== undefined && v.length > 0) {
|
|
247
|
+
session = decodeURIComponent(v);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const enabled = VC1B_ENABLED();
|
|
252
|
+
let active = enabled;
|
|
253
|
+
let highWater = "0";
|
|
254
|
+
let count = 0;
|
|
255
|
+
let occurrences = [];
|
|
256
|
+
if (enabled) {
|
|
257
|
+
try {
|
|
258
|
+
const store = createLedgerStore({ stateDir: ctx.stateDir });
|
|
259
|
+
try {
|
|
260
|
+
const reader = store.reader();
|
|
261
|
+
highWater = reader.highWater(session).toString();
|
|
262
|
+
const rows = reader.readSession(session);
|
|
263
|
+
count = rows.length;
|
|
264
|
+
// Identity only: never sourceBytes or prompt text (reader-only rule).
|
|
265
|
+
occurrences = rows.slice(-500).map((occ) => ({
|
|
266
|
+
seq: occ.seq.toString(),
|
|
267
|
+
eventId: occ.eventId,
|
|
268
|
+
kind: occ.kind,
|
|
269
|
+
digest: occ.digest,
|
|
270
|
+
...(occ.toolCallId !== undefined ? { toolCallId: occ.toolCallId } : {}),
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
finally {
|
|
274
|
+
store.close();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
// Non-fatal: a missing/corrupt ledger DB degrades to `enabled:false`.
|
|
279
|
+
active = false;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
const body = {
|
|
283
|
+
enabled: active,
|
|
284
|
+
session,
|
|
285
|
+
highWater,
|
|
286
|
+
count,
|
|
287
|
+
occurrences,
|
|
288
|
+
updatedAt: new Date().toISOString(),
|
|
289
|
+
};
|
|
290
|
+
sendJson(res, 200, body);
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
@@ -23,3 +23,4 @@ export { handleRagSettings } from "./routes-rag-settings.js";
|
|
|
23
23
|
export { handleRagMetrics } from "./routes-rag-metrics.js";
|
|
24
24
|
export { handleModelThresholds } from "./routes-model-thresholds.js";
|
|
25
25
|
export { handleWiki } from "./routes-wiki.js";
|
|
26
|
+
export { handleVectorCortexEvaluation, handleVectorCortexHealth, handleVectorCortexBreakersReset, handleVectorCortexLedger, } from "./routes-vector-cortex.js";
|
|
@@ -13,7 +13,7 @@ import { fileURLToPath } from "node:url";
|
|
|
13
13
|
import { createRequire } from "node:module";
|
|
14
14
|
import { NEW_UI } from "../../src/config.js";
|
|
15
15
|
import { log, setLogPath, setDashboardServerVersion } from "./state.js";
|
|
16
|
-
import { buildRouteContext, handleIndex, handleRepoIndex, handleEvents, handleGameState, handleGameScores, handlePerf, handlePerfSamples, handleAchievements, handleSessions, handleTopics, handleTurns, handleMaintenance, handleProviderCache, handleCacheStripes, handleMemoryStatus, handleSetupStatus, handleSetupDetect, handleSetupConfigure, handleMemoryMap, handleRaptorTree, handleRaptorBuildHistory, handleContextHealth, handleCachePoison, handleHealthSettings, handleEmbedderHealth, handleRagSettings, handleRagMetrics, handleModelThresholds, handleWiki, handleStatic, } from "./routes.js";
|
|
16
|
+
import { buildRouteContext, handleIndex, handleRepoIndex, handleEvents, handleGameState, handleGameScores, handlePerf, handlePerfSamples, handleAchievements, handleSessions, handleTopics, handleTurns, handleMaintenance, handleProviderCache, handleCacheStripes, handleMemoryStatus, handleSetupStatus, handleSetupDetect, handleSetupConfigure, handleMemoryMap, handleRaptorTree, handleRaptorBuildHistory, handleContextHealth, handleCachePoison, handleHealthSettings, handleEmbedderHealth, handleRagSettings, handleRagMetrics, handleModelThresholds, handleWiki, handleVectorCortexEvaluation, handleVectorCortexHealth, handleVectorCortexBreakersReset, handleVectorCortexLedger, handleStatic, } from "./routes.js";
|
|
17
17
|
export async function launchDashboardServer(stateDir) {
|
|
18
18
|
// Our own package version — exposed at /api/version so the launcher can
|
|
19
19
|
// detect a stale server (started by an older build) and replace it on
|
|
@@ -241,6 +241,14 @@ export async function launchDashboardServer(stateDir) {
|
|
|
241
241
|
return;
|
|
242
242
|
if (handleWiki(req, res, ctx))
|
|
243
243
|
return;
|
|
244
|
+
if (handleVectorCortexEvaluation(req, res, ctx))
|
|
245
|
+
return;
|
|
246
|
+
if (handleVectorCortexHealth(req, res, ctx))
|
|
247
|
+
return;
|
|
248
|
+
if (handleVectorCortexBreakersReset(req, res, ctx))
|
|
249
|
+
return;
|
|
250
|
+
if (handleVectorCortexLedger(req, res, ctx))
|
|
251
|
+
return;
|
|
244
252
|
handleStatic(req, res, ctx);
|
|
245
253
|
});
|
|
246
254
|
// Bind base + range are env-configurable so tests can use a private,
|
|
@@ -4,6 +4,7 @@ import { estimateSessionTokens, estimateBlockTokens, estimateMessageTokens, } fr
|
|
|
4
4
|
import { runCompact, piCompactWouldNoop } from "../mega-pipeline.js";
|
|
5
5
|
import { pressureFromPct, pressureRatio, } from "../mega-config.js";
|
|
6
6
|
import { appendMirrorMessages } from "./mirror-append.js";
|
|
7
|
+
import { appendMessagesToLedger } from "../mega-runtime/vector-cortex-ledger.js";
|
|
7
8
|
import { epochIdFor } from "../../src/mirror/epoch.js";
|
|
8
9
|
import { computeLiveTrimCut, liveTrimSummaryMessage } from "../mega-trim.js";
|
|
9
10
|
import { messageContentText } from "./context-handler/messageText.js";
|
|
@@ -101,6 +102,16 @@ export function registerContextHandler(pi, runtime, config) {
|
|
|
101
102
|
runtime.logger.warn("db-mirror-append-fail", { error: String(e) });
|
|
102
103
|
}
|
|
103
104
|
}
|
|
105
|
+
// VC1B (S1): canonical messages -> v2 ledger occurrences. Flag-OFF opens
|
|
106
|
+
// no DB (byte-identical predecessor); non-fatal. onFailure surfaces
|
|
107
|
+
// per-append rejections (e.g. EVT_SEQ_REGRESSION on rewind/fork) as
|
|
108
|
+
// structured warnings rather than swallowing them silently.
|
|
109
|
+
try {
|
|
110
|
+
appendMessagesToLedger(runtime.currentStateDir, runtime.rt.sessionId, messages, runtime.logger);
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
runtime.logger.warn("vc1b-ledger-append-fail", { error: String(e) });
|
|
114
|
+
}
|
|
104
115
|
// S52 / v0.16.1: per-model threshold override. The user can tune the
|
|
105
116
|
// fire point + safety margin PER MODEL (different providers' models range
|
|
106
117
|
// 8K-1M+ context, so one global tier % is wrong). Falls back to env/default
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex-ledger.ts — VC1B occurrence-ledger writer wiring (S1).
|
|
3
|
+
*
|
|
4
|
+
* Wires ONLY the `LedgerWriter` capability into message ingestion: each
|
|
5
|
+
* canonical message that flows through the compaction pipeline becomes an
|
|
6
|
+
* occurrence in the v2 ledger. The wiring is writer-only (never reader/admin
|
|
7
|
+
* here — the dashboard GET owns the reader), matching the capability-gated
|
|
8
|
+
* CONTRACTS §Store rule. A tool RESULT occurrence references exactly one
|
|
9
|
+
* earlier call via `toolCallId` (the ledger enforces EVT_TOOL_CALL_MISSING).
|
|
10
|
+
*
|
|
11
|
+
* When MEGACOMPACT_VC1B is OFF the seam opens NO ledger DB at all — and even if
|
|
12
|
+
* a caller already holds a store, its write path is inert (S2 flag-gate in
|
|
13
|
+
* store.ts) — so the OFF behavior is byte-identical to the pre-VC1B predecessor.
|
|
14
|
+
*
|
|
15
|
+
* Local-only (PREVENT-PI-004), no `any` (PREVENT-011), no console.log (events
|
|
16
|
+
* go through the ledger emit seam); non-fatal — a ledger write failure never
|
|
17
|
+
* breaks the agent loop.
|
|
18
|
+
*/
|
|
19
|
+
import { createHash } from "node:crypto";
|
|
20
|
+
import { VC1B_ENABLED } from "../../src/config/vector-cortex.js";
|
|
21
|
+
import { createLedgerStore, } from "../../src/vector-cortex/ledger/store.js";
|
|
22
|
+
/** Open the ledger writer for ingestion, or null when VC1B is disabled. */
|
|
23
|
+
export function openLedgerWriter(stateDir) {
|
|
24
|
+
if (!VC1B_ENABLED())
|
|
25
|
+
return null;
|
|
26
|
+
const store = createLedgerStore({ stateDir });
|
|
27
|
+
return { writer: store.writer(), close: () => store.close() };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Append one occurrence for a canonical message. `kind` is the neutral kind;
|
|
31
|
+
* when `toolCallId` is present the ledger enforces exactly-one reference to an
|
|
32
|
+
* earlier call. Flag-OFF (null handle) and the writer's own inert path are
|
|
33
|
+
* no-ops. Non-fatal: never throws to the loop — a failure is surfaced as
|
|
34
|
+
* `{ ok: false, code }` so the caller can log the reason (Q02).
|
|
35
|
+
*/
|
|
36
|
+
export function appendLedgerMessage(handle, input) {
|
|
37
|
+
try {
|
|
38
|
+
const res = handle.writer.append(input);
|
|
39
|
+
return res.ok ? { ok: true } : { ok: false, code: res.code };
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
return { ok: false, code: String(e) };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Append one occurrence per canonical message in `messages` (session-scoped,
|
|
47
|
+
* sequence = 1-based index). Opens the writer, appends each, closes the handle.
|
|
48
|
+
* Returns the number of accepted occurrences (0 when disabled OR when every
|
|
49
|
+
* append was a non-fatal no-op). This is the S1 ingestion seam.
|
|
50
|
+
*
|
|
51
|
+
* Monotonic-prefix assumption (Q02): the FIRST accepted append establishes the
|
|
52
|
+
* per-session high-water, and each subsequent append must carry `seq =
|
|
53
|
+
* highWater + 1`. Append order here follows `messages` array order with 1-based
|
|
54
|
+
* indices, so a shorter/mid-removal/reordered `messages` list after a prior
|
|
55
|
+
* taller run (rewind/fork) can drive `seq` backwards and be rejected with
|
|
56
|
+
* `EVT_SEQ_REGRESSION`. Such appends fail on the ledger and, without `onFailure`,
|
|
57
|
+
* are swallowed silently — so the caller should pass `onFailure` to log them.
|
|
58
|
+
*/
|
|
59
|
+
export function appendMessagesToLedger(stateDir, sessionId, messages, onFailure) {
|
|
60
|
+
const ledger = openLedgerWriter(stateDir);
|
|
61
|
+
if (!ledger)
|
|
62
|
+
return 0;
|
|
63
|
+
try {
|
|
64
|
+
let accepted = 0;
|
|
65
|
+
for (let i = 0; i < messages.length; i++) {
|
|
66
|
+
const input = messageToLedgerInput(messages[i], sessionId, i);
|
|
67
|
+
const res = appendLedgerMessage(ledger, input);
|
|
68
|
+
if (res.ok) {
|
|
69
|
+
accepted++;
|
|
70
|
+
}
|
|
71
|
+
else if (onFailure) {
|
|
72
|
+
onFailure.warn("vc1b-ledger-append-skip", {
|
|
73
|
+
session: sessionId,
|
|
74
|
+
seq: input.seq.toString(),
|
|
75
|
+
eventId: input.eventId,
|
|
76
|
+
kind: input.kind,
|
|
77
|
+
reason: res.code ?? "unknown",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return accepted;
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
ledger.close();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Map an AgentMessage to a ledger occurrence input. `eventId` is the stable
|
|
89
|
+
* content digest so re-observed identical messages are (event_id,digest)-deduped;
|
|
90
|
+
* `kind` mirrors the canonical role. `toolCallId` is intentionally NOT set here:
|
|
91
|
+
* pi discriminates messages by `role` only and the tool-call id lives in
|
|
92
|
+
* variant-specific `.content`/`.tool_calls` we must not reach into, so the
|
|
93
|
+
* exactly-one tool back-edge (EVT_TOOL_CALL_MISSING) is exercised at the
|
|
94
|
+
* store/acceptance level and the full live mapping is deferred to the VC1
|
|
95
|
+
* producer-wiring sprint.
|
|
96
|
+
*/
|
|
97
|
+
export function messageToLedgerInput(msg, session, indexInSession) {
|
|
98
|
+
const m = msg;
|
|
99
|
+
const text = messageText(msg);
|
|
100
|
+
const role = m.role ?? "unknown";
|
|
101
|
+
const digest = `sha256:${createHash("sha256").update(text).digest("hex")}`;
|
|
102
|
+
return {
|
|
103
|
+
session,
|
|
104
|
+
seq: BigInt(indexInSession + 1),
|
|
105
|
+
eventId: m.id ?? digest,
|
|
106
|
+
kind: role,
|
|
107
|
+
sourceBytes: new TextEncoder().encode(text),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** Best-effort text extraction from an AgentMessage (string or part array). */
|
|
111
|
+
function messageText(msg) {
|
|
112
|
+
const content = msg.content;
|
|
113
|
+
if (content == null)
|
|
114
|
+
return "";
|
|
115
|
+
if (typeof content === "string")
|
|
116
|
+
return content;
|
|
117
|
+
if (Array.isArray(content)) {
|
|
118
|
+
return content
|
|
119
|
+
.map((p) => {
|
|
120
|
+
const part = p;
|
|
121
|
+
return typeof part.text === "string" ? part.text : "";
|
|
122
|
+
})
|
|
123
|
+
.join("\n");
|
|
124
|
+
}
|
|
125
|
+
if (typeof content === "object") {
|
|
126
|
+
const maybe = content.text;
|
|
127
|
+
if (typeof maybe === "string")
|
|
128
|
+
return maybe;
|
|
129
|
+
}
|
|
130
|
+
return "";
|
|
131
|
+
}
|