pi-mega-compact 0.20.42 → 0.20.43

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.
Files changed (43) hide show
  1. package/assets/vector-cortex/encoder-v1/manifest.json +1 -1
  2. package/dist/config/vector-cortex-enc0a.js +32 -0
  3. package/dist/config/vector-cortex.js +2 -2
  4. package/dist/config.js +1 -1
  5. package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +1 -0
  6. package/dist/src/config/vector-cortex-enc0a.js +32 -0
  7. package/dist/src/config/vector-cortex.js +2 -2
  8. package/dist/src/config.js +1 -1
  9. package/dist/src/vector-cortex/_acceptance-enc0a-contract.js +60 -0
  10. package/dist/src/vector-cortex/_acceptance-vc2a-conformance.js +90 -0
  11. package/dist/src/vector-cortex/_acceptance-vc2a-runtime.js +285 -0
  12. package/dist/src/vector-cortex/_acceptance-vc2b-conformance.js +92 -0
  13. package/dist/src/vector-cortex/_acceptance-vc2b-heads.js +221 -0
  14. package/dist/src/vector-cortex/encoder/asset.js +3 -2
  15. package/dist/src/vector-cortex/encoder/decision.js +75 -0
  16. package/dist/src/vector-cortex/encoder/types-vc2c.js +41 -0
  17. package/dist/src/vector-cortex/encoder/types.js +13 -34
  18. package/dist/vector-cortex/_acceptance-enc0a-contract.js +60 -0
  19. package/dist/vector-cortex/_acceptance-vc2a-conformance.js +90 -0
  20. package/dist/vector-cortex/_acceptance-vc2a-runtime.js +285 -0
  21. package/dist/vector-cortex/_acceptance-vc2b-conformance.js +92 -0
  22. package/dist/vector-cortex/_acceptance-vc2b-heads.js +221 -0
  23. package/dist/vector-cortex/encoder/asset.js +3 -2
  24. package/dist/vector-cortex/encoder/decision.js +75 -0
  25. package/dist/vector-cortex/encoder/types-vc2c.js +41 -0
  26. package/dist/vector-cortex/encoder/types.js +13 -34
  27. package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +6 -0
  28. package/package.json +1 -1
  29. package/src/config/vector-cortex-enc0a.ts +34 -0
  30. package/src/config/vector-cortex.ts +2 -2
  31. package/src/config.ts +1 -0
  32. package/src/vector-cortex/_acceptance-enc0a-contract.ts +71 -0
  33. package/src/vector-cortex/_acceptance-vc2a-conformance.ts +119 -0
  34. package/src/vector-cortex/_acceptance-vc2a-runtime.ts +300 -0
  35. package/src/vector-cortex/_acceptance-vc2b-conformance.ts +121 -0
  36. package/src/vector-cortex/_acceptance-vc2b-heads.ts +234 -0
  37. package/src/vector-cortex/encoder/asset.ts +3 -2
  38. package/src/vector-cortex/encoder/bench-export.ts +2 -2
  39. package/src/vector-cortex/encoder/decision.ts +125 -0
  40. package/src/vector-cortex/encoder/runtime-native.ts +1 -1
  41. package/src/vector-cortex/encoder/runtime-wasm.ts +1 -1
  42. package/src/vector-cortex/encoder/types-vc2c.ts +124 -0
  43. package/src/vector-cortex/encoder/types.ts +18 -115
@@ -0,0 +1,221 @@
1
+ /** VC2B acceptance — multi-head invariant + independence + forced triad through
2
+ * the REAL encode-or-fallback router (no mocks, including unique failure
3
+ * injection where the learned asset is deleted after A selection but before
4
+ * inference). Extracted from vc2b-acceptance.test.ts so the aggregator stays
5
+ * under the soft line limit. Shared context (withFlagsOn, stageVerifyingAssetDir,
6
+ * token/order constants) is injected by the aggregator to avoid a circular import.
7
+ */
8
+ import { test, describe } from "node:test";
9
+ import assert from "node:assert/strict";
10
+ import { rmSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { ENC_FAIL, ENCODER_HEAD_DIMS } from "./encoder/types.js";
13
+ import { encodeVectorSet, l2Norm } from "./encoder/heads.js";
14
+ import { ENCODER_TRIGRAM_WIDTH } from "./encoder/trigram.js";
15
+ import { embedLexical, ENCODER_LEXICAL_WIDTH } from "./encoder/lexical.js";
16
+ import { encodeOrFallback } from "./encoder/router.js";
17
+ import { createEncoderRuntime } from "./encoder/runtime.js";
18
+ import { createEncoderHeadsReporter } from "./encoder/emit-vc2b.js";
19
+ export function registerHeads(ctx) {
20
+ const { withFlagsOn, stageVerifyingAssetDir, SET_TOKENS, EMPTY_TOKENS, ORDERED_DIMS } = ctx;
21
+ // Suite 4 — invariant + unique failure injection + forced triad
22
+ describe("multi-head invariant + independence + triad", () => {
23
+ test("invariant: every emitted norm is 0 or within 1e-6 of 1", () => {
24
+ for (const tokens of [SET_TOKENS, EMPTY_TOKENS, [7], Array.from({ length: 300 }, (_, i) => i)]) {
25
+ const set = encodeVectorSet(tokens);
26
+ for (const hv of set.heads) {
27
+ const n = l2Norm(hv.values);
28
+ assert.equal(n === 0 || Math.abs(n - 1) <= 1e-6, true, `${hv.head} norm ${n}`);
29
+ }
30
+ }
31
+ });
32
+ test("repeat drift <= 1e-6 across repeated seeded exports (all five heads)", () => {
33
+ for (let rep = 0; rep < 3; rep++) {
34
+ const a = encodeVectorSet(SET_TOKENS);
35
+ const b = encodeVectorSet(SET_TOKENS);
36
+ for (let i = 0; i < a.heads.length; i++) {
37
+ for (let j = 0; j < a.heads[i].values.length; j++) {
38
+ assert.equal(Math.abs(a.heads[i].values[j] - b.heads[i].values[j]) <= 1e-6, true);
39
+ }
40
+ }
41
+ }
42
+ });
43
+ test("unique failure injection: delete model after A selection but before inference; router catches the real load() failure and selects independently initialized B", () => {
44
+ // This scenario is ON-dependent: it asserts a fallback emission, which is
45
+ // VC2B-flag-gated, and drives the VC2A runtime into an A load — so it self-pins
46
+ // both flags ON and is thus valid under either the default-ON run or the
47
+ // MEGACOMPACT_VC2B=0 parity run.
48
+ withFlagsOn(() => {
49
+ // Stage a learned asset the VC2A runtime would VERIFY into mode A, then
50
+ // REMOVE model.onnx before encoding. The router's load() returns the real
51
+ // ENC_ASSET_UNREADABLE failure code and must hand off to the independently
52
+ // initialized asset-free trigram B — emitting vector_cortex_encoder_fallback_selected
53
+ // from the production seam (S2: a true end-to-end router test, not a
54
+ // simulated direct call to selectTrigramBFallback).
55
+ const dir = stageVerifyingAssetDir();
56
+ const emitted = [];
57
+ const reporter = createEncoderHeadsReporter((e) => emitted.push(e));
58
+ try {
59
+ // A is selectable at this point (a staging runtime verifies it).
60
+ const probe = createEncoderRuntime();
61
+ assert.equal(probe.load(dir).ok, true, "staged asset verifies into A");
62
+ // "After A selection but before inference": the on-disk model is gone.
63
+ rmSync(join(dir, "model.onnx"), { force: true });
64
+ const verdict = encodeOrFallback({ tokens: SET_TOKENS }, dir, { reporter });
65
+ assert.equal(verdict.ok, true);
66
+ assert.equal(verdict.mode, "B", "router handoff selects independently initialized B");
67
+ assert.equal(verdict.width, 512);
68
+ if (verdict.ok) {
69
+ assert.equal(verdict.vector.length, 512);
70
+ assert.equal(verdict.code, ENC_FAIL.ASSET_UNREADABLE, "load() reported the real failure code");
71
+ }
72
+ assert.ok(emitted.includes("vector_cortex_encoder_fallback_selected"), "fallback-selected fired from the real router seam: " + emitted.join(","));
73
+ // Distinct vectors for distinct inputs — the fallback is not a constant.
74
+ const again = encodeOrFallback({ tokens: [9, 8, 7, 6] }, dir, { reporter });
75
+ assert.equal(again.ok, true);
76
+ if (verdict.ok && again.ok && verdict.mode === "B" && again.mode === "B") {
77
+ let diff = 0;
78
+ for (let i = 0; i < verdict.vector.length; i++)
79
+ diff += Math.abs(verdict.vector[i] - again.vector[i]);
80
+ assert.ok(diff > 1e-3, "independent trigram B is input-sensitive");
81
+ }
82
+ }
83
+ finally {
84
+ rmSync(dir, { recursive: true, force: true });
85
+ }
86
+ });
87
+ });
88
+ test("forced triad A / B / C through the encode-or-fallback router", () => {
89
+ // ON-dependent: asserts heads_emitted / fallback_selected emissions, so it
90
+ // self-pins both flags ON (valid under either the default-ON run or the
91
+ // MEGACOMPACT_VC2B=0 parity run).
92
+ withFlagsOn(() => {
93
+ // A = learned projections: a verifying asset dir routes to a VectorSetV1 with
94
+ // the five heads in ordered dims (emitting heads_emitted).
95
+ const dirA = stageVerifyingAssetDir();
96
+ const emittedA = [];
97
+ try {
98
+ const reporterA = createEncoderHeadsReporter((e) => emittedA.push(e));
99
+ const a = encodeOrFallback({ tokens: SET_TOKENS }, dirA, { reporter: reporterA });
100
+ assert.equal(a.ok, true);
101
+ assert.equal(a.mode, "A");
102
+ if (a.ok) {
103
+ assert.equal(a.vectorSet.heads.length, 5);
104
+ assert.deepEqual(a.vectorSet.heads.map((h) => h.dim), ORDERED_DIMS);
105
+ }
106
+ assert.ok(emittedA.includes("vector_cortex_encoder_heads_emitted"));
107
+ }
108
+ finally {
109
+ rmSync(dirA, { recursive: true, force: true });
110
+ }
111
+ // B = 512d trigram selected when the learned asset directory is REMOVED: the
112
+ // router's load() fails (no manual fetch) and hands off to B. Remove a staged
113
+ // asset dir so the directory is genuinely absent, proving B needs no asset.
114
+ const dirB = stageVerifyingAssetDir();
115
+ rmSync(dirB, { recursive: true, force: true }); // asset directory REMOVED
116
+ const emittedB = [];
117
+ const reporterB = createEncoderHeadsReporter((e) => emittedB.push(e));
118
+ const b = encodeOrFallback({ tokens: SET_TOKENS }, dirB, { reporter: reporterB });
119
+ assert.equal(b.ok, true);
120
+ assert.equal(b.mode, "B", "B works without an asset dir");
121
+ assert.equal(b.width, 512);
122
+ if (b.ok) {
123
+ assert.equal(b.vector.length, 512);
124
+ assert.equal(b.limitation, null);
125
+ }
126
+ assert.ok(emittedB.includes("vector_cortex_encoder_fallback_selected"), "B selection emits fallback-selected");
127
+ // C = token/phrase lexical forced when both A and B runtimes are disabled.
128
+ const emittedC = [];
129
+ const reporterC = createEncoderHeadsReporter((e) => emittedC.push(e));
130
+ const c = encodeOrFallback({ tokens: SET_TOKENS }, dirB, { reporter: reporterC, forceFallback: "C" });
131
+ assert.equal(c.ok, true);
132
+ assert.equal(c.mode, "C");
133
+ assert.equal(c.width, ENCODER_LEXICAL_WIDTH);
134
+ if (c.ok && c.mode === "C") {
135
+ assert.equal(c.vector.length, ENCODER_LEXICAL_WIDTH);
136
+ assert.ok((c.limitation ?? "").length > 0, "C reports its semantic-context limitation");
137
+ // Q04: a FORCED C is an intentional selection, not a demotion or rollback,
138
+ // so it must NOT be stamped with ENC_FAIL.ROLLBACK.
139
+ assert.equal(c.code, null, "forced C is not a rollback/demotion (code = null)");
140
+ }
141
+ assert.ok(emittedC.includes("vector_cortex_encoder_fallback_selected"), "C selection emits fallback-selected");
142
+ // Widths are disjoint across the triad (no shared feature space).
143
+ const aWidths = Object.values(ENCODER_HEAD_DIMS);
144
+ for (const w of [...aWidths, ENCODER_LEXICAL_WIDTH])
145
+ assert.notEqual(w, ENCODER_TRIGRAM_WIDTH);
146
+ });
147
+ });
148
+ test("forced fallback (B/C) wins over the empty-input degenerate case (Q02)", () => {
149
+ // Q02: a caller that explicitly forces a fallback mode must get that mode
150
+ // even for EMPTY input — empty tokens must NOT silently short-circuit to B.
151
+ // Asserts fallback_selected emissions → ON-dependent, so it self-pins via
152
+ // withFlagsOn (valid under either external env, same as the forced-triad test).
153
+ withFlagsOn(() => {
154
+ const emittedC = [];
155
+ const reporterC = createEncoderHeadsReporter((e) => emittedC.push(e));
156
+ const c = encodeOrFallback({ tokens: EMPTY_TOKENS }, "", { reporter: reporterC, forceFallback: "C" });
157
+ assert.equal(c.ok, true);
158
+ assert.equal(c.mode, "C", "forced C must win over empty-input B selection");
159
+ if (c.ok && c.mode === "C") {
160
+ assert.equal(c.vector.length, ENCODER_LEXICAL_WIDTH);
161
+ assert.equal(c.code, null, "forced C carries no rollback/demotion code (Q04)");
162
+ }
163
+ assert.ok(emittedC.includes("vector_cortex_encoder_fallback_selected"));
164
+ // Forced B on empty input also stays B (force mode is honored, no failure
165
+ // code — a forced mode is not a rollback/demotion, so code is null).
166
+ const emittedB = [];
167
+ const reporterB = createEncoderHeadsReporter((e) => emittedB.push(e));
168
+ const b = encodeOrFallback({ tokens: EMPTY_TOKENS }, "", { reporter: reporterB, forceFallback: "B" });
169
+ assert.equal(b.ok, true);
170
+ assert.equal(b.mode, "B");
171
+ if (b.ok && b.mode === "B") {
172
+ assert.equal(b.vector.length, ENCODER_TRIGRAM_WIDTH);
173
+ assert.equal(b.code, null, "forced B carries no rollback/demotion code (Q04)");
174
+ }
175
+ });
176
+ });
177
+ test("A/B/C use disjoint widths and independent algorithms", () => {
178
+ // A head widths are 384/128/128/64/32; B is 512; C is 256 — no shared space.
179
+ const aWidths = Object.values(ENCODER_HEAD_DIMS);
180
+ const bWidth = ENCODER_TRIGRAM_WIDTH;
181
+ const cWidth = ENCODER_LEXICAL_WIDTH;
182
+ for (const w of [...aWidths, cWidth])
183
+ assert.notEqual(w, bWidth);
184
+ // B works with the asset absent; C works with both vector runtimes disabled
185
+ // (C does not depend on B or A — it embeds tokens directly).
186
+ const cTokens = embedLexical("independently computed lexical with vector runtimes disabled");
187
+ assert.equal(cTokens.length, ENCODER_LEXICAL_WIDTH);
188
+ });
189
+ test("router seam enforces the verified per-manifest token capacity: over-cap input routes to B with ENC_SHAPE_INVALID, never an over-cap A VectorSet", () => {
190
+ // Q01: the router's mode-A path must enforce the VC2A contract
191
+ // "only batch1/<=maxTokens verified assets reach inference" at its own seam.
192
+ // A verified asset declaring maxTokens=64 with an input of 100 tokens must
193
+ // NOT produce an ok:true mode-A VectorSetV1 whose inputTokens breach the
194
+ // model's declared capacity — instead the router rejects it and falls back
195
+ // to the asset-free trigram B, reporting the real shape failure code.
196
+ withFlagsOn(() => {
197
+ const dir = stageVerifyingAssetDir(64); // verified low-cap manifest
198
+ try {
199
+ const over = encodeOrFallback({ tokens: Array.from({ length: 100 }, (_, i) => i) }, dir);
200
+ assert.equal(over.ok, true, "over-cap input still yields a usable (fallback) verdict");
201
+ assert.equal(over.mode, "B", "over-cap input must route to the B fallback, not an A VectorSet");
202
+ if (over.ok) {
203
+ assert.equal(over.code, ENC_FAIL.SHAPE_INVALID, "reported the real shape failure code");
204
+ assert.equal(over.vector.length, ENCODER_TRIGRAM_WIDTH);
205
+ }
206
+ // A within-cap input against the SAME verified manifest still reaches a
207
+ // qualified mode-A VectorSet — the capacity rejection is input-scoped,
208
+ // not a blanket demotion of the verified asset.
209
+ const within = encodeOrFallback({ tokens: SET_TOKENS }, dir);
210
+ assert.equal(within.ok, true);
211
+ assert.equal(within.mode, "A", "within-cap input still reaches mode A");
212
+ if (within.ok)
213
+ assert.equal(within.vectorSet.heads.length, 5);
214
+ }
215
+ finally {
216
+ rmSync(dir, { recursive: true, force: true });
217
+ }
218
+ });
219
+ });
220
+ });
221
+ }
@@ -2,7 +2,8 @@
2
2
  * vector-cortex/encoder/asset.ts — VC2A asset verification (task 2).
3
3
  *
4
4
  * Verifies a ModelManifestV1 before any allocation: SHA-256 the ONNX and
5
- * tokenizer against the manifest digests, require opset 17, batch exactly 1 and
5
+ * tokenizer against the manifest digests, require opset 21 (ENC-0a re-baseline),
6
+ * batch exactly 1 and
6
7
  * maximum 512 tokens, and confirm the current platform is in the supported
7
8
  * matrix. On ANY of these the caller demotes to mode B (asset-free trigram) —
8
9
  * never a remote fetch (PREVENT-PI-004). A truncated/unreadable asset during
@@ -73,7 +74,7 @@ function isManifest(m) {
73
74
  *
74
75
  * - manifest parse/shape failure -> ENC_MANIFEST_INVALID -> mode B
75
76
  * - unsupported platform -> ENC_PLATFORM_UNSUPPORTED -> mode B
76
- * - opset != 17 -> ENC_OPSET_INVALID -> mode B
77
+ * - opset != 21 -> ENC_OPSET_INVALID -> mode B
77
78
  * - batch != 1 -> ENC_BATCH_INVALID -> mode B
78
79
  * - maxTokens > 512 -> ENC_TOKENS_EXCEEDED -> mode B
79
80
  * - on-disk digest != manifest digest -> ENC_DIGEST_MISMATCH (one-byte mutation)
@@ -0,0 +1,75 @@
1
+ /**
2
+ * vector-cortex/encoder/decision.ts — ENC-0a backend-decision contract.
3
+ *
4
+ * The durable EncoderBackendDecisionV1 record: which ONNX runtime backend the
5
+ * real learned encoder ships on (transformers.js/WASM vs onnxruntime-node
6
+ * native), whether the 80 MiB install budget holds, the per-platform install
7
+ * matrix, the opset baseline (locked 21 by ENC-0a), the license verdict, and
8
+ * the pinned model/tokenizer sha256 digests.
9
+ *
10
+ * ENC-0a is the DECISION + MEASUREMENT sprint: this contract is what the
11
+ * deterministic resolver (`scripts/encoder/resolve-backend-decision.mjs`) and
12
+ * the durable record (`docs/vector-cortex/encoder-backend-decision.md`) both
13
+ * consume. ENC-0a also owns the opset flip: ENCODER_OPSET is re-baselined to 21
14
+ * in `types.ts` alongside the placeholder manifest (the 2026-08-05 trunk
15
+ * research dropped the earlier Xenova opset-17 requirement). ENC-0b asserts the
16
+ * staged real asset is opset 21 — no further constant change.
17
+ *
18
+ * Contract-first (ENGINEERING_PRACTICES §3). Pi-agnostic, dependency-free
19
+ * (PREVENT-PI-004 — local computation only, never a fetch). No `any`
20
+ * (PREVENT-011).
21
+ */
22
+ /**
23
+ * The normative ENC-0a budget: the 80 MiB install/asset cap (MODEL_ASSET.md
24
+ * §Qualification). Backend qualifies (budgetOk) iff the shipped byte-count fits.
25
+ */
26
+ export const ENCODER_INSTALL_BUDGET_MIB = 80;
27
+ /** The p95 latency gate at 512 tokens / 4 threads on linux-x64 (ms). */
28
+ export const ENCODER_DECISION_P95_MS = 40;
29
+ /**
30
+ * buildDecision — assemble a valid, platform-complete EncoderBackendDecisionV1.
31
+ *
32
+ * Pure helper consumed by the acceptance aggregator (and any TS consumer of the
33
+ * decision). Every EncoderPlatform must resolve to a row, and the passed
34
+ * per-platform rows must be complete (no row omitted) — a partial matrix is a
35
+ * contract violation, not a valid decision. All fields are passed in; this is a
36
+ * structural constructor, not a rules engine (the resolver owns the decision
37
+ * rule).
38
+ */
39
+ export function buildDecision(input) {
40
+ const { platformMatrix } = input;
41
+ const platforms = [
42
+ "linux-x64",
43
+ "linux-arm64",
44
+ "darwin-x64",
45
+ "darwin-arm64",
46
+ "win32-x64",
47
+ ];
48
+ for (const p of platforms) {
49
+ if (!Object.prototype.hasOwnProperty.call(platformMatrix, p)) {
50
+ throw new Error(`platform matrix is incomplete: missing row for ${p}`);
51
+ }
52
+ }
53
+ return {
54
+ schema: "encoder-backend-decision-v1",
55
+ backend: input.backend,
56
+ budgetOk: input.budgetOk,
57
+ opset: 21,
58
+ platformMatrix,
59
+ license: { spdx: "MIT", redistribution: true },
60
+ artifacts: {
61
+ model: {
62
+ path: input.modelPath,
63
+ bytes: input.modelBytes,
64
+ sha256: input.modelSha256,
65
+ },
66
+ tokenizer: {
67
+ path: input.tokenizerPath,
68
+ bytes: input.tokenizerBytes,
69
+ sha256: input.tokenizerSha256,
70
+ },
71
+ },
72
+ p95Ms: input.p95Ms,
73
+ blockedBy: input.blockedBy,
74
+ };
75
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * vector-cortex/encoder/types-vc2c.ts — VC2C qualification + calibration
3
+ * contracts (QualifiedEncoderV1 / CalibrationV1 / EVALUATION_THRESHOLDS).
4
+ *
5
+ * Extracted from types.ts (delegate-shell split) when types.ts crossed the
6
+ * 300-line soft limit. types.ts re-exports everything here; consumers import
7
+ * from types.ts unchanged.
8
+ *
9
+ * Pi-agnostic and dependency-free (PREVENT-PI-004). No `any` (PREVENT-011).
10
+ */
11
+ /** Normative per-head + asset qualification thresholds (MODEL_ASSET §qualification
12
+ * + EVALUATION.md §metrics). These are the constants `select.ts` evaluates the
13
+ * candidate's held-out metrics against (task 3 atomic check). */
14
+ export const EVALUATION_THRESHOLDS = {
15
+ semantic: { spearman: 0.75, recallAt10: 0.9 },
16
+ dependency: { precision: 0.97, recall: 0.95 },
17
+ contradiction: { precision: 0.98, recall: 0.9, ece: 0.05 },
18
+ cacheStability: { precision: 0.999, recall: 0.9 },
19
+ payloadRouting: { macroF1: 0.97, exactAnchorRecall: 1.0 },
20
+ reconstruction: { dependencyClosureRecall: 1.0 },
21
+ asset: { maxTokens: 512, maxLatencyP95Ms: 40, maxRssDeltaMib: 150 },
22
+ };
23
+ /** VC2C-specific qualification failure codes (returned, never thrown). */
24
+ export const ENC_QUALIFICATION_FAIL = {
25
+ /** The qualification manifest hash does not match the calibration that was fit
26
+ * (corrupt qualification manifest after calibration before selection). */
27
+ DIGEST_MISMATCH: "ENC_QUALIFICATION_DIGEST_MISMATCH",
28
+ /** One or more per-head EVALUATION thresholds failed (demotes all of A). */
29
+ THRESHOLD_FAILED: "ENC_QUALIFICATION_THRESHOLD_FAILED",
30
+ /** An asset-field qualification check (asset/latency/RSS) failed. */
31
+ ASSET_FAILED: "ENC_QUALIFICATION_ASSET_FAILED",
32
+ /** Calibration was attempted using held-out labels (fit prohibition). */
33
+ HELD_OUT_IN_FIT: "ENC_QUALIFICATION_HELD_OUT_IN_FIT",
34
+ };
35
+ /** The 4 registered VC2C conformance IDs (task 1: "register ENC-017..020"). */
36
+ export const ENC2C_IDS = [
37
+ "ENC-017",
38
+ "ENC-018",
39
+ "ENC-019",
40
+ "ENC-020",
41
+ ];
@@ -24,8 +24,13 @@ export const ENCODER_SUPPORTED_PLATFORMS = [
24
24
  "darwin-arm64",
25
25
  "win32-x64",
26
26
  ];
27
- /** ONNX opset required by the normative v1 target (opset 17). */
28
- export const ENCODER_OPSET = 17;
27
+ /** ONNX opset required by the normative v1 target. ENC-0a re-baselines from 17
28
+ * to 21: the committed placeholder asset (assets/vector-cortex/encoder-v1/)
29
+ * declares opset 21 in its manifest (the 2026-08-05 BAAI/bge-small-en-v1.5
30
+ * upstream export is opset 21; the earlier Xenova opset-17 requirement was
31
+ * dropped). The locked decision is recorded in
32
+ * docs/vector-cortex/encoder-backend-decision.md. */
33
+ export const ENCODER_OPSET = 21;
29
34
  /** Batch must be exactly 1 (single-request inference). */
30
35
  export const ENCODER_BATCH = 1;
31
36
  /** Maximum accepted token count (WordPiece, deterministic truncation). */
@@ -45,7 +50,7 @@ export const ENCODER_LATENCY_P95_MS = 40;
45
50
  export const ENCODER_SEMANTIC_WIDTH = 384;
46
51
  /** Exact VC2A failure codes (returned, never thrown across the boundary). */
47
52
  export const ENC_FAIL = {
48
- /** opset != 17. */
53
+ /** opset != 21 (ENC-0a re-baseline applied; placeholder manifest updated alongside). */
49
54
  OPSET_INVALID: "ENC_OPSET_INVALID",
50
55
  /** batch != 1. */
51
56
  BATCH_INVALID: "ENC_BATCH_INVALID",
@@ -136,34 +141,8 @@ export const ENC2B_IDS = [
136
141
  "ENC-015",
137
142
  "ENC-016",
138
143
  ];
139
- /** Normative per-head + asset qualification thresholds (MODEL_ASSET §qualification
140
- * + EVALUATION.md §metrics). These are the constants `select.ts` evaluates the
141
- * candidate's held-out metrics against (task 3 atomic check). */
142
- export const EVALUATION_THRESHOLDS = {
143
- semantic: { spearman: 0.75, recallAt10: 0.9 },
144
- dependency: { precision: 0.97, recall: 0.95 },
145
- contradiction: { precision: 0.98, recall: 0.9, ece: 0.05 },
146
- cacheStability: { precision: 0.999, recall: 0.9 },
147
- payloadRouting: { macroF1: 0.97, exactAnchorRecall: 1.0 },
148
- reconstruction: { dependencyClosureRecall: 1.0 },
149
- asset: { maxTokens: 512, maxLatencyP95Ms: 40, maxRssDeltaMib: 150 },
150
- };
151
- /** VC2C-specific qualification failure codes (returned, never thrown). */
152
- export const ENC_QUALIFICATION_FAIL = {
153
- /** The qualification manifest hash does not match the calibration that was fit
154
- * (corrupt qualification manifest after calibration before selection). */
155
- DIGEST_MISMATCH: "ENC_QUALIFICATION_DIGEST_MISMATCH",
156
- /** One or more per-head EVALUATION thresholds failed (demotes all of A). */
157
- THRESHOLD_FAILED: "ENC_QUALIFICATION_THRESHOLD_FAILED",
158
- /** An asset-field qualification check (asset/latency/RSS) failed. */
159
- ASSET_FAILED: "ENC_QUALIFICATION_ASSET_FAILED",
160
- /** Calibration was attempted using held-out labels (fit prohibition). */
161
- HELD_OUT_IN_FIT: "ENC_QUALIFICATION_HELD_OUT_IN_FIT",
162
- };
163
- /** The 4 registered VC2C conformance IDs (task 1: "register ENC-017..020"). */
164
- export const ENC2C_IDS = [
165
- "ENC-017",
166
- "ENC-018",
167
- "ENC-019",
168
- "ENC-020",
169
- ];
144
+ // ---------------------------------------------------------------------------
145
+ // VC2C encoder qualification + calibration: extracted to types-vc2c.ts
146
+ // (delegate-shell split, soft-limit compliance). Re-exported here.
147
+ // ---------------------------------------------------------------------------
148
+ export { EVALUATION_THRESHOLDS, ENC_QUALIFICATION_FAIL, ENC2C_IDS, } from "./types-vc2c.js";
@@ -252,5 +252,11 @@ export const VECTOR_CORTEX_SETTINGS: SettingGroup = {
252
252
  "Dedup tier-attribution rollup: per-tier dedup catch shares (L0/L1/L2/new percent of dedup decisions) read from the local events.log dedup_audit stream (GET /api/dedup-tier-attribution). OFF = 404 + no cache file, byte-identical predecessor.",
253
253
  true,
254
254
  ),
255
+ boolDirect(
256
+ "MEGACOMPACT_ENC_0A",
257
+ "ENC-0a Encoder Backend Decision",
258
+ "ENC-0a learned-encoder backend-decision lock: records the transformers.js/WASM vs onnxruntime-node choice, per-platform install matrix, opset-21 baseline and pinned digests in docs/vector-cortex/encoder-backend-decision.md. OFF = no decision record written / no resolver runs, mode B trigram byte-identical predecessor.",
259
+ true,
260
+ ),
255
261
  ],
256
262
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mega-compact",
3
- "version": "0.20.42",
3
+ "version": "0.20.43",
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,34 @@
1
+ /**
2
+ * config/vector-cortex-enc0a.ts — ENC-0a learned-encoder backend-decision 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-vc9a.ts..vector-cortex-vc9d.ts
6
+ * were. This is the first ENC (real learned encoder) sprint flag. vector-cortex.ts
7
+ * re-exports the ENUM below and root src/config.ts re-exports it, so no consumer
8
+ * import path changes.
9
+ *
10
+ * ENC-0a locks the runtime-backend choice (transformers.js/WASM vs
11
+ * onnxruntime-node native), the per-platform install-size matrix, the opset
12
+ * baseline (re-baselined 17 -> 21) and the license/pinning audit. It writes a
13
+ * durable decision record and bench JSON but touches neither the store schema
14
+ * nor stateDir tables (pure migration).
15
+ *
16
+ * The split is purely mechanical: ENC_0A_ENABLED is byte-identical in name,
17
+ * semantics, and default to the definition it replaces, and vector-cortex.ts
18
+ * re-exports it so every existing `from "./config/vector-cortex.js"` import
19
+ * keeps resolving unchanged.
20
+ *
21
+ * Pi-agnostic, dependency-free (PREVENT-PI-004 / PREVENT-011).
22
+ */
23
+
24
+ import { sprintFlag } from "./vector-cortex-flag.js";
25
+
26
+ /**
27
+ * ENC-0a — learned-encoder backend-decision lock. Default ON.
28
+ * `MEGACOMPACT_ENC_0A=0` disables and is byte-identical to the predecessor
29
+ * (placeholder encoder): no decision record is written and no newer
30
+ * backend-resolution script runs — the runtime keeps serving mode B trigram
31
+ * exactly as before. This flag MUST also be a dashboard SETTINGS toggle (visible
32
+ * in config UI, never in EXCLUDED_SETTINGS), mirroring VC4A..VC9D.
33
+ */
34
+ export const ENC_0A_ENABLED = (): boolean => sprintFlag("MEGACOMPACT_ENC_0A");
@@ -5,8 +5,7 @@
5
5
  * `=0`/`_DISABLED` off. Flag-OFF is byte-identical to the predecessor sprint's
6
6
  * behavior (for VC0A: mode C — observer absent, zero evaluation writes).
7
7
  *
8
- * The breaker/triad constants (TRIAD_RESILIENCE.md) live here so VC0C consumes
9
- * them without re-declaring the ownership boundary. Pi-agnostic, dependency-free.
8
+ * Breaker/triad constants (TRIAD_RESILIENCE.md) live here; pi-agnostic, dep-free.
10
9
  */
11
10
 
12
11
  import { sprintFlag } from "./vector-cortex-flag.js";
@@ -281,6 +280,7 @@ export { ML5C_ENABLED } from "./vector-cortex-ml5c.js";
281
280
  export { ML5D_ENABLED } from "./vector-cortex-ml5d.js";
282
281
  export { ML5E_ENABLED } from "./vector-cortex-ml5e.js";
283
282
  export { DEDUP_ATTR_ENABLED } from "./vector-cortex-dedup-attr.js";
283
+ export { ENC_0A_ENABLED } from "./vector-cortex-enc0a.js";
284
284
 
285
285
  // Breaker constants (TRIAD_RESILIENCE.md §breaker) extracted to vector-cortex-breakers.ts.
286
286
  export {
package/src/config.ts CHANGED
@@ -189,6 +189,7 @@ export {
189
189
  ML5D_ENABLED,
190
190
  ML5E_ENABLED,
191
191
  DEDUP_ATTR_ENABLED,
192
+ ENC_0A_ENABLED,
192
193
  BREAKER_WINDOW_MS,
193
194
  BREAKER_MIN_ATTEMPTS,
194
195
  BREAKER_PERF_FAILURES,
@@ -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
+ }