pi-mega-compact 0.21.2 → 0.21.4
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/extensions/dashboard-server/routes-rag-settings-helpers.js +1 -0
- package/dist/extensions/mega-compact-child.js +126 -0
- package/dist/extensions/mega-config.js +5 -0
- package/dist/extensions/mega-events/agent-handlers/turnEndHandler/recordTurnRow.js +12 -2
- package/dist/extensions/mega-events/context-handler/afterCompact.js +11 -0
- package/dist/extensions/mega-events/context-handler/dbMirrorAppend.js +8 -0
- package/dist/extensions/mega-events/health-handler.js +12 -2
- package/dist/extensions/mega-events/session-handlers.js +1 -0
- package/dist/extensions/mega-pipeline/compact/run.js +11 -0
- package/dist/extensions/mega-runtime/helpers.js +45 -0
- package/dist/extensions/mega-runtime/internal-errors.js +14 -0
- package/dist/extensions/mega-runtime/runtime-instrumentation.js +166 -0
- package/dist/extensions/mega-runtime/runtime.js +27 -193
- package/dist/extensions/mega-runtime/state.js +1 -1
- package/dist/extensions/mega-runtime/widget.js +1 -1
- package/dist/extensions/mega-turn-store.js +5 -0
- package/dist/src/bridge/factory.js +195 -0
- package/dist/src/bridge/types.js +10 -0
- package/dist/src/bridge.js +1 -0
- package/dist/src/contextHealth.js +13 -5
- package/dist/src/metrics/turns.js +6 -1
- package/dist/src/store/sqlite/context-health-cache-poison.js +60 -0
- package/dist/src/store/sqlite/context-health.js +6 -48
- package/dist/src/store/sqlite/embedding-cache.js +4 -0
- package/dist/src/store/sqlite/schema.js +4 -0
- package/dist/src/store/turns/memory-store/admin.js +119 -0
- package/dist/src/store/turns/memory-store/ctx.js +28 -0
- package/dist/src/store/turns/memory-store/read.js +110 -0
- package/dist/src/store/turns/memory-store/write.js +88 -0
- package/dist/src/store/turns/memory-store.js +44 -273
- package/dist/src/store/turns/migrations.js +4 -0
- package/dist/src/store/turns/schema.js +1 -0
- package/dist/src/store/turns/sqlite-store/read.js +13 -0
- package/dist/src/store/turns/sqlite-store/rows.js +4 -0
- package/dist/src/store/turns/sqlite-store/write.js +3 -3
- package/dist/src/store/turns/sqlite-store.js +4 -0
- package/extensions/dashboard-client/dist/assets/{AdminTab-BsA8-_bX.js → AdminTab-C4Y0_UVx.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AdminTab-BsA8-_bX.js.map → AdminTab-C4Y0_UVx.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{AreaChart-BRHEfWhc.js → AreaChart-MCWK9rn6.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-BRHEfWhc.js.map → AreaChart-MCWK9rn6.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-C-M0LaFc.js → BarChart-CvSGAiWV.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-C-M0LaFc.js.map → BarChart-CvSGAiWV.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-Cj3n59U3.js → CacheTab-DnMEVRro.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-Cj3n59U3.js.map → CacheTab-DnMEVRro.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ConfigTab-C016XTNC.js → ConfigTab-BExuZYy2.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ConfigTab-C016XTNC.js.map → ConfigTab-BExuZYy2.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-DE29fuqe.js → EventsTab-CspsEslY.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-DE29fuqe.js.map → EventsTab-CspsEslY.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/HealthTab-DiWzo2ML.js +2 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-DiWzo2ML.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-4fJ7M4S4.js → MaintenanceTab-9NJuv3dB.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-4fJ7M4S4.js.map → MaintenanceTab-9NJuv3dB.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CDbcK9e4.js → MemoryMapTab-YpJK1h17.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-CDbcK9e4.js.map → MemoryMapTab-YpJK1h17.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsCards-VUEcgGzo.js → MetricsCards-D2Mom1M7.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsCards-VUEcgGzo.js.map → MetricsCards-D2Mom1M7.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MetricsTab-DqWF7wud.js +2 -0
- package/extensions/dashboard-client/dist/assets/{MetricsTab-CKqJ0Zl-.js.map → MetricsTab-DqWF7wud.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-9Kxo79mi.js → OverviewTab-YuRxjV9U.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-9Kxo79mi.js.map → OverviewTab-YuRxjV9U.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-C4iveqrP.js → ReposTab-sXMrR7je.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-C4iveqrP.js.map → ReposTab-sXMrR7je.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DSEwkMQm.js → SessionsTab-4YCXeGNR.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DSEwkMQm.js.map → SessionsTab-4YCXeGNR.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-CCyWgy4O.js → SetupTab-67pZcM_W.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-CCyWgy4O.js.map → SetupTab-67pZcM_W.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CyD8e_e_.js → TimeSavedCard-DInjNETP.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CyD8e_e_.js.map → TimeSavedCard-DInjNETP.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnMemoryView-5tLbWkRv.js → TurnMemoryView-C3Bif8ix.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnMemoryView-5tLbWkRv.js.map → TurnMemoryView-C3Bif8ix.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/TurnsTab-BUGfiANp.js +2 -0
- package/extensions/dashboard-client/dist/assets/{TurnsTab-C7pm92Hg.js.map → TurnsTab-BUGfiANp.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-ObhcIyfN.js → VcStatusBadge-DKU7qz9f.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-ObhcIyfN.js.map → VcStatusBadge-DKU7qz9f.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BtHZb7o7.js → VectorCortexTab-BsVSf4xm.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-BtHZb7o7.js.map → VectorCortexTab-BsVSf4xm.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{WikiTab-lQ4l3QIK.js → WikiTab-DZw9_Fwd.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-lQ4l3QIK.js.map → WikiTab-DZw9_Fwd.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-DhQQAJGm.js → button-BLRPN489.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-DhQQAJGm.js.map → button-BLRPN489.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-Cfhz9X31.js → card-BGkkcM4Q.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-Cfhz9X31.js.map → card-BGkkcM4Q.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{client-extra-CKNOGEz_.js → client-extra-0OJClxHD.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{client-extra-CKNOGEz_.js.map → client-extra-0OJClxHD.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-JKjK9_cB.js → generateCategoricalChart-Dl5lmrHF.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-JKjK9_cB.js.map → generateCategoricalChart-Dl5lmrHF.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/health-lSeDFTz7.js.map +1 -1
- package/extensions/dashboard-client/dist/assets/{index-iuxgtzEW.js → index-CH_AD-S_.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{index-iuxgtzEW.js.map → index-CH_AD-S_.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{switch-7EHEQMSP.js → switch-BPP2-d12.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-7EHEQMSP.js.map → switch-BPP2-d12.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-z1lWY4UM.js → toggle-Dez0JaMV.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-z1lWY4UM.js.map → toggle-Dez0JaMV.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-sctOZuRM.js → useSSE-Cx2W7BTo.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-sctOZuRM.js.map → useSSE-Cx2W7BTo.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/api/health.ts +1 -0
- package/extensions/dashboard-client/src/tabs/HealthTab.tsx +1 -0
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +6 -0
- package/extensions/mega-compact-child.ts +129 -0
- package/extensions/mega-config-types.ts +5 -0
- package/extensions/mega-config.ts +5 -0
- package/extensions/mega-events/agent-handlers/turnEndHandler/recordTurnRow.ts +12 -2
- package/extensions/mega-events/context-handler/afterCompact.ts +11 -0
- package/extensions/mega-events/context-handler/dbMirrorAppend.ts +8 -0
- package/extensions/mega-events/health-handler.ts +13 -3
- package/extensions/mega-events/session-handlers.ts +1 -0
- package/extensions/mega-pipeline/compact/run.ts +11 -0
- package/extensions/mega-runtime/helpers.ts +46 -0
- package/extensions/mega-runtime/internal-errors.ts +30 -0
- package/extensions/mega-runtime/runtime-instrumentation.ts +195 -0
- package/extensions/mega-runtime/runtime.ts +29 -209
- package/extensions/mega-runtime/state.ts +1 -1
- package/extensions/mega-runtime/widget.ts +1 -1
- package/extensions/mega-turn-store.ts +9 -0
- package/package.json +2 -2
- package/src/bridge/factory.ts +245 -0
- package/src/bridge/types.ts +140 -0
- package/src/bridge.ts +24 -0
- package/src/contextHealth.ts +26 -6
- package/src/metrics/turns.ts +6 -1
- package/src/store/sqlite/context-health-cache-poison.ts +97 -0
- package/src/store/sqlite/context-health.ts +12 -84
- package/src/store/sqlite/embedding-cache.ts +4 -0
- package/src/store/sqlite/schema.ts +4 -0
- package/src/store/turns/memory-store/admin.ts +171 -0
- package/src/store/turns/memory-store/ctx.ts +62 -0
- package/src/store/turns/memory-store/read.ts +172 -0
- package/src/store/turns/memory-store/write.ts +126 -0
- package/src/store/turns/memory-store.ts +51 -330
- package/src/store/turns/migrations.ts +4 -0
- package/src/store/turns/schema.ts +1 -0
- package/src/store/turns/sqlite-store/read.ts +19 -0
- package/src/store/turns/sqlite-store/rows.ts +5 -0
- package/src/store/turns/sqlite-store/write.ts +3 -2
- package/src/store/turns/sqlite-store.ts +5 -0
- package/src/store/turns/types.ts +15 -0
- package/extensions/dashboard-client/dist/assets/HealthTab-D4eVI8ar.js +0 -2
- package/extensions/dashboard-client/dist/assets/HealthTab-D4eVI8ar.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/MetricsTab-CKqJ0Zl-.js +0 -2
- package/extensions/dashboard-client/dist/assets/TurnsTab-C7pm92Hg.js +0 -2
|
@@ -234,6 +234,11 @@ export function loadConfig(): MegaConfig {
|
|
|
234
234
|
// 3WF-1: TriggerGuard — guarantee a staged recall block on every context
|
|
235
235
|
// event even when session_start never fires. Default ON; OFF = byte-identical.
|
|
236
236
|
threeWayFailback: envBool("MEGACOMPACT_THREE_WAY_FAILBACK", true),
|
|
237
|
+
// Sprint A: Mega↔ithacus bridge — gate the child extension + bridge usage.
|
|
238
|
+
// Default ON; OFF (=0/`=false`) = byte-identical pre-bridge behavior.
|
|
239
|
+
// Runtime reads envBool(plain key), mirroring threeWayFailback (plain-write
|
|
240
|
+
// convention, not _DISABLED).
|
|
241
|
+
ithacusBridge: envBool("MEGACOMPACT_ITHACUS_BRIDGE", true),
|
|
237
242
|
// 3WF-2: ThrashGuard re-arm budget as a fraction of effectiveThreshold.
|
|
238
243
|
// 0.10 default (10% of the effective threshold) — see mega-config-types.
|
|
239
244
|
// Clamped to [0.01, 0.5]: below 1% the guard is almost never armed (any
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { MegaRuntime } from "../../../mega-runtime.js";
|
|
10
10
|
import type { MegaConfig } from "../../../mega-config.js";
|
|
11
|
-
import { ensureConversationIdFor, recordTurnWrite } from "../../../mega-turn-store.js";
|
|
11
|
+
import { ensureConversationIdFor, recordTurnWrite, turnReaderFor } from "../../../mega-turn-store.js";
|
|
12
12
|
import type { TurnEndEvent } from "./event.js";
|
|
13
13
|
|
|
14
14
|
/** S43: record one turn row with the cached metrics. Best-effort + non-fatal. */
|
|
@@ -28,12 +28,18 @@ export function recordTurnRow(
|
|
|
28
28
|
runtime.rt.sessionId,
|
|
29
29
|
runtime.currentStateDir,
|
|
30
30
|
);
|
|
31
|
+
// S49R: store the conversation-monotonic index (MAX+1) instead of the
|
|
32
|
+
// per-session event.turnIndex, which restarts at 0 on resume and would
|
|
33
|
+
// collide with UNIQUE(conversation_id, turn_index). Carry the session
|
|
34
|
+
// counter as sessionTurnIndex for the raw_transcript metrics join.
|
|
35
|
+
const turnIndex = turnReaderFor(runtime.currentStateDir).nextTurnIndexFor(convId);
|
|
31
36
|
recordTurnWrite(
|
|
32
37
|
config,
|
|
33
38
|
{
|
|
34
39
|
conversationId: convId,
|
|
35
40
|
sessionId: runtime.rt.sessionId,
|
|
36
|
-
turnIndex
|
|
41
|
+
turnIndex,
|
|
42
|
+
sessionTurnIndex: event.turnIndex,
|
|
37
43
|
role: (event as { role?: string }).role ?? "assistant",
|
|
38
44
|
endedAt: Date.now(),
|
|
39
45
|
startedAt: undefined,
|
|
@@ -57,5 +63,9 @@ export function recordTurnRow(
|
|
|
57
63
|
error: e instanceof Error ? e.message : String(e),
|
|
58
64
|
stack: e instanceof Error ? e.stack?.split("\n").slice(0, 3).join(" | ") : undefined,
|
|
59
65
|
});
|
|
66
|
+
// Sprint H (Finding 3 / Option A): the turn-row write is an internal
|
|
67
|
+
// store-write failure the API-error `errorRate` ring never sees. Feed the
|
|
68
|
+
// separate `storeErrorRate` 6th axis.
|
|
69
|
+
runtime.recordInternalError("store_write");
|
|
60
70
|
}
|
|
61
71
|
}
|
|
@@ -77,6 +77,8 @@ export async function persistEpochAndMaintain(
|
|
|
77
77
|
writeCheckpointEpoch(db, epoch);
|
|
78
78
|
} catch (e) {
|
|
79
79
|
runtime.logger.warn("planv2-epoch-fail", { error: String(e) });
|
|
80
|
+
// Sprint H (Option A): checkpoint_epoch write failure.
|
|
81
|
+
runtime.recordInternalError("store_write");
|
|
80
82
|
}
|
|
81
83
|
}
|
|
82
84
|
|
|
@@ -181,6 +183,9 @@ export async function persistEpochAndMaintain(
|
|
|
181
183
|
runtime.logger.warn("wiki_rebuild_failed", {
|
|
182
184
|
error: String(wikiErr),
|
|
183
185
|
});
|
|
186
|
+
// Sprint H (Option A): wiki rebuild writes (topic model / overrides)
|
|
187
|
+
// to the isolated store — internal store write.
|
|
188
|
+
runtime.recordInternalError("store_write");
|
|
184
189
|
}
|
|
185
190
|
|
|
186
191
|
// D1: seed the topic model from raw_transcript when context_chunks is
|
|
@@ -263,6 +268,9 @@ export async function persistEpochAndMaintain(
|
|
|
263
268
|
runtime.logger.warn("wiki_seed_failed", {
|
|
264
269
|
error: String(seedErr),
|
|
265
270
|
});
|
|
271
|
+
// Sprint H (Option A): wiki seed rebuild writes to the isolated
|
|
272
|
+
// store — internal store write.
|
|
273
|
+
runtime.recordInternalError("store_write");
|
|
266
274
|
}
|
|
267
275
|
|
|
268
276
|
// S27 Task 6: Fire-and-forget dedup pipeline.
|
|
@@ -280,6 +288,9 @@ export async function persistEpochAndMaintain(
|
|
|
280
288
|
}
|
|
281
289
|
} catch (e) {
|
|
282
290
|
runtime.logger.warn("db-mirror-epoch-fail", { error: String(e) });
|
|
291
|
+
// Sprint H (Option A): db-mirror downstream maintenance writes
|
|
292
|
+
// (stamp turns epoch / wiki / seed / dedup) — internal store writes.
|
|
293
|
+
runtime.recordInternalError("store_write");
|
|
283
294
|
}
|
|
284
295
|
}
|
|
285
296
|
|
|
@@ -105,6 +105,9 @@ export function appendMirrorAndLedger(
|
|
|
105
105
|
}
|
|
106
106
|
} catch (e) {
|
|
107
107
|
runtime.logger.warn("db-mirror-append-fail", { error: String(e) });
|
|
108
|
+
// Sprint H (Option A): raw_transcript / thread / tool_results write
|
|
109
|
+
// failure — internal store write. Feed the `storeErrorRate` axis.
|
|
110
|
+
runtime.recordInternalError("store_write");
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
|
|
@@ -121,5 +124,10 @@ export function appendMirrorAndLedger(
|
|
|
121
124
|
);
|
|
122
125
|
} catch (e) {
|
|
123
126
|
runtime.logger.warn("vc1b-ledger-append-fail", { error: String(e) });
|
|
127
|
+
// Sprint H (Option A): the v2 vector-cortex ledger append is a cortex
|
|
128
|
+
// write — this is the host-side hook for the cortex seam (the cortex
|
|
129
|
+
// contract forbids the store from holding a runtime handle, so the ring
|
|
130
|
+
// push happens here in the adapter, not inside src/vector-cortex).
|
|
131
|
+
runtime.recordInternalError("vector_index");
|
|
124
132
|
}
|
|
125
133
|
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { MegaRuntime } from "../mega-runtime.js";
|
|
13
|
+
import { RING_MAX } from "../mega-runtime/runtime.js";
|
|
13
14
|
import type { MegaConfig } from "../mega-config.js";
|
|
14
15
|
import { defaultEmbedder } from "../../src/embedder.js";
|
|
15
16
|
import { computeOutputQuality } from "../../src/contextHealth/outputQuality.js";
|
|
@@ -34,8 +35,6 @@ import {
|
|
|
34
35
|
} from "../../src/store/sqlite/context-health.js";
|
|
35
36
|
import { getHealthMitigate } from "../../src/store/sqlite/meta.js";
|
|
36
37
|
|
|
37
|
-
const RING_MAX = 5;
|
|
38
|
-
|
|
39
38
|
/** Extract assistant text from the turn_end event message. */
|
|
40
39
|
function extractAssistantText(event: { message?: { role?: string; content?: unknown } }): string {
|
|
41
40
|
const msg = event.message;
|
|
@@ -108,9 +107,17 @@ export function handleTurnEndHealth(
|
|
|
108
107
|
drift = computeDriftScore(topic, error, prefix);
|
|
109
108
|
}
|
|
110
109
|
|
|
111
|
-
// Error rate sub-score (1 = no errors)
|
|
110
|
+
// Error rate sub-score (1 = no errors) — API-retry errors only.
|
|
112
111
|
const errorScore = computeErrorEscalation(runtime.recentErrorCategories);
|
|
113
112
|
|
|
113
|
+
// Sprint H (B2): store-error sub-score (1 = no store-write failures).
|
|
114
|
+
// Distinct from errorScore — internal store/service-write failures
|
|
115
|
+
// (turn rows, recall, dbMirror, ledger, epoch, stats, memory consolidate,
|
|
116
|
+
// compact persist, vector index, embedder, migration) never reach the
|
|
117
|
+
// API-retry errorRate ring. Mirrors computeErrorEscalation: 1 - (n/RING_MAX).
|
|
118
|
+
const recentInternalCount = Math.min(runtime.recentInternalErrors.length, RING_MAX);
|
|
119
|
+
const storeErrorScore = 1 - recentInternalCount / RING_MAX;
|
|
120
|
+
|
|
114
121
|
// Cache health (from perf-handler)
|
|
115
122
|
const cacheHealth = runtime.rt._lastCacheHealthScore ?? 1.0;
|
|
116
123
|
|
|
@@ -154,6 +161,7 @@ export function handleTurnEndHealth(
|
|
|
154
161
|
errorRate: errorScore,
|
|
155
162
|
cacheHealth,
|
|
156
163
|
cachePoison,
|
|
164
|
+
storeErrorRate: storeErrorScore,
|
|
157
165
|
};
|
|
158
166
|
const composite = computeHealthScore(sub);
|
|
159
167
|
|
|
@@ -168,6 +176,7 @@ export function handleTurnEndHealth(
|
|
|
168
176
|
cacheHealth,
|
|
169
177
|
cachePoison,
|
|
170
178
|
composite,
|
|
179
|
+
storeErrorScore,
|
|
171
180
|
modelId: runtime.currentModel?.modelId,
|
|
172
181
|
repetitionRatio,
|
|
173
182
|
coherenceScore,
|
|
@@ -180,6 +189,7 @@ export function handleTurnEndHealth(
|
|
|
180
189
|
drift,
|
|
181
190
|
outputQuality,
|
|
182
191
|
errorRate: errorScore,
|
|
192
|
+
storeErrorRate: storeErrorScore,
|
|
183
193
|
cacheHealth,
|
|
184
194
|
cachePoison,
|
|
185
195
|
turnIndex: event.turnIndex,
|
|
@@ -111,6 +111,7 @@ export function registerSessionHandlers(
|
|
|
111
111
|
runtime.logger.info("db-auto-maintain", { result: m });
|
|
112
112
|
} catch (e) {
|
|
113
113
|
runtime.logger.warn("db-auto-maintain-fail", { error: String(e) });
|
|
114
|
+
runtime.recordInternalError("store_write");
|
|
114
115
|
}
|
|
115
116
|
runtime.dashboard.event("session_start", {
|
|
116
117
|
reason: event.reason,
|
|
@@ -166,6 +166,9 @@ function doCompact(
|
|
|
166
166
|
touchSession(sid, root, runtime.currentStateDir);
|
|
167
167
|
logDaily(sid, "compact", result.checkpointId, saved, runtime.currentStateDir);
|
|
168
168
|
} catch {
|
|
169
|
+
// Sprint H (Option A): session-activity / daily-log write is an internal
|
|
170
|
+
// store-write failure — feed the separate `storeErrorRate` axis.
|
|
171
|
+
runtime.recordInternalError("store_write");
|
|
169
172
|
/* non-fatal: stats bookkeeping only */
|
|
170
173
|
}
|
|
171
174
|
|
|
@@ -183,10 +186,14 @@ function doCompact(
|
|
|
183
186
|
if (n > 0) runtime.pushTicker(`${C.green}∫${C.reset} consolidated ${n} memory dup${n === 1 ? "" : "s"}`);
|
|
184
187
|
},
|
|
185
188
|
() => {
|
|
189
|
+
// Sprint H (Option A): memory-consolidation write failure.
|
|
190
|
+
runtime.recordInternalError("store_write");
|
|
186
191
|
/* swallow: consolidate failures must never surface to the user */
|
|
187
192
|
},
|
|
188
193
|
);
|
|
189
194
|
} catch {
|
|
195
|
+
// Sprint H (Option A): memory-consolidation write failure (sync throw).
|
|
196
|
+
runtime.recordInternalError("store_write");
|
|
190
197
|
/* non-fatal */
|
|
191
198
|
}
|
|
192
199
|
}
|
|
@@ -259,6 +266,8 @@ function doCompact(
|
|
|
259
266
|
}
|
|
260
267
|
}
|
|
261
268
|
} catch {
|
|
269
|
+
// Sprint H (Option A): RAPTOR tree-refresh write failure.
|
|
270
|
+
runtime.recordInternalError("vector_index");
|
|
262
271
|
/* non-fatal: tree refresh never blocks a compaction */
|
|
263
272
|
}
|
|
264
273
|
}
|
|
@@ -278,6 +287,8 @@ function doCompact(
|
|
|
278
287
|
latest.checkpointId,
|
|
279
288
|
latest.embedding,
|
|
280
289
|
).catch(() => {
|
|
290
|
+
// Sprint H (Option A): async global vector-index upsert failure.
|
|
291
|
+
runtime.recordInternalError("vector_index");
|
|
281
292
|
/* non-fatal: index refresh never blocks a compaction */
|
|
282
293
|
});
|
|
283
294
|
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { join, dirname } from "node:path";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
11
|
import { readFileSync } from "node:fs";
|
|
12
|
+
import { normalizeSessionId } from "../../src/store.js";
|
|
12
13
|
|
|
13
14
|
// ── Public string constants ────────────────────────────────────────────────
|
|
14
15
|
// Exported via the barrel — consumers (mega-events.ts, mega-pipeline.ts) use
|
|
@@ -111,3 +112,48 @@ export function ownVersion(): string {
|
|
|
111
112
|
CACHED_VERSION = v;
|
|
112
113
|
return v;
|
|
113
114
|
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* createSessionRuntime() — the default per-session runtime state.
|
|
118
|
+
*
|
|
119
|
+
* Extracted from runtime.ts (delegate-shell split) so the MegaRuntime class
|
|
120
|
+
* stays a field-declarations + 1-line-delegate shell. Returns a fresh
|
|
121
|
+
* SessionRuntime for each session (reset on session_start / session_tree).
|
|
122
|
+
* Mirrors the neuralwatt-mcr per-session closure.
|
|
123
|
+
*/
|
|
124
|
+
export function createSessionRuntime(): SessionRuntime {
|
|
125
|
+
return {
|
|
126
|
+
sessionId: normalizeSessionId(undefined),
|
|
127
|
+
persistedThisSession: false,
|
|
128
|
+
lastCheckpointId: undefined,
|
|
129
|
+
lastCompactedFrom: 0,
|
|
130
|
+
lastCompactedTokens: 0,
|
|
131
|
+
dedupSkips: 0,
|
|
132
|
+
dedupAttempts: 0,
|
|
133
|
+
tokensSaved: 0,
|
|
134
|
+
lastCompactAt: null,
|
|
135
|
+
lastRecallAt: null,
|
|
136
|
+
lastInjectAt: null,
|
|
137
|
+
_prevCacheHitPct: null,
|
|
138
|
+
_lastCacheHealthScore: undefined,
|
|
139
|
+
lastNativeCompactAt: null,
|
|
140
|
+
compactCount: 0,
|
|
141
|
+
recallInjections: 0,
|
|
142
|
+
cacheHitTokens: 0,
|
|
143
|
+
lengthStopPending: false,
|
|
144
|
+
errorRetryCount: 0,
|
|
145
|
+
errorRetryUntil: 0,
|
|
146
|
+
consecutiveErrors: 0,
|
|
147
|
+
lastErrorRetryAt: 0,
|
|
148
|
+
retryNudgePending: false,
|
|
149
|
+
errorRetrySessionCount: 0,
|
|
150
|
+
lastErrorText: undefined,
|
|
151
|
+
errorTextRepeatCount: 0,
|
|
152
|
+
poisonedAdviseSent: false,
|
|
153
|
+
providerOutageAdvised: false,
|
|
154
|
+
poisonedCompactSignatures: new Set(),
|
|
155
|
+
recallInjectedThisTurn: false,
|
|
156
|
+
poisonedCount: 0,
|
|
157
|
+
extensionInitiatedTurn: false,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* internal-errors.ts — Sprint H (Finding 3 / Option A) instrumentation.
|
|
3
|
+
*
|
|
4
|
+
* Free-function + context-interface sibling of `runtime.ts` (delegate-shell
|
|
5
|
+
* pattern). Holds the body of `recordInternalError(category)` so the
|
|
6
|
+
* `MegaRuntime` class stays a field-declarations + 1-line-delegate shell.
|
|
7
|
+
*
|
|
8
|
+
* Pushes a store/service-write failure category into the `recentInternalErrors`
|
|
9
|
+
* ring (capped at RING_MAX, shift when over). Called AT each failure emit site
|
|
10
|
+
* (see the §2.3a audit in docs/specs/c2-resume-and-health-fixes.md) — never by
|
|
11
|
+
* a central events.log filter. Feeds the distinct `storeErrorRate` 6th health
|
|
12
|
+
* axis (committed separately in Sprint H axis work).
|
|
13
|
+
*/
|
|
14
|
+
import type { MegaRuntime } from "./runtime.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* RING_MAX — the cap for the rolling health ring buffers
|
|
18
|
+
* (`recentTurnEmbeddings`, `recentErrorCategories`, `recentInternalErrors`).
|
|
19
|
+
* Defined here (with the ring writer) and re-exported from runtime.ts so the
|
|
20
|
+
* ring + its writer live together; health-handler.ts imports it.
|
|
21
|
+
*/
|
|
22
|
+
export const RING_MAX = 5;
|
|
23
|
+
|
|
24
|
+
/** Push a category into the internal-error ring. Mirrors `recentErrorCategories`. */
|
|
25
|
+
export function recordInternalErrorImpl(rt: MegaRuntime, category: string): void {
|
|
26
|
+
rt.recentInternalErrors.push(category);
|
|
27
|
+
if (rt.recentInternalErrors.length > RING_MAX) {
|
|
28
|
+
rt.recentInternalErrors.shift();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runtime-instrumentation.ts — base class holding MegaRuntime's field
|
|
3
|
+
* declarations (diagnostic counters + context-health ring buffers + the Sprint-H
|
|
4
|
+
* internal-error ring + live display/cache-stability state).
|
|
5
|
+
*
|
|
6
|
+
* Extracted from runtime.ts (delegate-shell split) so the MegaRuntime class
|
|
7
|
+
* stays a field-declarations + 1-line-delegate shell. As a base class, the
|
|
8
|
+
* field NAMES are unchanged (`this.diagLiveTrimFires`, `this.trimCache`, etc.) —
|
|
9
|
+
* call sites across the codebase and tests need no edits.
|
|
10
|
+
*/
|
|
11
|
+
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
12
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
13
|
+
import type { ModelSnapshot, GameState } from "../../src/store/sqlite.js";
|
|
14
|
+
import type { TickerEntry, WidgetData } from "./widget.js";
|
|
15
|
+
import type { FSWatcher } from "node:fs";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* DIAG counters for the "team run doesn't relieve context" investigation.
|
|
19
|
+
* Plain integers, incremented at the three compaction decision points. They
|
|
20
|
+
* let a headless test drive the real event handlers and assert the firing
|
|
21
|
+
* cadence without scraping log files. Inert in production (the live-trim and
|
|
22
|
+
* before-compact probes also emit logger.info, but these counters are always
|
|
23
|
+
* updated and cost nothing).
|
|
24
|
+
*/
|
|
25
|
+
export class RuntimeInstrumentation {
|
|
26
|
+
diagLiveTrimFires = 0; // context handler returned a trimmed view
|
|
27
|
+
diagLiveTrimReplays = 0; // v0.8.6: trim view returned via cached replay (skipped re-compact)
|
|
28
|
+
diagBeforeCompactFires = 0; // session_before_compact handler entered
|
|
29
|
+
diagBeforeCompactSupplied = 0; // session_before_compact supplied our trim
|
|
30
|
+
diagAgentEndIdle = 0; // agent_end with activeAgents===0
|
|
31
|
+
diagAgentEndDurable = 0; // agent_end fired ctx.compact() (mid-run durable trim)
|
|
32
|
+
diagAgentEndDurableSkipRecent = 0; // agent_end skipped ctx.compact() — compaction in last 10s (race guard)
|
|
33
|
+
// Per-skip-path counters for the team-run diagnosis.
|
|
34
|
+
diagCtxFastGate = 0; // returned at token fast-gate (below threshold)
|
|
35
|
+
diagCtxNoCompact = 0; // autoCompactCheck().shouldCompact === false
|
|
36
|
+
diagCtxDebounce = 0; // debounceUntil not yet elapsed
|
|
37
|
+
diagCtxRunSkipped = 0; // runCompact() returned skipped
|
|
38
|
+
diagCtxCutNull = 0; // computeLiveTrimCut returned null (anchor/boundary)
|
|
39
|
+
diagCtxThrown = 0; // live-trim try threw (caught)
|
|
40
|
+
|
|
41
|
+
// Context health instrumentation (v0.12): rolling ring buffers for
|
|
42
|
+
// drift detection + cache poison Layer 1 hash baseline.
|
|
43
|
+
recentTurnEmbeddings: number[][] = [];
|
|
44
|
+
recentErrorCategories: (string | null)[] = [];
|
|
45
|
+
lastPrefixHash: string | null = null;
|
|
46
|
+
lastErrorCategory: string | null = null;
|
|
47
|
+
|
|
48
|
+
// Sprint H (Finding 3): a SEPARATE internal-error ring fed by explicit
|
|
49
|
+
// `recordInternalError(category)` calls at each store/service-write failure
|
|
50
|
+
// emit site (Option A — NOT a central events.log filter). This captures
|
|
51
|
+
// internal store-write failures which the API-error `errorRate` ring never
|
|
52
|
+
// sees. The health-handler computes a distinct `storeErrorRate` 6th axis.
|
|
53
|
+
// Mirrors `recentErrorCategories` / `lastErrorCategory` exactly (cap = RING_MAX).
|
|
54
|
+
recentInternalErrors: string[] = [];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* S26 capture instrumentation: the "model_snapshots empty → $0.00 cost card"
|
|
58
|
+
* bug was invisible because captureModel swallowed the DB write in a silent
|
|
59
|
+
* `catch {}`. These always-updated counters (zero cost) let a headless test or
|
|
60
|
+
* a live capture tell whether captureModel ran and whether the snapshot landed.
|
|
61
|
+
*/
|
|
62
|
+
diagCaptureModelCalls = 0; // captureModel entered with a populated ctx.model
|
|
63
|
+
diagCaptureModelFails = 0; // recordModelSnapshot threw → model_snapshots stays empty
|
|
64
|
+
|
|
65
|
+
// ── Live display / cache-stability state (moved from runtime.ts shell) ────
|
|
66
|
+
|
|
67
|
+
// v0.8.6 cache-stability: the cached live-trim view for the current
|
|
68
|
+
// compaction epoch. Set after a fresh runCompact + computeLiveTrimCut, and
|
|
69
|
+
// replayed verbatim on subsequent gated context events in the SAME epoch
|
|
70
|
+
// (same checkpointId) so the provider KV-cache prefix stays stable instead
|
|
71
|
+
// of being invalidated by a freshly regenerated summary + sentinel every
|
|
72
|
+
// fire. Invalidated on session restart (resetRuntime) and on any native
|
|
73
|
+
// durable compaction (session_compact) that truncates the transcript.
|
|
74
|
+
trimCache: {
|
|
75
|
+
checkpointId: string;
|
|
76
|
+
cut: number;
|
|
77
|
+
summaryAgentMsg: AgentMessage;
|
|
78
|
+
ctxPct: number | null;
|
|
79
|
+
ctxTokens: number | null;
|
|
80
|
+
} | null = null;
|
|
81
|
+
debounceUntil = 0;
|
|
82
|
+
// S16: debounce for the agent_end resume nudge (avoid busy-loops).
|
|
83
|
+
resumeNudgeUntil = 0;
|
|
84
|
+
// Agent tracking for real-time widget updates
|
|
85
|
+
activeAgents = 0;
|
|
86
|
+
currentTurn = 0;
|
|
87
|
+
// S33: transient MEGA CACHE flare flag (armed by the turn_end scoring hook
|
|
88
|
+
// when cachePct > 100). Copied into widgetData.megaCacheFlare on the next
|
|
89
|
+
// snapshot() so the widget renders the oopsie gag, then reset (one cycle).
|
|
90
|
+
megaCacheFlare = false;
|
|
91
|
+
/** v0.8.3: ambient effect state for animated panel borders keyed off
|
|
92
|
+
* status transitions (level-up, mega-cache overshoot, achievement unlock,
|
|
93
|
+
* compaction start). Threaded into widgetData as `activeEffect`; the widget
|
|
94
|
+
* computes the per-frame phase from startedAt vs Date.now() (non-expired).
|
|
95
|
+
* Null when idle/expired. */
|
|
96
|
+
activeEffect: { type: "pulse" | "flash"; role: "accent" | "mega" | "red"; startedAt: number; durationMs: number } | null = null;
|
|
97
|
+
megaCacheFlarePct = 0;
|
|
98
|
+
levelUpFlare = false;
|
|
99
|
+
lastLevel = 0;
|
|
100
|
+
// S35: transient achievement-unlock flare (armed by the scoring hooks after
|
|
101
|
+
// evaluateAndUnlockAchievements returns newly-unlocked titles). Copied into
|
|
102
|
+
// widgetData.achievementFlare on the next snapshot() so the widget renders the
|
|
103
|
+
// unlock toast, then reset (one cycle — mirrors megaCacheFlare/levelUpFlare).
|
|
104
|
+
achievementFlare = false;
|
|
105
|
+
achievementFlareTitles: string[] = [];
|
|
106
|
+
// S33: last cumulative dedup-collapsed count seen by the session_compact
|
|
107
|
+
// hook, so we only record the DELTA as the dedupe score (leaderboard sums).
|
|
108
|
+
lastDedupCollapsed = 0;
|
|
109
|
+
// Recall block produced by auto-inline (resume/branch) that the next
|
|
110
|
+
// before_agent_start should prepend to the system prompt. Unset after use.
|
|
111
|
+
pendingRecallBlock: string | undefined;
|
|
112
|
+
// S21: memory recall block, parallel to pendingRecallBlock. Same one-shot
|
|
113
|
+
// semantics; composed with the checkpoint block in before_agent_start.
|
|
114
|
+
pendingMemoryRecallBlock: string | undefined;
|
|
115
|
+
statusKey: string | undefined; // current status text for dashboard
|
|
116
|
+
// Active model/provider (for real cost estimation). Captured from ctx.model
|
|
117
|
+
// on model_select + session_start; persisted to SQL so cost + the dashboard
|
|
118
|
+
// can read it without a live ctx.
|
|
119
|
+
currentModel: ModelSnapshot | undefined;
|
|
120
|
+
// Live "what it's doing right now" timestamp, used for the fresh-window.
|
|
121
|
+
lastActivityAt = 0;
|
|
122
|
+
// Live per-tier dedup trace (Phase 1): e.g. "L0 ✓ → L1 ✓ → L2 0.91 → stored".
|
|
123
|
+
// Built from the store's sync onTier callback during a compaction so the user
|
|
124
|
+
// watches each tier evaluate in real time. Cleared once the outcome settles.
|
|
125
|
+
tierTrace: string | undefined;
|
|
126
|
+
// Phase 3 — standout toolbar state.
|
|
127
|
+
// Recall/activity ticker: a small ring buffer (≤5) of recent compact/recall
|
|
128
|
+
// events so the widget shows a live history instead of a single last action.
|
|
129
|
+
ticker: TickerEntry[] = [];
|
|
130
|
+
readonly TICKER_MAX = 5;
|
|
131
|
+
// Pulsing status: set true while a compaction is in flight, cleared on result.
|
|
132
|
+
pulsing = false;
|
|
133
|
+
// S21.2: set by `applyMemoryOps` when a memory add/replace/remove lands in
|
|
134
|
+
// the current compaction. The pipeline reads this after a successful compact
|
|
135
|
+
// to decide whether to fire `consolidateMemories` (skip the work entirely
|
|
136
|
+
// when no memory rows changed).
|
|
137
|
+
memoriesTouchedThisCompaction = 0;
|
|
138
|
+
// Rolling "saved" goal for the progress bar — grows as we save more, so the
|
|
139
|
+
// bar always has a meaningful denominator (never sits at 100% forever).
|
|
140
|
+
savedGoal = 50_000;
|
|
141
|
+
// Last explain-why line (dedup reason / anchor-kept / superseded), surfaced
|
|
142
|
+
// while fresh.
|
|
143
|
+
lastWhy: string | undefined = undefined;
|
|
144
|
+
// v0.8.8 Perf dashboard instrumentation: turn/provider start timestamps +
|
|
145
|
+
// the 5s cpu/mem interval handle (one per MegaRuntime, cleared in dispose()).
|
|
146
|
+
perfTurnStart = 0;
|
|
147
|
+
perfProviderStart = 0;
|
|
148
|
+
perfCpuInterval: ReturnType<typeof setInterval> | null = null;
|
|
149
|
+
perfCpuBaseline: { user: number; sys: number } | undefined;
|
|
150
|
+
|
|
151
|
+
// Context tracking for the dashboard (updated in the context handler).
|
|
152
|
+
lastCtxTokens: number | null = null;
|
|
153
|
+
lastCtxPercent: number | null = null;
|
|
154
|
+
lastCtxWindow = 0;
|
|
155
|
+
|
|
156
|
+
// Latest computed widget payload (recomputed per snapshot, rendered per frame).
|
|
157
|
+
widgetData: WidgetData | null = null;
|
|
158
|
+
// v0.8.5: material-change signature from the last full snapshot() body. When
|
|
159
|
+
// the next snapshot()'s signature matches, the expensive recompute (6 sync
|
|
160
|
+
// SQLite opens) + writeFileSync(dashboard.json) are skipped — only the
|
|
161
|
+
// (already-registered) widget factory is refreshed. Kills the per-event
|
|
162
|
+
// main-thread block during typing/idle streaming with no material change.
|
|
163
|
+
lastSnapshotSig: string | null = null;
|
|
164
|
+
lastHeartbeatAt: number = 0;
|
|
165
|
+
// v0.8.5: bumped whenever the cached game-state memo is evicted (bumpGameState
|
|
166
|
+
// for in-process /mega-game writes, the fs.watch callback for cross-process
|
|
167
|
+
// dashboard-server writes, and bindRepo on repo switch) so the snapshot gate
|
|
168
|
+
// invalidates and the widget re-reads theme/mode after the change.
|
|
169
|
+
gameStateBump = 0;
|
|
170
|
+
// Cached cross-repo drift status (recomputed at most every 30s — it opens the
|
|
171
|
+
// machine-wide registry DB, so we don't want to do it on every render frame).
|
|
172
|
+
driftCache: { at: number; status: "ok" | "warn" } | null = null;
|
|
173
|
+
// S31: cached game-mode state (game_mode_on/theme/tui_display_mode). Lazily
|
|
174
|
+
// read from the game_state SQLite row on the first widget render, then
|
|
175
|
+
// memoized until bumpGameState() evicts it (called by /mega-game after a
|
|
176
|
+
// write) so the widget picks up theme/mode/level changes live without
|
|
177
|
+
// re-querying the DB on every render frame.
|
|
178
|
+
cachedGameState: GameState | undefined;
|
|
179
|
+
// S32: fs.watch on the current repo's sqlite.db so cross-process writes
|
|
180
|
+
// (e.g. the dashboard server's PUT /api/game-state, which runs as a detached
|
|
181
|
+
// child with no MegaRuntime ref) evict the cached game-state memo. Without
|
|
182
|
+
// this, /mega-game's in-process bumpGameState() is the only eviction trigger
|
|
183
|
+
// and the widget would keep showing stale theme/mode/toggle after a dashboard
|
|
184
|
+
// edit until a restart. The watcher tracks currentStateDir — closed + re-opened
|
|
185
|
+
// by ensureGameStateWatcher() on every bindRepo repo switch. Non-fatal: any
|
|
186
|
+
// fs.watch failure (missing file / platform issue) is swallowed; the next
|
|
187
|
+
// getCachedGameState() snapshot re-queries the DB anyway.
|
|
188
|
+
gameStateWatcher?: FSWatcher;
|
|
189
|
+
gameStateWatchDir?: string;
|
|
190
|
+
// P2: the last ExtensionContext handed to snapshot()/renderWidget(), stashed
|
|
191
|
+
// so the fs.watch game-state callback can force a widget re-render without
|
|
192
|
+
// a context event (cross-process dashboard edits while pi is idle). Cleared
|
|
193
|
+
// implicitly on construction (undefined → watcher skips until first snap).
|
|
194
|
+
lastWidgetCtx?: ExtensionContext;
|
|
195
|
+
}
|