pi-mega-compact 0.20.42 → 0.20.44
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/assets/vector-cortex/encoder-v1/manifest.json +1 -1
- package/assets/vector-cortex/encoder-v1/model-card.json +1 -1
- package/assets/vector-cortex/encoder-v1/model.onnx +0 -0
- package/assets/vector-cortex/encoder-v1/tokenizer.json +1 -1
- package/dist/config/vector-cortex-enc0a.js +32 -0
- package/dist/config/vector-cortex-enc0b.js +34 -0
- package/dist/config/vector-cortex.js +3 -3
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +2 -0
- package/dist/src/config/vector-cortex-enc0a.js +32 -0
- package/dist/src/config/vector-cortex-enc0b.js +34 -0
- package/dist/src/config/vector-cortex.js +3 -3
- package/dist/src/config.js +1 -1
- package/dist/src/vector-cortex/_acceptance-enc0a-contract.js +60 -0
- package/dist/src/vector-cortex/_acceptance-vc2a-conformance.js +90 -0
- package/dist/src/vector-cortex/_acceptance-vc2a-runtime.js +285 -0
- package/dist/src/vector-cortex/_acceptance-vc2b-conformance.js +92 -0
- package/dist/src/vector-cortex/_acceptance-vc2b-heads.js +221 -0
- package/dist/src/vector-cortex/encoder/asset.js +3 -2
- package/dist/src/vector-cortex/encoder/decision.js +75 -0
- package/dist/src/vector-cortex/encoder/emit.js +2 -0
- package/dist/src/vector-cortex/encoder/encoder-onnx-dispatch.js +58 -0
- package/dist/src/vector-cortex/encoder/onnx.js +147 -0
- package/dist/src/vector-cortex/encoder/runtime-wasm.js +17 -4
- package/dist/src/vector-cortex/encoder/runtime.js +17 -7
- package/dist/src/vector-cortex/encoder/types-vc2c.js +50 -0
- package/dist/src/vector-cortex/encoder/types.js +13 -34
- package/dist/vector-cortex/_acceptance-enc0a-contract.js +60 -0
- package/dist/vector-cortex/_acceptance-vc2a-conformance.js +90 -0
- package/dist/vector-cortex/_acceptance-vc2a-runtime.js +285 -0
- package/dist/vector-cortex/_acceptance-vc2b-conformance.js +92 -0
- package/dist/vector-cortex/_acceptance-vc2b-heads.js +221 -0
- package/dist/vector-cortex/encoder/asset.js +3 -2
- package/dist/vector-cortex/encoder/decision.js +75 -0
- package/dist/vector-cortex/encoder/emit.js +2 -0
- package/dist/vector-cortex/encoder/encoder-onnx-dispatch.js +58 -0
- package/dist/vector-cortex/encoder/onnx.js +147 -0
- package/dist/vector-cortex/encoder/runtime-wasm.js +17 -4
- package/dist/vector-cortex/encoder/runtime.js +17 -7
- package/dist/vector-cortex/encoder/types-vc2c.js +50 -0
- package/dist/vector-cortex/encoder/types.js +13 -34
- package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +12 -0
- package/package.json +3 -2
- package/src/config/vector-cortex-enc0a.ts +34 -0
- package/src/config/vector-cortex-enc0b.ts +36 -0
- package/src/config/vector-cortex.ts +3 -3
- package/src/config.ts +2 -0
- package/src/vector-cortex/_acceptance-enc0a-contract.ts +71 -0
- package/src/vector-cortex/_acceptance-vc2a-conformance.ts +119 -0
- package/src/vector-cortex/_acceptance-vc2a-runtime.ts +300 -0
- package/src/vector-cortex/_acceptance-vc2b-conformance.ts +121 -0
- package/src/vector-cortex/_acceptance-vc2b-heads.ts +234 -0
- package/src/vector-cortex/encoder/asset.ts +3 -2
- package/src/vector-cortex/encoder/bench-export.ts +2 -2
- package/src/vector-cortex/encoder/decision.ts +125 -0
- package/src/vector-cortex/encoder/emit.ts +5 -1
- package/src/vector-cortex/encoder/encoder-onnx-dispatch.ts +76 -0
- package/src/vector-cortex/encoder/onnx.ts +198 -0
- package/src/vector-cortex/encoder/runtime-native.ts +1 -1
- package/src/vector-cortex/encoder/runtime-wasm.ts +21 -8
- package/src/vector-cortex/encoder/runtime.ts +27 -9
- package/src/vector-cortex/encoder/types-vc2c.ts +134 -0
- package/src/vector-cortex/encoder/types.ts +19 -115
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/** ENC-0a buildDecision contract constructor suite — extracted from
|
|
2
|
+
* enc0a-acceptance.test.ts for soft-limit compliance. Receives the contract
|
|
3
|
+
* constructor + constants from the aggregator (no import cycle).
|
|
4
|
+
*/
|
|
5
|
+
import { test, describe } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import type { EncoderPlatformRow } from "./encoder/decision.js";
|
|
8
|
+
|
|
9
|
+
export interface Enc0aContractCtx {
|
|
10
|
+
buildDecision: typeof import("./encoder/decision.js").buildDecision;
|
|
11
|
+
PLATFORMS: readonly ["linux-x64", "linux-arm64", "darwin-x64", "darwin-arm64", "win32-x64"];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function registerEnc0aContract(ctx: Enc0aContractCtx): void {
|
|
15
|
+
const { buildDecision, PLATFORMS } = ctx;
|
|
16
|
+
|
|
17
|
+
describe("buildDecision contract constructor", () => {
|
|
18
|
+
test("rejects an incomplete platform matrix", () => {
|
|
19
|
+
const matrix = {
|
|
20
|
+
"linux-x64": { runtime: "onnxruntime-web", installMiB: 33, demotion: "none" },
|
|
21
|
+
"linux-arm64": { runtime: "onnxruntime-web", installMiB: 33, demotion: "none" },
|
|
22
|
+
"darwin-x64": { runtime: "onnxruntime-web", installMiB: 33, demotion: "wasm" },
|
|
23
|
+
"darwin-arm64": { runtime: "onnxruntime-web", installMiB: 33, demotion: "none" },
|
|
24
|
+
// win32-x64 omitted
|
|
25
|
+
} as Record<(typeof PLATFORMS)[number], EncoderPlatformRow>;
|
|
26
|
+
assert.throws(() =>
|
|
27
|
+
buildDecision({
|
|
28
|
+
backend: "wasm",
|
|
29
|
+
budgetOk: true,
|
|
30
|
+
p95Ms: 18.2,
|
|
31
|
+
platformMatrix: matrix,
|
|
32
|
+
modelPath: "model.onnx",
|
|
33
|
+
modelBytes: 1,
|
|
34
|
+
modelSha256: "a".repeat(64),
|
|
35
|
+
tokenizerPath: "tokenizer.json",
|
|
36
|
+
tokenizerBytes: 1,
|
|
37
|
+
tokenizerSha256: "b".repeat(64),
|
|
38
|
+
blockedBy: [],
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("builds a valid decision with opset 21 + MIT license for a complete matrix", () => {
|
|
44
|
+
const matrix = {
|
|
45
|
+
"linux-x64": { runtime: "onnxruntime-web", installMiB: 33, demotion: "none" },
|
|
46
|
+
"linux-arm64": { runtime: "onnxruntime-web", installMiB: 33, demotion: "none" },
|
|
47
|
+
"darwin-x64": { runtime: "onnxruntime-web", installMiB: 33, demotion: "wasm" },
|
|
48
|
+
"darwin-arm64": { runtime: "onnxruntime-web", installMiB: 33, demotion: "none" },
|
|
49
|
+
"win32-x64": { runtime: "onnxruntime-web", installMiB: 33, demotion: "none" },
|
|
50
|
+
} as Record<(typeof PLATFORMS)[number], EncoderPlatformRow>;
|
|
51
|
+
const d = buildDecision({
|
|
52
|
+
backend: "wasm",
|
|
53
|
+
budgetOk: true,
|
|
54
|
+
p95Ms: 18.2,
|
|
55
|
+
platformMatrix: matrix,
|
|
56
|
+
modelPath: "model.onnx",
|
|
57
|
+
modelBytes: 24117248,
|
|
58
|
+
modelSha256: "a".repeat(64),
|
|
59
|
+
tokenizerPath: "tokenizer.json",
|
|
60
|
+
tokenizerBytes: 50000,
|
|
61
|
+
tokenizerSha256: "b".repeat(64),
|
|
62
|
+
blockedBy: [],
|
|
63
|
+
});
|
|
64
|
+
assert.equal(d.schema, "encoder-backend-decision-v1");
|
|
65
|
+
assert.equal(d.opset, 21);
|
|
66
|
+
assert.equal(d.backend, "wasm");
|
|
67
|
+
assert.deepEqual(d.license, { spdx: "MIT", redistribution: true });
|
|
68
|
+
assert.equal(d.platformMatrix["darwin-x64"].demotion, "wasm");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _acceptance-vc2a-conformance.ts — ENC-001..008 conformance rows + the named
|
|
3
|
+
* assertions (ENC-ASSET-001 / ENC-DIGEST-002 / ENC-PLATFORM-003), each driven
|
|
4
|
+
* through the REAL encoder asset/runtime (no mocks). Extracted from
|
|
5
|
+
* vc2a-acceptance.test.ts so the aggregator stays under the tests/ soft limit.
|
|
6
|
+
*
|
|
7
|
+
* The aggregator passes its shared imports/helpers as a context object, so this
|
|
8
|
+
* sibling never imports the aggregator (no import cycle at module load).
|
|
9
|
+
*/
|
|
10
|
+
import { test, describe } from "node:test";
|
|
11
|
+
import assert from "node:assert/strict";
|
|
12
|
+
import type { EncoderLoadResult } from "./encoder/types.js";
|
|
13
|
+
|
|
14
|
+
/** Context from the aggregator — only domain-specific helpers, not node:test/assert. */
|
|
15
|
+
export interface Vc2aConformanceCtx {
|
|
16
|
+
ENC_IDS: readonly string[];
|
|
17
|
+
ENC_FAIL: typeof import("./encoder/types.js").ENC_FAIL;
|
|
18
|
+
fixture: (id: string) => {
|
|
19
|
+
id: string;
|
|
20
|
+
input: { scenario: string };
|
|
21
|
+
expected: { ok: boolean; code?: string; mode?: string };
|
|
22
|
+
};
|
|
23
|
+
buildDir: (scenario: string) => Built;
|
|
24
|
+
rmBuilt: (b: Built) => void;
|
|
25
|
+
optionsFor: (scenario: string) => import("./encoder/runtime.js").CreateEncoderRuntimeOptions;
|
|
26
|
+
createEncoderRuntime: typeof import("./encoder/runtime.js").createEncoderRuntime;
|
|
27
|
+
verifyEncoderAsset: typeof import("./encoder/asset.js").verifyEncoderAsset;
|
|
28
|
+
readEncoderManifest: typeof import("./encoder/asset.js").readEncoderManifest;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Structural stand-in for the aggregator's local `Built` (dir + scenario). */
|
|
32
|
+
interface Built {
|
|
33
|
+
dir: string;
|
|
34
|
+
scenario: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function registerVc2aConformance(ctx: Vc2aConformanceCtx): void {
|
|
38
|
+
const {
|
|
39
|
+
ENC_IDS,
|
|
40
|
+
ENC_FAIL,
|
|
41
|
+
fixture,
|
|
42
|
+
buildDir,
|
|
43
|
+
rmBuilt,
|
|
44
|
+
optionsFor,
|
|
45
|
+
createEncoderRuntime,
|
|
46
|
+
verifyEncoderAsset,
|
|
47
|
+
readEncoderManifest,
|
|
48
|
+
} = ctx;
|
|
49
|
+
|
|
50
|
+
// -------------------------------------------------------------------------
|
|
51
|
+
// ENC-001..008 conformance rows through the real runtime
|
|
52
|
+
// -------------------------------------------------------------------------
|
|
53
|
+
describe("ENC-001..008 conformance rows", () => {
|
|
54
|
+
for (const id of ENC_IDS) {
|
|
55
|
+
test(`${id}: resolves through the real runtime to the documented result`, () => {
|
|
56
|
+
const fx = fixture(id);
|
|
57
|
+
const built = buildDir(fx.input.scenario);
|
|
58
|
+
try {
|
|
59
|
+
const rt = createEncoderRuntime(optionsFor(fx.input.scenario));
|
|
60
|
+
const load: EncoderLoadResult = rt.load(built.dir);
|
|
61
|
+
assert.equal(load.ok, fx.expected.ok, `${id} ok`);
|
|
62
|
+
if (!load.ok) {
|
|
63
|
+
assert.equal(load.code, fx.expected.code, `${id} exact failure code`);
|
|
64
|
+
if (fx.expected.mode) assert.equal(load.mode, fx.expected.mode, `${id} mode`);
|
|
65
|
+
} else {
|
|
66
|
+
assert.equal(load.mode, "A", `${id} should be mode A`);
|
|
67
|
+
}
|
|
68
|
+
} finally {
|
|
69
|
+
rmBuilt(built);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// -------------------------------------------------------------------------
|
|
76
|
+
// VC2A named assertions
|
|
77
|
+
// -------------------------------------------------------------------------
|
|
78
|
+
describe("VC2A named assertions", () => {
|
|
79
|
+
test("ENC-ASSET-001: opset21 manifest + matching digests load as mode A", () => {
|
|
80
|
+
const fx = fixture("ENC-ASSET-001");
|
|
81
|
+
assert.equal(fx.expected.ok, true);
|
|
82
|
+
const built = buildDir("valid");
|
|
83
|
+
try {
|
|
84
|
+
const load = createEncoderRuntime().load(built.dir);
|
|
85
|
+
assert.equal(load.ok, true);
|
|
86
|
+
if (load.ok) assert.equal(load.mode, "A");
|
|
87
|
+
} finally {
|
|
88
|
+
rmBuilt(built);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
test("ENC-DIGEST-002: one-byte model mutation demotes before load", () => {
|
|
92
|
+
const fx = fixture("ENC-DIGEST-002");
|
|
93
|
+
assert.equal(fx.expected.code, ENC_FAIL.DIGEST_MISMATCH);
|
|
94
|
+
const built = buildDir("mutate-onnx");
|
|
95
|
+
try {
|
|
96
|
+
const res = verifyEncoderAsset(built.dir, readEncoderManifest(built.dir));
|
|
97
|
+
assert.equal(res.ok, false);
|
|
98
|
+
if (!res.ok) assert.equal(res.code, ENC_FAIL.DIGEST_MISMATCH);
|
|
99
|
+
} finally {
|
|
100
|
+
rmBuilt(built);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
test("ENC-PLATFORM-003: unsupported architecture selects trigram B", () => {
|
|
104
|
+
const fx = fixture("ENC-PLATFORM-003");
|
|
105
|
+
assert.equal(fx.expected.mode, "B");
|
|
106
|
+
const built = buildDir("valid");
|
|
107
|
+
try {
|
|
108
|
+
const load = createEncoderRuntime({ platform: () => null }).load(built.dir);
|
|
109
|
+
assert.equal(load.ok, false);
|
|
110
|
+
if (!load.ok) {
|
|
111
|
+
assert.equal(load.mode, "B", "trigram B selected");
|
|
112
|
+
assert.equal(load.code, ENC_FAIL.PLATFORM_UNSUPPORTED);
|
|
113
|
+
}
|
|
114
|
+
} finally {
|
|
115
|
+
rmBuilt(built);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/** VC2A runtime invariant + injection + triad + budget acceptance suites.
|
|
2
|
+
* Extracted from vc2a-acceptance.test.ts (soft-limit compliance). Context injected. */
|
|
3
|
+
import { test, describe } from "node:test";
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import type { ModelManifestV1 } from "./encoder/types.js";
|
|
8
|
+
|
|
9
|
+
/** Context from the aggregator — only domain-specific helpers, not node:test/assert. */
|
|
10
|
+
export interface Vc2aRuntimeCtx {
|
|
11
|
+
ENC_FAIL: typeof import("./encoder/types.js").ENC_FAIL;
|
|
12
|
+
ENCODER_RSS_BUDGET_BYTES: number;
|
|
13
|
+
ENCODER_LATENCY_P95_MS: number;
|
|
14
|
+
tmpAsset: (prefix: string) => string;
|
|
15
|
+
baseManifest: (over?: Partial<ModelManifestV1>) => ModelManifestV1;
|
|
16
|
+
buildDir: (scenario: string) => Built;
|
|
17
|
+
rmBuilt: (b: Built) => void;
|
|
18
|
+
sha256: (bytes: Uint8Array) => string;
|
|
19
|
+
percentile: (sorted: number[], p: number) => number;
|
|
20
|
+
createEncoderRuntime: typeof import("./encoder/runtime.js").createEncoderRuntime;
|
|
21
|
+
verifyEncoderAsset: typeof import("./encoder/asset.js").verifyEncoderAsset;
|
|
22
|
+
readEncoderManifest: typeof import("./encoder/asset.js").readEncoderManifest;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Structural stand-in for the aggregator's local `Built` (dir + scenario). */
|
|
26
|
+
interface Built {
|
|
27
|
+
dir: string;
|
|
28
|
+
scenario: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function registerVc2aRuntime(ctx: Vc2aRuntimeCtx): void {
|
|
32
|
+
const {
|
|
33
|
+
ENC_FAIL,
|
|
34
|
+
ENCODER_RSS_BUDGET_BYTES,
|
|
35
|
+
ENCODER_LATENCY_P95_MS,
|
|
36
|
+
tmpAsset,
|
|
37
|
+
baseManifest,
|
|
38
|
+
buildDir,
|
|
39
|
+
rmBuilt,
|
|
40
|
+
sha256,
|
|
41
|
+
percentile,
|
|
42
|
+
createEncoderRuntime,
|
|
43
|
+
verifyEncoderAsset,
|
|
44
|
+
readEncoderManifest,
|
|
45
|
+
} = ctx;
|
|
46
|
+
|
|
47
|
+
// -------------------------------------------------------------------------
|
|
48
|
+
// Invariant + unique failure injection + forced triad
|
|
49
|
+
// -------------------------------------------------------------------------
|
|
50
|
+
describe("encoder runtime invariant + injection + triad", () => {
|
|
51
|
+
test("invariant: only batch1/max512 verified assets reach inference", () => {
|
|
52
|
+
const built = buildDir("valid");
|
|
53
|
+
try {
|
|
54
|
+
const rt = createEncoderRuntime();
|
|
55
|
+
const load = rt.load(built.dir);
|
|
56
|
+
assert.equal(load.ok, true);
|
|
57
|
+
if (load.ok) assert.equal(load.mode, "A");
|
|
58
|
+
// dims 1..512 infer; 0 and 513+ are shape-rejected.
|
|
59
|
+
for (const n of [1, 64, 512]) {
|
|
60
|
+
const inf = rt.infer({ tokens: Array.from({ length: n }, (_, i) => i % 500) });
|
|
61
|
+
assert.equal(inf.ok, true, `dim ${n} infers`);
|
|
62
|
+
}
|
|
63
|
+
for (const n of [0, 513, 1000]) {
|
|
64
|
+
const inf = rt.infer({ tokens: Array.from({ length: n }) });
|
|
65
|
+
assert.equal(inf.ok, false, `dim ${n} shape-rejected`);
|
|
66
|
+
if (!inf.ok) assert.equal(inf.code, ENC_FAIL.SHAPE_INVALID);
|
|
67
|
+
}
|
|
68
|
+
// A batch>1 manifest never reaches inference: verification demotes to B.
|
|
69
|
+
const bad = buildDir("batch-2");
|
|
70
|
+
try {
|
|
71
|
+
const checker = createEncoderRuntime();
|
|
72
|
+
const check = checker.load(bad.dir);
|
|
73
|
+
assert.equal(check.ok, false);
|
|
74
|
+
if (!check.ok) assert.equal(check.code, ENC_FAIL.BATCH_INVALID);
|
|
75
|
+
} finally {
|
|
76
|
+
rmBuilt(bad);
|
|
77
|
+
}
|
|
78
|
+
} finally {
|
|
79
|
+
rmBuilt(built);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
test("1..513 maxTokens manifests: 1..512 verify+infer, 513 demotes TOKENS_EXCEEDED", () => {
|
|
83
|
+
for (const maxTok of [1, 64, 512]) {
|
|
84
|
+
const dir = tmpAsset("vc2a-dim");
|
|
85
|
+
mkdirSync(dir, { recursive: true });
|
|
86
|
+
const onnx = Buffer.from(`dim-${maxTok}`, "binary");
|
|
87
|
+
const tok = Buffer.from('{"vocab":[]}', "utf8");
|
|
88
|
+
writeFileSync(join(dir, "model.onnx"), onnx);
|
|
89
|
+
writeFileSync(join(dir, "tokenizer.json"), tok);
|
|
90
|
+
const m = baseManifest({
|
|
91
|
+
maxTokens: maxTok,
|
|
92
|
+
onnx: { path: "model.onnx", sha256: sha256(onnx), bytes: onnx.length },
|
|
93
|
+
tokenizer: { path: "tokenizer.json", sha256: sha256(tok), bytes: tok.length },
|
|
94
|
+
});
|
|
95
|
+
writeFileSync(join(dir, "manifest.json"), JSON.stringify(m));
|
|
96
|
+
assert.equal(verifyEncoderAsset(dir, readEncoderManifest(dir)).ok, true, `maxTokens ${maxTok} verifies`);
|
|
97
|
+
const rt = createEncoderRuntime();
|
|
98
|
+
assert.equal(rt.load(dir).ok, true, `maxTokens ${maxTok} loads`);
|
|
99
|
+
const inf = rt.infer({ tokens: Array.from({ length: maxTok }) });
|
|
100
|
+
assert.equal(inf.ok, true, `cap ${maxTok} infers`);
|
|
101
|
+
rmSync(dir, { recursive: true, force: true });
|
|
102
|
+
}
|
|
103
|
+
// 513 demotes.
|
|
104
|
+
const dir513 = tmpAsset("vc2a-dim-513");
|
|
105
|
+
mkdirSync(dir513, { recursive: true });
|
|
106
|
+
const onnx513 = Buffer.from("dim-513", "binary");
|
|
107
|
+
const tok513 = Buffer.from('{"vocab":[]}', "utf8");
|
|
108
|
+
writeFileSync(join(dir513, "model.onnx"), onnx513);
|
|
109
|
+
writeFileSync(join(dir513, "tokenizer.json"), tok513);
|
|
110
|
+
const m513 = baseManifest({
|
|
111
|
+
maxTokens: 513,
|
|
112
|
+
onnx: { path: "model.onnx", sha256: sha256(onnx513), bytes: onnx513.length },
|
|
113
|
+
tokenizer: { path: "tokenizer.json", sha256: sha256(tok513), bytes: tok513.length },
|
|
114
|
+
});
|
|
115
|
+
writeFileSync(join(dir513, "manifest.json"), JSON.stringify(m513));
|
|
116
|
+
const res = verifyEncoderAsset(dir513, readEncoderManifest(dir513));
|
|
117
|
+
assert.equal(res.ok, false);
|
|
118
|
+
if (!res.ok) assert.equal(res.code, ENC_FAIL.TOKENS_EXCEEDED);
|
|
119
|
+
rmSync(dir513, { recursive: true, force: true });
|
|
120
|
+
});
|
|
121
|
+
test("truncated ONNX during digest read demotes ENC_ASSET_UNREADABLE", () => {
|
|
122
|
+
// LIVE-platform manifest with absent model.onnx -> unreadable -> ASSET_UNREADABLE.
|
|
123
|
+
const built = buildDir("missing-onnx");
|
|
124
|
+
try {
|
|
125
|
+
const load = createEncoderRuntime().load(built.dir);
|
|
126
|
+
assert.equal(load.ok, false);
|
|
127
|
+
if (!load.ok) {
|
|
128
|
+
assert.equal(load.code, ENC_FAIL.ASSET_UNREADABLE);
|
|
129
|
+
assert.equal(load.mode, "B");
|
|
130
|
+
}
|
|
131
|
+
} finally {
|
|
132
|
+
rmBuilt(built);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
test("allocator failure after verification demotes ENC_ASSET_UNREADABLE", () => {
|
|
136
|
+
const built = buildDir("valid");
|
|
137
|
+
try {
|
|
138
|
+
const load = createEncoderRuntime({ host: { allocatorFails: () => true } }).load(built.dir);
|
|
139
|
+
assert.equal(load.ok, false);
|
|
140
|
+
if (!load.ok) assert.equal(load.code, ENC_FAIL.ASSET_UNREADABLE);
|
|
141
|
+
} finally {
|
|
142
|
+
rmBuilt(built);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
test("forced triad A / B / C", () => {
|
|
146
|
+
const dirA = buildDir("valid");
|
|
147
|
+
try {
|
|
148
|
+
assert.equal(createEncoderRuntime().load(dirA.dir).ok, true);
|
|
149
|
+
} finally {
|
|
150
|
+
rmBuilt(dirA);
|
|
151
|
+
}
|
|
152
|
+
// B: missing asset => asset-free trigram.
|
|
153
|
+
const dirB = buildDir("missing-onnx");
|
|
154
|
+
try {
|
|
155
|
+
const load = createEncoderRuntime().load(dirB.dir);
|
|
156
|
+
assert.equal(load.ok, false);
|
|
157
|
+
if (!load.ok) assert.equal(load.mode, "B");
|
|
158
|
+
} finally {
|
|
159
|
+
rmBuilt(dirB);
|
|
160
|
+
}
|
|
161
|
+
// C: lexical forced by mode C (rollback path).
|
|
162
|
+
const dirC = tmpAsset("vc2a-C");
|
|
163
|
+
mkdirSync(dirC, { recursive: true });
|
|
164
|
+
try {
|
|
165
|
+
const load = createEncoderRuntime({ forcedMode: "C" }).load(dirC);
|
|
166
|
+
assert.equal(load.ok, false);
|
|
167
|
+
if (!load.ok) assert.equal(load.mode, "C");
|
|
168
|
+
} finally {
|
|
169
|
+
rmSync(dirC, { recursive: true, force: true });
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
test("acceptance budgets: infer p95 <=40ms and encoder marginal footprint <=150MiB", () => {
|
|
173
|
+
// Q02: rssBytes = encoder MARGINAL footprint, never whole-process RSS.
|
|
174
|
+
// p95 via linear interpolation — not max sample.
|
|
175
|
+
const built = buildDir("valid");
|
|
176
|
+
try {
|
|
177
|
+
const rt = createEncoderRuntime();
|
|
178
|
+
assert.equal(rt.load(built.dir).ok, true);
|
|
179
|
+
const latencies: number[] = [];
|
|
180
|
+
for (let i = 0; i < 200; i++) {
|
|
181
|
+
const inf = rt.infer({ tokens: Array.from({ length: 128 }, (_, k) => k) });
|
|
182
|
+
assert.equal(inf.ok, true);
|
|
183
|
+
if (inf.ok) {
|
|
184
|
+
latencies.push(inf.latencyMs);
|
|
185
|
+
assert.ok(inf.rssBytes <= ENCODER_RSS_BUDGET_BYTES, "encoder marginal footprint <=150MiB");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
const p95 = percentile(latencies, 0.95);
|
|
189
|
+
assert.ok(p95 <= ENCODER_LATENCY_P95_MS, `p95 ${p95} <= 40ms`);
|
|
190
|
+
} finally {
|
|
191
|
+
rmBuilt(built);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
test("Q01: a long-lived runtime cannot drift over the 150MiB marginal budget", () => {
|
|
195
|
+
// selfAllocated models a REUSABLE projection buffer — must not accumulate.
|
|
196
|
+
// 100k inferences prove no irreversible budget demotion.
|
|
197
|
+
const built = buildDir("valid");
|
|
198
|
+
try {
|
|
199
|
+
const rt = createEncoderRuntime();
|
|
200
|
+
assert.equal(rt.load(built.dir).ok, true);
|
|
201
|
+
let firstRss = 0;
|
|
202
|
+
for (let i = 0; i < 100_000; i++) {
|
|
203
|
+
const inf = rt.infer({ tokens: Array.from({ length: 4 }, () => i % 500) });
|
|
204
|
+
assert.equal(inf.ok, true, `infer #${i} still ok`);
|
|
205
|
+
if (inf.ok) {
|
|
206
|
+
if (i === 0) firstRss = inf.rssBytes;
|
|
207
|
+
assert.equal(inf.rssBytes, firstRss, `marginal footprint flat at infer #${i}`);
|
|
208
|
+
assert.ok(inf.rssBytes <= ENCODER_RSS_BUDGET_BYTES, `still within budget at infer #${i}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
assert.equal(rt.mode, "A", "mode A survives 100k inferences (no irreversible budget demotion)");
|
|
212
|
+
} finally {
|
|
213
|
+
rmBuilt(built);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("Q03: per-manifest maxTokens is enforced at inference (over-cap rejected)", () => {
|
|
218
|
+
// maxTokens=64 manifest: 65..512 tokens must be SHAPE_INVALID.
|
|
219
|
+
const dir = tmpAsset("vc2a-q03");
|
|
220
|
+
mkdirSync(dir, { recursive: true });
|
|
221
|
+
const onnx = Buffer.from("q03-lowcap", "binary");
|
|
222
|
+
const tok = Buffer.from('{"vocab":[]}', "utf8");
|
|
223
|
+
writeFileSync(join(dir, "model.onnx"), onnx);
|
|
224
|
+
writeFileSync(join(dir, "tokenizer.json"), tok);
|
|
225
|
+
const m = baseManifest({
|
|
226
|
+
maxTokens: 64,
|
|
227
|
+
onnx: { path: "model.onnx", sha256: sha256(onnx), bytes: onnx.length },
|
|
228
|
+
tokenizer: { path: "tokenizer.json", sha256: sha256(tok), bytes: tok.length },
|
|
229
|
+
});
|
|
230
|
+
writeFileSync(join(dir, "manifest.json"), JSON.stringify(m));
|
|
231
|
+
try {
|
|
232
|
+
const rt = createEncoderRuntime();
|
|
233
|
+
assert.equal(rt.load(dir).ok, true, "maxTokens=64 manifest loads (mode A)");
|
|
234
|
+
assert.equal(rt.infer({ tokens: Array.from({ length: 64 }, (_, k) => k) }).ok, true, "cap 64 infers");
|
|
235
|
+
for (const over of [65, 128, 512]) {
|
|
236
|
+
const inf = rt.infer({ tokens: Array.from({ length: over }) });
|
|
237
|
+
assert.equal(inf.ok, false, `${over} tokens rejected against a 64-cap manifest`);
|
|
238
|
+
if (!inf.ok) assert.equal(inf.code, ENC_FAIL.SHAPE_INVALID);
|
|
239
|
+
}
|
|
240
|
+
} finally {
|
|
241
|
+
rmSync(dir, { recursive: true, force: true });
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test("Q04: MEGACOMPACT_VC2A=0 makes the default factory select mode C (rollback)", () => {
|
|
246
|
+
// Flag OFF => default factory is fixed at mode C (byte-identical predecessor).
|
|
247
|
+
const saved = process.env.MEGACOMPACT_VC2A;
|
|
248
|
+
process.env.MEGACOMPACT_VC2A = "0";
|
|
249
|
+
try {
|
|
250
|
+
// An explicitly forced "C" also reports ROLLBACK (existing contract).
|
|
251
|
+
const forced = createEncoderRuntime({ forcedMode: "C" });
|
|
252
|
+
// The default factory under flag-off must match that exactly.
|
|
253
|
+
const byFlag = createEncoderRuntime();
|
|
254
|
+
for (const rt of [forced, byFlag]) {
|
|
255
|
+
assert.equal(rt.mode, "C", "flag-off / forced runtime starts in mode C");
|
|
256
|
+
const built = buildDir("valid");
|
|
257
|
+
try {
|
|
258
|
+
const load = rt.load(built.dir);
|
|
259
|
+
assert.equal(load.ok, false);
|
|
260
|
+
if (!load.ok) {
|
|
261
|
+
assert.equal(load.mode, "C", "flag-off default factory reports mode C");
|
|
262
|
+
assert.equal(load.code, ENC_FAIL.ROLLBACK, "ROLLBACK, not MANIFEST_INVALID");
|
|
263
|
+
}
|
|
264
|
+
} finally {
|
|
265
|
+
rmBuilt(built);
|
|
266
|
+
}
|
|
267
|
+
const inf = rt.infer({ tokens: [1, 2, 3] });
|
|
268
|
+
assert.equal(inf.ok, false, "no learned infer on the flag-off path");
|
|
269
|
+
}
|
|
270
|
+
} finally {
|
|
271
|
+
if (saved === undefined) delete process.env.MEGACOMPACT_VC2A;
|
|
272
|
+
else process.env.MEGACOMPACT_VC2A = saved;
|
|
273
|
+
}
|
|
274
|
+
// Restore the module-scope pin (flag ON) for subsequent scenarios.
|
|
275
|
+
process.env.MEGACOMPACT_VC2A = "1";
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test("all digest corruptions demote before load", () => {
|
|
279
|
+
for (const which of ["onnx", "tokenizer", "both"] as const) {
|
|
280
|
+
const dir = tmpAsset("vc2a-corr");
|
|
281
|
+
mkdirSync(dir, { recursive: true });
|
|
282
|
+
const onnx = Buffer.from("corrupt-me-onnx", "binary");
|
|
283
|
+
const tok = Buffer.from('{"vocab":[]}', "utf8");
|
|
284
|
+
writeFileSync(join(dir, "model.onnx"), onnx);
|
|
285
|
+
writeFileSync(join(dir, "tokenizer.json"), tok);
|
|
286
|
+
const m = baseManifest({
|
|
287
|
+
onnx: { path: "model.onnx", sha256: sha256(onnx), bytes: onnx.length },
|
|
288
|
+
tokenizer: { path: "tokenizer.json", sha256: sha256(tok), bytes: tok.length },
|
|
289
|
+
});
|
|
290
|
+
if (which === "onnx" || which === "both") writeFileSync(join(dir, "model.onnx"), Buffer.concat([onnx, Buffer.from("X")]));
|
|
291
|
+
if (which === "tokenizer" || which === "both") writeFileSync(join(dir, "tokenizer.json"), Buffer.concat([tok, Buffer.from("X")]));
|
|
292
|
+
writeFileSync(join(dir, "manifest.json"), JSON.stringify(m));
|
|
293
|
+
const res = verifyEncoderAsset(dir, readEncoderManifest(dir));
|
|
294
|
+
assert.equal(res.ok, false, `corrupt ${which} demotes`);
|
|
295
|
+
if (!res.ok) assert.equal(res.code, ENC_FAIL.DIGEST_MISMATCH, `corrupt ${which} code`);
|
|
296
|
+
rmSync(dir, { recursive: true, force: true });
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/** VC2B acceptance — ENC-009..016 conformance rows + the ENC-HEAD-001 /
|
|
2
|
+
* ENC-ZERO-002 / ENC-FALLBACK-003 named assertions, resolved through the REAL
|
|
3
|
+
* heads/trigram producers (no mocks). Extracted from vc2b-acceptance.test.ts so
|
|
4
|
+
* the aggregator stays under the soft line limit. Context (fixture loader,
|
|
5
|
+
* shared token/order constants) is injected by the aggregator to avoid a
|
|
6
|
+
* circular import.
|
|
7
|
+
*/
|
|
8
|
+
import { test, describe } from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
ENC2B_IDS,
|
|
13
|
+
ENCODER_HEAD_DIMS,
|
|
14
|
+
type EncoderHeadName,
|
|
15
|
+
} from "./encoder/types.js";
|
|
16
|
+
import { encodeVectorSet, projectHead, l2Norm } from "./encoder/heads.js";
|
|
17
|
+
import {
|
|
18
|
+
embedTrigram512,
|
|
19
|
+
ENCODER_TRIGRAM_WIDTH,
|
|
20
|
+
selectTrigramBFallback,
|
|
21
|
+
} from "./encoder/trigram.js";
|
|
22
|
+
import type { EFixture } from "./vc2b-acceptance.test.js";
|
|
23
|
+
|
|
24
|
+
export interface ConformanceCtx {
|
|
25
|
+
fixture: (id: string) => EFixture;
|
|
26
|
+
SET_TOKENS: number[];
|
|
27
|
+
EMPTY_TOKENS: number[];
|
|
28
|
+
ORDERED_DIMS: number[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function registerConformanceRows(ctx: ConformanceCtx): void {
|
|
32
|
+
const { fixture, SET_TOKENS, EMPTY_TOKENS, ORDERED_DIMS } = ctx;
|
|
33
|
+
|
|
34
|
+
// Suite 2 — ENC-009..016 conformance rows through the real producers
|
|
35
|
+
describe("ENC-009..016 conformance rows", () => {
|
|
36
|
+
test("ENC-009: full-set produces five heads with ordered dims", () => {
|
|
37
|
+
const fx = fixture("ENC-009");
|
|
38
|
+
assert.equal(fx.expected.ok, true);
|
|
39
|
+
const set = encodeVectorSet(SET_TOKENS);
|
|
40
|
+
assert.equal(set.heads.length, fx.expected.heads);
|
|
41
|
+
assert.deepEqual(
|
|
42
|
+
set.heads.map((h) => h.dim),
|
|
43
|
+
fx.expected.dims,
|
|
44
|
+
"ordered dims",
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
for (const id of ENC2B_IDS.slice(1, 6)) {
|
|
49
|
+
test(`${id}: ${fixture(id).input.head} head emits its declared dim`, () => {
|
|
50
|
+
const fx = fixture(id);
|
|
51
|
+
assert.equal(fx.expected.ok, true);
|
|
52
|
+
const head = fx.input.head as EncoderHeadName;
|
|
53
|
+
assert.ok(head);
|
|
54
|
+
const hv = projectHead(head, SET_TOKENS);
|
|
55
|
+
assert.equal(hv.dim, ENCODER_HEAD_DIMS[head]);
|
|
56
|
+
assert.equal(hv.dim, fx.expected.dim, "declared dim");
|
|
57
|
+
assert.equal(hv.values.length, hv.dim);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
test("ENC-015: zero-input produces finite all-zero vectors for every head", () => {
|
|
62
|
+
const fx = fixture("ENC-015");
|
|
63
|
+
assert.equal(fx.expected.ok, true);
|
|
64
|
+
assert.equal(fx.expected.zero, true);
|
|
65
|
+
const set = encodeVectorSet(EMPTY_TOKENS);
|
|
66
|
+
assert.equal(set.heads.length, fx.expected.heads);
|
|
67
|
+
for (const hv of set.heads) {
|
|
68
|
+
for (const v of hv.values) assert.equal(Number.isFinite(v), true, "finite");
|
|
69
|
+
assert.equal(hv.values.every((v) => v === 0), true, `head ${hv.head} all-zero`);
|
|
70
|
+
assert.equal(l2Norm(hv.values), 0);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("ENC-016: asset-free trigram B emits 512 dims", () => {
|
|
75
|
+
const fx = fixture("ENC-016");
|
|
76
|
+
assert.equal(fx.expected.ok, true);
|
|
77
|
+
assert.equal(fx.expected.mode, "B");
|
|
78
|
+
assert.equal(fx.expected.width, 512);
|
|
79
|
+
const v = embedTrigram512("the model is removed but trigram B still works");
|
|
80
|
+
assert.equal(v.length, ENCODER_TRIGRAM_WIDTH);
|
|
81
|
+
assert.equal(v.length, 512);
|
|
82
|
+
const n = l2Norm(v);
|
|
83
|
+
assert.equal(n === 0 || Math.abs(n - 1) <= 1e-6, true);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Suite 3 — named assertions
|
|
88
|
+
describe("VC2B named assertions", () => {
|
|
89
|
+
test("ENC-HEAD-001: all five output shapes match ordered dims", () => {
|
|
90
|
+
const fx = fixture("ENC-HEAD-001");
|
|
91
|
+
assert.equal(fx.expected.ok, true);
|
|
92
|
+
const set = encodeVectorSet(SET_TOKENS);
|
|
93
|
+
assert.deepEqual(
|
|
94
|
+
set.heads.map((h) => h.dim),
|
|
95
|
+
ORDERED_DIMS,
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
test("ENC-ZERO-002: empty input produces finite zero vectors", () => {
|
|
99
|
+
const fx = fixture("ENC-ZERO-002");
|
|
100
|
+
assert.equal(fx.expected.ok, true);
|
|
101
|
+
const set = encodeVectorSet(EMPTY_TOKENS);
|
|
102
|
+
for (const hv of set.heads) {
|
|
103
|
+
assert.equal(hv.values.every((v) => v === 0), true);
|
|
104
|
+
assert.equal(hv.values.every((v) => Number.isFinite(v)), true);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
test("ENC-FALLBACK-003: removed model still yields 512d trigram B", () => {
|
|
108
|
+
const fx = fixture("ENC-FALLBACK-003");
|
|
109
|
+
assert.equal(fx.expected.ok, true);
|
|
110
|
+
assert.equal(fx.expected.mode, "B");
|
|
111
|
+
assert.equal(fx.expected.width, 512);
|
|
112
|
+
// The learned asset is gone (asset dir absent); the asset-free trigram B
|
|
113
|
+
// still produces a full 512-dim vector — no import of the learned asset.
|
|
114
|
+
const v = embedTrigram512("no learned model present, trigram independent");
|
|
115
|
+
assert.equal(v.length, 512);
|
|
116
|
+
const sel = selectTrigramBFallback();
|
|
117
|
+
assert.equal(sel.mode, "B");
|
|
118
|
+
assert.equal(sel.dim, 512);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
}
|