pi-mega-compact 0.20.24 → 0.20.26
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-vector-cortex-crystals.js +6 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-diagnostics.js +6 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-economics.js +6 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-eval.js +2 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-heal.js +9 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-health.js +4 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-ledger.js +2 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-outcomes.js +10 -2
- package/dist/extensions/dashboard-server/routes-vector-cortex-plans.js +2 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-platform.js +13 -2
- package/dist/extensions/dashboard-server/routes-vector-cortex-policy.js +6 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-query.js +2 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-reconstruct.js +5 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-render.js +2 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-repair.js +5 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-residual.js +2 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-rollout.js +56 -3
- package/dist/extensions/dashboard-server/routes-vector-cortex-shards.js +5 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-topology.js +2 -0
- package/dist/extensions/dashboard-server/server.js +4 -2
- package/dist/extensions/dashboard-server/vc-status.js +17 -0
- package/dist/extensions/mega-dashboard-bounce.js +79 -0
- package/dist/extensions/mega-dashboard-cmds.js +57 -24
- package/dist/extensions/mega-events/context-handler/afterCompact.js +2 -2
- package/dist/extensions/mega-events/context-handler/pipelineRun.js +17 -2
- package/dist/extensions/mega-events/register.js +17 -0
- package/dist/extensions/mega-pipeline/recall.js +11 -0
- package/extensions/dashboard-client/dist/assets/{AreaChart-BzEedilo.js → AreaChart-DRErPez1.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-BzEedilo.js.map → AreaChart-DRErPez1.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-CzAVg1_J.js → BarChart-Cwxel3M7.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-CzAVg1_J.js.map → BarChart-Cwxel3M7.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-D2-rzTuX.js → CacheTab-D4j3vwFu.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-D2-rzTuX.js.map → CacheTab-D4j3vwFu.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-DB7g1Szy.js → EventsTab-BA7t_fsH.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-DB7g1Szy.js.map → EventsTab-BA7t_fsH.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-Cvkmi-R3.js → HealthTab-Ci9gtYDP.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-Cvkmi-R3.js.map → HealthTab-Ci9gtYDP.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-g_udcOO7.js → MaintenanceTab-BeqWn-xu.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-g_udcOO7.js.map → MaintenanceTab-BeqWn-xu.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-DAjBaf8P.js → MemoryMapTab-BreZegCV.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-DAjBaf8P.js.map → MemoryMapTab-BreZegCV.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-13dYYocB.js → MetricsTab-DLbgfJT2.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-13dYYocB.js.map → MetricsTab-DLbgfJT2.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-CLpCyLvx.js → OverviewTab-BtcXdrnC.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-CLpCyLvx.js.map → OverviewTab-BtcXdrnC.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-EdAqUrwG.js → ReposTab-DpDLEzV9.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-EdAqUrwG.js.map → ReposTab-DpDLEzV9.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-C21ZuOL_.js → SessionsTab-CMe5jSrZ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-C21ZuOL_.js.map → SessionsTab-CMe5jSrZ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-CP7lE3L_.js → SetupTab-C3OY8mc7.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-CP7lE3L_.js.map → SetupTab-C3OY8mc7.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-DZ3QR8qt.js → TimeSavedCard-BFPJUQzs.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-DZ3QR8qt.js.map → TimeSavedCard-BFPJUQzs.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-CNchE5rD.js → TurnsTab-Ujt29pKI.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-CNchE5rD.js.map → TurnsTab-Ujt29pKI.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-CfxZW91A.js +2 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-CfxZW91A.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{WikiTab-BIe5Z9Nc.js → WikiTab-BiKXVwGT.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-BIe5Z9Nc.js.map → WikiTab-BiKXVwGT.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-BrVreSt5.js → button-DJwGcw0u.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-BrVreSt5.js.map → button-DJwGcw0u.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-D9F4wbqs.js → card-CgjBf5LZ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-D9F4wbqs.js.map → card-CgjBf5LZ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-mkdzCnMP.js → generateCategoricalChart-CTQIl2qs.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-mkdzCnMP.js.map → generateCategoricalChart-CTQIl2qs.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-CtlmOlj1.js → index-Bu8CZUMX.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{index-CtlmOlj1.js.map → index-Bu8CZUMX.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{switch-BXmp5iwA.js → switch-uUiS1Raq.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-BXmp5iwA.js.map → switch-uUiS1Raq.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-BgawNwW9.js → toggle-Dv3OEscH.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-BgawNwW9.js.map → toggle-Dv3OEscH.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-DZKX73Ea.js → useSSE-n6ymAic3.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-DZKX73Ea.js.map → useSSE-n6ymAic3.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/tabs/VcStatusBadge.tsx +24 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexClosureCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexCrystalsCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexDiagnosticsCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexEconomicsCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexLedgerCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexOutcomesCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexPlansCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexPlatformCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexPolicyCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexRenderCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexRepairCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexRestoreCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexRolloutCard.tsx +12 -6
- package/extensions/dashboard-client/src/tabs/VectorCortexShardsCard.tsx +23 -11
- package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +5 -7
- package/extensions/dashboard-client/src/tabs/VectorCortexTopologyCard.tsx +28 -14
- package/extensions/dashboard-client/src/types/vector-cortex-vc7.ts +6 -0
- package/extensions/dashboard-client/src/types/vector-cortex-vc8.ts +6 -0
- package/extensions/dashboard-client/src/types/vector-cortex.ts +26 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-cache.ts +2 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-diagnostics.ts +2 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-economics.ts +2 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-heal.ts +6 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-outcomes.ts +2 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-platform.ts +2 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-policy.ts +2 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex.ts +19 -0
- package/extensions/dashboard-server/routes-vector-cortex-crystals.ts +6 -0
- package/extensions/dashboard-server/routes-vector-cortex-diagnostics.ts +6 -0
- package/extensions/dashboard-server/routes-vector-cortex-economics.ts +6 -0
- package/extensions/dashboard-server/routes-vector-cortex-eval.ts +2 -0
- package/extensions/dashboard-server/routes-vector-cortex-heal.ts +9 -0
- package/extensions/dashboard-server/routes-vector-cortex-health.ts +4 -0
- package/extensions/dashboard-server/routes-vector-cortex-ledger.ts +2 -0
- package/extensions/dashboard-server/routes-vector-cortex-outcomes.ts +11 -2
- package/extensions/dashboard-server/routes-vector-cortex-plans.ts +2 -0
- package/extensions/dashboard-server/routes-vector-cortex-platform.ts +14 -2
- package/extensions/dashboard-server/routes-vector-cortex-policy.ts +6 -0
- package/extensions/dashboard-server/routes-vector-cortex-query.ts +2 -0
- package/extensions/dashboard-server/routes-vector-cortex-reconstruct.ts +5 -0
- package/extensions/dashboard-server/routes-vector-cortex-render.ts +2 -0
- package/extensions/dashboard-server/routes-vector-cortex-repair.ts +5 -0
- package/extensions/dashboard-server/routes-vector-cortex-residual.ts +2 -0
- package/extensions/dashboard-server/routes-vector-cortex-rollout.ts +58 -3
- package/extensions/dashboard-server/routes-vector-cortex-shards.ts +5 -0
- package/extensions/dashboard-server/routes-vector-cortex-topology.ts +2 -0
- package/extensions/dashboard-server/server.ts +4 -2
- package/extensions/dashboard-server/vc-status.ts +22 -0
- package/extensions/mega-dashboard-bounce.ts +97 -0
- package/extensions/mega-dashboard-cmds.ts +63 -24
- package/extensions/mega-events/context-handler/afterCompact.ts +2 -2
- package/extensions/mega-events/context-handler/pipelineRun.ts +18 -3
- package/extensions/mega-events/register.ts +14 -1
- package/extensions/mega-pipeline/recall.ts +10 -0
- package/package.json +1 -1
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-B3WuPeyn.js +0 -2
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-B3WuPeyn.js.map +0 -1
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
import { VC7A_ENABLED } from "../../src/config.js";
|
|
27
27
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
28
28
|
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
29
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
29
30
|
// Actual events emitted by src/vector-cortex/cache/crystal-emit.ts.
|
|
30
31
|
const CRYSTAL_EVENTS = [
|
|
31
32
|
"vector_cortex_crystal_written",
|
|
@@ -67,6 +68,11 @@ export function handleVectorCortexCrystals(req, res, ctx) {
|
|
|
67
68
|
lastFailure: null,
|
|
68
69
|
updatedAt: new Date().toISOString(),
|
|
69
70
|
deferredReason: "crystal_store_not_instantiated_v0_20_23",
|
|
71
|
+
status: deriveVcStatus({
|
|
72
|
+
enabled,
|
|
73
|
+
deferredReason: "crystal_store_not_instantiated_v0_20_23",
|
|
74
|
+
hasData: vcCount(counts, "vector_cortex_crystal_written") > 0,
|
|
75
|
+
}),
|
|
70
76
|
};
|
|
71
77
|
sendJson(res, 200, body);
|
|
72
78
|
return true;
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
import { VC7C_ENABLED } from "../../src/config.js";
|
|
29
29
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
30
30
|
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
31
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
31
32
|
// Actual events emitted by src/vector-cortex/cache/diagnostics-emit.ts.
|
|
32
33
|
const DIAGNOSTICS_EVENTS = ["vector_cortex_cache_serve_blocked"];
|
|
33
34
|
/**
|
|
@@ -67,6 +68,11 @@ export function handleVectorCortexDiagnostics(req, res, ctx) {
|
|
|
67
68
|
lastFailure: null,
|
|
68
69
|
updatedAt: new Date().toISOString(),
|
|
69
70
|
deferredReason: "cache_classifier_not_wired_v0_20_23",
|
|
71
|
+
status: deriveVcStatus({
|
|
72
|
+
enabled,
|
|
73
|
+
deferredReason: "cache_classifier_not_wired_v0_20_23",
|
|
74
|
+
hasData: vcCount(counts, "vector_cortex_cache_serve_blocked") > 0,
|
|
75
|
+
}),
|
|
70
76
|
};
|
|
71
77
|
sendJson(res, 200, body);
|
|
72
78
|
return true;
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
import { VC7B_ENABLED } from "../../src/config.js";
|
|
26
26
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
27
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
27
28
|
/**
|
|
28
29
|
* Reader-only GET /api/vector-cortex/cache-economics (VC7B).
|
|
29
30
|
*
|
|
@@ -54,6 +55,11 @@ export function handleVectorCortexEconomics(req, res, _ctx) {
|
|
|
54
55
|
lastFailure: null,
|
|
55
56
|
updatedAt: new Date().toISOString(),
|
|
56
57
|
deferredReason: "economics_not_computed_v0_20_23",
|
|
58
|
+
status: deriveVcStatus({
|
|
59
|
+
enabled,
|
|
60
|
+
deferredReason: "economics_not_computed_v0_20_23",
|
|
61
|
+
hasData: false,
|
|
62
|
+
}),
|
|
57
63
|
};
|
|
58
64
|
sendJson(res, 200, body);
|
|
59
65
|
return true;
|
|
@@ -13,6 +13,7 @@ import { VC0A_ENABLED } from "../../src/config.js";
|
|
|
13
13
|
import { readEvalRows } from "../../src/vector-cortex/eval/persist.js";
|
|
14
14
|
import { summarizeEvalRows } from "../../src/vector-cortex/eval/reader.js";
|
|
15
15
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
16
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
16
17
|
/** Reader-only aggregate GET /api/vector-cortex/evaluation. */
|
|
17
18
|
export function handleVectorCortexEvaluation(req, res, ctx) {
|
|
18
19
|
const url = req.url ?? "";
|
|
@@ -43,6 +44,7 @@ export function handleVectorCortexEvaluation(req, res, ctx) {
|
|
|
43
44
|
},
|
|
44
45
|
rejects: [], // VC0C wires live breaker/reject telemetry here
|
|
45
46
|
updatedAt: new Date().toISOString(),
|
|
47
|
+
status: deriveVcStatus({ enabled, hasData: summary.samples > 0 }),
|
|
46
48
|
};
|
|
47
49
|
sendJson(res, 200, body);
|
|
48
50
|
return true;
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { VC6A_ENABLED, VC6B_ENABLED } from "../../src/config.js";
|
|
23
23
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
24
24
|
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
25
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
25
26
|
// Actual event names emitted by src/vector-cortex/heal/emit.ts + restore-emit.ts.
|
|
26
27
|
const CLOSURE_EVENTS = [
|
|
27
28
|
"vector_cortex_closure_optimized",
|
|
@@ -56,6 +57,10 @@ export function handleVectorCortexClosureProof(req, res, ctx) {
|
|
|
56
57
|
optimizedTraversalTotal: 0,
|
|
57
58
|
lastRejection: null,
|
|
58
59
|
updatedAt: new Date().toISOString(),
|
|
60
|
+
status: deriveVcStatus({
|
|
61
|
+
enabled,
|
|
62
|
+
hasData: vcCount(counts, "vector_cortex_closure_optimized") > 0,
|
|
63
|
+
}),
|
|
59
64
|
};
|
|
60
65
|
sendJson(res, 200, body);
|
|
61
66
|
return true;
|
|
@@ -92,6 +97,10 @@ export function handleVectorCortexRestore(req, res, ctx) {
|
|
|
92
97
|
digestRejections: vcCount(counts, "vector_cortex_restore_digest_rejected"),
|
|
93
98
|
lastRejection: null,
|
|
94
99
|
updatedAt: new Date().toISOString(),
|
|
100
|
+
status: deriveVcStatus({
|
|
101
|
+
enabled,
|
|
102
|
+
hasData: vcCount(counts, "vector_cortex_source_restored") > 0,
|
|
103
|
+
}),
|
|
95
104
|
};
|
|
96
105
|
sendJson(res, 200, body);
|
|
97
106
|
return true;
|
|
@@ -16,6 +16,7 @@ import { VC0C_ENABLED, VC2C_ENABLED } from "../../src/config.js";
|
|
|
16
16
|
import { createVectorCortexSafety } from "../mega-runtime/vector-cortex-safety.js";
|
|
17
17
|
import { readEncoderManifest, verifyEncoderAsset, detectPlatform } from "../../src/vector-cortex/encoder/asset.js";
|
|
18
18
|
import { sendJson, readJsonBody } from "./routes-vector-cortex-shared.js";
|
|
19
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
19
20
|
/** Resolve the committed encoder-v1 asset dir by walking up to the repo root. */
|
|
20
21
|
function encoderAssetDir() {
|
|
21
22
|
let dir = dirname(fileURLToPath(import.meta.url));
|
|
@@ -137,6 +138,7 @@ export function handleVectorCortexHealth(req, res, ctx) {
|
|
|
137
138
|
stateSource: "ephemeral",
|
|
138
139
|
encoderAssetDigest: enc.assetDigest,
|
|
139
140
|
encoderMode: enc.mode,
|
|
141
|
+
status: deriveVcStatus({ enabled: false, hasData: false }),
|
|
140
142
|
};
|
|
141
143
|
if (!card) {
|
|
142
144
|
sendJson(res, 200, fallback);
|
|
@@ -174,6 +176,7 @@ export function handleVectorCortexHealth(req, res, ctx) {
|
|
|
174
176
|
stateSource: card.stateSource,
|
|
175
177
|
encoderAssetDigest: enc.assetDigest,
|
|
176
178
|
encoderMode: enc.mode,
|
|
179
|
+
status: deriveVcStatus({ enabled, hasData: true, structuralOnly: true }),
|
|
177
180
|
};
|
|
178
181
|
sendJson(res, 200, body);
|
|
179
182
|
return true;
|
|
@@ -222,6 +225,7 @@ export function handleVectorCortexBreakersReset(req, res, ctx) {
|
|
|
222
225
|
probeCount: rec.probeCount,
|
|
223
226
|
manualReason: rec.manualReason,
|
|
224
227
|
updatedAt: rec.updatedAt,
|
|
228
|
+
status: deriveVcStatus({ enabled: true, hasData: true }),
|
|
225
229
|
};
|
|
226
230
|
sendJson(res, 200, body);
|
|
227
231
|
}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { VC1B_ENABLED } from "../../src/config.js";
|
|
15
15
|
import { createLedgerStore } from "../../src/vector-cortex/ledger/store.js";
|
|
16
16
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
17
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
17
18
|
/**
|
|
18
19
|
* Reader-only GET /api/vector-cortex/ledger (VC1B).
|
|
19
20
|
*/
|
|
@@ -76,6 +77,7 @@ export function handleVectorCortexLedger(req, res, ctx) {
|
|
|
76
77
|
count,
|
|
77
78
|
occurrences,
|
|
78
79
|
updatedAt: new Date().toISOString(),
|
|
80
|
+
status: deriveVcStatus({ enabled: active, hasData: count > 0 }),
|
|
79
81
|
};
|
|
80
82
|
sendJson(res, 200, body);
|
|
81
83
|
return true;
|
|
@@ -18,11 +18,16 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { VC8A_ENABLED } from "../../src/config.js";
|
|
20
20
|
import { sendJson, readJsonBody } from "./routes-vector-cortex-shared.js";
|
|
21
|
+
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
22
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
23
|
+
// Actual events emitted by src/vector-cortex/outcomes/* — the outcome append is
|
|
24
|
+
// the sole aggregate signal (consent grants/revokes are not emitted as events).
|
|
25
|
+
const OUTCOME_EVENTS = ["vector_cortex_outcome_appended"];
|
|
21
26
|
/**
|
|
22
27
|
* GET /api/vector-cortex/outcomes — reader-only outcomes aggregate (VC8A).
|
|
23
28
|
* POST /api/vector-cortex/outcomes/consent — audited consent admin API.
|
|
24
29
|
*/
|
|
25
|
-
export function handleVectorCortexOutcomes(req, res,
|
|
30
|
+
export function handleVectorCortexOutcomes(req, res, ctx) {
|
|
26
31
|
const url = req.url ?? "";
|
|
27
32
|
const path = url.split("?")[0] ?? url;
|
|
28
33
|
if (path === "/api/vector-cortex/outcomes/consent") {
|
|
@@ -62,17 +67,20 @@ export function handleVectorCortexOutcomes(req, res, _ctx) {
|
|
|
62
67
|
return true;
|
|
63
68
|
}
|
|
64
69
|
const enabled = VC8A_ENABLED();
|
|
70
|
+
const counts = countVcEvents(ctx.stateDir, OUTCOME_EVENTS);
|
|
71
|
+
const outcomeCount = vcCount(counts, "vector_cortex_outcome_appended");
|
|
65
72
|
const mode = enabled ? "A" : "C";
|
|
66
73
|
const body = {
|
|
67
74
|
enabled,
|
|
68
75
|
mode,
|
|
69
|
-
outcomeCount
|
|
76
|
+
outcomeCount,
|
|
70
77
|
consentedSessions: 0,
|
|
71
78
|
revokedSessions: 0,
|
|
72
79
|
manifestCount: 0,
|
|
73
80
|
excludedCount: 0,
|
|
74
81
|
lastFailure: null,
|
|
75
82
|
updatedAt: new Date().toISOString(),
|
|
83
|
+
status: deriveVcStatus({ enabled, hasData: outcomeCount > 0 }),
|
|
76
84
|
};
|
|
77
85
|
sendJson(res, 200, body);
|
|
78
86
|
return true;
|
|
@@ -23,6 +23,7 @@ import { VC5A_ENABLED } from "../../src/config.js";
|
|
|
23
23
|
import { DAG_IDS } from "../../src/vector-cortex/prompt-dag/types.js";
|
|
24
24
|
import { PLN_IDS } from "../../src/vector-cortex/planner/types.js";
|
|
25
25
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
26
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
26
27
|
/**
|
|
27
28
|
* Reader-only GET /api/vector-cortex/plans (VC5A).
|
|
28
29
|
*/
|
|
@@ -43,6 +44,7 @@ export function handleVectorCortexPlans(req, res, _ctx) {
|
|
|
43
44
|
plannerCount: enabled ? PLN_IDS.length : 0,
|
|
44
45
|
plans: [],
|
|
45
46
|
updatedAt: new Date().toISOString(),
|
|
47
|
+
status: deriveVcStatus({ enabled, hasData: true, structuralOnly: true }),
|
|
46
48
|
};
|
|
47
49
|
sendJson(res, 200, body);
|
|
48
50
|
return true;
|
|
@@ -15,8 +15,16 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { VC8C_ENABLED } from "../../src/config.js";
|
|
17
17
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
18
|
+
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
19
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
20
|
+
// Actual events emitted by src/vector-cortex/platform/* — a parity run checks
|
|
21
|
+
// fixtures and a demotion records an engine-selection downgrade.
|
|
22
|
+
const PLATFORM_EVENTS = [
|
|
23
|
+
"vector_cortex_engine_parity_checked",
|
|
24
|
+
"vector_cortex_engine_selection_demoted",
|
|
25
|
+
];
|
|
18
26
|
/** GET /api/vector-cortex/platform — reader-only engine parity/selection aggregate (VC8C). */
|
|
19
|
-
export function handleVectorCortexPlatform(req, res,
|
|
27
|
+
export function handleVectorCortexPlatform(req, res, ctx) {
|
|
20
28
|
const url = req.url ?? "";
|
|
21
29
|
const path = url.split("?")[0] ?? url;
|
|
22
30
|
if (path !== "/api/vector-cortex/platform")
|
|
@@ -26,16 +34,19 @@ export function handleVectorCortexPlatform(req, res, _ctx) {
|
|
|
26
34
|
return true;
|
|
27
35
|
}
|
|
28
36
|
const enabled = VC8C_ENABLED();
|
|
37
|
+
const counts = countVcEvents(ctx.stateDir, PLATFORM_EVENTS);
|
|
29
38
|
const mode = enabled ? "A" : "C";
|
|
39
|
+
const fixtureCount = vcCount(counts, "vector_cortex_engine_parity_checked");
|
|
30
40
|
const body = {
|
|
31
41
|
enabled,
|
|
32
42
|
mode,
|
|
33
|
-
fixtureCount
|
|
43
|
+
fixtureCount,
|
|
34
44
|
passed: 0,
|
|
35
45
|
failed: 0,
|
|
36
46
|
externalRunnerConfigured: process.env.MEGACOMPACT_RUST_RUNNER !== undefined,
|
|
37
47
|
lastFailure: null,
|
|
38
48
|
updatedAt: new Date().toISOString(),
|
|
49
|
+
status: deriveVcStatus({ enabled, hasData: fixtureCount > 0 }),
|
|
39
50
|
};
|
|
40
51
|
sendJson(res, 200, body);
|
|
41
52
|
return true;
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { VC8B_ENABLED } from "../../src/config.js";
|
|
19
19
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
20
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
20
21
|
/** GET /api/vector-cortex/policy — reader-only policy + shadow aggregate (VC8B). */
|
|
21
22
|
export function handleVectorCortexPolicy(req, res, _ctx) {
|
|
22
23
|
const url = req.url ?? "";
|
|
@@ -40,6 +41,11 @@ export function handleVectorCortexPolicy(req, res, _ctx) {
|
|
|
40
41
|
lastFailure: null,
|
|
41
42
|
updatedAt: new Date().toISOString(),
|
|
42
43
|
deferredReason: "shadow_controller_not_instantiated_v0_20_23",
|
|
44
|
+
status: deriveVcStatus({
|
|
45
|
+
enabled,
|
|
46
|
+
deferredReason: "shadow_controller_not_instantiated_v0_20_23",
|
|
47
|
+
hasData: false,
|
|
48
|
+
}),
|
|
43
49
|
};
|
|
44
50
|
sendJson(res, 200, body);
|
|
45
51
|
return true;
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { VC3C_ENABLED } from "../../src/config.js";
|
|
16
16
|
import { ROUTER_KEY_VERSION } from "../../src/vector-cortex/topology/query.js";
|
|
17
17
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
18
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
18
19
|
/**
|
|
19
20
|
* Reader-only GET /api/vector-cortex/query (VC3C query-layer diagnostics).
|
|
20
21
|
*/
|
|
@@ -40,6 +41,7 @@ export function handleVectorCortexQuery(req, res, _ctx) {
|
|
|
40
41
|
enabled,
|
|
41
42
|
routerVersion: ROUTER_KEY_VERSION,
|
|
42
43
|
updatedAt: new Date().toISOString(),
|
|
44
|
+
status: deriveVcStatus({ enabled, hasData: true, structuralOnly: true }),
|
|
43
45
|
};
|
|
44
46
|
sendJson(res, 200, body);
|
|
45
47
|
return true;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { VC4C_ENABLED } from "../../src/config.js";
|
|
10
10
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
11
11
|
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
12
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
12
13
|
// Closure attempt/rejection events emitted by src/vector-cortex/heal/emit.ts.
|
|
13
14
|
const RECONSTRUCT_EVENTS = [
|
|
14
15
|
"vector_cortex_closure_optimized",
|
|
@@ -34,6 +35,10 @@ export function handleVectorCortexReconstruct(req, res, ctx) {
|
|
|
34
35
|
spanTotal: 0,
|
|
35
36
|
byteTotal: 0,
|
|
36
37
|
updatedAt: new Date().toISOString(),
|
|
38
|
+
status: deriveVcStatus({
|
|
39
|
+
enabled,
|
|
40
|
+
hasData: vcCount(counts, "vector_cortex_closure_optimized") > 0,
|
|
41
|
+
}),
|
|
37
42
|
};
|
|
38
43
|
sendJson(res, 200, body);
|
|
39
44
|
return true;
|
|
@@ -17,6 +17,7 @@ import { REN_IDS } from "../../src/vector-cortex/render/types.js";
|
|
|
17
17
|
import { PRO_IDS } from "../../src/vector-cortex/provider/types.js";
|
|
18
18
|
import { KNOWN_PROVIDER_KEYS } from "../../src/vector-cortex/provider/registry.js";
|
|
19
19
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
20
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
20
21
|
/** Reader-only GET /api/vector-cortex/render (VC5B). */
|
|
21
22
|
export function handleVectorCortexRender(req, res, _ctx) {
|
|
22
23
|
const url = req.url ?? "";
|
|
@@ -34,6 +35,7 @@ export function handleVectorCortexRender(req, res, _ctx) {
|
|
|
34
35
|
providerCount: enabled ? PRO_IDS.length : 0,
|
|
35
36
|
knownProfiles: enabled ? KNOWN_PROVIDER_KEYS : [],
|
|
36
37
|
updatedAt: new Date().toISOString(),
|
|
38
|
+
status: deriveVcStatus({ enabled, hasData: true, structuralOnly: true }),
|
|
37
39
|
};
|
|
38
40
|
sendJson(res, 200, body);
|
|
39
41
|
return true;
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
import { VC6C_ENABLED } from "../../src/config.js";
|
|
24
24
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
25
25
|
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
26
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
26
27
|
// Actual event names emitted by src/vector-cortex/heal/repair-emit.ts.
|
|
27
28
|
const REPAIR_EVENTS = [
|
|
28
29
|
"vector_cortex_repair_planned",
|
|
@@ -65,6 +66,10 @@ export function handleVectorCortexRepair(req, res, ctx) {
|
|
|
65
66
|
lastBackoffMs: null,
|
|
66
67
|
lastFailure: null,
|
|
67
68
|
updatedAt: new Date().toISOString(),
|
|
69
|
+
status: deriveVcStatus({
|
|
70
|
+
enabled,
|
|
71
|
+
hasData: vcCount(counts, "vector_cortex_repair_planned") > 0,
|
|
72
|
+
}),
|
|
68
73
|
};
|
|
69
74
|
sendJson(res, 200, body);
|
|
70
75
|
return true;
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { VC4B_ENABLED } from "../../src/config.js";
|
|
22
22
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
23
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
23
24
|
/**
|
|
24
25
|
* Reader-only GET /api/vector-cortex/residual (VC4B).
|
|
25
26
|
*/
|
|
@@ -45,6 +46,7 @@ export function handleVectorCortexResidual(req, res, _ctx) {
|
|
|
45
46
|
encodedByteTotal: 0,
|
|
46
47
|
exactByteTotal: 0,
|
|
47
48
|
updatedAt: new Date().toISOString(),
|
|
49
|
+
status: deriveVcStatus({ enabled, hasData: false, structuralOnly: true }),
|
|
48
50
|
};
|
|
49
51
|
sendJson(res, 200, body);
|
|
50
52
|
return true;
|
|
@@ -11,11 +11,22 @@
|
|
|
11
11
|
* Guardrails: PREVENT-PI-004 (local in-process state only), PREVENT-011 (no
|
|
12
12
|
* `any`), reader-only aggregate (counts + gate state only).
|
|
13
13
|
*/
|
|
14
|
+
import { readFileSync } from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
14
16
|
import { VC5C_ENABLED } from "../../src/config.js";
|
|
15
17
|
import { ROLLOUT_GATES, ROLLOUT_BUCKETS } from "../../src/vector-cortex/rollout/types.js";
|
|
16
18
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
19
|
+
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
20
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
21
|
+
// Rollout events: assigned/promotion-blocked from rollout/emit.ts, plus the
|
|
22
|
+
// explicit decision event appended by pipelineRun.ts:79 after decideLivePath.
|
|
23
|
+
const ROLLOUT_EVENTS = [
|
|
24
|
+
"vector_cortex_rollout_assigned",
|
|
25
|
+
"vector_cortex_rollout_promotion_blocked",
|
|
26
|
+
"vector_cortex_rollout_decision",
|
|
27
|
+
];
|
|
17
28
|
/** Reader-only GET /api/vector-cortex/rollout (VC5C). */
|
|
18
|
-
export function handleVectorCortexRollout(req, res,
|
|
29
|
+
export function handleVectorCortexRollout(req, res, ctx) {
|
|
19
30
|
const url = req.url ?? "";
|
|
20
31
|
const path = url.split("?")[0] ?? url;
|
|
21
32
|
if (path !== "/api/vector-cortex/rollout")
|
|
@@ -25,6 +36,11 @@ export function handleVectorCortexRollout(req, res, _ctx) {
|
|
|
25
36
|
return true;
|
|
26
37
|
}
|
|
27
38
|
const enabled = VC5C_ENABLED();
|
|
39
|
+
const counts = countVcEvents(ctx.stateDir, ROLLOUT_EVENTS);
|
|
40
|
+
const eventCount = vcCount(counts, "vector_cortex_rollout_assigned") +
|
|
41
|
+
vcCount(counts, "vector_cortex_rollout_promotion_blocked") +
|
|
42
|
+
vcCount(counts, "vector_cortex_rollout_decision");
|
|
43
|
+
const sessionCount = enabled ? distinctRolloutSessions(ctx.stateDir) : 0;
|
|
28
44
|
const gateIndex = 0; // Ephemeral rollout state: no durable gate in this sprint.
|
|
29
45
|
const gatePct = ROLLOUT_GATES[gateIndex];
|
|
30
46
|
const body = {
|
|
@@ -33,11 +49,48 @@ export function handleVectorCortexRollout(req, res, _ctx) {
|
|
|
33
49
|
gatePct: enabled ? gatePct : 0,
|
|
34
50
|
buckets: ROLLOUT_BUCKETS,
|
|
35
51
|
bucketCount: enabled ? gatePct * 100 : 0,
|
|
36
|
-
events: 0,
|
|
37
|
-
sessions: 0,
|
|
52
|
+
events: enabled ? eventCount : 0,
|
|
53
|
+
sessions: enabled ? sessionCount : 0,
|
|
38
54
|
promotionBlocked: false,
|
|
39
55
|
updatedAt: new Date().toISOString(),
|
|
56
|
+
status: deriveVcStatus({ enabled, hasData: eventCount > 0 }),
|
|
40
57
|
};
|
|
41
58
|
sendJson(res, 200, body);
|
|
42
59
|
return true;
|
|
43
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Count distinct session ids among rollout_assigned events in the tail of
|
|
63
|
+
* events.log. Best-effort: a missing/unreadable log or malformed lines yield 0.
|
|
64
|
+
* Only the `sessionId` field of rollout_assigned lines is inspected (aggregate
|
|
65
|
+
* only, never session payloads/prompts).
|
|
66
|
+
*/
|
|
67
|
+
function distinctRolloutSessions(stateDir) {
|
|
68
|
+
const seen = new Set();
|
|
69
|
+
let raw;
|
|
70
|
+
try {
|
|
71
|
+
raw = readFileSync(join(stateDir, "events.log"), "utf-8");
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
const lines = raw.split("\n");
|
|
77
|
+
const start = Math.max(0, lines.length - 10000);
|
|
78
|
+
for (let i = start; i < lines.length; i++) {
|
|
79
|
+
const line = lines[i];
|
|
80
|
+
if (line.length === 0)
|
|
81
|
+
continue;
|
|
82
|
+
let ev = null;
|
|
83
|
+
try {
|
|
84
|
+
ev = JSON.parse(line);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (ev?.event === "vector_cortex_rollout_assigned" &&
|
|
90
|
+
typeof ev.sessionId === "string" &&
|
|
91
|
+
ev.sessionId.length > 0) {
|
|
92
|
+
seen.add(ev.sessionId);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return seen.size;
|
|
96
|
+
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import { VC4A_ENABLED } from "../../src/config.js";
|
|
21
21
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
22
22
|
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
23
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
23
24
|
// Actual events emitted by src/vector-cortex/shards/manifest.ts. VC4A has no
|
|
24
25
|
// per-tier (semantic/exact) write event — the manifest build is the single
|
|
25
26
|
// shard-write signal — so semanticCount is wired to it and exactCount stays 0
|
|
@@ -50,6 +51,10 @@ export function handleVectorCortexShards(req, res, ctx) {
|
|
|
50
51
|
byteTotal: 0,
|
|
51
52
|
protectedByteTotal: 0,
|
|
52
53
|
updatedAt: new Date().toISOString(),
|
|
54
|
+
status: deriveVcStatus({
|
|
55
|
+
enabled,
|
|
56
|
+
hasData: vcCount(counts, "vector_cortex_shard_manifest_built") > 0,
|
|
57
|
+
}),
|
|
53
58
|
};
|
|
54
59
|
sendJson(res, 200, body);
|
|
55
60
|
return true;
|
|
@@ -26,6 +26,7 @@ import { Logger } from "../../src/log.js";
|
|
|
26
26
|
import { createCortexStore } from "../../src/vector-cortex/cortex/store.js";
|
|
27
27
|
import { buildTopologyGraph } from "../../src/vector-cortex/topology/index.js";
|
|
28
28
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
29
|
+
import { deriveVcStatus } from "./vc-status.js";
|
|
29
30
|
/** Well-known cortex record kind that carries a canonical candidate payload. */
|
|
30
31
|
const TOPOLOGY_RECORD_KIND = "topology";
|
|
31
32
|
/**
|
|
@@ -88,6 +89,7 @@ export function handleVectorCortexTopology(req, res, ctx) {
|
|
|
88
89
|
? { nodes, edges, generationDigest }
|
|
89
90
|
: {}),
|
|
90
91
|
updatedAt: new Date().toISOString(),
|
|
92
|
+
status: deriveVcStatus({ enabled: active, hasData: summary.recordCount > 0 }),
|
|
91
93
|
};
|
|
92
94
|
sendJson(res, 200, body);
|
|
93
95
|
return true;
|
|
@@ -254,9 +254,11 @@ export async function launchDashboardServer(stateDir) {
|
|
|
254
254
|
}));
|
|
255
255
|
v6.listen(port, "::1", () => log("ipv6 loopback bound", { port })); // guardrails-allow PREVENT-PI-004: IPv6 loopback (::1) mirror of the dashboard server
|
|
256
256
|
}
|
|
257
|
-
// Write port.pid
|
|
257
|
+
// Write port.pid (VC0F B2: stamp `version` so the launcher can detect
|
|
258
|
+
// a stale runner by comparing the marker against its own version
|
|
259
|
+
// without an HTTP probe — closes the orphan case for pre-B2 servers).
|
|
258
260
|
try {
|
|
259
|
-
writeFileSync(portFile, JSON.stringify({ port, pid: process.pid }));
|
|
261
|
+
writeFileSync(portFile, JSON.stringify({ port, pid: process.pid, version: SERVER_VERSION }));
|
|
260
262
|
}
|
|
261
263
|
catch (e) {
|
|
262
264
|
log("could not write port.pid", { error: String(e) });
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/vc-status.ts — shared status derivation for Vector Cortex
|
|
3
|
+
* dashboard routes. Every VC route computes a status field so the client can
|
|
4
|
+
* show meaningful state (live / awaiting data / deferred / structural) instead
|
|
5
|
+
* of bare zeros.
|
|
6
|
+
*
|
|
7
|
+
* Guardrails: PREVENT-011 (no `any`).
|
|
8
|
+
*/
|
|
9
|
+
export function deriveVcStatus(opts) {
|
|
10
|
+
if (!opts.enabled)
|
|
11
|
+
return "off";
|
|
12
|
+
if (opts.deferredReason)
|
|
13
|
+
return "deferred";
|
|
14
|
+
if (opts.structuralOnly)
|
|
15
|
+
return "structural";
|
|
16
|
+
return opts.hasData ? "live" : "awaiting_data";
|
|
17
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mega-dashboard-bounce.ts — VC0F stale-runner detection + bounce.
|
|
3
|
+
*
|
|
4
|
+
* Delegate of `mega-dashboard-cmds.ts` (kept under the extensions/ soft limit):
|
|
5
|
+
* owns the once-per-process staleness gate and the pure
|
|
6
|
+
* `bounceStaleRunnerIfAny` decision, which is the durable restart-on-upgrade
|
|
7
|
+
* seam — after `pi update --extensions` replaces the on-disk package, the next
|
|
8
|
+
* `session_start` probes the running dashboard, sees the version mismatch, and
|
|
9
|
+
* kills + respawns the stale runner so it serves the current code.
|
|
10
|
+
*
|
|
11
|
+
* The function is dependency-injected so unit tests (VC0F C1–C3) can stub every
|
|
12
|
+
* primitive; the production wiring (live discovery / version / kill) lives in
|
|
13
|
+
* `mega-dashboard-cmds.ts` and is passed in. No network here — the localhost
|
|
14
|
+
* HTTP probes live behind the injected `isServerRunning`/`serverVersion` deps
|
|
15
|
+
* (already audited PREVENT-PI-004 in the parent file).
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Once-per-process staleness gate (VC0F A2). After the FIRST successful probe
|
|
19
|
+
* we skip re-probing on later /mega-dashboard invocations or session-start
|
|
20
|
+
* events within the same extension process — the probe is cheap but the
|
|
21
|
+
* kill+respawn it triggers is disruptive. Set regardless of outcome.
|
|
22
|
+
*/
|
|
23
|
+
let stalenessCheckedThisProcess = false;
|
|
24
|
+
/** Test-only seam: clear the once-per-process gate between unit tests. */
|
|
25
|
+
export function resetStalenessGateForTests() {
|
|
26
|
+
stalenessCheckedThisProcess = false;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Detect + replace a STALE dashboard runner for the current repo (VC0F A1).
|
|
30
|
+
*
|
|
31
|
+
* A runner is stale when it is an orphan (live but missing its port.pid
|
|
32
|
+
* marker), when its marker's stamped `version` differs from this extension's
|
|
33
|
+
* own version (VC0F B2 — avoids the HTTP probe), or when the version it
|
|
34
|
+
* reports over HTTP differs from our own (fallback for pre-B2 servers whose
|
|
35
|
+
* marker has no `version` field). A stale runner is killed so the next launch
|
|
36
|
+
* serves the current on-disk code.
|
|
37
|
+
*
|
|
38
|
+
* Best-effort and non-fatal (Goal 4): any failure returns `{bounced:false}`
|
|
39
|
+
* and never throws. Runs at most once per extension process (A2).
|
|
40
|
+
*/
|
|
41
|
+
export async function bounceStaleRunnerIfAny(deps) {
|
|
42
|
+
if (stalenessCheckedThisProcess)
|
|
43
|
+
return { bounced: false };
|
|
44
|
+
try {
|
|
45
|
+
stalenessCheckedThisProcess = true; // once per process, regardless of outcome
|
|
46
|
+
const info = await deps.isServerRunning();
|
|
47
|
+
if (!info)
|
|
48
|
+
return { bounced: false };
|
|
49
|
+
const orphan = !info.hasPidFile;
|
|
50
|
+
const want = deps.ownVersion();
|
|
51
|
+
const marker = deps.markerVersion();
|
|
52
|
+
let stale;
|
|
53
|
+
let from = null;
|
|
54
|
+
if (orphan) {
|
|
55
|
+
stale = true; // live server with no marker → orphan by definition
|
|
56
|
+
}
|
|
57
|
+
else if (want != null && marker != null) {
|
|
58
|
+
stale = marker !== want; // B2: compare the stamped marker, skip the HTTP probe
|
|
59
|
+
from = marker;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const running = await deps.serverVersion(info.port);
|
|
63
|
+
from = running;
|
|
64
|
+
stale = want != null && running != null && running !== want;
|
|
65
|
+
}
|
|
66
|
+
if (stale) {
|
|
67
|
+
deps.notify(orphan
|
|
68
|
+
? "[mega-compact] replacing orphaned dashboard server…"
|
|
69
|
+
: `[mega-compact] replacing stale dashboard (${from ?? "?"} → ${want ?? "?"})…`);
|
|
70
|
+
deps.killServerOnPort(info.port);
|
|
71
|
+
return { bounced: true };
|
|
72
|
+
}
|
|
73
|
+
return { bounced: false };
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Best-effort, non-fatal — a failed probe/kill never breaks the caller.
|
|
77
|
+
return { bounced: false };
|
|
78
|
+
}
|
|
79
|
+
}
|