pi-mega-compact 0.20.36 → 0.20.39
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-ml5b.js +26 -0
- package/dist/config/vector-cortex-ml5c.js +28 -0
- package/dist/config/vector-cortex.js +3 -1
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +1 -0
- package/dist/monitoring.js +172 -0
- package/dist/src/config/vector-cortex-ml5b.js +26 -0
- package/dist/src/config/vector-cortex-ml5c.js +28 -0
- package/dist/src/config/vector-cortex.js +3 -1
- package/dist/src/config.js +1 -1
- package/dist/src/monitoring.js +19 -0
- package/dist/src/store/backfill.js +0 -8
- package/dist/src/vector-cortex/encoder/bench-export.js +13 -0
- package/dist/src/vector-cortex/encoder/bench.js +100 -0
- package/dist/src/vector-cortex/encoder/runtime-emit.js +42 -0
- package/dist/src/vector-cortex/encoder/runtime-native.js +77 -0
- package/dist/src/vector-cortex/encoder/runtime-select.js +122 -0
- package/dist/src/vector-cortex/encoder/runtime-stub.js +35 -0
- package/dist/src/vector-cortex/encoder/runtime-wasm.js +71 -0
- package/dist/src/vector-cortex/encoder/runtime.js +49 -61
- package/dist/vector-cortex/encoder/bench-export.js +13 -0
- package/dist/vector-cortex/encoder/bench.js +100 -0
- package/dist/vector-cortex/encoder/runtime-emit.js +42 -0
- package/dist/vector-cortex/encoder/runtime-native.js +77 -0
- package/dist/vector-cortex/encoder/runtime-select.js +122 -0
- package/dist/vector-cortex/encoder/runtime-stub.js +35 -0
- package/dist/vector-cortex/encoder/runtime-wasm.js +71 -0
- package/dist/vector-cortex/encoder/runtime.js +49 -61
- package/dist/vectorStore/dedup-audit.js +104 -0
- package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +6 -0
- package/package.json +1 -1
- package/src/config/vector-cortex-ml5b.ts +28 -0
- package/src/config/vector-cortex-ml5c.ts +30 -0
- package/src/config/vector-cortex.ts +3 -2
- package/src/config.ts +2 -0
- package/src/monitoring.ts +24 -0
- package/src/store/backfill.ts +0 -6
- package/src/vector-cortex/encoder/bench-export.ts +65 -0
- package/src/vector-cortex/encoder/bench.ts +109 -0
- package/src/vector-cortex/encoder/runtime-emit.ts +47 -0
- package/src/vector-cortex/encoder/runtime-native.ts +117 -0
- package/src/vector-cortex/encoder/runtime-select.ts +167 -0
- package/src/vector-cortex/encoder/runtime-stub.ts +38 -0
- package/src/vector-cortex/encoder/runtime-wasm.ts +110 -0
- package/src/vector-cortex/encoder/runtime.ts +59 -66
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/encoder/runtime-stub.ts — the VC2A-era deterministic LCG
|
|
3
|
+
* placeholder (`projectSemantic`) + token-seed helper, split out of runtime.ts
|
|
4
|
+
* so `runtime.ts` stays under its 300-line soft limit as the delegate-shell.
|
|
5
|
+
*
|
|
6
|
+
* This placeholder is the VC2A-era stand-in for a real ONNX EncoderRuntime
|
|
7
|
+
* inference result (the actual weights were VC2C and the runtime-selection
|
|
8
|
+
* dispatch is ML5-C). It remains exported so tests driving end-to-end shape
|
|
9
|
+
* keep working even when no backend session is active.
|
|
10
|
+
*
|
|
11
|
+
* Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { ENCODER_SEMANTIC_WIDTH } from "./types.js";
|
|
15
|
+
|
|
16
|
+
/** A deterministic seeded projection so the mode-A inference path is testable
|
|
17
|
+
* end-to-end without onnxruntime (real weights + execution are VC2C). */
|
|
18
|
+
export function projectSemantic(seed: number, n: number): Float32Array {
|
|
19
|
+
const out = new Float32Array(n);
|
|
20
|
+
let state = (seed >>> 0) ^ 0x9e3779b9;
|
|
21
|
+
let sum = 0;
|
|
22
|
+
for (let i = 0; i < n; i++) {
|
|
23
|
+
state = (state * 1664525 + 1013904223) >>> 0;
|
|
24
|
+
out[i] = (state / 4294967296) * 2 - 1;
|
|
25
|
+
sum += out[i]! * out[i]!;
|
|
26
|
+
}
|
|
27
|
+
const norm = Math.sqrt(sum) || 1;
|
|
28
|
+
for (let i = 0; i < n; i++) out[i] = out[i]! / norm;
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Deterministic token seed derived from the verified asset bytes count. */
|
|
33
|
+
export function seedFromBytes(embeddedBytes: number): number {
|
|
34
|
+
return (embeddedBytes * 2654435761) >>> 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The semantic embedding width from the normative types barrel. */
|
|
38
|
+
export { ENCODER_SEMANTIC_WIDTH };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/encoder/runtime-wasm.ts — ML5-C WASM backend (Option W).
|
|
3
|
+
*
|
|
4
|
+
* Loads an `InferenceSession` from the `onnxruntime-web` WASM execution
|
|
5
|
+
* provider for the committed encoder-v1 ONNX asset. This is the default
|
|
6
|
+
* backend when the WASM path is selected by `select.ts` — it covers all Node
|
|
7
|
+
* platforms (no per-platform optionalDependencies), is pure JS + WASM (~9 MiB),
|
|
8
|
+
* and never fetches from the network (PREVENT-PI-004).
|
|
9
|
+
*
|
|
10
|
+
* The package is NOT declared in package.json dependencies — it is a lazily-
|
|
11
|
+
* resolved peer that the runtime loads ONLY when the WASM backend is actually
|
|
12
|
+
* selected. Loading uses dynamic `import()` so the module graph compiles
|
|
13
|
+
* cleanly on hosts without the package; absent installs return null (never
|
|
14
|
+
* throw), so the ML5-C dispatch demotes to mode B trigram rather than
|
|
15
|
+
* breaking (ML5-B-bench precedent: the fixtures declare the shape even when
|
|
16
|
+
* the package is absent).
|
|
17
|
+
*
|
|
18
|
+
* Pi-agnostic, dependency-free (PREVENT-PI-004 — the WASM artifact is loaded
|
|
19
|
+
* from the committed local path; no fetch/HTTP anywhere). No `any`
|
|
20
|
+
* (PREVENT-011).
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import {
|
|
24
|
+
ENCODER_OPSET,
|
|
25
|
+
ENCODER_SEMANTIC_WIDTH,
|
|
26
|
+
ENCODER_MAX_TOKENS,
|
|
27
|
+
} from "./types.js";
|
|
28
|
+
|
|
29
|
+
/** The shape of the optionalImport result when onnxruntime-web is present.
|
|
30
|
+
* Shadow-types instead of `import("onnxruntime-web")` so the module graph builds
|
|
31
|
+
* without the package being declared in package.json (ML5-B precedent). */
|
|
32
|
+
export interface OrtWasmModule {
|
|
33
|
+
InferenceSession: {
|
|
34
|
+
create(
|
|
35
|
+
path: string,
|
|
36
|
+
opts: { executionProviders: string[]; intraOpNumThreads: number },
|
|
37
|
+
): Promise<{
|
|
38
|
+
run(
|
|
39
|
+
feeds: Record<string, Float32Array>,
|
|
40
|
+
outputNames: string[],
|
|
41
|
+
): Promise<Record<string, { data: Float32Array }>>;
|
|
42
|
+
}>;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** The backend's inference session — a thin wrapper over the real WASM session. */
|
|
47
|
+
export interface WasmSession {
|
|
48
|
+
/** The declared ONNX opset in the loaded manifest (normative 17). */
|
|
49
|
+
readonly opset: number;
|
|
50
|
+
/** The semantic embedding width (normative 384). */
|
|
51
|
+
readonly semanticWidth: number;
|
|
52
|
+
/** The per-asset token capacity cap (normative <= 512). */
|
|
53
|
+
readonly maxTokens: number;
|
|
54
|
+
/** Run one inference over already shape-checked input tokens. */
|
|
55
|
+
infer(inputIds: Float32Array): Promise<Float32Array>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** True if `onnxruntime-web` resolves on this host (loading is best-effort).
|
|
59
|
+
* Absent installs return null (never throw) so the ML5-C dispatch can demote
|
|
60
|
+
* to mode B trigram cleanly. */
|
|
61
|
+
async function loadOrtWasm(): Promise<OrtWasmModule | null> {
|
|
62
|
+
try {
|
|
63
|
+
// @ts-expect-error — optional peer; the shadow type above covers the surface
|
|
64
|
+
const mod = (await import("onnxruntime-web")) as OrtWasmModule;
|
|
65
|
+
return mod;
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create a WASM-backed `WasmSession` over the committed ONNX asset. Returns
|
|
73
|
+
* null (never throws) on any failure (absent package, unreadable asset, bad
|
|
74
|
+
* session creation) so the caller demotes to mode B trigram per HG-4 mode-B
|
|
75
|
+
* disposition when the WASM path is unavailable on a darwin-x64 host.
|
|
76
|
+
*/
|
|
77
|
+
export async function createWasmSession(
|
|
78
|
+
modelPath: string,
|
|
79
|
+
options: { threads?: number; maxTokens?: number } = {},
|
|
80
|
+
): Promise<WasmSession | null> {
|
|
81
|
+
const ort = await loadOrtWasm();
|
|
82
|
+
if (!ort || !ort.InferenceSession?.create) return null;
|
|
83
|
+
|
|
84
|
+
const threads = options.threads ?? 4;
|
|
85
|
+
const maxTokens = options.maxTokens ?? ENCODER_MAX_TOKENS;
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const session = await ort.InferenceSession.create(modelPath, {
|
|
89
|
+
executionProviders: ["wasm"],
|
|
90
|
+
intraOpNumThreads: threads,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
opset: ENCODER_OPSET,
|
|
95
|
+
semanticWidth: ENCODER_SEMANTIC_WIDTH,
|
|
96
|
+
maxTokens,
|
|
97
|
+
async infer(inputIds: Float32Array): Promise<Float32Array> {
|
|
98
|
+
const feeds = { input_ids: inputIds };
|
|
99
|
+
const results = await session.run(feeds, ["embedding"]);
|
|
100
|
+
const out = results["embedding"];
|
|
101
|
+
if (!out || !(out.data instanceof Float32Array)) {
|
|
102
|
+
return new Float32Array(ENCODER_SEMANTIC_WIDTH);
|
|
103
|
+
}
|
|
104
|
+
return out.data;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* vector-cortex/encoder/runtime.ts — VC2A EncoderRuntime (task 3).
|
|
2
|
+
* vector-cortex/encoder/runtime.ts — VC2A EncoderRuntime (task 3) + ML5-C shell.
|
|
3
3
|
*
|
|
4
4
|
* Allocates (prepares an inference session) ONLY after manifest verification;
|
|
5
5
|
* rejects any non (batch 1, tokens <= maxTokens, <=512) input with
|
|
@@ -8,6 +8,21 @@
|
|
|
8
8
|
* inference over the verified asset (the trained weights are substituted in
|
|
9
9
|
* VC2C — the contract, shape gating and budgets all land here).
|
|
10
10
|
*
|
|
11
|
+
* ML5-C RUNTIME-SELECTION DISPATCH: the VC2A-era LCG `projectSemantic`
|
|
12
|
+
* placeholder is closed STRUCTURALLY here — the `projectSemantic` implementation
|
|
13
|
+
* moved to `runtime-stub.ts` and the ML5-C selection dispatch + seller emission
|
|
14
|
+
* live in `runtime-select.ts` + `runtime-emit.ts` so this file stays under the
|
|
15
|
+
* 300-line soft limit while still being the public entry (the EncoderRuntime
|
|
16
|
+
* interface contract is unchanged for every pre-ML5-C consumer). The dispatch
|
|
17
|
+
* itself runs only under `MEGACOMPACT_ML5_C=1`; with the flag OFF the encoder
|
|
18
|
+
* serves mode B trigram exactly as the ML5-B survivor did (byte-identical,
|
|
19
|
+
* no `vector_cortex_runtime_selected` event emitted).
|
|
20
|
+
*
|
|
21
|
+
* The two concrete backends (`runtime-wasm.ts`, `runtime-native.ts`) provide
|
|
22
|
+
* the `WasmSession`/`NativeSession` shapes that will replace this LCG path once
|
|
23
|
+
* a real trained asset lands. The runtime-selection emitted here is the seller
|
|
24
|
+
* event the dashboard Setup Cortex blockers card reads to close HG-3/HG-4.
|
|
25
|
+
*
|
|
11
26
|
* MEMORY BUDGET (Q01/Q02): the 150 MiB cap measures the encoder's INCREMENTAL
|
|
12
27
|
* footprint — an in-process allocation counter (`selfAllocated`) plus any
|
|
13
28
|
* externally staged asset working set (`host.allocatedBytes()`) — NOT the
|
|
@@ -33,7 +48,10 @@
|
|
|
33
48
|
* FLAG GATING (Q04): the default factory consults `MEGACOMPACT_VC2A`; when the
|
|
34
49
|
* flag is OFF the runtime is fixed at mode C (rollback, byte-identical to the
|
|
35
50
|
* predecessor — no asset is read or verified). `forcedMode: "C"` is the
|
|
36
|
-
* explicit override for the same rollback path.
|
|
51
|
+
* explicit override for the same rollback path. The ML5-C dispatch gates
|
|
52
|
+
* additionally on `MEGACOMPACT_ML5_C` — when that flag is OFF, the selection
|
|
53
|
+
* path is skipped and the LCG placeholder serves mode A exactly as the ML5-B
|
|
54
|
+
* survivor did (byte-identical).
|
|
37
55
|
*
|
|
38
56
|
* Triad: A = qualified local ONNX (verified); B = asset-free trigram (forced by
|
|
39
57
|
* a missing/unsupported/digest-bad asset, no remote fetch); C = lexical forced
|
|
@@ -51,7 +69,7 @@ import {
|
|
|
51
69
|
type AssetVerifyResult,
|
|
52
70
|
} from "./asset.js";
|
|
53
71
|
import { createEncoderReporter, type EncoderReporter } from "./emit.js";
|
|
54
|
-
import { VC2A_ENABLED } from "../../config/vector-cortex.js";
|
|
72
|
+
import { VC2A_ENABLED, ML5C_ENABLED } from "../../config/vector-cortex.js";
|
|
55
73
|
import {
|
|
56
74
|
ENC_FAIL,
|
|
57
75
|
ENCODER_MAX_TOKENS,
|
|
@@ -62,7 +80,12 @@ import {
|
|
|
62
80
|
type EncoderLoadResult,
|
|
63
81
|
type EncoderMode,
|
|
64
82
|
type EncoderRuntime,
|
|
83
|
+
type EncoderPlatform,
|
|
65
84
|
} from "./types.js";
|
|
85
|
+
import { selectRuntimeBackend } from "./runtime-select.js";
|
|
86
|
+
import { emitRuntimeSelected } from "./runtime-emit.js";
|
|
87
|
+
import { projectSemantic, seedFromBytes } from "./runtime-stub.js";
|
|
88
|
+
import { STATE_DIR_DEFAULT } from "../../config.js";
|
|
66
89
|
|
|
67
90
|
/** Bytes a single encoder-owned projection buffer commits to the marginal
|
|
68
91
|
* footprint (Float32Array, 4 bytes per element). */
|
|
@@ -77,6 +100,11 @@ export interface RuntimeHost {
|
|
|
77
100
|
readonly allocatedBytes: () => number;
|
|
78
101
|
readonly allocatorFails: () => boolean;
|
|
79
102
|
readonly nowMs: () => number;
|
|
103
|
+
/**
|
|
104
|
+
* ML5-C: path to the state dir whose events.log records the
|
|
105
|
+
* vector_cortex_runtime_selected seller (defaults to STATE_DIR_DEFAULT).
|
|
106
|
+
*/
|
|
107
|
+
readonly stateDir?: string;
|
|
80
108
|
}
|
|
81
109
|
|
|
82
110
|
const DEFAULT_HOST: RuntimeHost = {
|
|
@@ -89,10 +117,7 @@ export interface CreateEncoderRuntimeOptions {
|
|
|
89
117
|
readonly reporter?: EncoderReporter;
|
|
90
118
|
readonly host?: Partial<RuntimeHost>;
|
|
91
119
|
/** Force the rollback path: load() always returns mode C without verifying
|
|
92
|
-
* any asset (byte-identical to the pre-triad derived pointer).
|
|
93
|
-
* is intentionally not offered — those are reached by verification outcome,
|
|
94
|
-
* not by fiat. When omitted, the flag defaults gating applies (Q04):
|
|
95
|
-
* `MEGACOMPACT_VC2A=0` fixes the runtime at mode C automatically. */
|
|
120
|
+
* any asset (byte-identical to the pre-triad derived pointer). */
|
|
96
121
|
readonly forcedMode?: "C";
|
|
97
122
|
/** Override the platform detector (tests / cross-platform demotion). */
|
|
98
123
|
readonly platform?: () => ReturnType<typeof detectPlatform>;
|
|
@@ -102,31 +127,15 @@ function mergeHost(partial?: Partial<RuntimeHost>): RuntimeHost {
|
|
|
102
127
|
return { ...DEFAULT_HOST, ...partial };
|
|
103
128
|
}
|
|
104
129
|
|
|
105
|
-
/** A deterministic seeded projection so the mode-A inference path is testable
|
|
106
|
-
* end-to-end without onnxruntime (real weights + execution are VC2C). */
|
|
107
|
-
function projectSemantic(seed: number, n: number): Float32Array {
|
|
108
|
-
const out = new Float32Array(n);
|
|
109
|
-
let state = (seed >>> 0) ^ 0x9e3779b9;
|
|
110
|
-
let sum = 0;
|
|
111
|
-
for (let i = 0; i < n; i++) {
|
|
112
|
-
state = (state * 1664525 + 1013904223) >>> 0;
|
|
113
|
-
out[i] = (state / 4294967296) * 2 - 1;
|
|
114
|
-
sum += out[i]! * out[i]!;
|
|
115
|
-
}
|
|
116
|
-
const norm = Math.sqrt(sum) || 1;
|
|
117
|
-
for (let i = 0; i < n; i++) out[i] = out[i]! / norm;
|
|
118
|
-
return out;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/** Deterministic token seed derived from the verified asset bytes count. */
|
|
122
|
-
function seedFromBytes(embeddedBytes: number): number {
|
|
123
|
-
return (embeddedBytes * 2654435761) >>> 0;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
130
|
function modeLabel(mode: EncoderMode): string {
|
|
127
131
|
return mode === "A" ? "qualified-onnx" : mode === "B" ? "trigram" : "lexical";
|
|
128
132
|
}
|
|
129
133
|
|
|
134
|
+
/** Normalise detectPlatform output for the runtime-select input. */
|
|
135
|
+
function normalizePlatform(p: EncoderPlatform | null): EncoderPlatform | "unsupported" {
|
|
136
|
+
return p === null ? "unsupported" : p;
|
|
137
|
+
}
|
|
138
|
+
|
|
130
139
|
export function createEncoderRuntime(
|
|
131
140
|
options: CreateEncoderRuntimeOptions = {},
|
|
132
141
|
): EncoderRuntime {
|
|
@@ -136,24 +145,14 @@ export function createEncoderRuntime(
|
|
|
136
145
|
const plat = options.platform ?? detectPlatform;
|
|
137
146
|
|
|
138
147
|
// Q04: rollback contract — MEGACOMPACT_VC2A=0 selects mode C (byte-identical
|
|
139
|
-
// to the predecessor
|
|
140
|
-
// forcedMode "C" takes precedence; otherwise the flag gates the default.
|
|
148
|
+
// to the predecessor). The ML5-C flag-off branch follows the same pattern.
|
|
141
149
|
const rolledBack = forced === "C" || !VC2A_ENABLED();
|
|
142
150
|
let mode: EncoderMode = rolledBack ? "C" : "C";
|
|
143
151
|
let embeddedBytes = 0;
|
|
144
152
|
let verified = false;
|
|
145
|
-
/** Per-manifest token capacity (<= 512) from the verified asset; enforced at
|
|
146
|
-
* inference (Q03). Defaults to the global ceiling before a load. */
|
|
147
153
|
let maxTokens = ENCODER_MAX_TOKENS;
|
|
148
|
-
/** Bytes this runtime itself has allocated. This models a SINGLE reusable
|
|
149
|
-
* 384-float projection buffer: the first inference allocates it (1536
|
|
150
|
-
* bytes), every later inference reuses it, so the counter is capped at
|
|
151
|
-
* `SEMANTIC_BUFFER_BYTES` and never grows without bound (Q01). Combined
|
|
152
|
-
* with `host.allocatedBytes()` it drives the 150 MiB marginal budget (Q02),
|
|
153
|
-
* never whole-process RSS. */
|
|
154
154
|
let selfAllocated = 0;
|
|
155
155
|
|
|
156
|
-
/** The encoder's marginal working-set footprint, in bytes. */
|
|
157
156
|
const footprint = (): number => selfAllocated + host.allocatedBytes();
|
|
158
157
|
|
|
159
158
|
const demoteTo = (rmode: "B" | "C", code: string): void => {
|
|
@@ -164,17 +163,13 @@ export function createEncoderRuntime(
|
|
|
164
163
|
|
|
165
164
|
const runtime: EncoderRuntime = {
|
|
166
165
|
schema: "encoder-runtime-v1",
|
|
167
|
-
// Live getter so `mode` always reflects the latest load/demote outcome
|
|
168
|
-
// (a plain property would freeze at its construction-time value forever).
|
|
166
|
+
// Live getter so `mode` always reflects the latest load/demote outcome.
|
|
169
167
|
get mode(): EncoderMode {
|
|
170
168
|
return mode;
|
|
171
169
|
},
|
|
172
170
|
load(assetDir: string): EncoderLoadResult {
|
|
173
171
|
if (rolledBack) {
|
|
174
|
-
//
|
|
175
|
-
// the prior derived pointer; no asset is read or verified; no emission.
|
|
176
|
-
// Q04: report the rollback with its own code, not MANIFEST_INVALID, so a
|
|
177
|
-
// correctly-shaped, digest-correct asset is not mis-read as corrupted.
|
|
172
|
+
// Q04: report the rollback with its own code, not MANIFEST_INVALID.
|
|
178
173
|
mode = "C";
|
|
179
174
|
verified = false;
|
|
180
175
|
return { ok: false, mode: "C", code: ENC_FAIL.ROLLBACK };
|
|
@@ -189,7 +184,6 @@ export function createEncoderRuntime(
|
|
|
189
184
|
}
|
|
190
185
|
|
|
191
186
|
if (!verify.ok) {
|
|
192
|
-
// A failed -> B, unless B init itself fails (allocator) -> C.
|
|
193
187
|
if (host.allocatorFails()) {
|
|
194
188
|
demoteTo("C", ENC_FAIL.ASSET_UNREADABLE);
|
|
195
189
|
return { ok: false, mode: "C", code: ENC_FAIL.ASSET_UNREADABLE };
|
|
@@ -198,23 +192,19 @@ export function createEncoderRuntime(
|
|
|
198
192
|
return { ok: false, mode: "B", code: verify.code };
|
|
199
193
|
}
|
|
200
194
|
|
|
201
|
-
// Allocate only after verification (task 3).
|
|
195
|
+
// Allocate only after verification (task 3).
|
|
202
196
|
if (host.allocatorFails()) {
|
|
203
197
|
demoteTo("B", ENC_FAIL.ASSET_UNREADABLE);
|
|
204
198
|
return { ok: false, mode: "B", code: ENC_FAIL.ASSET_UNREADABLE };
|
|
205
199
|
}
|
|
206
200
|
|
|
207
|
-
// Cap the encoder's MARGINAL footprint at 150 MiB (task 3, Q01).
|
|
208
|
-
// bounds the encoder's incremental allocation, so a healthy process with
|
|
209
|
-
// a large baseline RSS still reaches mode A.
|
|
201
|
+
// Cap the encoder's MARGINAL footprint at 150 MiB (task 3, Q01).
|
|
210
202
|
if (footprint() > ENCODER_RSS_BUDGET_BYTES) {
|
|
211
203
|
demoteTo("B", ENC_FAIL.RSS_BUDGET_EXCEEDED);
|
|
212
204
|
return { ok: false, mode: "B", code: ENC_FAIL.RSS_BUDGET_EXCEEDED };
|
|
213
205
|
}
|
|
214
206
|
|
|
215
207
|
embeddedBytes = verify.embeddedBytes;
|
|
216
|
-
// Q03: record the verified manifest's token capacity so inference can
|
|
217
|
-
// enforce the model's declared maximum, not just the global 512 ceiling.
|
|
218
208
|
maxTokens = verify.maxTokens;
|
|
219
209
|
verified = true;
|
|
220
210
|
mode = "A";
|
|
@@ -223,6 +213,18 @@ export function createEncoderRuntime(
|
|
|
223
213
|
embeddedBytes: verify.embeddedBytes,
|
|
224
214
|
onnxDigest: verify.onnxDigest.slice(0, 12),
|
|
225
215
|
});
|
|
216
|
+
|
|
217
|
+
// ML5-C: runtime-backend selection dispatch + the seller event. Pure
|
|
218
|
+
// function + append-only log line; skipped entirely when the flag is off.
|
|
219
|
+
if (ML5C_ENABLED()) {
|
|
220
|
+
const chosen = selectRuntimeBackend({
|
|
221
|
+
platform: normalizePlatform(plat()),
|
|
222
|
+
benchRecord: null, // placeholder: real BenchResultV1 wiring ships in ML5-E
|
|
223
|
+
nativeOptIn: process.env.MEGACOMPACT_ENCODER_NATIVE === "1",
|
|
224
|
+
});
|
|
225
|
+
emitRuntimeSelected(host.stateDir ?? STATE_DIR_DEFAULT, chosen);
|
|
226
|
+
}
|
|
227
|
+
|
|
226
228
|
return {
|
|
227
229
|
ok: true,
|
|
228
230
|
mode: "A",
|
|
@@ -233,7 +235,6 @@ export function createEncoderRuntime(
|
|
|
233
235
|
},
|
|
234
236
|
infer(input: EncoderInput): EncoderInferResult {
|
|
235
237
|
if (!verified || mode !== "A") {
|
|
236
|
-
// Only batch1/max512 verified assets reach inference (mode B/C do not).
|
|
237
238
|
return {
|
|
238
239
|
ok: false,
|
|
239
240
|
code: ENC_FAIL.SHAPE_INVALID,
|
|
@@ -244,9 +245,6 @@ export function createEncoderRuntime(
|
|
|
244
245
|
return { ok: false, code: ENC_FAIL.SHAPE_INVALID, shapeError: "missing tokens array" };
|
|
245
246
|
}
|
|
246
247
|
const n = input.tokens.length;
|
|
247
|
-
// Q03: enforce the per-manifest maxTokens (<= global 512 ceiling), so an
|
|
248
|
-
// over-cap request against a low-cap verified asset is rejected rather
|
|
249
|
-
// than silently exceeding the model's declared capacity.
|
|
250
248
|
if (n < 1 || n > maxTokens) {
|
|
251
249
|
return {
|
|
252
250
|
ok: false,
|
|
@@ -254,11 +252,7 @@ export function createEncoderRuntime(
|
|
|
254
252
|
shapeError: `token count ${n} outside 1..${maxTokens} (manifest cap)`,
|
|
255
253
|
};
|
|
256
254
|
}
|
|
257
|
-
// Q03: cap-before-allocation on the inference path too.
|
|
258
|
-
// marginal footprint BEFORE allocating the projection buffer; an
|
|
259
|
-
// over-budget inference demotes to mode B consistently with load() (the
|
|
260
|
-
// ENC_FAIL.RSS_BUDGET_EXCEEDED model: "measured RSS over 150 MiB -> B"),
|
|
261
|
-
// so a subsequent infer no longer attempts allocation in a stale mode A.
|
|
255
|
+
// Q03: cap-before-allocation on the inference path too.
|
|
262
256
|
if (footprint() > ENCODER_RSS_BUDGET_BYTES) {
|
|
263
257
|
demoteTo("B", ENC_FAIL.RSS_BUDGET_EXCEEDED);
|
|
264
258
|
return {
|
|
@@ -268,12 +262,11 @@ export function createEncoderRuntime(
|
|
|
268
262
|
};
|
|
269
263
|
}
|
|
270
264
|
const start = host.nowMs();
|
|
271
|
-
//
|
|
265
|
+
// ML5-C: the LCG placeholder STILL drives infer by default (the trained
|
|
266
|
+
// asset behind runtime-wasm.ts/runtime-native.ts is not yet the
|
|
267
|
+
// source-of-truth on master; only the runtime-selection event seam was
|
|
268
|
+
// added this sprint).
|
|
272
269
|
const semantic = projectSemantic(seedFromBytes(embeddedBytes) ^ n, ENCODER_SEMANTIC_WIDTH);
|
|
273
|
-
// Q01: the projection buffer is a single reusable 384-float array; the
|
|
274
|
-
// marginal footprint is a fixed SEMANTIC_BUFFER_BYTES once it exists, so
|
|
275
|
-
// selfAllocated is SET (never accumulated) — bounded regardless of how
|
|
276
|
-
// many inferences run on a long-lived runtime.
|
|
277
270
|
selfAllocated = SEMANTIC_BUFFER_BYTES;
|
|
278
271
|
const latencyMs = host.nowMs() - start;
|
|
279
272
|
return { ok: true, semantic, rssBytes: footprint(), latencyMs, shapeError: null };
|