pi-mega-compact 0.19.3 → 0.20.1
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.js +24 -0
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/routes-cache.test/_helpers.js +2 -0
- package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +2 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-helpers.js +100 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-residual.js +51 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-shards.js +48 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex.js +2 -0
- package/dist/extensions/dashboard-server/routes.js +1 -1
- package/dist/extensions/dashboard-server/server.js +41 -16
- package/dist/extensions/dashboard-server/tailscale.js +32 -0
- package/dist/src/config/vector-cortex.js +24 -0
- package/dist/src/config.js +1 -1
- package/dist/src/vector-cortex/residual/codec.js +224 -0
- package/dist/src/vector-cortex/residual/dct.js +158 -0
- package/dist/src/vector-cortex/residual/fixture-payload.js +77 -0
- package/dist/src/vector-cortex/residual/gf256.js +182 -0
- package/dist/src/vector-cortex/residual/parity.js +245 -0
- package/dist/src/vector-cortex/residual/quantize.js +200 -0
- package/dist/src/vector-cortex/residual/stream.js +124 -0
- package/dist/src/vector-cortex/residual/types.js +55 -0
- package/dist/src/vector-cortex/shards/exact.js +134 -0
- package/dist/src/vector-cortex/shards/manifest.js +237 -0
- package/dist/src/vector-cortex/shards/semantic.js +137 -0
- package/dist/src/vector-cortex/shards/types.js +51 -0
- package/dist/vector-cortex/residual/codec.js +224 -0
- package/dist/vector-cortex/residual/dct.js +158 -0
- package/dist/vector-cortex/residual/fixture-payload.js +77 -0
- package/dist/vector-cortex/residual/gf256.js +182 -0
- package/dist/vector-cortex/residual/parity.js +245 -0
- package/dist/vector-cortex/residual/quantize.js +200 -0
- package/dist/vector-cortex/residual/stream.js +124 -0
- package/dist/vector-cortex/residual/types.js +55 -0
- package/dist/vector-cortex/shards/exact.js +134 -0
- package/dist/vector-cortex/shards/manifest.js +237 -0
- package/dist/vector-cortex/shards/semantic.js +137 -0
- package/dist/vector-cortex/shards/types.js +51 -0
- package/extensions/dashboard-client/dist/assets/{AreaChart-DqiFSnDx.js → AreaChart-n4z5w9Ox.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-DqiFSnDx.js.map → AreaChart-n4z5w9Ox.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-Cqg-PQMK.js → BarChart-BLGjWWBr.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-Cqg-PQMK.js.map → BarChart-BLGjWWBr.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-BPNs0xIF.js → CacheTab-CAnrKKVK.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-BPNs0xIF.js.map → CacheTab-CAnrKKVK.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-BQf7OGkf.js → EventsTab-D-GL7Ngq.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-BQf7OGkf.js.map → EventsTab-D-GL7Ngq.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-B14TaSPN.js → HealthTab-C4x5qQ8s.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-B14TaSPN.js.map → HealthTab-C4x5qQ8s.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-D8lkRoa1.js → MaintenanceTab-BSPs0eq5.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-D8lkRoa1.js.map → MaintenanceTab-BSPs0eq5.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-BOWtGfpx.js → MemoryMapTab-BWEUtTSu.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-BOWtGfpx.js.map → MemoryMapTab-BWEUtTSu.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-7XI9cWaX.js → MetricsTab-Dhm1c3Cx.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-7XI9cWaX.js.map → MetricsTab-Dhm1c3Cx.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-C9KaGYvh.js → OverviewTab-Cm6cySiQ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-C9KaGYvh.js.map → OverviewTab-Cm6cySiQ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-BwESNhox.js → ReposTab-DxLN1N4K.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-BwESNhox.js.map → ReposTab-DxLN1N4K.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DKH55Rda.js → SessionsTab-CZuI4ISW.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DKH55Rda.js.map → SessionsTab-CZuI4ISW.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SetupTab-zDxf-nJd.js → SetupTab-C_0VOomm.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SetupTab-zDxf-nJd.js.map → SetupTab-C_0VOomm.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-C9isog4L.js → TimeSavedCard-BhbaRLmi.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-C9isog4L.js.map → TimeSavedCard-BhbaRLmi.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-ciI6ydvj.js → TurnsTab-CXJmbjje.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-ciI6ydvj.js.map → TurnsTab-CXJmbjje.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-BGe9hu3r.js +2 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-BGe9hu3r.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{WikiTab-DcYHc734.js → WikiTab-C5uvMCzp.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-DcYHc734.js.map → WikiTab-C5uvMCzp.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-DF8lx4bt.js → button-Cl_fxJcg.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-DF8lx4bt.js.map → button-Cl_fxJcg.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-DIoDheSZ.js → card-BH8Le5YM.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-DIoDheSZ.js.map → card-BH8Le5YM.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-BFRzeYX3.js → generateCategoricalChart-sZ6ZNtBi.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-BFRzeYX3.js.map → generateCategoricalChart-sZ6ZNtBi.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-DSZON0Yi.js → index-CX9zv8cJ.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{index-DSZON0Yi.js.map → index-CX9zv8cJ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{switch-l4qo22mU.js → switch-CXJhcjhM.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-l4qo22mU.js.map → switch-CXJhcjhM.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-DPn6td1_.js → toggle-CoLtIc6y.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-DPn6td1_.js.map → toggle-CoLtIc6y.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-BLmolqTJ.js → useSSE-fSXho606.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-BLmolqTJ.js.map → useSSE-fSXho606.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/api/vector-cortex.ts +9 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +35 -0
- package/extensions/dashboard-client/src/types/vector-cortex.ts +13 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex.ts +53 -0
- package/extensions/dashboard-server/routes-cache.test/_helpers.ts +2 -0
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +12 -0
- package/extensions/dashboard-server/routes-vector-cortex-helpers.ts +110 -0
- package/extensions/dashboard-server/routes-vector-cortex-residual.ts +60 -0
- package/extensions/dashboard-server/routes-vector-cortex-shards.ts +57 -0
- package/extensions/dashboard-server/routes-vector-cortex.ts +2 -0
- package/extensions/dashboard-server/routes.ts +2 -0
- package/extensions/dashboard-server/server.ts +46 -17
- package/extensions/dashboard-server/tailscale.ts +32 -0
- package/package.json +1 -1
- package/src/config/vector-cortex.ts +26 -0
- package/src/config.ts +2 -0
- package/src/vector-cortex/residual/codec.ts +292 -0
- package/src/vector-cortex/residual/dct.ts +166 -0
- package/src/vector-cortex/residual/fixture-payload.ts +90 -0
- package/src/vector-cortex/residual/gf256.ts +196 -0
- package/src/vector-cortex/residual/parity.ts +283 -0
- package/src/vector-cortex/residual/quantize.ts +230 -0
- package/src/vector-cortex/residual/stream.ts +135 -0
- package/src/vector-cortex/residual/types.ts +236 -0
- package/src/vector-cortex/shards/exact.ts +141 -0
- package/src/vector-cortex/shards/manifest.ts +276 -0
- package/src/vector-cortex/shards/semantic.ts +156 -0
- package/src/vector-cortex/shards/types.ts +212 -0
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-qTZ7NWng.js +0 -2
- package/extensions/dashboard-client/dist/assets/VectorCortexTab-qTZ7NWng.js.map +0 -1
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/residual/stream.ts — canonical PROTECTED STREAM serialization
|
|
3
|
+
* for the VC4B residual codec.
|
|
4
|
+
*
|
|
5
|
+
* The protected stream is `header + all block scales/coefficient arrays +
|
|
6
|
+
* corrections` (RESIDUAL_CODEC §erasure parity), serialized in exactly this
|
|
7
|
+
* canonical order so encode and decode are byte-symmetric:
|
|
8
|
+
*
|
|
9
|
+
* header (46 bytes) magic `VCR1` | u32 LE originalLength | 32-byte SHA-256
|
|
10
|
+
* | u16 LE blockSize | u16 LE k | u16 LE m
|
|
11
|
+
* blocks for each block in ascending index:
|
|
12
|
+
* float32 LE scale | 4096 * int16 LE coefficient
|
|
13
|
+
* corrections varint blockCount, then per non-empty block
|
|
14
|
+
* u32 LE blockIndex | varint count
|
|
15
|
+
* | count * (u16 LE offset, u8 original)
|
|
16
|
+
*
|
|
17
|
+
* Pure serialization: no storage, no console, no network (PREVENT-PI-004 /
|
|
18
|
+
* PREVENT-011).
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
parseCorrections,
|
|
23
|
+
serializeCorrections,
|
|
24
|
+
} from "./quantize.js";
|
|
25
|
+
import {
|
|
26
|
+
RESIDUAL_BLOCK_SIZE,
|
|
27
|
+
RESIDUAL_HEADER_BYTES,
|
|
28
|
+
RESIDUAL_MAGIC,
|
|
29
|
+
RS_DATA_SHARDS,
|
|
30
|
+
RS_PARITY_SHARDS,
|
|
31
|
+
type QuantizedBlockV1,
|
|
32
|
+
type ResidualCodecV1,
|
|
33
|
+
type ResidualHeaderV1,
|
|
34
|
+
} from "./types.js";
|
|
35
|
+
|
|
36
|
+
/** Per-block serialized size: float32 scale + n int16 coefficients. */
|
|
37
|
+
export function blockBytes(blockSize: number = RESIDUAL_BLOCK_SIZE): number {
|
|
38
|
+
return 4 + blockSize * 2;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Serialize the canonical 46-byte header. */
|
|
42
|
+
export function serializeHeader(header: ResidualHeaderV1): Uint8Array {
|
|
43
|
+
const out = new Uint8Array(RESIDUAL_HEADER_BYTES);
|
|
44
|
+
const view = new DataView(out.buffer);
|
|
45
|
+
for (let i = 0; i < 4; i++) out[i] = RESIDUAL_MAGIC.charCodeAt(i);
|
|
46
|
+
view.setUint32(4, header.originalLength, true);
|
|
47
|
+
const digest = Buffer.from(header.payloadDigest, "hex");
|
|
48
|
+
out.set(digest.subarray(0, 32), 8);
|
|
49
|
+
view.setUint16(40, header.blockSize, true);
|
|
50
|
+
view.setUint16(42, header.dataShards, true);
|
|
51
|
+
view.setUint16(44, header.parityShards, true);
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Parse the canonical header. Returns null on magic/geometry mismatch. */
|
|
56
|
+
export function parseHeader(bytes: Uint8Array): ResidualHeaderV1 | null {
|
|
57
|
+
if (bytes.length < RESIDUAL_HEADER_BYTES) return null;
|
|
58
|
+
for (let i = 0; i < 4; i++) {
|
|
59
|
+
if (bytes[i] !== RESIDUAL_MAGIC.charCodeAt(i)) return null;
|
|
60
|
+
}
|
|
61
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
62
|
+
const originalLength = view.getUint32(4, true);
|
|
63
|
+
const payloadDigest = Buffer.from(bytes.subarray(8, 40)).toString("hex");
|
|
64
|
+
const blockSize = view.getUint16(40, true);
|
|
65
|
+
const dataShards = view.getUint16(42, true);
|
|
66
|
+
const parityShards = view.getUint16(44, true);
|
|
67
|
+
if (blockSize !== RESIDUAL_BLOCK_SIZE) return null;
|
|
68
|
+
if (dataShards !== RS_DATA_SHARDS || parityShards !== RS_PARITY_SHARDS) return null;
|
|
69
|
+
return {
|
|
70
|
+
magic: RESIDUAL_MAGIC,
|
|
71
|
+
originalLength,
|
|
72
|
+
payloadDigest,
|
|
73
|
+
blockSize: RESIDUAL_BLOCK_SIZE,
|
|
74
|
+
dataShards: RS_DATA_SHARDS,
|
|
75
|
+
parityShards: RS_PARITY_SHARDS,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Serialize the full protected stream for one encoded artifact. */
|
|
80
|
+
export function serializeStream(codec: ResidualCodecV1): Uint8Array {
|
|
81
|
+
const head = serializeHeader(codec.header);
|
|
82
|
+
const perBlock = blockBytes(codec.header.blockSize);
|
|
83
|
+
const corrections = serializeCorrections(codec.corrections);
|
|
84
|
+
const out = new Uint8Array(
|
|
85
|
+
head.length + codec.blocks.length * perBlock + corrections.length,
|
|
86
|
+
);
|
|
87
|
+
out.set(head, 0);
|
|
88
|
+
const view = new DataView(out.buffer);
|
|
89
|
+
let pos = head.length;
|
|
90
|
+
for (const block of codec.blocks) {
|
|
91
|
+
view.setFloat32(pos, block.scale, true);
|
|
92
|
+
pos += 4;
|
|
93
|
+
for (let i = 0; i < block.coefficients.length; i++) {
|
|
94
|
+
view.setInt16(pos, block.coefficients[i]!, true);
|
|
95
|
+
pos += 2;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
out.set(corrections, pos);
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Parse a protected stream back into the codec artifact. Null on malformed. */
|
|
103
|
+
export function parseStream(stream: Uint8Array): ResidualCodecV1 | null {
|
|
104
|
+
const header = parseHeader(stream);
|
|
105
|
+
if (!header) return null;
|
|
106
|
+
const perBlock = blockBytes(header.blockSize);
|
|
107
|
+
const blockCount = Math.ceil(header.originalLength / header.blockSize);
|
|
108
|
+
const bodyEnd = RESIDUAL_HEADER_BYTES + blockCount * perBlock;
|
|
109
|
+
if (stream.length < bodyEnd) return null;
|
|
110
|
+
const view = new DataView(stream.buffer, stream.byteOffset, stream.byteLength);
|
|
111
|
+
const blocks: QuantizedBlockV1[] = [];
|
|
112
|
+
let pos = RESIDUAL_HEADER_BYTES;
|
|
113
|
+
for (let b = 0; b < blockCount; b++) {
|
|
114
|
+
const scale = view.getFloat32(pos, true);
|
|
115
|
+
pos += 4;
|
|
116
|
+
const coefficients = new Int16Array(header.blockSize);
|
|
117
|
+
for (let i = 0; i < header.blockSize; i++) {
|
|
118
|
+
coefficients[i] = view.getInt16(pos, true);
|
|
119
|
+
pos += 2;
|
|
120
|
+
}
|
|
121
|
+
blocks.push({ scale, coefficients });
|
|
122
|
+
}
|
|
123
|
+
const parsed = parseCorrections(stream, pos);
|
|
124
|
+
if (!parsed) return null;
|
|
125
|
+
// Every correction must name a block that exists.
|
|
126
|
+
for (const block of parsed.blocks) {
|
|
127
|
+
if (block.blockIndex >= blockCount) return null;
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
schema: "residual-codec-v1",
|
|
131
|
+
header,
|
|
132
|
+
blocks,
|
|
133
|
+
corrections: parsed.blocks,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/residual/types.ts — reversible residual payload codec (VC4B).
|
|
3
|
+
*
|
|
4
|
+
* Owns `ResidualCodecV1` / `ParityShardV1` — the contract of the sprint failure
|
|
5
|
+
* triad:
|
|
6
|
+
*
|
|
7
|
+
* A = admitted residual (DCT + int16 + exact corrections) + RS(9,6) parity;
|
|
8
|
+
* B = exact compressed bytes (forced when the >95% accounting rejects A);
|
|
9
|
+
* C = ledger bytes (forced when A/B decode fails).
|
|
10
|
+
*
|
|
11
|
+
* Semantic vectors NEVER claim to recover exact text. Exact bytes come only from
|
|
12
|
+
* exact payload shards (VC4A `ExactShardV1`) or this REVERSIBLE codec: a block
|
|
13
|
+
* DCT-II analysis, int16 quantization, and a block-scoped exact correction
|
|
14
|
+
* stream that makes post-decode byte error exactly zero for admitted artifacts.
|
|
15
|
+
* Numeric erasure parity protects the codec bytes; it is not a substitute for
|
|
16
|
+
* the exact payload (RESIDUAL_CODEC.md).
|
|
17
|
+
*
|
|
18
|
+
* Consumes only reviewer-accepted predecessor contracts (VC1A EventV2 bytes via
|
|
19
|
+
* VC4A shard ranges) and the common contracts. Pure types + registered
|
|
20
|
+
* conformance IDs: no storage, no console, no network (PREVENT-PI-004 /
|
|
21
|
+
* PREVENT-011).
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Fixed transform block length (RESIDUAL_CODEC §byte scope: 4096). */
|
|
25
|
+
export const RESIDUAL_BLOCK_SIZE = 4096;
|
|
26
|
+
|
|
27
|
+
/** Reed–Solomon shard geometry: k=6 data shards, m=3 parity shards. */
|
|
28
|
+
export const RS_DATA_SHARDS = 6;
|
|
29
|
+
export const RS_PARITY_SHARDS = 3;
|
|
30
|
+
export const RS_TOTAL_SHARDS = RS_DATA_SHARDS + RS_PARITY_SHARDS;
|
|
31
|
+
|
|
32
|
+
/** GF(2^8) primitive polynomial for the parity field (0x11d). */
|
|
33
|
+
export const GF_PRIMITIVE_POLYNOMIAL = 0x11d;
|
|
34
|
+
|
|
35
|
+
/** Header magic bytes `VCR1`. */
|
|
36
|
+
export const RESIDUAL_MAGIC = "VCR1";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Admission ratio: residual is admitted only when its FULL encoded size is at
|
|
40
|
+
* most `floor(0.95 * exactCompressedSize)` (RESIDUAL_CODEC §admission). The
|
|
41
|
+
* accounting counts every persisted byte — header, scales, coefficients,
|
|
42
|
+
* corrections, shard metadata, all 9 shards, and digests.
|
|
43
|
+
*/
|
|
44
|
+
export const ADMISSION_NUMERATOR = 95;
|
|
45
|
+
export const ADMISSION_DENOMINATOR = 100;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Canonical header of an encoded residual artifact. Serialized (little-endian)
|
|
49
|
+
* as: magic `VCR1` (4 bytes), u32 original length, 32-byte SHA-256 of the
|
|
50
|
+
* ORIGINAL payload, u16 block size, u16 data shard count `k`, u16 parity count
|
|
51
|
+
* `m` — 46 bytes total.
|
|
52
|
+
*/
|
|
53
|
+
export interface ResidualHeaderV1 {
|
|
54
|
+
readonly magic: typeof RESIDUAL_MAGIC;
|
|
55
|
+
/** Original (pre-padding) payload length in bytes. */
|
|
56
|
+
readonly originalLength: number;
|
|
57
|
+
/** SHA-256 of the original payload bytes, lowercase hex (64 chars). */
|
|
58
|
+
readonly payloadDigest: string;
|
|
59
|
+
readonly blockSize: typeof RESIDUAL_BLOCK_SIZE;
|
|
60
|
+
readonly dataShards: typeof RS_DATA_SHARDS;
|
|
61
|
+
readonly parityShards: typeof RS_PARITY_SHARDS;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Serialized header byte length: 4 + 4 + 32 + 2 + 2 + 2. */
|
|
65
|
+
export const RESIDUAL_HEADER_BYTES = 46;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* One transform block's quantized coefficients. `scale` is the per-block float32
|
|
69
|
+
* scale `max(abs(c))/32767` (exactly 0 for an all-zero block); `coefficients`
|
|
70
|
+
* are the int16 quantized DCT-II coefficients in ascending frequency order.
|
|
71
|
+
*/
|
|
72
|
+
export interface QuantizedBlockV1 {
|
|
73
|
+
/** Per-block float32 LE scale. Zero for an all-zero coefficient block. */
|
|
74
|
+
readonly scale: number;
|
|
75
|
+
/** Int16 coefficients, length exactly `RESIDUAL_BLOCK_SIZE`. */
|
|
76
|
+
readonly coefficients: Int16Array;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* One exact byte correction inside a block: the reconstruction differed from
|
|
81
|
+
* the original at `offset`, and `original` is the authoritative byte.
|
|
82
|
+
*/
|
|
83
|
+
export interface CorrectionV1 {
|
|
84
|
+
/** Offset within the block, 0..4095. */
|
|
85
|
+
readonly offset: number;
|
|
86
|
+
/** The original (authoritative) byte value, 0..255. */
|
|
87
|
+
readonly original: number;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The block-scoped exact correction stream. Blocks appear in ascending
|
|
92
|
+
* `blockIndex`; each block's corrections are sorted by ascending offset with no
|
|
93
|
+
* duplicate offset. Omitted blocks have an implicit count of zero.
|
|
94
|
+
*/
|
|
95
|
+
export interface BlockCorrectionsV1 {
|
|
96
|
+
readonly blockIndex: number;
|
|
97
|
+
readonly corrections: readonly CorrectionV1[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* A fully encoded residual artifact before shard splitting: the header plus the
|
|
102
|
+
* per-block quantization and the exact correction stream. Serializing this in
|
|
103
|
+
* canonical order produces the PROTECTED STREAM that the parity layer splits.
|
|
104
|
+
*/
|
|
105
|
+
export interface ResidualCodecV1 {
|
|
106
|
+
readonly schema: "residual-codec-v1";
|
|
107
|
+
readonly header: ResidualHeaderV1;
|
|
108
|
+
readonly blocks: readonly QuantizedBlockV1[];
|
|
109
|
+
readonly corrections: readonly BlockCorrectionsV1[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* One Reed–Solomon shard over the protected stream. Shards 0..5 are the
|
|
114
|
+
* systematic data shards (the protected stream split into `k=6` equal,
|
|
115
|
+
* zero-padded pieces); shards 6..8 are the parity shards, in that order. Every
|
|
116
|
+
* shard carries its own SHA-256 so an unknown corruption is DETECTED (and can
|
|
117
|
+
* then be marked as a known erasure) even though it is never blindly corrected.
|
|
118
|
+
*/
|
|
119
|
+
export interface ParityShardV1 {
|
|
120
|
+
readonly schema: "parity-shard-v1";
|
|
121
|
+
/** Shard index 0..8 (0..5 data, 6..8 parity). */
|
|
122
|
+
readonly index: number;
|
|
123
|
+
readonly kind: "data" | "parity";
|
|
124
|
+
/** Shard payload bytes; every shard has the same length. */
|
|
125
|
+
readonly bytes: Uint8Array;
|
|
126
|
+
/** SHA-256 of `bytes`, lowercase hex. */
|
|
127
|
+
readonly digest: string;
|
|
128
|
+
/** Length of the UNPADDED protected stream (needed to truncate on recovery). */
|
|
129
|
+
readonly streamLength: number;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Byte accounting handed forward to VC4C (spec §next handoff). */
|
|
133
|
+
export interface ResidualAccountingV1 {
|
|
134
|
+
/** Every persisted residual byte: header + scales + coefficients + corrections + shards + digests. */
|
|
135
|
+
readonly encodedSize: number;
|
|
136
|
+
/** Size of the competing exact compressed representation. */
|
|
137
|
+
readonly exactCompressedSize: number;
|
|
138
|
+
/** `floor(0.95 * exactCompressedSize)` — the inclusive admission ceiling. */
|
|
139
|
+
readonly admissionCeiling: number;
|
|
140
|
+
/** Number of correction entries across every block (density numerator). */
|
|
141
|
+
readonly correctionCount: number;
|
|
142
|
+
/** Number of transform blocks. */
|
|
143
|
+
readonly blockCount: number;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Failure codes the residual codec / parity layer can return. */
|
|
147
|
+
export type ResidualFailureCode =
|
|
148
|
+
| "RES_QUANTIZE_RANGE"
|
|
149
|
+
| "RES_TOO_MANY_ERASURES"
|
|
150
|
+
| "RES_DUPLICATE_SHARD_INDEX"
|
|
151
|
+
| "RES_SHARD_DIGEST_MISMATCH"
|
|
152
|
+
| "RES_SHARD_LENGTH_MISMATCH"
|
|
153
|
+
| "RES_SINGULAR_MATRIX"
|
|
154
|
+
| "RES_PAYLOAD_DIGEST_MISMATCH"
|
|
155
|
+
| "RES_HEADER_INVALID"
|
|
156
|
+
| "RES_CORRECTION_DUPLICATE_OFFSET"
|
|
157
|
+
| "RES_CORRECTION_RANGE"
|
|
158
|
+
| "RES_NOT_ADMITTED";
|
|
159
|
+
|
|
160
|
+
/** Encode result: an admitted artifact, or the exact reason it was not admitted. */
|
|
161
|
+
export type ResidualEncodeResult =
|
|
162
|
+
| {
|
|
163
|
+
ok: true;
|
|
164
|
+
/** Mode A: the residual was admitted. */
|
|
165
|
+
admitted: true;
|
|
166
|
+
codec: ResidualCodecV1;
|
|
167
|
+
shards: readonly ParityShardV1[];
|
|
168
|
+
accounting: ResidualAccountingV1;
|
|
169
|
+
}
|
|
170
|
+
| {
|
|
171
|
+
ok: true;
|
|
172
|
+
/** Mode B: encode succeeded but accounting rejected it; store exact bytes. */
|
|
173
|
+
admitted: false;
|
|
174
|
+
code: "RES_NOT_ADMITTED";
|
|
175
|
+
accounting: ResidualAccountingV1;
|
|
176
|
+
}
|
|
177
|
+
| { ok: false; code: ResidualFailureCode };
|
|
178
|
+
|
|
179
|
+
/** Decode result: the exact original bytes, or the exact failure code. */
|
|
180
|
+
export type ResidualDecodeResult =
|
|
181
|
+
| { ok: true; bytes: Uint8Array }
|
|
182
|
+
| { ok: false; code: ResidualFailureCode };
|
|
183
|
+
|
|
184
|
+
/** Parity reconstruction result over a (possibly partial) shard set. */
|
|
185
|
+
export type ParityRecoveryResult =
|
|
186
|
+
| { ok: true; stream: Uint8Array; recoveredIndices: readonly number[] }
|
|
187
|
+
| { ok: false; code: ResidualFailureCode };
|
|
188
|
+
|
|
189
|
+
/** The two structured events the VC4B reporter emits. */
|
|
190
|
+
export type ResidualEventName =
|
|
191
|
+
| "vector_cortex_residual_admitted"
|
|
192
|
+
| "vector_cortex_parity_recovery_failed";
|
|
193
|
+
|
|
194
|
+
/** Injected emit callback — same (event, fields) shape as the other VC seams. */
|
|
195
|
+
export type ResidualEmitter = (
|
|
196
|
+
event: ResidualEventName,
|
|
197
|
+
fields: Record<string, unknown>,
|
|
198
|
+
) => void;
|
|
199
|
+
|
|
200
|
+
/** Typed, best-effort reporter bound to the two residual event names. */
|
|
201
|
+
export interface ResidualReporter {
|
|
202
|
+
readonly residualAdmitted: (fields: Record<string, unknown>) => void;
|
|
203
|
+
readonly parityRecoveryFailed: (fields: Record<string, unknown>) => void;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Aggregate-only residual metrics exposed to the dashboard. NEVER payload:
|
|
208
|
+
* counts, byte totals and ratios only (SECURITY_PRIVACY — the exact ledger is
|
|
209
|
+
* not training data and residual payloads are never rendered).
|
|
210
|
+
*/
|
|
211
|
+
export interface ResidualMetricsV1 {
|
|
212
|
+
readonly encodeAttempts: number;
|
|
213
|
+
readonly admittedCount: number;
|
|
214
|
+
readonly rejectedCount: number;
|
|
215
|
+
readonly recoveryFailures: number;
|
|
216
|
+
readonly encodedByteTotal: number;
|
|
217
|
+
readonly exactByteTotal: number;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Registered RES conformance ID range (RES-001..050). The acceptance test reads
|
|
222
|
+
* these rows from the v2 manifest and asserts each returns its manifest
|
|
223
|
+
* `ok`/`code`. The three named assertions (RES-DCT-001 / RES-RS-002 /
|
|
224
|
+
* RES-ADMIT-003) live alongside them.
|
|
225
|
+
*/
|
|
226
|
+
export const RES_IDS: readonly string[] = Array.from(
|
|
227
|
+
{ length: 50 },
|
|
228
|
+
(_v, i) => `RES-${String(i + 1).padStart(3, "0")}`,
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
/** Named RES conformance assertions (the sprint's headline rows). */
|
|
232
|
+
export const RES_NAMED_IDS = [
|
|
233
|
+
"RES-DCT-001",
|
|
234
|
+
"RES-RS-002",
|
|
235
|
+
"RES-ADMIT-003",
|
|
236
|
+
] as const;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vector-cortex/shards/exact.ts — exact tier partition (VC4A).
|
|
3
|
+
*
|
|
4
|
+
* Carves the session's PROTECTED spans — every tool call/result pair, every
|
|
5
|
+
* anchor, every invalid UTF-8 event — into `ExactShardV1` payloads of the
|
|
6
|
+
* ORIGINAL bytes, verbatim and never normalized (SHD-UTF8-002: invalid bytes
|
|
7
|
+
* are exact-only and preserved unchanged — the codec's strict-fatal classifier
|
|
8
|
+
* means an invalid event has no lossy text to re-encode; we copy `originalBytes`
|
|
9
|
+
* directly). Each protected span is ATOMIC: a tool call/result pair is one
|
|
10
|
+
* `ProtectedSpan`, so no exact shard EVER splits a pair, even when the pair
|
|
11
|
+
* straddles the target-size boundary (SHD-PAIR-001).
|
|
12
|
+
*
|
|
13
|
+
* The partition walks the protected spans in canonical stream order (ascending
|
|
14
|
+
* first-seq), accrues each span's bytes, and closes an exact shard the moment
|
|
15
|
+
* adding the next atomic span would exceed `targetSize`. A single span over the
|
|
16
|
+
* budget still occupies exactly one shard — the pair case never splits.
|
|
17
|
+
*
|
|
18
|
+
* Triad: A = used with the semantic tier; B = the same exact spans preserved
|
|
19
|
+
* alongside extractive-derived semantic content; C = exact anchors/current
|
|
20
|
+
* transcript ONLY (this partition alone, with zero semantic shards).
|
|
21
|
+
*
|
|
22
|
+
* Pure/deterministic: hashes + array walking only, no storage, no console, no
|
|
23
|
+
* network (PREVENT-PI-004 / PREVENT-011).
|
|
24
|
+
*/
|
|
25
|
+
import { createHash } from "node:crypto";
|
|
26
|
+
import type { EventV2 } from "../ledger/types.js";
|
|
27
|
+
import { cumulativeOffsets } from "./semantic.js";
|
|
28
|
+
import type { ExactPartitionInput, ExactPartitionResult, ExactShardCase, ExactShardV1, ProtectedSpan } from "./types.js";
|
|
29
|
+
|
|
30
|
+
/** Deterministic exact-shard digest over the verbatim original bytes. */
|
|
31
|
+
function sealExactDigest(sessionId: string, bytes: Uint8Array): string {
|
|
32
|
+
const h = createHash("sha256");
|
|
33
|
+
h.update(`exact-shard-v1|${sessionId}|`);
|
|
34
|
+
h.update(bytes);
|
|
35
|
+
return `sha256:${h.digest("hex")}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Combine per-span cases into one shard case (invalid dominates, then tool-pair). */
|
|
39
|
+
function combineCase(span: ProtectedSpan, acc: ExactShardCase): ExactShardCase {
|
|
40
|
+
if (span.case === "invalid-utf8" || acc === "invalid-utf8") return "invalid-utf8";
|
|
41
|
+
if (span.case === "tool-pair" || acc === "tool-pair") return "tool-pair";
|
|
42
|
+
return "anchor";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Concatenate an ordered group of events' original bytes, verbatim. */
|
|
46
|
+
function concatBytes(events: readonly EventV2[]): Uint8Array {
|
|
47
|
+
let len = 0;
|
|
48
|
+
for (const e of events) len += e.originalBytes.length;
|
|
49
|
+
const out = new Uint8Array(len);
|
|
50
|
+
let off = 0;
|
|
51
|
+
for (const e of events) {
|
|
52
|
+
out.set(e.originalBytes, off);
|
|
53
|
+
off += e.originalBytes.length;
|
|
54
|
+
}
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Partition the exact tier (task 3). Returns `ok:true` with a list of
|
|
60
|
+
* `ExactShardV1` whose (sorted) ranges are contiguous, non-overlapping and
|
|
61
|
+
* jointly cover every protected span exactly once, each preserving the original
|
|
62
|
+
* bytes verbatim. Defensive failures mirror the semantic tier: a bad target size
|
|
63
|
+
* rejects with `SHD_INVALID_TARGET_SIZE`; a protected span referencing an event
|
|
64
|
+
* outside the session's stream, or a mixed-session span, rejects with
|
|
65
|
+
* `SHD_CROSS_SESSION`.
|
|
66
|
+
*/
|
|
67
|
+
export function partitionExact(input: ExactPartitionInput): ExactPartitionResult {
|
|
68
|
+
const { sessionId, events, protectedSpans, targetSize } = input;
|
|
69
|
+
if (!Number.isFinite(targetSize) || targetSize <= 0) {
|
|
70
|
+
return { ok: false, code: "SHD_INVALID_TARGET_SIZE" };
|
|
71
|
+
}
|
|
72
|
+
const stream = new Set(events.map((e) => e.seq.toString()));
|
|
73
|
+
for (const span of protectedSpans) {
|
|
74
|
+
if (span.events.some((e) => e.sessionId !== sessionId || !stream.has(e.seq.toString()))) {
|
|
75
|
+
return { ok: false, code: "SHD_CROSS_SESSION" };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const offsets = cumulativeOffsets(events);
|
|
79
|
+
if (protectedSpans.length === 0) return { ok: true, shards: [] };
|
|
80
|
+
|
|
81
|
+
// Process protected spans in canonical stream order (ascending first-seq;
|
|
82
|
+
// equal first-seq preserves input order for determinism).
|
|
83
|
+
const ordered = [...protectedSpans].sort((a, b) => {
|
|
84
|
+
const as = a.events.length ? a.events[0].seq : 0n;
|
|
85
|
+
const bs = b.events.length ? b.events[0].seq : 0n;
|
|
86
|
+
return as < bs ? -1 : as > bs ? 1 : 0;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const shards: ExactShardV1[] = [];
|
|
90
|
+
let batch: ProtectedSpan[] = [];
|
|
91
|
+
let batchBytes = 0;
|
|
92
|
+
let batchCase: ExactShardCase = "anchor";
|
|
93
|
+
|
|
94
|
+
const spanBytes = (s: ProtectedSpan): number =>
|
|
95
|
+
s.events.reduce((n, e) => n + e.originalBytes.length, 0);
|
|
96
|
+
|
|
97
|
+
const flush = (): void => {
|
|
98
|
+
if (batch.length === 0) return;
|
|
99
|
+
const first = batch[0];
|
|
100
|
+
const last = batch[batch.length - 1];
|
|
101
|
+
const firstEv = first.events[0];
|
|
102
|
+
const lastEv = last.events[last.events.length - 1];
|
|
103
|
+
const start = offsets.of(firstEv.seq);
|
|
104
|
+
const end = offsets.of(lastEv.seq);
|
|
105
|
+
const byteStart = start ? start.byteStart : 0;
|
|
106
|
+
const byteEnd = end ? end.byteEnd : byteStart;
|
|
107
|
+
const bytes = concatBytes(batch.flatMap((s) => s.events));
|
|
108
|
+
shards.push({
|
|
109
|
+
schema: "exact-shard-v1",
|
|
110
|
+
sessionId,
|
|
111
|
+
range: {
|
|
112
|
+
sessionId,
|
|
113
|
+
seqStart: firstEv.seq,
|
|
114
|
+
seqEnd: lastEv.seq,
|
|
115
|
+
byteStart,
|
|
116
|
+
byteEnd,
|
|
117
|
+
},
|
|
118
|
+
kind: "exact",
|
|
119
|
+
originalBytes: bytes,
|
|
120
|
+
digest: sealExactDigest(sessionId, bytes),
|
|
121
|
+
byteCount: batchBytes,
|
|
122
|
+
case: batchCase,
|
|
123
|
+
});
|
|
124
|
+
batch = [];
|
|
125
|
+
batchBytes = 0;
|
|
126
|
+
batchCase = "anchor";
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
for (const span of ordered) {
|
|
130
|
+
const sz = spanBytes(span);
|
|
131
|
+
// Close at a complete-span boundary when adding this atomic span would
|
|
132
|
+
// exceed the budget and we already hold at least one complete span.
|
|
133
|
+
if (batch.length > 0 && batchBytes + sz > targetSize) flush();
|
|
134
|
+
batch.push(span);
|
|
135
|
+
batchBytes += sz;
|
|
136
|
+
batchCase = combineCase(span, batchCase);
|
|
137
|
+
}
|
|
138
|
+
flush();
|
|
139
|
+
|
|
140
|
+
return { ok: true, shards };
|
|
141
|
+
}
|