agentic-qe 3.7.22 → 3.8.0
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/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +31 -0
- package/README.md +2 -2
- package/dist/cli/bundle.js +5688 -1243
- package/dist/cli/commands/audit.d.ts +43 -0
- package/dist/cli/commands/audit.js +125 -0
- package/dist/cli/commands/learning.js +106 -1
- package/dist/cli/commands/ruvector-commands.d.ts +15 -0
- package/dist/cli/commands/ruvector-commands.js +271 -0
- package/dist/cli/index.js +4 -0
- package/dist/coordination/behavior-tree/decorators.d.ts +108 -0
- package/dist/coordination/behavior-tree/decorators.js +251 -0
- package/dist/coordination/behavior-tree/index.d.ts +12 -0
- package/dist/coordination/behavior-tree/index.js +15 -0
- package/dist/coordination/behavior-tree/nodes.d.ts +165 -0
- package/dist/coordination/behavior-tree/nodes.js +338 -0
- package/dist/coordination/behavior-tree/qe-trees.d.ts +105 -0
- package/dist/coordination/behavior-tree/qe-trees.js +181 -0
- package/dist/coordination/coherence-action-gate.d.ts +284 -0
- package/dist/coordination/coherence-action-gate.js +512 -0
- package/dist/coordination/index.d.ts +4 -0
- package/dist/coordination/index.js +8 -0
- package/dist/coordination/reasoning-qec.d.ts +315 -0
- package/dist/coordination/reasoning-qec.js +585 -0
- package/dist/coordination/task-executor.d.ts +16 -0
- package/dist/coordination/task-executor.js +99 -0
- package/dist/coordination/workflow-orchestrator.d.ts +29 -0
- package/dist/coordination/workflow-orchestrator.js +42 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.d.ts +135 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.js +327 -0
- package/dist/domains/visual-accessibility/index.d.ts +1 -0
- package/dist/domains/visual-accessibility/index.js +4 -0
- package/dist/governance/coherence-validator.d.ts +112 -0
- package/dist/governance/coherence-validator.js +180 -0
- package/dist/governance/index.d.ts +1 -0
- package/dist/governance/index.js +2 -0
- package/dist/governance/witness-chain.d.ts +311 -0
- package/dist/governance/witness-chain.js +509 -0
- package/dist/integrations/browser/qe-dashboard/clustering.d.ts +48 -0
- package/dist/integrations/browser/qe-dashboard/clustering.js +183 -0
- package/dist/integrations/browser/qe-dashboard/index.d.ts +12 -0
- package/dist/integrations/browser/qe-dashboard/index.js +15 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.d.ts +165 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.js +260 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.d.ts +144 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.js +277 -0
- package/dist/integrations/ruvector/cognitive-container-codec.d.ts +51 -0
- package/dist/integrations/ruvector/cognitive-container-codec.js +180 -0
- package/dist/integrations/ruvector/cognitive-container.d.ts +125 -0
- package/dist/integrations/ruvector/cognitive-container.js +306 -0
- package/dist/integrations/ruvector/coherence-gate.d.ts +309 -0
- package/dist/integrations/ruvector/coherence-gate.js +631 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.d.ts +176 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.js +301 -0
- package/dist/integrations/ruvector/dither-adapter.d.ts +122 -0
- package/dist/integrations/ruvector/dither-adapter.js +295 -0
- package/dist/integrations/ruvector/domain-transfer.d.ts +129 -0
- package/dist/integrations/ruvector/domain-transfer.js +220 -0
- package/dist/integrations/ruvector/feature-flags.d.ts +214 -2
- package/dist/integrations/ruvector/feature-flags.js +167 -2
- package/dist/integrations/ruvector/filter-adapter.d.ts +71 -0
- package/dist/integrations/ruvector/filter-adapter.js +285 -0
- package/dist/integrations/ruvector/gnn-wrapper.d.ts +20 -0
- package/dist/integrations/ruvector/gnn-wrapper.js +40 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.d.ts +237 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.js +394 -0
- package/dist/integrations/ruvector/index.d.ts +8 -2
- package/dist/integrations/ruvector/index.js +18 -2
- package/dist/integrations/ruvector/interfaces.d.ts +40 -0
- package/dist/integrations/ruvector/sona-persistence.d.ts +54 -0
- package/dist/integrations/ruvector/sona-persistence.js +162 -0
- package/dist/integrations/ruvector/sona-three-loop.d.ts +392 -0
- package/dist/integrations/ruvector/sona-three-loop.js +814 -0
- package/dist/integrations/ruvector/sona-wrapper.d.ts +97 -0
- package/dist/integrations/ruvector/sona-wrapper.js +147 -3
- package/dist/integrations/ruvector/spectral-math.d.ts +101 -0
- package/dist/integrations/ruvector/spectral-math.js +254 -0
- package/dist/integrations/ruvector/temporal-compression.d.ts +163 -0
- package/dist/integrations/ruvector/temporal-compression.js +318 -0
- package/dist/integrations/ruvector/thompson-sampler.d.ts +61 -0
- package/dist/integrations/ruvector/thompson-sampler.js +118 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.d.ts +80 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.js +63 -0
- package/dist/integrations/ruvector/transfer-verification.d.ts +119 -0
- package/dist/integrations/ruvector/transfer-verification.js +115 -0
- package/dist/kernel/hnsw-adapter.d.ts +52 -1
- package/dist/kernel/hnsw-adapter.js +139 -4
- package/dist/kernel/hnsw-index-provider.d.ts +5 -0
- package/dist/kernel/native-hnsw-backend.d.ts +110 -0
- package/dist/kernel/native-hnsw-backend.js +408 -0
- package/dist/learning/aqe-learning-engine.d.ts +2 -0
- package/dist/learning/aqe-learning-engine.js +65 -0
- package/dist/learning/experience-capture.d.ts +10 -0
- package/dist/learning/experience-capture.js +34 -0
- package/dist/learning/index.d.ts +2 -0
- package/dist/learning/index.js +4 -0
- package/dist/learning/metrics-tracker.d.ts +11 -0
- package/dist/learning/metrics-tracker.js +14 -0
- package/dist/learning/pattern-lifecycle.d.ts +29 -0
- package/dist/learning/pattern-lifecycle.js +74 -0
- package/dist/learning/pattern-store.d.ts +8 -0
- package/dist/learning/pattern-store.js +8 -2
- package/dist/learning/regret-tracker.d.ts +201 -0
- package/dist/learning/regret-tracker.js +361 -0
- package/dist/mcp/bundle.js +5834 -398
- package/dist/routing/index.d.ts +4 -2
- package/dist/routing/index.js +3 -1
- package/dist/routing/neural-tiny-dancer-router.d.ts +268 -0
- package/dist/routing/neural-tiny-dancer-router.js +514 -0
- package/dist/routing/queen-integration.js +5 -5
- package/dist/routing/routing-config.d.ts +6 -0
- package/dist/routing/routing-config.js +1 -0
- package/dist/routing/simple-neural-router.d.ts +76 -0
- package/dist/routing/simple-neural-router.js +202 -0
- package/dist/routing/tiny-dancer-router.d.ts +20 -1
- package/dist/routing/tiny-dancer-router.js +21 -2
- package/dist/test-scheduling/dag-attention-scheduler.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-scheduler.js +358 -0
- package/dist/test-scheduling/dag-attention-types.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-types.js +10 -0
- package/dist/test-scheduling/index.d.ts +1 -0
- package/dist/test-scheduling/index.js +4 -0
- package/dist/test-scheduling/pipeline.d.ts +8 -0
- package/dist/test-scheduling/pipeline.js +28 -0
- package/package.json +6 -2
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cognitive Container Export/Import (RVF v2, Task 4.1)
|
|
3
|
+
*
|
|
4
|
+
* Produces full cognitive containers that bundle all brain state into a single
|
|
5
|
+
* self-verifying binary format. Each container includes:
|
|
6
|
+
* - Patterns, embeddings, Q-values, LoRA weights, graph state, witness chain
|
|
7
|
+
* - Container manifest with per-segment SHA-256 checksums
|
|
8
|
+
* - Ed25519 signing for container authenticity (Node.js crypto)
|
|
9
|
+
* - COW (copy-on-write) branching for cheap forks
|
|
10
|
+
*
|
|
11
|
+
* Binary layout:
|
|
12
|
+
* [MAGIC 8B][VERSION 4B][MANIFEST_LEN 4B][MANIFEST JSON][SEGMENT DATA...]
|
|
13
|
+
*
|
|
14
|
+
* @module integrations/ruvector/cognitive-container
|
|
15
|
+
*/
|
|
16
|
+
import { Buffer } from 'buffer';
|
|
17
|
+
import Database from 'better-sqlite3';
|
|
18
|
+
import { type MergeStrategy } from './brain-shared.js';
|
|
19
|
+
export interface ContainerSegment {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly offset: number;
|
|
22
|
+
readonly length: number;
|
|
23
|
+
readonly checksum: string;
|
|
24
|
+
readonly compressed: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface ContainerManifest {
|
|
27
|
+
readonly version: string;
|
|
28
|
+
readonly created: string;
|
|
29
|
+
readonly source: string;
|
|
30
|
+
readonly segments: ContainerSegment[];
|
|
31
|
+
readonly checksums: Record<string, string>;
|
|
32
|
+
readonly signature?: string;
|
|
33
|
+
readonly branchOf?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ExportOptions {
|
|
36
|
+
readonly domains?: readonly string[];
|
|
37
|
+
readonly compress?: boolean;
|
|
38
|
+
readonly sign?: boolean;
|
|
39
|
+
readonly privateKey?: Buffer;
|
|
40
|
+
readonly sourceId?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ImportOptions {
|
|
43
|
+
readonly mergeStrategy: MergeStrategy;
|
|
44
|
+
readonly dryRun?: boolean;
|
|
45
|
+
readonly verifySignature?: boolean;
|
|
46
|
+
readonly publicKey?: Buffer;
|
|
47
|
+
}
|
|
48
|
+
export interface ImportResult {
|
|
49
|
+
readonly imported: number;
|
|
50
|
+
readonly skipped: number;
|
|
51
|
+
readonly conflicts: number;
|
|
52
|
+
readonly segmentsRestored: number;
|
|
53
|
+
}
|
|
54
|
+
export interface VerificationResult {
|
|
55
|
+
readonly valid: boolean;
|
|
56
|
+
readonly manifestValid: boolean;
|
|
57
|
+
readonly segmentsValid: boolean;
|
|
58
|
+
readonly signatureValid: boolean | null;
|
|
59
|
+
readonly errors: string[];
|
|
60
|
+
}
|
|
61
|
+
export interface ContainerInfo {
|
|
62
|
+
readonly version: string;
|
|
63
|
+
readonly created: string;
|
|
64
|
+
readonly source: string;
|
|
65
|
+
readonly segmentCount: number;
|
|
66
|
+
readonly segmentNames: string[];
|
|
67
|
+
readonly totalDataBytes: number;
|
|
68
|
+
readonly signed: boolean;
|
|
69
|
+
readonly branchOf: string | null;
|
|
70
|
+
}
|
|
71
|
+
export interface Ed25519KeyPair {
|
|
72
|
+
readonly publicKey: Buffer;
|
|
73
|
+
readonly privateKey: Buffer;
|
|
74
|
+
}
|
|
75
|
+
/** Generate an Ed25519 key pair for container signing. */
|
|
76
|
+
export declare function generateSigningKeyPair(): Ed25519KeyPair;
|
|
77
|
+
export declare class CognitiveContainer {
|
|
78
|
+
/**
|
|
79
|
+
* Export a full cognitive container from the database.
|
|
80
|
+
*
|
|
81
|
+
* Produces a self-contained binary Buffer including all brain segments
|
|
82
|
+
* with per-segment checksums and optional Ed25519 signing.
|
|
83
|
+
*/
|
|
84
|
+
exportContainer(db: Database.Database, options?: ExportOptions): {
|
|
85
|
+
data: Buffer;
|
|
86
|
+
manifest: ContainerManifest;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Import a cognitive container into the database.
|
|
90
|
+
*
|
|
91
|
+
* Verifies segment checksums before importing. Optionally verifies
|
|
92
|
+
* the Ed25519 signature.
|
|
93
|
+
*/
|
|
94
|
+
importContainer(data: Buffer, db: Database.Database, options: ImportOptions): ImportResult;
|
|
95
|
+
/**
|
|
96
|
+
* Verify container integrity without importing.
|
|
97
|
+
*
|
|
98
|
+
* Checks: magic, manifest parse, segment checksums, optional signature.
|
|
99
|
+
*/
|
|
100
|
+
verifyContainer(data: Buffer, publicKey?: Buffer): VerificationResult;
|
|
101
|
+
/**
|
|
102
|
+
* Create a COW (copy-on-write) branch of a container.
|
|
103
|
+
*
|
|
104
|
+
* The branch references the parent container by ID and includes only
|
|
105
|
+
* the manifest with updated metadata. The segment data is shared
|
|
106
|
+
* (not duplicated).
|
|
107
|
+
*/
|
|
108
|
+
branchContainer(sourceData: Buffer, branchName: string): {
|
|
109
|
+
data: Buffer;
|
|
110
|
+
manifest: ContainerManifest;
|
|
111
|
+
};
|
|
112
|
+
/** Get container info without importing or fully verifying. */
|
|
113
|
+
getContainerInfo(data: Buffer): ContainerInfo;
|
|
114
|
+
private buildSignedPayload;
|
|
115
|
+
private verifySignatureInternal;
|
|
116
|
+
private verifyChecksums;
|
|
117
|
+
private requireValidSignature;
|
|
118
|
+
private dryRunImport;
|
|
119
|
+
private executeImport;
|
|
120
|
+
private verifySegmentChecksums;
|
|
121
|
+
private verifySignatureStatus;
|
|
122
|
+
}
|
|
123
|
+
/** Create a CognitiveContainer instance. */
|
|
124
|
+
export declare function createCognitiveContainer(): CognitiveContainer;
|
|
125
|
+
//# sourceMappingURL=cognitive-container.d.ts.map
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cognitive Container Export/Import (RVF v2, Task 4.1)
|
|
3
|
+
*
|
|
4
|
+
* Produces full cognitive containers that bundle all brain state into a single
|
|
5
|
+
* self-verifying binary format. Each container includes:
|
|
6
|
+
* - Patterns, embeddings, Q-values, LoRA weights, graph state, witness chain
|
|
7
|
+
* - Container manifest with per-segment SHA-256 checksums
|
|
8
|
+
* - Ed25519 signing for container authenticity (Node.js crypto)
|
|
9
|
+
* - COW (copy-on-write) branching for cheap forks
|
|
10
|
+
*
|
|
11
|
+
* Binary layout:
|
|
12
|
+
* [MAGIC 8B][VERSION 4B][MANIFEST_LEN 4B][MANIFEST JSON][SEGMENT DATA...]
|
|
13
|
+
*
|
|
14
|
+
* @module integrations/ruvector/cognitive-container
|
|
15
|
+
*/
|
|
16
|
+
import { generateKeyPairSync, sign, verify, randomUUID } from 'crypto';
|
|
17
|
+
import { Buffer } from 'buffer';
|
|
18
|
+
import { ensureTargetTables, mergeGenericRow, mergeAppendOnlyRow, TABLE_CONFIGS, PK_COLUMNS, CONFIDENCE_COLUMNS, TIMESTAMP_COLUMNS, deserializeRowBlobs, TABLE_BLOB_COLUMNS, } from './brain-shared.js';
|
|
19
|
+
import { SEGMENT_NAMES, sha256buf, collectSegmentData, serializeSegment, deserializeSegment, packContainer, unpackHeader, extractSegments, } from './cognitive-container-codec.js';
|
|
20
|
+
/** Generate an Ed25519 key pair for container signing. */
|
|
21
|
+
export function generateSigningKeyPair() {
|
|
22
|
+
const { publicKey, privateKey } = generateKeyPairSync('ed25519', {
|
|
23
|
+
publicKeyEncoding: { type: 'spki', format: 'der' },
|
|
24
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'der' },
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
publicKey: Buffer.from(publicKey),
|
|
28
|
+
privateKey: Buffer.from(privateKey),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// CognitiveContainer
|
|
33
|
+
// ============================================================================
|
|
34
|
+
export class CognitiveContainer {
|
|
35
|
+
/**
|
|
36
|
+
* Export a full cognitive container from the database.
|
|
37
|
+
*
|
|
38
|
+
* Produces a self-contained binary Buffer including all brain segments
|
|
39
|
+
* with per-segment checksums and optional Ed25519 signing.
|
|
40
|
+
*/
|
|
41
|
+
exportContainer(db, options = {}) {
|
|
42
|
+
const compress = options.compress ?? true;
|
|
43
|
+
const sourceId = options.sourceId ?? randomUUID();
|
|
44
|
+
const segmentData = collectSegmentData(db, options.domains);
|
|
45
|
+
const segmentBuffers = [];
|
|
46
|
+
const segments = [];
|
|
47
|
+
const checksums = {};
|
|
48
|
+
let currentOffset = 0;
|
|
49
|
+
for (const name of SEGMENT_NAMES) {
|
|
50
|
+
const tableData = segmentData[name];
|
|
51
|
+
const buf = serializeSegment(tableData, compress);
|
|
52
|
+
const checksum = sha256buf(buf);
|
|
53
|
+
segments.push({
|
|
54
|
+
name,
|
|
55
|
+
offset: currentOffset,
|
|
56
|
+
length: buf.length,
|
|
57
|
+
checksum,
|
|
58
|
+
compressed: compress,
|
|
59
|
+
});
|
|
60
|
+
checksums[name] = checksum;
|
|
61
|
+
segmentBuffers.push(buf);
|
|
62
|
+
currentOffset += buf.length;
|
|
63
|
+
}
|
|
64
|
+
const manifest = {
|
|
65
|
+
version: '2.0.0',
|
|
66
|
+
created: new Date().toISOString(),
|
|
67
|
+
source: sourceId,
|
|
68
|
+
segments,
|
|
69
|
+
checksums,
|
|
70
|
+
};
|
|
71
|
+
if (options.sign && options.privateKey) {
|
|
72
|
+
const payload = this.buildSignedPayload(manifest);
|
|
73
|
+
const signature = sign(null, Buffer.from(payload, 'utf-8'), { key: options.privateKey, format: 'der', type: 'pkcs8' });
|
|
74
|
+
manifest.signature = signature.toString('hex');
|
|
75
|
+
}
|
|
76
|
+
const data = packContainer(manifest, segmentBuffers);
|
|
77
|
+
return { data, manifest };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Import a cognitive container into the database.
|
|
81
|
+
*
|
|
82
|
+
* Verifies segment checksums before importing. Optionally verifies
|
|
83
|
+
* the Ed25519 signature.
|
|
84
|
+
*/
|
|
85
|
+
importContainer(data, db, options) {
|
|
86
|
+
const { manifest, dataOffset } = unpackHeader(data);
|
|
87
|
+
const segmentBuffers = extractSegments(data, dataOffset, manifest.segments);
|
|
88
|
+
this.verifyChecksums(manifest.segments, segmentBuffers);
|
|
89
|
+
if (options.verifySignature) {
|
|
90
|
+
this.requireValidSignature(manifest, options.publicKey);
|
|
91
|
+
}
|
|
92
|
+
if (options.dryRun) {
|
|
93
|
+
return this.dryRunImport(manifest, segmentBuffers);
|
|
94
|
+
}
|
|
95
|
+
ensureTargetTables(db);
|
|
96
|
+
return this.executeImport(db, manifest, segmentBuffers, options.mergeStrategy);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Verify container integrity without importing.
|
|
100
|
+
*
|
|
101
|
+
* Checks: magic, manifest parse, segment checksums, optional signature.
|
|
102
|
+
*/
|
|
103
|
+
verifyContainer(data, publicKey) {
|
|
104
|
+
const errors = [];
|
|
105
|
+
let manifestValid = false;
|
|
106
|
+
let segmentsValid = false;
|
|
107
|
+
let signatureValid = null;
|
|
108
|
+
let manifest;
|
|
109
|
+
let dataOffset;
|
|
110
|
+
try {
|
|
111
|
+
const result = unpackHeader(data);
|
|
112
|
+
manifest = result.manifest;
|
|
113
|
+
dataOffset = result.dataOffset;
|
|
114
|
+
manifestValid = true;
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
118
|
+
return { valid: false, manifestValid, segmentsValid, signatureValid, errors };
|
|
119
|
+
}
|
|
120
|
+
segmentsValid = this.verifySegmentChecksums(data, dataOffset, manifest, errors);
|
|
121
|
+
signatureValid = this.verifySignatureStatus(manifest, publicKey, errors);
|
|
122
|
+
const valid = manifestValid && segmentsValid
|
|
123
|
+
&& (signatureValid === null || signatureValid);
|
|
124
|
+
return { valid, manifestValid, segmentsValid, signatureValid, errors };
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Create a COW (copy-on-write) branch of a container.
|
|
128
|
+
*
|
|
129
|
+
* The branch references the parent container by ID and includes only
|
|
130
|
+
* the manifest with updated metadata. The segment data is shared
|
|
131
|
+
* (not duplicated).
|
|
132
|
+
*/
|
|
133
|
+
branchContainer(sourceData, branchName) {
|
|
134
|
+
const { manifest: src, dataOffset } = unpackHeader(sourceData);
|
|
135
|
+
const segBufs = extractSegments(sourceData, dataOffset, src.segments);
|
|
136
|
+
const branchManifest = {
|
|
137
|
+
version: src.version,
|
|
138
|
+
created: new Date().toISOString(),
|
|
139
|
+
source: branchName,
|
|
140
|
+
segments: src.segments.map(seg => ({ ...seg })),
|
|
141
|
+
checksums: { ...src.checksums },
|
|
142
|
+
branchOf: src.source,
|
|
143
|
+
};
|
|
144
|
+
const buffers = [];
|
|
145
|
+
for (const seg of src.segments) {
|
|
146
|
+
buffers.push(segBufs.get(seg.name));
|
|
147
|
+
}
|
|
148
|
+
const data = packContainer(branchManifest, buffers);
|
|
149
|
+
return { data, manifest: branchManifest };
|
|
150
|
+
}
|
|
151
|
+
/** Get container info without importing or fully verifying. */
|
|
152
|
+
getContainerInfo(data) {
|
|
153
|
+
const { manifest } = unpackHeader(data);
|
|
154
|
+
const totalDataBytes = manifest.segments.reduce((sum, s) => sum + s.length, 0);
|
|
155
|
+
return {
|
|
156
|
+
version: manifest.version,
|
|
157
|
+
created: manifest.created,
|
|
158
|
+
source: manifest.source,
|
|
159
|
+
segmentCount: manifest.segments.length,
|
|
160
|
+
segmentNames: manifest.segments.map(s => s.name),
|
|
161
|
+
totalDataBytes,
|
|
162
|
+
signed: !!manifest.signature,
|
|
163
|
+
branchOf: manifest.branchOf ?? null,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
// --------------------------------------------------------------------------
|
|
167
|
+
// Private helpers
|
|
168
|
+
// --------------------------------------------------------------------------
|
|
169
|
+
buildSignedPayload(manifest) {
|
|
170
|
+
return JSON.stringify({
|
|
171
|
+
version: manifest.version,
|
|
172
|
+
created: manifest.created,
|
|
173
|
+
source: manifest.source,
|
|
174
|
+
checksums: manifest.checksums,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
verifySignatureInternal(manifest, publicKey) {
|
|
178
|
+
if (!manifest.signature)
|
|
179
|
+
return false;
|
|
180
|
+
const payload = this.buildSignedPayload(manifest);
|
|
181
|
+
return verify(null, Buffer.from(payload, 'utf-8'), { key: publicKey, format: 'der', type: 'spki' }, Buffer.from(manifest.signature, 'hex'));
|
|
182
|
+
}
|
|
183
|
+
verifyChecksums(segments, segmentBuffers) {
|
|
184
|
+
for (const seg of segments) {
|
|
185
|
+
const buf = segmentBuffers.get(seg.name);
|
|
186
|
+
if (!buf)
|
|
187
|
+
throw new Error(`Missing segment data: ${seg.name}`);
|
|
188
|
+
const actual = sha256buf(buf);
|
|
189
|
+
if (actual !== seg.checksum) {
|
|
190
|
+
throw new Error(`Checksum mismatch for segment '${seg.name}': ` +
|
|
191
|
+
`expected ${seg.checksum}, got ${actual}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
requireValidSignature(manifest, publicKey) {
|
|
196
|
+
if (!manifest.signature) {
|
|
197
|
+
throw new Error('Container is not signed but signature verification was requested');
|
|
198
|
+
}
|
|
199
|
+
if (!publicKey) {
|
|
200
|
+
throw new Error('Public key required for signature verification');
|
|
201
|
+
}
|
|
202
|
+
if (!this.verifySignatureInternal(manifest, publicKey)) {
|
|
203
|
+
throw new Error('Container signature verification failed');
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
dryRunImport(manifest, segmentBuffers) {
|
|
207
|
+
let total = 0;
|
|
208
|
+
for (const seg of manifest.segments) {
|
|
209
|
+
const buf = segmentBuffers.get(seg.name);
|
|
210
|
+
const tableData = deserializeSegment(buf, seg.compressed);
|
|
211
|
+
for (const rows of Object.values(tableData)) {
|
|
212
|
+
total += (rows?.length ?? 0);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return { imported: total, skipped: 0, conflicts: 0, segmentsRestored: manifest.segments.length };
|
|
216
|
+
}
|
|
217
|
+
executeImport(db, manifest, segmentBuffers, mergeStrategy) {
|
|
218
|
+
let imported = 0;
|
|
219
|
+
let skipped = 0;
|
|
220
|
+
let conflicts = 0;
|
|
221
|
+
let segmentsRestored = 0;
|
|
222
|
+
const importAll = db.transaction(() => {
|
|
223
|
+
for (const seg of manifest.segments) {
|
|
224
|
+
const buf = segmentBuffers.get(seg.name);
|
|
225
|
+
const tableData = deserializeSegment(buf, seg.compressed);
|
|
226
|
+
segmentsRestored++;
|
|
227
|
+
for (const [tableName, rows] of Object.entries(tableData)) {
|
|
228
|
+
if (!Array.isArray(rows) || rows.length === 0)
|
|
229
|
+
continue;
|
|
230
|
+
const config = TABLE_CONFIGS.find(c => c.tableName === tableName);
|
|
231
|
+
if (!config)
|
|
232
|
+
continue;
|
|
233
|
+
const blobCols = TABLE_BLOB_COLUMNS[tableName];
|
|
234
|
+
let processedRows = rows;
|
|
235
|
+
if (blobCols && blobCols.length > 0) {
|
|
236
|
+
processedRows = processedRows.map(r => deserializeRowBlobs(r, blobCols));
|
|
237
|
+
}
|
|
238
|
+
for (const row of processedRows) {
|
|
239
|
+
let result;
|
|
240
|
+
if (config.dedupColumns && config.dedupColumns.length > 0) {
|
|
241
|
+
result = mergeAppendOnlyRow(db, config.tableName, row, config.dedupColumns);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
const idCol = PK_COLUMNS[config.tableName] || 'id';
|
|
245
|
+
const tsCol = TIMESTAMP_COLUMNS[config.tableName];
|
|
246
|
+
const confCol = CONFIDENCE_COLUMNS[config.tableName];
|
|
247
|
+
result = mergeGenericRow(db, config.tableName, row, idCol, mergeStrategy, tsCol, confCol);
|
|
248
|
+
}
|
|
249
|
+
imported += result.imported;
|
|
250
|
+
skipped += result.skipped;
|
|
251
|
+
conflicts += result.conflicts;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
importAll();
|
|
257
|
+
return { imported, skipped, conflicts, segmentsRestored };
|
|
258
|
+
}
|
|
259
|
+
verifySegmentChecksums(data, dataOffset, manifest, errors) {
|
|
260
|
+
try {
|
|
261
|
+
const segBufs = extractSegments(data, dataOffset, manifest.segments);
|
|
262
|
+
let allGood = true;
|
|
263
|
+
for (const seg of manifest.segments) {
|
|
264
|
+
const buf = segBufs.get(seg.name);
|
|
265
|
+
if (!buf) {
|
|
266
|
+
errors.push(`Missing segment: ${seg.name}`);
|
|
267
|
+
allGood = false;
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (sha256buf(buf) !== seg.checksum) {
|
|
271
|
+
errors.push(`Checksum mismatch for '${seg.name}'`);
|
|
272
|
+
allGood = false;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return allGood;
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
verifySignatureStatus(manifest, publicKey, errors) {
|
|
283
|
+
if (!manifest.signature)
|
|
284
|
+
return null;
|
|
285
|
+
if (!publicKey)
|
|
286
|
+
return null;
|
|
287
|
+
try {
|
|
288
|
+
const valid = this.verifySignatureInternal(manifest, publicKey);
|
|
289
|
+
if (!valid)
|
|
290
|
+
errors.push('Signature verification failed');
|
|
291
|
+
return valid;
|
|
292
|
+
}
|
|
293
|
+
catch (err) {
|
|
294
|
+
errors.push(`Signature error: ${err instanceof Error ? err.message : String(err)}`);
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// ============================================================================
|
|
300
|
+
// Convenience factory
|
|
301
|
+
// ============================================================================
|
|
302
|
+
/** Create a CognitiveContainer instance. */
|
|
303
|
+
export function createCognitiveContainer() {
|
|
304
|
+
return new CognitiveContainer();
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=cognitive-container.js.map
|