pi-mega-compact 0.20.70 → 0.20.72
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-setup-cortex.js +7 -1
- package/dist/extensions/dashboard-server/routes-vector-cortex-crystals.js +45 -30
- package/dist/extensions/dashboard-server/routes-vector-cortex-diagnostics.js +50 -29
- package/dist/extensions/dashboard-server/routes-vector-cortex-economics.js +33 -20
- package/dist/extensions/dashboard-server/routes-vector-cortex-helpers.js +54 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-policy.js +33 -16
- package/dist/src/vector-cortex/cache/store.js +25 -2
- package/dist/src/vector-cortex/encoder/asset.js +34 -2
- package/dist/src/vector-cortex/encoder/router.js +31 -3
- package/dist/src/vector-cortex/livewire/livewire-live.js +163 -0
- package/dist/src/vector-cortex/livewire/livewire-registry.js +73 -0
- package/dist/src/vector-cortex/livewire/livewire-runtime.js +107 -0
- package/dist/src/vector-cortex/livewire/livewire-snapshot.js +101 -0
- package/dist/src/vector-cortex/livewire/livewire-types.js +19 -0
- package/dist/src/vector-cortex/provider/registry.js +44 -12
- package/dist/src/vector-cortex/setup-cortex-blockers-compute.js +43 -7
- package/dist/vector-cortex/cache/store.js +25 -2
- package/dist/vector-cortex/encoder/asset.js +34 -2
- package/dist/vector-cortex/encoder/router.js +31 -3
- package/dist/vector-cortex/provider/registry.js +44 -12
- package/dist/vector-cortex/setup-cortex-blockers-compute.js +43 -7
- package/extensions/dashboard-server/routes-setup-cortex.ts +8 -1
- package/extensions/dashboard-server/routes-vector-cortex-crystals.ts +46 -30
- package/extensions/dashboard-server/routes-vector-cortex-diagnostics.ts +52 -29
- package/extensions/dashboard-server/routes-vector-cortex-economics.ts +35 -20
- package/extensions/dashboard-server/routes-vector-cortex-helpers.ts +84 -0
- package/extensions/dashboard-server/routes-vector-cortex-policy.ts +35 -16
- package/package.json +1 -1
- package/src/vector-cortex/cache/store.ts +26 -2
- package/src/vector-cortex/encoder/asset.ts +46 -3
- package/src/vector-cortex/encoder/router.ts +56 -2
- package/src/vector-cortex/encoder/types.ts +3 -0
- package/src/vector-cortex/livewire/livewire-live.ts +223 -0
- package/src/vector-cortex/livewire/livewire-registry.ts +91 -0
- package/src/vector-cortex/livewire/livewire-runtime.ts +117 -0
- package/src/vector-cortex/livewire/livewire-snapshot.ts +108 -0
- package/src/vector-cortex/livewire/livewire-types.ts +84 -0
- package/src/vector-cortex/provider/economics.ts +9 -31
- package/src/vector-cortex/provider/registry.ts +82 -11
- package/src/vector-cortex/provider/types.ts +37 -0
- package/src/vector-cortex/setup-cortex-blockers-compute.ts +48 -7
|
@@ -28,18 +28,25 @@ import type { RouteContext } from "./routes-core.js";
|
|
|
28
28
|
import { VC7B_ENABLED } from "../../src/config.js";
|
|
29
29
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
30
30
|
import { deriveVcStatus } from "./vc-status.js";
|
|
31
|
+
import { readLivewireSnapshot } from "../../src/vector-cortex/livewire/livewire-registry.js";
|
|
31
32
|
import type { VectorCortexEconomicsView } from "./api-contracts/vector-cortex-economics.js";
|
|
32
33
|
|
|
34
|
+
// The flag-off deferred reason, kept byte-identical to the pre-LIVEWIRE
|
|
35
|
+
// predecessor (VC7B: `economics_not_computed_v0_20_23`).
|
|
36
|
+
const DEFERRED_REASON = "economics_not_computed_v0_20_23";
|
|
37
|
+
|
|
33
38
|
/**
|
|
34
39
|
* Reader-only GET /api/vector-cortex/cache-economics (VC7B).
|
|
35
40
|
*
|
|
36
|
-
* Counts, profile tallies, and ECON_* codes only
|
|
37
|
-
*
|
|
41
|
+
* Counts, profile tallies, and ECON_* codes only. With the flag ON it surfaces
|
|
42
|
+
* the LIVEWIRE-provided profile economics tallies + the runtime `computed` bit;
|
|
43
|
+
* with the flag OFF it returns the byte-identical legacy deferred view (mode C,
|
|
44
|
+
* deferredReason present).
|
|
38
45
|
*/
|
|
39
46
|
export function handleVectorCortexEconomics(
|
|
40
47
|
req: IncomingMessage,
|
|
41
48
|
res: ServerResponse,
|
|
42
|
-
|
|
49
|
+
ctx: RouteContext,
|
|
43
50
|
): boolean {
|
|
44
51
|
const url = req.url ?? "";
|
|
45
52
|
const path = url.split("?")[0] ?? url;
|
|
@@ -50,25 +57,33 @@ export function handleVectorCortexEconomics(
|
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
const enabled = VC7B_ENABLED();
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
if (!enabled) {
|
|
61
|
+
// Flag-off parity: byte-identical to the predecessor (mode C + deferred).
|
|
62
|
+
const body: VectorCortexEconomicsView = {
|
|
63
|
+
enabled: false,
|
|
64
|
+
mode: "C",
|
|
65
|
+
profileCount: 0,
|
|
66
|
+
provenExclusions: 0,
|
|
67
|
+
unprovenExclusions: 0,
|
|
68
|
+
lastFailure: null,
|
|
69
|
+
updatedAt: new Date().toISOString(),
|
|
70
|
+
deferredReason: DEFERRED_REASON,
|
|
71
|
+
status: deriveVcStatus({ enabled: false, hasData: false }),
|
|
72
|
+
};
|
|
73
|
+
sendJson(res, 200, body);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const econ = readLivewireSnapshot(ctx.stateDir).economics;
|
|
58
78
|
const body: VectorCortexEconomicsView = {
|
|
59
|
-
enabled,
|
|
60
|
-
mode,
|
|
61
|
-
profileCount:
|
|
62
|
-
provenExclusions:
|
|
63
|
-
unprovenExclusions:
|
|
64
|
-
lastFailure:
|
|
79
|
+
enabled: true,
|
|
80
|
+
mode: "A",
|
|
81
|
+
profileCount: econ.profileCount,
|
|
82
|
+
provenExclusions: econ.provenExclusions,
|
|
83
|
+
unprovenExclusions: econ.unprovenExclusions,
|
|
84
|
+
lastFailure: econ.lastFailure,
|
|
65
85
|
updatedAt: new Date().toISOString(),
|
|
66
|
-
|
|
67
|
-
status: deriveVcStatus({
|
|
68
|
-
enabled,
|
|
69
|
-
deferredReason: "economics_not_computed_v0_20_23",
|
|
70
|
-
hasData: false,
|
|
71
|
-
}),
|
|
86
|
+
status: deriveVcStatus({ enabled: true, hasData: econ.computed }),
|
|
72
87
|
};
|
|
73
88
|
sendJson(res, 200, body);
|
|
74
89
|
return true;
|
|
@@ -108,3 +108,87 @@ export async function seedEval(dir: string): Promise<void> {
|
|
|
108
108
|
{ session: "s1", seq: 4, event: "encode", value: 12, unit: "ms", mode: "A" },
|
|
109
109
|
]);
|
|
110
110
|
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Seed a LIVEWIRE aggregate snapshot directly on disk so the spawned dashboard
|
|
114
|
+
* server (a separate process) rehydrates real subsystem counts and its reader-only
|
|
115
|
+
* routes report LIVE (non-deferred) data. This is how the LIVEWIRE route tests
|
|
116
|
+
* prove the wiring: the runtimes' persisted counts are exactly what a reader
|
|
117
|
+
* process reconstructs. Counts + codes + triad mode only (SECURITY_PRIVACY).
|
|
118
|
+
*/
|
|
119
|
+
export async function seedLivewireSnapshot(
|
|
120
|
+
dir: string,
|
|
121
|
+
overrides?: {
|
|
122
|
+
crystals?: Partial<Record<
|
|
123
|
+
"crystalCount" | "totalBytes" | "hits" | "misses" | "hitBytes" |
|
|
124
|
+
"writes" | "duplicateWrites" | "collisions",
|
|
125
|
+
number
|
|
126
|
+
>>;
|
|
127
|
+
diagnostics?: Partial<Record<
|
|
128
|
+
"profileMisses" | "rangeMisses" | "dependencyMisses" | "requestMisses" |
|
|
129
|
+
"generationMisses" | "unknownMisses" | "serveBlocked",
|
|
130
|
+
number
|
|
131
|
+
>> & { breakerState?: string };
|
|
132
|
+
economics?: {
|
|
133
|
+
computed?: boolean;
|
|
134
|
+
profileCount?: number;
|
|
135
|
+
provenExclusions?: number;
|
|
136
|
+
unprovenExclusions?: number;
|
|
137
|
+
};
|
|
138
|
+
policy?: {
|
|
139
|
+
shadowDecisions?: number;
|
|
140
|
+
clampedDecisions?: number;
|
|
141
|
+
rejectedInputs?: number;
|
|
142
|
+
pressureVersion?: number;
|
|
143
|
+
liveMutations?: number;
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
): Promise<void> {
|
|
147
|
+
const { saveLivewireSnapshot } = await import(
|
|
148
|
+
"../../src/vector-cortex/livewire/livewire-snapshot.js"
|
|
149
|
+
);
|
|
150
|
+
const c = overrides?.crystals ?? {};
|
|
151
|
+
const d = overrides?.diagnostics ?? {};
|
|
152
|
+
const e = overrides?.economics ?? {};
|
|
153
|
+
const p = overrides?.policy ?? {};
|
|
154
|
+
saveLivewireSnapshot(dir, {
|
|
155
|
+
schema: "vector-cortex-livewire-v1",
|
|
156
|
+
crystals: {
|
|
157
|
+
mode: "A",
|
|
158
|
+
crystalCount: c.crystalCount ?? 3,
|
|
159
|
+
totalBytes: c.totalBytes ?? 1024,
|
|
160
|
+
hits: c.hits ?? 0,
|
|
161
|
+
misses: c.misses ?? 0,
|
|
162
|
+
hitBytes: c.hitBytes ?? 0,
|
|
163
|
+
writes: c.writes ?? 0,
|
|
164
|
+
duplicateWrites: c.duplicateWrites ?? 0,
|
|
165
|
+
collisions: c.collisions ?? 0,
|
|
166
|
+
},
|
|
167
|
+
diagnostics: {
|
|
168
|
+
profileMisses: d.profileMisses ?? 0,
|
|
169
|
+
rangeMisses: d.rangeMisses ?? 0,
|
|
170
|
+
dependencyMisses: d.dependencyMisses ?? 0,
|
|
171
|
+
requestMisses: d.requestMisses ?? 0,
|
|
172
|
+
generationMisses: d.generationMisses ?? 0,
|
|
173
|
+
unknownMisses: d.unknownMisses ?? 0,
|
|
174
|
+
serveBlocked: d.serveBlocked ?? 0,
|
|
175
|
+
breakerState: d.breakerState ?? "CLOSED_A",
|
|
176
|
+
lastFailure: null,
|
|
177
|
+
},
|
|
178
|
+
economics: {
|
|
179
|
+
profileCount: e.profileCount ?? 4,
|
|
180
|
+
provenExclusions: e.provenExclusions ?? 1,
|
|
181
|
+
unprovenExclusions: e.unprovenExclusions ?? 0,
|
|
182
|
+
computed: e.computed ?? true,
|
|
183
|
+
lastFailure: null,
|
|
184
|
+
},
|
|
185
|
+
policy: {
|
|
186
|
+
shadowDecisions: p.shadowDecisions ?? 0,
|
|
187
|
+
clampedDecisions: p.clampedDecisions ?? 0,
|
|
188
|
+
rejectedInputs: p.rejectedInputs ?? 0,
|
|
189
|
+
liveMutations: p.liveMutations ?? 0,
|
|
190
|
+
pressureVersion: (p.pressureVersion ?? 1) as 1 | 2,
|
|
191
|
+
lastFailure: null,
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
}
|
|
@@ -21,13 +21,18 @@ import type { RouteContext } from "./routes-core.js";
|
|
|
21
21
|
import { VC8B_ENABLED } from "../../src/config.js";
|
|
22
22
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
23
23
|
import { deriveVcStatus } from "./vc-status.js";
|
|
24
|
+
import { readLivewireSnapshot } from "../../src/vector-cortex/livewire/livewire-registry.js";
|
|
24
25
|
import type { VectorCortexPolicyView } from "./api-contracts/vector-cortex-policy.js";
|
|
25
26
|
|
|
27
|
+
// The flag-off deferred reason, kept byte-identical to the pre-LIVEWIRE
|
|
28
|
+
// predecessor (VC8B: `shadow_controller_not_instantiated_v0_20_23`).
|
|
29
|
+
const DEFERRED_REASON = "shadow_controller_not_instantiated_v0_20_23";
|
|
30
|
+
|
|
26
31
|
/** GET /api/vector-cortex/policy — reader-only policy + shadow aggregate (VC8B). */
|
|
27
32
|
export function handleVectorCortexPolicy(
|
|
28
33
|
req: IncomingMessage,
|
|
29
34
|
res: ServerResponse,
|
|
30
|
-
|
|
35
|
+
ctx: RouteContext,
|
|
31
36
|
): boolean {
|
|
32
37
|
const url = req.url ?? "";
|
|
33
38
|
const path = url.split("?")[0] ?? url;
|
|
@@ -39,23 +44,37 @@ export function handleVectorCortexPolicy(
|
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
const enabled = VC8B_ENABLED();
|
|
42
|
-
|
|
47
|
+
if (!enabled) {
|
|
48
|
+
// Flag-off parity: byte-identical to the predecessor (mode C + deferred).
|
|
49
|
+
const body: VectorCortexPolicyView = {
|
|
50
|
+
enabled: false,
|
|
51
|
+
mode: "C",
|
|
52
|
+
shadowDecisions: 0,
|
|
53
|
+
clampedDecisions: 0,
|
|
54
|
+
rejectedInputs: 0,
|
|
55
|
+
liveMutations: 0,
|
|
56
|
+
pressureVersion: 1,
|
|
57
|
+
lastFailure: null,
|
|
58
|
+
updatedAt: new Date().toISOString(),
|
|
59
|
+
deferredReason: DEFERRED_REASON,
|
|
60
|
+
status: deriveVcStatus({ enabled: false, hasData: false }),
|
|
61
|
+
};
|
|
62
|
+
sendJson(res, 200, body);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const policy = readLivewireSnapshot(ctx.stateDir).policy;
|
|
43
67
|
const body: VectorCortexPolicyView = {
|
|
44
|
-
enabled,
|
|
45
|
-
mode,
|
|
46
|
-
shadowDecisions:
|
|
47
|
-
clampedDecisions:
|
|
48
|
-
rejectedInputs:
|
|
49
|
-
liveMutations:
|
|
50
|
-
pressureVersion:
|
|
51
|
-
lastFailure:
|
|
68
|
+
enabled: true,
|
|
69
|
+
mode: "A",
|
|
70
|
+
shadowDecisions: policy.shadowDecisions,
|
|
71
|
+
clampedDecisions: policy.clampedDecisions,
|
|
72
|
+
rejectedInputs: policy.rejectedInputs,
|
|
73
|
+
liveMutations: policy.liveMutations,
|
|
74
|
+
pressureVersion: policy.pressureVersion,
|
|
75
|
+
lastFailure: policy.lastFailure,
|
|
52
76
|
updatedAt: new Date().toISOString(),
|
|
53
|
-
|
|
54
|
-
status: deriveVcStatus({
|
|
55
|
-
enabled,
|
|
56
|
-
deferredReason: "shadow_controller_not_instantiated_v0_20_23",
|
|
57
|
-
hasData: false,
|
|
58
|
-
}),
|
|
77
|
+
status: deriveVcStatus({ enabled: true, hasData: policy.shadowDecisions > 0 }),
|
|
59
78
|
};
|
|
60
79
|
sendJson(res, 200, body);
|
|
61
80
|
return true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mega-compact",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.72",
|
|
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",
|
|
@@ -78,6 +78,11 @@ export class CrystalStore {
|
|
|
78
78
|
private writes = 0;
|
|
79
79
|
private duplicateWrites = 0;
|
|
80
80
|
private collisions = 0;
|
|
81
|
+
/** Restart-survival crystal count/bytes (LIVEWIRE rehydrate). The `committed`
|
|
82
|
+
* map is empty in a fresh process; these offsets carry the persisted totals
|
|
83
|
+
* so the dashboard does not reset to zero on restart. */
|
|
84
|
+
private rehydratedCrystalCount = 0;
|
|
85
|
+
private rehydratedTotalBytes = 0;
|
|
81
86
|
|
|
82
87
|
/** Freeze a crystal object for a key/bytes pair (digest computed here). */
|
|
83
88
|
static freeze(keyDigest: string, bytes: Uint8Array, key: CrystalV1["key"]): CrystalV1 {
|
|
@@ -196,11 +201,11 @@ export class CrystalStore {
|
|
|
196
201
|
|
|
197
202
|
/** Reader-only aggregate for the dashboard seam — counts and bytes only. */
|
|
198
203
|
stats(): CrystalStoreStats {
|
|
199
|
-
let totalBytes =
|
|
204
|
+
let totalBytes = this.rehydratedTotalBytes;
|
|
200
205
|
for (const c of this.committed.values()) totalBytes += c.byteCount;
|
|
201
206
|
return {
|
|
202
207
|
mode: this.mode(),
|
|
203
|
-
crystalCount: this.committed.size,
|
|
208
|
+
crystalCount: this.rehydratedCrystalCount + this.committed.size,
|
|
204
209
|
totalBytes,
|
|
205
210
|
hits: this.hits,
|
|
206
211
|
misses: this.misses,
|
|
@@ -210,4 +215,23 @@ export class CrystalStore {
|
|
|
210
215
|
collisions: this.collisions,
|
|
211
216
|
};
|
|
212
217
|
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Restart survival: seed the CUMULATIVE counters from a previously-persisted
|
|
221
|
+
* aggregate (LIVEWIRE). The in-memory `committed` map is naturally empty in a
|
|
222
|
+
* fresh process — this only restores the running totals the dashboard reports,
|
|
223
|
+
* so a process restart does not reset the dashboard to zero. It deliberately
|
|
224
|
+
* does NOT reconstruct crystals: frozen bytes are never persisted to the
|
|
225
|
+
* reader aggregate, only the counts.
|
|
226
|
+
*/
|
|
227
|
+
rehydrate(stats: CrystalStoreStats): void {
|
|
228
|
+
this.rehydratedCrystalCount = stats.crystalCount;
|
|
229
|
+
this.rehydratedTotalBytes = stats.totalBytes;
|
|
230
|
+
this.hits = stats.hits;
|
|
231
|
+
this.misses = stats.misses;
|
|
232
|
+
this.hitBytes = stats.hitBytes;
|
|
233
|
+
this.writes = stats.writes;
|
|
234
|
+
this.duplicateWrites = stats.duplicateWrites;
|
|
235
|
+
this.collisions = stats.collisions;
|
|
236
|
+
}
|
|
213
237
|
}
|
|
@@ -26,7 +26,19 @@ import {
|
|
|
26
26
|
} from "./types.js";
|
|
27
27
|
|
|
28
28
|
export type AssetVerifyResult =
|
|
29
|
-
| {
|
|
29
|
+
| {
|
|
30
|
+
ok: true;
|
|
31
|
+
embeddedBytes: number;
|
|
32
|
+
maxTokens: number;
|
|
33
|
+
onnxDigest: string;
|
|
34
|
+
tokenizerDigest: string;
|
|
35
|
+
/**
|
|
36
|
+
* ML5-A (VC2B-2): digest of the manifest-pinned `trained-heads.json`
|
|
37
|
+
* sibling when the manifest declares `headWeights`; null when the
|
|
38
|
+
* manifest ships no head weights (the committed placeholder bundle).
|
|
39
|
+
*/
|
|
40
|
+
headWeightsDigest: string | null;
|
|
41
|
+
}
|
|
30
42
|
| { ok: false; code: string };
|
|
31
43
|
|
|
32
44
|
/** True when `p` is a single basename: non-empty, no path separators, no "..",
|
|
@@ -80,7 +92,14 @@ function isManifest(m: unknown): m is ModelManifestV1 {
|
|
|
80
92
|
typeof o.onnx.path === "string" &&
|
|
81
93
|
typeof o.onnx.sha256 === "string" &&
|
|
82
94
|
typeof o.tokenizer.path === "string" &&
|
|
83
|
-
typeof o.tokenizer.sha256 === "string"
|
|
95
|
+
typeof o.tokenizer.sha256 === "string" &&
|
|
96
|
+
// ML5-A (VC2B-2): optional headWeights must, when present, be a valid
|
|
97
|
+
// ManifestAssetFile (path basename + sha256 + bytes).
|
|
98
|
+
(o.headWeights === undefined ||
|
|
99
|
+
(!!o.headWeights &&
|
|
100
|
+
typeof o.headWeights.path === "string" &&
|
|
101
|
+
typeof o.headWeights.sha256 === "string" &&
|
|
102
|
+
typeof o.headWeights.bytes === "number"))
|
|
84
103
|
);
|
|
85
104
|
}
|
|
86
105
|
|
|
@@ -122,6 +141,11 @@ export function verifyEncoderAsset(
|
|
|
122
141
|
if (!isBasename(manifest.onnx.path) || !isBasename(manifest.tokenizer.path)) {
|
|
123
142
|
return { ok: false, code: ENC_FAIL.MANIFEST_INVALID };
|
|
124
143
|
}
|
|
144
|
+
// ML5-A (VC2B-2): a manifest-declared headWeights path must also be a bare
|
|
145
|
+
// basename (no traversal into arbitrary paths off the asset dir).
|
|
146
|
+
if (manifest.headWeights !== undefined && !isBasename(manifest.headWeights.path)) {
|
|
147
|
+
return { ok: false, code: ENC_FAIL.MANIFEST_INVALID };
|
|
148
|
+
}
|
|
125
149
|
|
|
126
150
|
const onnxPath = join(assetDir, manifest.onnx.path);
|
|
127
151
|
const onnxDigest = digestFile(onnxPath);
|
|
@@ -133,13 +157,32 @@ export function verifyEncoderAsset(
|
|
|
133
157
|
if (tokDigest === null) return { ok: false, code: ENC_FAIL.ASSET_UNREADABLE };
|
|
134
158
|
if (tokDigest !== manifest.tokenizer.sha256) return { ok: false, code: ENC_FAIL.DIGEST_MISMATCH };
|
|
135
159
|
|
|
160
|
+
// ML5-A (VC2B-2): verify the manifest-pinned trained-heads sibling when the
|
|
161
|
+
// manifest declares it. Absent declaration -> headWeightsDigest: null and no
|
|
162
|
+
// failure (committed placeholder bundle ships no trained weights).
|
|
163
|
+
let headWeightsDigest: string | null = null;
|
|
164
|
+
if (manifest.headWeights !== undefined) {
|
|
165
|
+
const hwPath = join(assetDir, manifest.headWeights.path);
|
|
166
|
+
const hwDigest = digestFile(hwPath);
|
|
167
|
+
if (hwDigest === null) return { ok: false, code: ENC_FAIL.ASSET_UNREADABLE };
|
|
168
|
+
if (hwDigest !== manifest.headWeights.sha256) return { ok: false, code: ENC_FAIL.DIGEST_MISMATCH };
|
|
169
|
+
headWeightsDigest = hwDigest;
|
|
170
|
+
}
|
|
171
|
+
|
|
136
172
|
let embeddedBytes = 0;
|
|
137
173
|
try {
|
|
138
174
|
embeddedBytes = statSync(onnxPath).size + statSync(tokPath).size;
|
|
139
175
|
} catch {
|
|
140
176
|
return { ok: false, code: ENC_FAIL.ASSET_UNREADABLE };
|
|
141
177
|
}
|
|
142
|
-
return {
|
|
178
|
+
return {
|
|
179
|
+
ok: true,
|
|
180
|
+
embeddedBytes,
|
|
181
|
+
maxTokens: manifest.maxTokens,
|
|
182
|
+
onnxDigest,
|
|
183
|
+
tokenizerDigest: tokDigest,
|
|
184
|
+
headWeightsDigest,
|
|
185
|
+
};
|
|
143
186
|
}
|
|
144
187
|
|
|
145
188
|
/**
|
|
@@ -26,15 +26,24 @@
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
import { createEncoderRuntime } from "./runtime.js";
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
encodeVectorSet,
|
|
31
|
+
loadHeadProjections,
|
|
32
|
+
projectHeadFromTrunk,
|
|
33
|
+
type HeadProjectionOptions,
|
|
34
|
+
type HeadProjectionTable,
|
|
35
|
+
} from "./heads.js";
|
|
30
36
|
import { embedTrigram512, selectTrigramBFallback } from "./trigram.js";
|
|
31
37
|
import { embedLexical, selectLexicalC } from "./lexical.js";
|
|
32
38
|
import { createEncoderHeadsReporter, type EncoderHeadsReporter } from "./emit-vc2b.js";
|
|
39
|
+
import { ML5A_ENABLED } from "../../config/vector-cortex.js";
|
|
33
40
|
import {
|
|
34
41
|
ENC_FAIL,
|
|
42
|
+
ENCODER_HEAD_ORDER,
|
|
35
43
|
type EncoderInput,
|
|
36
44
|
type EncoderLoadResult,
|
|
37
45
|
type EncoderRuntime,
|
|
46
|
+
type HeadVector,
|
|
38
47
|
type VectorSetV1,
|
|
39
48
|
} from "./types.js";
|
|
40
49
|
|
|
@@ -61,6 +70,15 @@ export interface RouterOptions extends HeadProjectionOptions {
|
|
|
61
70
|
/** Forced fallback: skips the A load and selects the named VC2B fallback
|
|
62
71
|
* (used to exercise C when A and B are both disabled). Optional. */
|
|
63
72
|
readonly forceFallback?: "B" | "C";
|
|
73
|
+
/**
|
|
74
|
+
* ML5-A (VC2B-2): path to the `trained-heads-v1` artifact. When supplied AND
|
|
75
|
+
* the MEGACOMPACT_ML5_A gate is on AND the artifact loads (correct seed +
|
|
76
|
+
* shape), the mode-A VectorSet is produced by projecting the real trained head
|
|
77
|
+
* matrices over the trunk embedding (`projectHeadFromTrunk`). When absent /
|
|
78
|
+
* flag-off / unloadable, the mode-A producer falls back to the deterministic
|
|
79
|
+
* LCG placeholder `encodeVectorSet` (byte-identical predecessor).
|
|
80
|
+
*/
|
|
81
|
+
readonly trainedHeadsPath?: string;
|
|
64
82
|
}
|
|
65
83
|
|
|
66
84
|
/** Deterministic text derived from an int token sequence so the asset-free
|
|
@@ -133,10 +151,46 @@ export function encodeOrFallback(
|
|
|
133
151
|
if (!inferred.ok) {
|
|
134
152
|
return fallbackFromLoad({ ok: false, mode: "B", code: inferred.code }, reporter, tokens);
|
|
135
153
|
}
|
|
136
|
-
const vectorSet =
|
|
154
|
+
const vectorSet = produceVectorSet(inferred.semantic, tokens, options, reporter);
|
|
137
155
|
return { ok: true, mode: "A", vectorSet, code: null };
|
|
138
156
|
}
|
|
139
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Produce a mode-A `VectorSetV1` from the [1,384] trunk embedding (the
|
|
160
|
+
* `runtime.infer` result). VC2B-2 ML5-A: when real trained heads are loaded
|
|
161
|
+
* (`MEGACOMPACT_ML5_A` on + a `trainedHeadsPath` that loads), the multi-head
|
|
162
|
+
* output is projected through the real trained projection matrices via
|
|
163
|
+
* `projectHeadFromTrunk`. Otherwise (flag-off / absent / unloadable artifact)
|
|
164
|
+
* the deterministic LCG placeholder `encodeVectorSet` serves mode A —
|
|
165
|
+
* byte-identical to the VC2B predecessor. Non-fatal: an unloadable artifact
|
|
166
|
+
* degrades to the placeholder, never a throw.
|
|
167
|
+
*/
|
|
168
|
+
function produceVectorSet(
|
|
169
|
+
trunkEmbedding: Float32Array,
|
|
170
|
+
tokens: readonly number[],
|
|
171
|
+
options: RouterOptions,
|
|
172
|
+
reporter: EncoderHeadsReporter,
|
|
173
|
+
): VectorSetV1 {
|
|
174
|
+
const table: HeadProjectionTable | null =
|
|
175
|
+
ML5A_ENABLED() && options.trainedHeadsPath !== undefined
|
|
176
|
+
? loadHeadProjections(options.trainedHeadsPath)
|
|
177
|
+
: null;
|
|
178
|
+
if (table !== null) {
|
|
179
|
+
const heads: HeadVector[] = ENCODER_HEAD_ORDER.map((h) =>
|
|
180
|
+
projectHeadFromTrunk(h, trunkEmbedding, table),
|
|
181
|
+
);
|
|
182
|
+
reporter.headsEmitted({
|
|
183
|
+
heads: heads.length,
|
|
184
|
+
dims: heads.map((h) => h.dim).join("/"),
|
|
185
|
+
normalized: true,
|
|
186
|
+
tokens: tokens.length,
|
|
187
|
+
});
|
|
188
|
+
return { schema: "vector-set-v1", inputTokens: [...tokens], heads, normalized: true };
|
|
189
|
+
}
|
|
190
|
+
// ML5-A placeholder fallback (byte-identical predecessor).
|
|
191
|
+
return encodeVectorSet(tokens, { reporter, seed: options.seed });
|
|
192
|
+
}
|
|
193
|
+
|
|
140
194
|
/**
|
|
141
195
|
* Catch a (real or forced) A load failure (ok === false only) and select the
|
|
142
196
|
* B/C fallback that emits `vector_cortex_encoder_fallback_selected` from the
|
|
@@ -92,6 +92,9 @@ export interface ModelManifestV1 {
|
|
|
92
92
|
readonly heads: EncoderHeads;
|
|
93
93
|
readonly onnx: ManifestAssetFile;
|
|
94
94
|
readonly tokenizer: ManifestAssetFile;
|
|
95
|
+
/** ML5-A (VC2B-2): optional sibling `trained-heads.json` (`trained-heads-v1`) shipping
|
|
96
|
+
* REAL trained head weights; absent in the placeholder bundle, non-fatal when missing. */
|
|
97
|
+
readonly headWeights?: ManifestAssetFile;
|
|
95
98
|
readonly totalBytes: number;
|
|
96
99
|
readonly trainingManifestDigest: string;
|
|
97
100
|
}
|