pi-mega-compact 0.20.18 → 0.20.20
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-vc8c.js +31 -0
- package/dist/config/vector-cortex.js +19 -0
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/api-contracts/vector-cortex-platform.js +12 -0
- package/dist/extensions/dashboard-server/api-contracts/vector-cortex-policy.js +12 -0
- package/dist/extensions/dashboard-server/route-dispatch.js +12 -0
- package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +2 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-platform.js +42 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-policy.js +45 -0
- package/dist/src/config/vector-cortex-vc8c.js +31 -0
- package/dist/src/config/vector-cortex.js +19 -0
- package/dist/src/config.js +1 -1
- package/dist/src/vector-cortex/cache/_diagnostics-fixture.js +79 -5
- package/dist/src/vector-cortex/cache/diagnostics.js +17 -8
- package/dist/src/vector-cortex/controller/_adaptive-fixture.js +126 -0
- package/dist/src/vector-cortex/controller/policy-emit.js +56 -0
- package/dist/src/vector-cortex/migrations/pressure-v2-ops.js +166 -0
- package/dist/src/vector-cortex/migrations/pressure-v2-types.js +32 -0
- package/dist/src/vector-cortex/migrations/pressure-v2.js +36 -0
- package/dist/src/vector-cortex/migrations/request-hash-v2-ops.js +23 -7
- package/dist/src/vector-cortex/platform/cross-read.js +98 -0
- package/dist/src/vector-cortex/platform/emit.js +54 -0
- package/dist/src/vector-cortex/platform/select.js +104 -0
- package/dist/src/vector-cortex/platform/types.js +57 -0
- package/dist/vector-cortex/cache/_diagnostics-fixture.js +79 -5
- package/dist/vector-cortex/cache/diagnostics.js +17 -8
- package/dist/vector-cortex/controller/_adaptive-fixture.js +126 -0
- package/dist/vector-cortex/controller/policy-emit.js +56 -0
- package/dist/vector-cortex/controller/policy.js +158 -0
- package/dist/vector-cortex/controller/shadow.js +117 -0
- package/dist/vector-cortex/controller/types.js +85 -0
- package/dist/vector-cortex/migrations/pressure-v2-ops.js +166 -0
- package/dist/vector-cortex/migrations/pressure-v2-types.js +32 -0
- package/dist/vector-cortex/migrations/pressure-v2.js +36 -0
- package/dist/vector-cortex/migrations/request-hash-v2-ops.js +23 -7
- package/dist/vector-cortex/platform/cross-read.js +98 -0
- package/dist/vector-cortex/platform/emit.js +54 -0
- package/dist/vector-cortex/platform/select.js +104 -0
- package/dist/vector-cortex/platform/types.js +57 -0
- package/extensions/dashboard-client/dist/assets/{AreaChart-BOGp2sag.js → AreaChart-BkfB-LSQ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-BOGp2sag.js.map → AreaChart-BkfB-LSQ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-BHgA-QPL.js → BarChart-Cs1kogko.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-BHgA-QPL.js.map → BarChart-Cs1kogko.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-6E7lwM74.js → CacheTab-BZgaguGr.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-6E7lwM74.js.map → CacheTab-BZgaguGr.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-BEtNmFHz.js → EventsTab-BFbkI_MO.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-BEtNmFHz.js.map → EventsTab-BFbkI_MO.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-DGxZulRH.js → HealthTab-CvlOENCX.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-DGxZulRH.js.map → HealthTab-CvlOENCX.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-C86jppQE.js → MaintenanceTab-CtBuz2qL.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-C86jppQE.js.map → MaintenanceTab-CtBuz2qL.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-J3VVxooZ.js → MemoryMapTab-K4775S4d.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-J3VVxooZ.js.map → MemoryMapTab-K4775S4d.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-yn9AFumo.js → MetricsTab-DVGcFInz.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-yn9AFumo.js.map → MetricsTab-DVGcFInz.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-BMarUiq3.js → OverviewTab-4LmW5ZCl.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-BMarUiq3.js.map → OverviewTab-4LmW5ZCl.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-DxnzMive.js → ReposTab-StebchgQ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-DxnzMive.js.map → ReposTab-StebchgQ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DXKpDUuC.js → SessionsTab-C3D_XAkX.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DXKpDUuC.js.map → SessionsTab-C3D_XAkX.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-BctuV-CJ.js → SetupTab-BTBGyppF.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-BctuV-CJ.js.map → SetupTab-BTBGyppF.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-D8yOC96S.js → TimeSavedCard-CTPi_AAW.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-D8yOC96S.js.map → TimeSavedCard-CTPi_AAW.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-BBxqGYH-.js → TurnsTab-DSOGcY5Q.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-BBxqGYH-.js.map → TurnsTab-DSOGcY5Q.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-OMW8_RFf.js +2 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-OMW8_RFf.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{WikiTab-DdJQSagO.js → WikiTab-Db-qFDdg.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-DdJQSagO.js.map → WikiTab-Db-qFDdg.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-B4Q9h_8Y.js → button-BF4UgBAD.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-B4Q9h_8Y.js.map → button-BF4UgBAD.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-WyR31hUV.js → card-XmXoYQqB.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-WyR31hUV.js.map → card-XmXoYQqB.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-pTio6Bq3.js → generateCategoricalChart-Be8hM1aU.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-pTio6Bq3.js.map → generateCategoricalChart-Be8hM1aU.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/index-Difwoltx.css +1 -0
- package/extensions/dashboard-client/dist/assets/{index-BoLUiNsd.js → index-NXDgILxv.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{index-BoLUiNsd.js.map → index-NXDgILxv.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{switch-5dieXxoo.js → switch-kUZCrbia.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-5dieXxoo.js.map → switch-kUZCrbia.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-BFc-7_LL.js → toggle-DEe5mCwF.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-BFc-7_LL.js.map → toggle-DEe5mCwF.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-BqmKNBAI.js → useSSE-BlCyLqge.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-BqmKNBAI.js.map → useSSE-BlCyLqge.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +2 -2
- package/extensions/dashboard-client/src/api/vector-cortex.ts +18 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexPlatformCard.tsx +42 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexPolicyCard.tsx +43 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +4 -0
- package/extensions/dashboard-client/src/tabs/useVectorCortexPoll.ts +10 -0
- package/extensions/dashboard-client/src/types/vector-cortex-vc8.ts +34 -1
- package/extensions/dashboard-client/src/types/vector-cortex.ts +1 -1
- package/extensions/dashboard-server/api-contracts/vector-cortex-platform.ts +34 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-policy.ts +36 -0
- package/extensions/dashboard-server/route-dispatch.ts +12 -0
- package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +12 -0
- package/extensions/dashboard-server/routes-vector-cortex-platform.ts +52 -0
- package/extensions/dashboard-server/routes-vector-cortex-policy.ts +55 -0
- package/package.json +1 -1
- package/src/config/vector-cortex-vc8c.ts +33 -0
- package/src/config/vector-cortex.ts +21 -0
- package/src/config.ts +2 -0
- package/src/vector-cortex/cache/_diagnostics-fixture.ts +163 -5
- package/src/vector-cortex/cache/diagnostics.ts +18 -9
- package/src/vector-cortex/controller/_adaptive-fixture.ts +230 -0
- package/src/vector-cortex/controller/policy-emit.ts +82 -0
- package/src/vector-cortex/migrations/pressure-v2-ops.ts +204 -0
- package/src/vector-cortex/migrations/pressure-v2-types.ts +83 -0
- package/src/vector-cortex/migrations/pressure-v2.ts +59 -0
- package/src/vector-cortex/migrations/request-hash-v2-ops.ts +21 -6
- package/src/vector-cortex/platform/cross-read.ts +122 -0
- package/src/vector-cortex/platform/emit.ts +77 -0
- package/src/vector-cortex/platform/select.ts +131 -0
- package/src/vector-cortex/platform/types.ts +169 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-BTF1AGCJ.js +0 -2
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-BTF1AGCJ.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-CYpzq9Lm.css +0 -1
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
fetchVectorCortexEconomics,
|
|
21
21
|
fetchVectorCortexDiagnostics,
|
|
22
22
|
fetchVectorCortexOutcomes,
|
|
23
|
+
fetchVectorCortexPolicy,
|
|
24
|
+
fetchVectorCortexPlatform,
|
|
23
25
|
fetchVectorCortexShards,
|
|
24
26
|
fetchVectorCortexTopology,
|
|
25
27
|
type VectorCortexEvaluationSummary,
|
|
@@ -37,6 +39,8 @@ import {
|
|
|
37
39
|
type VectorCortexEconomicsView,
|
|
38
40
|
type VectorCortexDiagnosticsView,
|
|
39
41
|
type VectorCortexOutcomesView,
|
|
42
|
+
type VectorCortexPolicyView,
|
|
43
|
+
type VectorCortexPlatformView,
|
|
40
44
|
type VectorCortexShardsView,
|
|
41
45
|
type VectorCortexTopologyView,
|
|
42
46
|
} from "../api/vector-cortex";
|
|
@@ -61,6 +65,8 @@ export interface VectorCortexPollState {
|
|
|
61
65
|
economics: VectorCortexEconomicsView | null;
|
|
62
66
|
diagnostics: VectorCortexDiagnosticsView | null;
|
|
63
67
|
outcomes: VectorCortexOutcomesView | null;
|
|
68
|
+
policy: VectorCortexPolicyView | null;
|
|
69
|
+
platform: VectorCortexPlatformView | null;
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
export function useVectorCortexPoll(): [
|
|
@@ -87,6 +93,8 @@ export function useVectorCortexPoll(): [
|
|
|
87
93
|
economics: null,
|
|
88
94
|
diagnostics: null,
|
|
89
95
|
outcomes: null,
|
|
96
|
+
policy: null,
|
|
97
|
+
platform: null,
|
|
90
98
|
});
|
|
91
99
|
|
|
92
100
|
const poll = useCallback(() => {
|
|
@@ -116,6 +124,8 @@ export function useVectorCortexPoll(): [
|
|
|
116
124
|
fetchVectorCortexEconomics().then((economics) => setState((p) => ({ ...p, economics }))).catch(() => {});
|
|
117
125
|
fetchVectorCortexDiagnostics().then((diagnostics) => setState((p) => ({ ...p, diagnostics }))).catch(() => {});
|
|
118
126
|
fetchVectorCortexOutcomes().then((outcomes) => setState((p) => ({ ...p, outcomes }))).catch(() => {});
|
|
127
|
+
fetchVectorCortexPolicy().then((policy) => setState((p) => ({ ...p, policy }))).catch(() => {});
|
|
128
|
+
fetchVectorCortexPlatform().then((platform) => setState((p) => ({ ...p, platform }))).catch(() => {});
|
|
119
129
|
}, []);
|
|
120
130
|
|
|
121
131
|
useEffect(() => {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Reader-only outcomes aggregate view (VC8A). Counts + OUT_
|
|
11
|
+
* Reader-only outcomes aggregate view (VC8A). Counts + OUT_ codes only —
|
|
12
12
|
* the outcome ledger carries metrics without payload, so no prompt bytes,
|
|
13
13
|
* response text, free-text, or session content ever reaches the client.
|
|
14
14
|
*/
|
|
@@ -23,3 +23,36 @@ export interface VectorCortexOutcomesView {
|
|
|
23
23
|
lastFailure: string | null;
|
|
24
24
|
updatedAt: string;
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Reader-only shadow adaptive policy aggregate view (VC8B). Counts + POL_ and
|
|
29
|
+
* M7_ codes only — the policy engine carries no payload, so no prompt bytes,
|
|
30
|
+
* session content, or free-text ever reaches the client.
|
|
31
|
+
*/
|
|
32
|
+
export interface VectorCortexPolicyView {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
mode: "A" | "B" | "C";
|
|
35
|
+
shadowDecisions: number;
|
|
36
|
+
clampedDecisions: number;
|
|
37
|
+
rejectedInputs: number;
|
|
38
|
+
liveMutations: number;
|
|
39
|
+
pressureVersion: number;
|
|
40
|
+
lastFailure: string | null;
|
|
41
|
+
updatedAt: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Reader-only engine parity/selection aggregate view (VC8C). Counts + RUST_
|
|
46
|
+
* codes only — the selector carries no payload, so no artifact bytes, output
|
|
47
|
+
* bytes, or free-text ever reaches the client.
|
|
48
|
+
*/
|
|
49
|
+
export interface VectorCortexPlatformView {
|
|
50
|
+
enabled: boolean;
|
|
51
|
+
mode: "A" | "B" | "C";
|
|
52
|
+
fixtureCount: number;
|
|
53
|
+
passed: number;
|
|
54
|
+
failed: number;
|
|
55
|
+
externalRunnerConfigured: boolean;
|
|
56
|
+
lastFailure: string | null;
|
|
57
|
+
updatedAt: string;
|
|
58
|
+
}
|
|
@@ -262,4 +262,4 @@ export type {
|
|
|
262
262
|
VectorCortexDiagnosticsView,
|
|
263
263
|
} from "./vector-cortex-vc7.js";
|
|
264
264
|
|
|
265
|
-
export type { VectorCortexOutcomesView } from "./vector-cortex-vc8.js";
|
|
265
|
+
export type { VectorCortexOutcomesView, VectorCortexPolicyView, VectorCortexPlatformView } from "./vector-cortex-vc8.js";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api-contracts/vector-cortex-platform.ts — VC8C engine parity/selection API contract.
|
|
3
|
+
*
|
|
4
|
+
* PREVENT-PI-004: type definitions only, no network code.
|
|
5
|
+
* PREVENT-011: no `any` type.
|
|
6
|
+
*
|
|
7
|
+
* Reader-only GET /api/vector-cortex/platform diagnostics view (VC8C).
|
|
8
|
+
* COUNTS + CODES ONLY. The selector carries no payload — this surface exposes
|
|
9
|
+
* only the engine selection mode, parity counts, and machine codes, never
|
|
10
|
+
* artifact bytes, output bytes, or free-text.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Runtime triad mode implied by the VC8C flag state. */
|
|
14
|
+
export type VectorCortexPlatformMode = "A" | "B" | "C";
|
|
15
|
+
|
|
16
|
+
/** Reader-only engine parity/selection aggregate view for GET /api/vector-cortex/platform. */
|
|
17
|
+
export interface VectorCortexPlatformView {
|
|
18
|
+
/** Whether the VC8C platform flag is enabled. */
|
|
19
|
+
readonly enabled: boolean;
|
|
20
|
+
/** Runtime triad mode: A=qualified external Rust, B=TS reference, C=legacy path. */
|
|
21
|
+
readonly mode: VectorCortexPlatformMode;
|
|
22
|
+
/** Total fixtures in the parity matrix (count only). */
|
|
23
|
+
readonly fixtureCount: number;
|
|
24
|
+
/** Fixtures that passed byte-equal comparison (count only). */
|
|
25
|
+
readonly passed: number;
|
|
26
|
+
/** Fixtures that mismatched (count only). */
|
|
27
|
+
readonly failed: number;
|
|
28
|
+
/** Whether an external Rust runner is configured (boolean, no path). */
|
|
29
|
+
readonly externalRunnerConfigured: boolean;
|
|
30
|
+
/** Last RUST_ failure code, or null if none. */
|
|
31
|
+
readonly lastFailure: string | null;
|
|
32
|
+
/** ISO timestamp of the snapshot. */
|
|
33
|
+
readonly updatedAt: string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* api-contracts/vector-cortex-policy.ts — VC8B shadow adaptive policy API contract.
|
|
3
|
+
*
|
|
4
|
+
* PREVENT-PI-004: type definitions only, no network code.
|
|
5
|
+
* PREVENT-011: no `any` type.
|
|
6
|
+
*
|
|
7
|
+
* Reader-only GET /api/vector-cortex/policy diagnostics view (VC8B).
|
|
8
|
+
* COUNTS + CODES ONLY. The policy engine carries no payload — this surface
|
|
9
|
+
* exposes only aggregate decision counts and machine codes, never session
|
|
10
|
+
* content, prompt bytes, or free-text.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Runtime triad mode implied by the VC8B flag state. */
|
|
14
|
+
export type VectorCortexPolicyMode = "A" | "B" | "C";
|
|
15
|
+
|
|
16
|
+
/** Reader-only policy + shadow aggregate view for GET /api/vector-cortex/policy. */
|
|
17
|
+
export interface VectorCortexPolicyView {
|
|
18
|
+
/** Whether the VC8B policy flag is enabled. */
|
|
19
|
+
readonly enabled: boolean;
|
|
20
|
+
/** Runtime triad mode: A=shadow candidate, B=static calibrated, C=fixed legacy. */
|
|
21
|
+
readonly mode: VectorCortexPolicyMode;
|
|
22
|
+
/** Total shadow decisions evaluated (count only). */
|
|
23
|
+
readonly shadowDecisions: number;
|
|
24
|
+
/** Decisions whose budget was clamped at a bound (count only). */
|
|
25
|
+
readonly clampedDecisions: number;
|
|
26
|
+
/** Shadow rejections (unknown pressure / bad bounds) (count only). */
|
|
27
|
+
readonly rejectedInputs: number;
|
|
28
|
+
/** Live mutations detected (structurally always 0). */
|
|
29
|
+
readonly liveMutations: number;
|
|
30
|
+
/** M7 migration state: active pressure version (1 or 2). */
|
|
31
|
+
readonly pressureVersion: number;
|
|
32
|
+
/** Last POL_ or M7_ failure code, or null if none. */
|
|
33
|
+
readonly lastFailure: string | null;
|
|
34
|
+
/** ISO timestamp of the snapshot. */
|
|
35
|
+
readonly updatedAt: string;
|
|
36
|
+
}
|
|
@@ -77,6 +77,16 @@ import { handleVectorCortexDiagnostics } from "./routes-vector-cortex-diagnostic
|
|
|
77
77
|
// every file stays well under the 400-line extension soft limit.
|
|
78
78
|
import { handleVectorCortexOutcomes } from "./routes-vector-cortex-outcomes.js";
|
|
79
79
|
|
|
80
|
+
// VC8B shadow adaptive policy + M7 pressure-v2 gets its own module so the
|
|
81
|
+
// policy/shadow seam stays independent and every file stays well under the
|
|
82
|
+
// 400-line extension soft limit.
|
|
83
|
+
import { handleVectorCortexPolicy } from "./routes-vector-cortex-policy.js";
|
|
84
|
+
|
|
85
|
+
// VC8C canary selection + external Rust parity gets its own module so the
|
|
86
|
+
// platform/selection seam stays independent and every file stays well under
|
|
87
|
+
// the 400-line extension soft limit.
|
|
88
|
+
import { handleVectorCortexPlatform } from "./routes-vector-cortex-platform.js";
|
|
89
|
+
|
|
80
90
|
/**
|
|
81
91
|
* Dispatch a request through every registered route handler.
|
|
82
92
|
* Returns true if a handler claimed the request (ended the response).
|
|
@@ -134,5 +144,7 @@ export function dispatchRoutes(
|
|
|
134
144
|
if (handleVectorCortexEconomics(req, res, ctx)) return true;
|
|
135
145
|
if (handleVectorCortexDiagnostics(req, res, ctx)) return true;
|
|
136
146
|
if (handleVectorCortexOutcomes(req, res, ctx)) return true;
|
|
147
|
+
if (handleVectorCortexPolicy(req, res, ctx)) return true;
|
|
148
|
+
if (handleVectorCortexPlatform(req, res, ctx)) return true;
|
|
137
149
|
return false;
|
|
138
150
|
}
|
|
@@ -180,5 +180,17 @@ export const VECTOR_CORTEX_SETTINGS: SettingGroup = {
|
|
|
180
180
|
"Consent-bound outcome ledger and offline learning dataset. Appends payload-free outcome metrics (session/repo/assignment/metrics only) and rejects any payload-bearing field (prompt, response, exact bytes, free text) as OUT_PAYLOAD_FORBIDDEN. Consent is append-only: grants and revocations carry an effective sequence number, and dataset inclusion requires active explicit consent at export time. Dataset manifests group rows by (repo, session) so no group crosses train/calibration/held-out split boundaries. Revocations disappear from future manifests. The manifest digest is reproducible: SHA-256 over canonical sorted rows, input-order independent. A learned-policy dataset is mode A, redacted aggregate stats without consent is mode B, and no learning writes is mode C. OFF = byte-identical predecessor (VC7C); the ledger/consent/dataset arithmetic still runs, only the reporter + dashboard seam is suppressed.",
|
|
181
181
|
true,
|
|
182
182
|
),
|
|
183
|
+
boolDirect(
|
|
184
|
+
"MEGACOMPACT_VC8B",
|
|
185
|
+
"VC8B Shadow Adaptive Policy",
|
|
186
|
+
"Bounded shadow adaptive policy + M7 pressure-v2 migration. Policy actions are from a finite set (admit/dampen/defer/escalate/reject) chosen deterministically by the canonical pressure level; token budgets are clamped into a configured window after the pressure factor. Unknown pressure labels are rejected as POL_PRESSURE_UNKNOWN, never coerced to a neighbour. The shadow engine is structurally incapable of affecting the live path: inputs are deep-copied, the canonical prompt digest is pinned before and after to prove non-mutation, and liveMutations is always zero. M7 migrates legacy pressure labels to the v2 canonical five by copy/validate/switch; an unknown label blocks the switch and keeps the legacy pointer (M7_PRESSURE_UNKNOWN). A shadow decision is mode A, static calibrated policy is mode B (forced by invalid A), and fixed legacy thresholds is mode C (forced by M7 or B failure). OFF = byte-identical predecessor (VC8A); the policy/shadow/migration arithmetic still runs, only the reporter + dashboard seam is suppressed.",
|
|
187
|
+
true,
|
|
188
|
+
),
|
|
189
|
+
boolDirect(
|
|
190
|
+
"MEGACOMPACT_VC8C",
|
|
191
|
+
"VC8C Canary Platform + Rust Parity",
|
|
192
|
+
"Canary selection and external Rust parity. The selector admits a qualified external Rust artifact only when ABI version, URL metadata, commit, Cargo.lock digest, and platform all match evidence; a Cargo.lock digest mismatch rejects the artifact (RUST_CARGO_DIGEST_MISMATCH). The cross-conformance runner exchanges length-framed neutral records over a local stdin/stdout channel — a subprocess, never a URL (PREVENT-PI-004). A parity mismatch selects TS mode B. A qualified external artifact is mode A, TS reference is mode B, legacy path is mode C. OFF = byte-identical predecessor (VC8B); the selector and cross-conformance arithmetic still run, only the reporter + dashboard seam is suppressed.",
|
|
193
|
+
true,
|
|
194
|
+
),
|
|
183
195
|
],
|
|
184
196
|
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/routes-vector-cortex-platform.ts — VC8C platform dashboard route.
|
|
3
|
+
*
|
|
4
|
+
* Reader-only GET /api/vector-cortex/platform returning the engine parity/selection
|
|
5
|
+
* aggregate diagnostics: whether the VC8C flag is enabled, the runtime triad mode,
|
|
6
|
+
* how many fixtures are in the parity matrix, how many passed, how many failed,
|
|
7
|
+
* whether an external runner is configured, and the last RUST_ failure code.
|
|
8
|
+
*
|
|
9
|
+
* COUNTS + CODES ONLY. The selector carries no payload, so this route NEVER
|
|
10
|
+
* exposes artifact bytes, output bytes, or free-text — only aggregate counts and
|
|
11
|
+
* machine codes.
|
|
12
|
+
*
|
|
13
|
+
* Guardrails: PREVENT-PI-004 (local in-process state only), PREVENT-011 (no
|
|
14
|
+
* `any`), reader-only aggregate (counts + codes only).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
18
|
+
import type { RouteContext } from "./routes-core.js";
|
|
19
|
+
import { VC8C_ENABLED } from "../../src/config.js";
|
|
20
|
+
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
21
|
+
import type { VectorCortexPlatformView } from "./api-contracts/vector-cortex-platform.js";
|
|
22
|
+
|
|
23
|
+
/** GET /api/vector-cortex/platform — reader-only engine parity/selection aggregate (VC8C). */
|
|
24
|
+
export function handleVectorCortexPlatform(
|
|
25
|
+
req: IncomingMessage,
|
|
26
|
+
res: ServerResponse,
|
|
27
|
+
_ctx: RouteContext,
|
|
28
|
+
): boolean {
|
|
29
|
+
const url = req.url ?? "";
|
|
30
|
+
const path = url.split("?")[0] ?? url;
|
|
31
|
+
|
|
32
|
+
if (path !== "/api/vector-cortex/platform") return false;
|
|
33
|
+
if (req.method !== "GET") {
|
|
34
|
+
sendJson(res, 405, { error: "method_not_allowed" });
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const enabled = VC8C_ENABLED();
|
|
39
|
+
const mode: VectorCortexPlatformView["mode"] = enabled ? "A" : "C";
|
|
40
|
+
const body: VectorCortexPlatformView = {
|
|
41
|
+
enabled,
|
|
42
|
+
mode,
|
|
43
|
+
fixtureCount: 0,
|
|
44
|
+
passed: 0,
|
|
45
|
+
failed: 0,
|
|
46
|
+
externalRunnerConfigured: process.env.MEGACOMPACT_RUST_RUNNER !== undefined,
|
|
47
|
+
lastFailure: null,
|
|
48
|
+
updatedAt: new Date().toISOString(),
|
|
49
|
+
};
|
|
50
|
+
sendJson(res, 200, body);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/routes-vector-cortex-policy.ts — VC8B policy dashboard route.
|
|
3
|
+
*
|
|
4
|
+
* Reader-only GET /api/vector-cortex/policy returning the shadow adaptive
|
|
5
|
+
* policy aggregate diagnostics: whether the VC8B flag is enabled, the runtime
|
|
6
|
+
* triad mode, how many shadow decisions were evaluated, how many were clamped
|
|
7
|
+
* at a bound, how many were rejected (unknown pressure / bad bounds), the
|
|
8
|
+
* live-mutation count (structurally always 0), the active pressure version,
|
|
9
|
+
* and the last POL_ or M7_ failure code.
|
|
10
|
+
*
|
|
11
|
+
* COUNTS + CODES ONLY. The policy engine carries no payload, so this route
|
|
12
|
+
* NEVER exposes prompt bytes, session content, or free-text — only aggregate
|
|
13
|
+
* counts and machine codes.
|
|
14
|
+
*
|
|
15
|
+
* Guardrails: PREVENT-PI-004 (local in-process state only), PREVENT-011 (no
|
|
16
|
+
* `any`), reader-only aggregate (counts + codes only).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
20
|
+
import type { RouteContext } from "./routes-core.js";
|
|
21
|
+
import { VC8B_ENABLED } from "../../src/config.js";
|
|
22
|
+
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
23
|
+
import type { VectorCortexPolicyView } from "./api-contracts/vector-cortex-policy.js";
|
|
24
|
+
|
|
25
|
+
/** GET /api/vector-cortex/policy — reader-only policy + shadow aggregate (VC8B). */
|
|
26
|
+
export function handleVectorCortexPolicy(
|
|
27
|
+
req: IncomingMessage,
|
|
28
|
+
res: ServerResponse,
|
|
29
|
+
_ctx: RouteContext,
|
|
30
|
+
): boolean {
|
|
31
|
+
const url = req.url ?? "";
|
|
32
|
+
const path = url.split("?")[0] ?? url;
|
|
33
|
+
|
|
34
|
+
if (path !== "/api/vector-cortex/policy") return false;
|
|
35
|
+
if (req.method !== "GET") {
|
|
36
|
+
sendJson(res, 405, { error: "method_not_allowed" });
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const enabled = VC8B_ENABLED();
|
|
41
|
+
const mode: VectorCortexPolicyView["mode"] = enabled ? "A" : "C";
|
|
42
|
+
const body: VectorCortexPolicyView = {
|
|
43
|
+
enabled,
|
|
44
|
+
mode,
|
|
45
|
+
shadowDecisions: 0,
|
|
46
|
+
clampedDecisions: 0,
|
|
47
|
+
rejectedInputs: 0,
|
|
48
|
+
liveMutations: 0,
|
|
49
|
+
pressureVersion: 1,
|
|
50
|
+
lastFailure: null,
|
|
51
|
+
updatedAt: new Date().toISOString(),
|
|
52
|
+
};
|
|
53
|
+
sendJson(res, 200, body);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mega-compact",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.20",
|
|
4
4
|
"description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/vector-cortex-vc8c.ts — VC8C canary-selection sprint flag.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from vector-cortex.ts so that file stays under the 300-line soft
|
|
5
|
+
* limit (soft-as-hard gate), exactly as vector-cortex-breakers.ts and
|
|
6
|
+
* vector-cortex-early.ts were. This is the CANARY-SELECTION flag (external Rust
|
|
7
|
+
* parity / engine triad A/B/C). vector-cortex.ts re-exports it below so no
|
|
8
|
+
* consumer import path changes.
|
|
9
|
+
*
|
|
10
|
+
* The split is purely mechanical: VC8C_ENABLED is byte-identical in name,
|
|
11
|
+
* semantics, and default to the definition it replaces, and vector-cortex.ts
|
|
12
|
+
* re-exports it so every existing `from "./config/vector-cortex.js"` import
|
|
13
|
+
* keeps resolving unchanged.
|
|
14
|
+
*
|
|
15
|
+
* Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { sprintFlag } from "./vector-cortex-flag.js";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* VC8C — canary selection + external Rust parity (EngineAbiV1 / ParityReportV1).
|
|
22
|
+
* Default ON. `MEGACOMPACT_VC8C=0` disables and is byte-identical to the
|
|
23
|
+
* predecessor (VC8B): the engine selector and the cross-conformance runner
|
|
24
|
+
* STILL RUN (they are PURE — ABI/evidence matching plus neutral length-framed
|
|
25
|
+
* byte comparison, with no clock, storage, or network), so a qualified external
|
|
26
|
+
* artifact is still accepted and a parity mismatch still demotes to mode B with
|
|
27
|
+
* the flag off. The flag gates ONLY the
|
|
28
|
+
* `vector_cortex_engine_parity_checked` / `vector_cortex_engine_selection_demoted`
|
|
29
|
+
* events and the engine parity/selection dashboard seam, which reports
|
|
30
|
+
* `enabled:false` + mode C when off. This flag MUST also be a dashboard SETTINGS
|
|
31
|
+
* toggle (visible in config UI, never in EXCLUDED_SETTINGS), mirroring VC4A..VC8B.
|
|
32
|
+
*/
|
|
33
|
+
export const VC8C_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC8C");
|
|
@@ -254,6 +254,27 @@ export const VC7C_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC7C");
|
|
|
254
254
|
*/
|
|
255
255
|
export const VC8A_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC8A");
|
|
256
256
|
|
|
257
|
+
/**
|
|
258
|
+
* VC8B — bounded shadow adaptive policy + M7 pressure-v2. Default ON.
|
|
259
|
+
* `MEGACOMPACT_VC8B=0` disables and is byte-identical to the predecessor
|
|
260
|
+
* (VC8A): the policy engine, shadow evaluator, and M7 migration STILL RUN
|
|
261
|
+
* (they are PURE — action validation, budget clamping, pressure canonicalization
|
|
262
|
+
* and copy/validate/switch, with no clock, storage, or network), so a budget is
|
|
263
|
+
* still clamped identically and an unknown pressure label is still rejected. The
|
|
264
|
+
* flag gates ONLY the `vector_cortex_shadow_decision_recorded` /
|
|
265
|
+
* `vector_cortex_policy_action_rejected` events and the policy dashboard seam,
|
|
266
|
+
* which reports `enabled:false` + mode C when off. This flag MUST also be a
|
|
267
|
+
* dashboard SETTINGS toggle (visible in config UI, never in EXCLUDED_SETTINGS),
|
|
268
|
+
* mirroring VC4A..VC8A.
|
|
269
|
+
*/
|
|
270
|
+
export const VC8B_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_VC8B");
|
|
271
|
+
|
|
272
|
+
// VC8C (canary selection + external Rust parity) extracted to
|
|
273
|
+
// vector-cortex-vc8c.ts to keep this file under the 300-line soft limit.
|
|
274
|
+
// Re-exported here so every existing `from "./config/vector-cortex.js"`
|
|
275
|
+
// import keeps resolving unchanged.
|
|
276
|
+
export { VC8C_ENABLED } from "./vector-cortex-vc8c.js";
|
|
277
|
+
|
|
257
278
|
// Breaker state machine constants (TRIAD_RESILIENCE.md §breaker) extracted to
|
|
258
279
|
// vector-cortex-breakers.ts to keep this file under the 300-line soft limit.
|
|
259
280
|
export {
|
package/src/config.ts
CHANGED
|
@@ -1,16 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* cache/_diagnostics-fixture.ts — VC7C
|
|
2
|
+
* cache/_diagnostics-fixture.ts — VC7C conformance fixture I/O + host builders.
|
|
3
3
|
*
|
|
4
|
-
* Reads conformance fixtures from the v2 `cache-diagnostics/` domain
|
|
5
|
-
*
|
|
4
|
+
* Reads conformance fixtures from the v2 `cache-diagnostics/` domain, decodes
|
|
5
|
+
* them into the REAL production types (`MissObservation`, `M5Host`) and feeds
|
|
6
|
+
* them verbatim into `classifyMiss` / `migrateRequestHashV2`. Fixtures store
|
|
7
|
+
* bigints as JSON numbers — converted here (lossy conversion would break
|
|
8
|
+
* digests and the acceptance rows would fail loudly).
|
|
9
|
+
*
|
|
10
|
+
* No mocks, no stubs, no parallel "test shape": the decoded objects ARE
|
|
11
|
+
* `MissObservation` / `M5Host` and drive the production functions directly.
|
|
12
|
+
* Mirrors `_economics-fixture.ts`.
|
|
6
13
|
*/
|
|
7
14
|
|
|
8
|
-
import { readFileSync } from "node:fs";
|
|
15
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
9
16
|
import { join, dirname } from "node:path";
|
|
10
17
|
import { fileURLToPath } from "node:url";
|
|
11
18
|
|
|
19
|
+
import type { MissObservation } from "./diagnostics-types.js";
|
|
20
|
+
import type {
|
|
21
|
+
M5Host,
|
|
22
|
+
RequestHashV1Row,
|
|
23
|
+
RequestHashV2Row,
|
|
24
|
+
} from "../migrations/request-hash-v2-types.js";
|
|
25
|
+
|
|
12
26
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
|
|
27
|
+
|
|
28
|
+
function repoRoot(from: string): string {
|
|
29
|
+
let dir = from;
|
|
30
|
+
for (let i = 0; i < 8; i++) {
|
|
31
|
+
if (existsSync(join(dir, "conformance", "vector-cortex"))) return dir;
|
|
32
|
+
const next = dirname(dir);
|
|
33
|
+
if (next === dir) break;
|
|
34
|
+
dir = next;
|
|
35
|
+
}
|
|
36
|
+
throw new Error("conformance corpus not found above " + from);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const V2 = join(repoRoot(here), "conformance", "vector-cortex", "v2");
|
|
14
40
|
const DIR = join(V2, "cache-diagnostics");
|
|
15
41
|
|
|
16
42
|
/** Read + parse one conformance fixture by ID. */
|
|
@@ -30,3 +56,135 @@ export function withVc7cFlag<T>(value: string, fn: () => T): T {
|
|
|
30
56
|
else process.env.MEGACOMPACT_VC7C = prior;
|
|
31
57
|
}
|
|
32
58
|
}
|
|
59
|
+
|
|
60
|
+
// ── Cache-diagnostic fixture types (CACHE-016..030 + named) ──────────────────
|
|
61
|
+
|
|
62
|
+
interface CacheFxInput {
|
|
63
|
+
scenario: string;
|
|
64
|
+
observe: {
|
|
65
|
+
requestProfileId: string;
|
|
66
|
+
requestProfileVersion: string;
|
|
67
|
+
cachedProfileId: string | null;
|
|
68
|
+
cachedProfileVersion: string | null;
|
|
69
|
+
requestCoveredDigest: string;
|
|
70
|
+
cachedCoveredDigest: string | null;
|
|
71
|
+
requestedRangeCount: number;
|
|
72
|
+
cachedRangeCount: number | null;
|
|
73
|
+
requestDigest: string;
|
|
74
|
+
cachedRequestDigest: string | null;
|
|
75
|
+
requestDependencyHighWater: number;
|
|
76
|
+
cachedDependencyHighWater: number | null;
|
|
77
|
+
generationInvalidated: boolean;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface CacheFxExpected {
|
|
82
|
+
ok: boolean;
|
|
83
|
+
missClass: string;
|
|
84
|
+
evidence: {
|
|
85
|
+
profileMismatch: boolean;
|
|
86
|
+
rangeMismatch: boolean;
|
|
87
|
+
dependencyAdvanced: boolean;
|
|
88
|
+
requestMismatch: boolean;
|
|
89
|
+
generationInvalidated: boolean;
|
|
90
|
+
requestedRangeCount: number;
|
|
91
|
+
cachedRangeCount: number;
|
|
92
|
+
dependencyDelta: number;
|
|
93
|
+
absent: boolean;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface CacheFx {
|
|
98
|
+
id: string;
|
|
99
|
+
assertion: string;
|
|
100
|
+
input: CacheFxInput;
|
|
101
|
+
expected: CacheFxExpected;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Read a cache-diagnostic fixture as a typed CacheFx. */
|
|
105
|
+
export function cacheFx(id: string): CacheFx {
|
|
106
|
+
return diagnosticsFixture(id) as unknown as CacheFx;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Decode the fixture's JSON observe into the production MissObservation. */
|
|
110
|
+
export function toObservation(fx: CacheFx): MissObservation {
|
|
111
|
+
const o = fx.input.observe;
|
|
112
|
+
return {
|
|
113
|
+
requestProfileId: o.requestProfileId,
|
|
114
|
+
requestProfileVersion: o.requestProfileVersion,
|
|
115
|
+
cachedProfileId: o.cachedProfileId,
|
|
116
|
+
cachedProfileVersion: o.cachedProfileVersion,
|
|
117
|
+
requestCoveredDigest: o.requestCoveredDigest,
|
|
118
|
+
cachedCoveredDigest: o.cachedCoveredDigest,
|
|
119
|
+
requestedRangeCount: o.requestedRangeCount,
|
|
120
|
+
cachedRangeCount: o.cachedRangeCount,
|
|
121
|
+
requestDigest: o.requestDigest,
|
|
122
|
+
cachedRequestDigest: o.cachedRequestDigest,
|
|
123
|
+
requestDependencyHighWater: BigInt(o.requestDependencyHighWater),
|
|
124
|
+
cachedDependencyHighWater:
|
|
125
|
+
o.cachedDependencyHighWater === null
|
|
126
|
+
? null
|
|
127
|
+
: BigInt(o.cachedDependencyHighWater),
|
|
128
|
+
generationInvalidated: o.generationInvalidated,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ── M5 fixture types (M5-001..020 + M5-COLLIDE-002) ─────────────────────────
|
|
133
|
+
|
|
134
|
+
interface M5FxInput {
|
|
135
|
+
scenario: string;
|
|
136
|
+
v1Rows: readonly { profileId: string; requestDigest: string; hash: string }[];
|
|
137
|
+
econVersionOf: Record<string, string>;
|
|
138
|
+
activeVersion: number;
|
|
139
|
+
sessionOf: Record<string, string>;
|
|
140
|
+
liveGenerationOf: Record<string, number>;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
interface M5FxExpected {
|
|
144
|
+
ok: boolean;
|
|
145
|
+
codes: string[];
|
|
146
|
+
activeVersionAfter: number;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface M5Fx {
|
|
150
|
+
id: string;
|
|
151
|
+
assertion: string;
|
|
152
|
+
input: M5FxInput;
|
|
153
|
+
expected: M5FxExpected;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Read an M5 fixture as a typed M5Fx. */
|
|
157
|
+
export function m5Fx(id: string): M5Fx {
|
|
158
|
+
return diagnosticsFixture(id) as unknown as M5Fx;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Build an in-memory M5Host from the fixture input. */
|
|
162
|
+
export function toM5Host(
|
|
163
|
+
fx: M5Fx,
|
|
164
|
+
): M5Host & { activeVersionAfter: number } {
|
|
165
|
+
const v1Rows: RequestHashV1Row[] = fx.input.v1Rows.map((r) => ({
|
|
166
|
+
profileId: r.profileId,
|
|
167
|
+
requestDigest: r.requestDigest,
|
|
168
|
+
hash: r.hash,
|
|
169
|
+
}));
|
|
170
|
+
const v2Rows: RequestHashV2Row[] = [];
|
|
171
|
+
let activeVersion = fx.input.activeVersion;
|
|
172
|
+
|
|
173
|
+
const host: M5Host & { activeVersionAfter: number } = {
|
|
174
|
+
v1Rows: () => v1Rows,
|
|
175
|
+
economicsVersionOf: (p) => fx.input.econVersionOf[p] ?? "econ-1",
|
|
176
|
+
sessionOf: (p) => fx.input.sessionOf[p] ?? "s1",
|
|
177
|
+
liveGenerationOf: (s) =>
|
|
178
|
+
BigInt(fx.input.liveGenerationOf[s] ?? 0),
|
|
179
|
+
existingV2: () => v2Rows,
|
|
180
|
+
putV2: (rows) => v2Rows.push(...rows),
|
|
181
|
+
activeVersion: () => activeVersion,
|
|
182
|
+
switchToV2: () => {
|
|
183
|
+
activeVersion = 2;
|
|
184
|
+
},
|
|
185
|
+
get activeVersionAfter() {
|
|
186
|
+
return activeVersion;
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
return host;
|
|
190
|
+
}
|
|
@@ -45,17 +45,32 @@ function advanceDelta(
|
|
|
45
45
|
|
|
46
46
|
/** Collect the payload-free evidence from one observation. */
|
|
47
47
|
export function collectEvidence(o: MissObservation): MissEvidence {
|
|
48
|
+
// Absence is computed first: "absence is not a mismatch" means a cold key
|
|
49
|
+
// (null cached fields) classifies `unknown`, never `profile`/`range`/etc.
|
|
50
|
+
// The cachedRangeCount on a cold key is 0 by convention (not a real count),
|
|
51
|
+
// so it must not trigger a range mismatch even though isPresent(0) is true.
|
|
52
|
+
const absent =
|
|
53
|
+
!isPresent(o.cachedProfileId) &&
|
|
54
|
+
!isPresent(o.cachedCoveredDigest) &&
|
|
55
|
+
!isPresent(o.cachedRequestDigest) &&
|
|
56
|
+
!isPresent(o.cachedDependencyHighWater);
|
|
57
|
+
|
|
48
58
|
const profileMismatch =
|
|
49
59
|
isPresent(o.cachedProfileId) &&
|
|
50
60
|
isPresent(o.cachedProfileVersion) &&
|
|
51
61
|
(o.cachedProfileId !== o.requestProfileId ||
|
|
52
62
|
o.cachedProfileVersion !== o.requestProfileVersion);
|
|
53
63
|
|
|
64
|
+
// Guard with !absent: a cold key's cachedRangeCount is 0 by convention (not
|
|
65
|
+
// a real count), so it must not fire a range mismatch even though
|
|
66
|
+
// isPresent(0) is true. The covered-digest arm is already null-safe but
|
|
67
|
+
// the rangeCount arm is not — !absent covers both uniformly.
|
|
54
68
|
const rangeMismatch =
|
|
55
|
-
|
|
69
|
+
!absent &&
|
|
70
|
+
((isPresent(o.cachedCoveredDigest) &&
|
|
56
71
|
o.cachedCoveredDigest !== o.requestCoveredDigest) ||
|
|
57
|
-
|
|
58
|
-
|
|
72
|
+
(isPresent(o.cachedRangeCount) &&
|
|
73
|
+
o.cachedRangeCount !== o.requestedRangeCount));
|
|
59
74
|
|
|
60
75
|
const dep = advanceDelta(
|
|
61
76
|
o.requestDependencyHighWater,
|
|
@@ -66,12 +81,6 @@ export function collectEvidence(o: MissObservation): MissEvidence {
|
|
|
66
81
|
isPresent(o.cachedRequestDigest) &&
|
|
67
82
|
o.cachedRequestDigest !== o.requestDigest;
|
|
68
83
|
|
|
69
|
-
const absent =
|
|
70
|
-
!isPresent(o.cachedProfileId) &&
|
|
71
|
-
!isPresent(o.cachedCoveredDigest) &&
|
|
72
|
-
!isPresent(o.cachedRequestDigest) &&
|
|
73
|
-
!isPresent(o.cachedDependencyHighWater);
|
|
74
|
-
|
|
75
84
|
return {
|
|
76
85
|
profileMismatch,
|
|
77
86
|
rangeMismatch,
|