@fortemi/core 2026.7.11 → 2026.7.12

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.
@@ -0,0 +1,2195 @@
1
+ import Ajv2020 from 'ajv/dist/2020.js';
2
+ import { gzipSync, gunzipSync } from 'fflate';
3
+ import { v5 } from 'uuid';
4
+
5
+ // src/aiwg-index.ts
6
+ var REQUIRED_RECORD_FIELDS = [
7
+ "schema_version",
8
+ "id",
9
+ "type",
10
+ "source",
11
+ "facets",
12
+ "tags",
13
+ "concepts",
14
+ "relationships",
15
+ "provenance",
16
+ "privacy",
17
+ "updated_at"
18
+ ];
19
+ function hasString(value) {
20
+ return typeof value === "string" && value.length > 0;
21
+ }
22
+ function isPlainRecord(value) {
23
+ return !!value && typeof value === "object" && !Array.isArray(value);
24
+ }
25
+ function isOptionalStringArray(value) {
26
+ return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
27
+ }
28
+ function isSupportedIndexSchemaVersion(value) {
29
+ return value === "aiwg.fortemi.index.export.v1" || value === "aiwg.fortemi.index.export.v2";
30
+ }
31
+ function isSupportedRecordSchemaVersion(value) {
32
+ return value === "aiwg.fortemi.index.record.v1" || value === "aiwg.fortemi.index.record.v2";
33
+ }
34
+ function validateOptionalRichMetadata(item, index, errors) {
35
+ if (item.skos_concepts !== void 0) {
36
+ if (!Array.isArray(item.skos_concepts)) {
37
+ errors.push("items[" + index + "].skos_concepts must be an array when present");
38
+ } else {
39
+ for (const [conceptIndex, concept] of item.skos_concepts.entries()) {
40
+ if (!isPlainRecord(concept)) {
41
+ errors.push("items[" + index + "].skos_concepts[" + conceptIndex + "] must be an object");
42
+ continue;
43
+ }
44
+ if (!hasString(concept.id)) errors.push("items[" + index + "].skos_concepts[" + conceptIndex + "].id is required");
45
+ if (!hasString(concept.prefLabel)) errors.push("items[" + index + "].skos_concepts[" + conceptIndex + "].prefLabel is required");
46
+ if (!isOptionalStringArray(concept.altLabels)) errors.push("items[" + index + "].skos_concepts[" + conceptIndex + "].altLabels must be a string array");
47
+ if (concept.metadata !== void 0 && !isPlainRecord(concept.metadata)) {
48
+ errors.push("items[" + index + "].skos_concepts[" + conceptIndex + "].metadata must be an object");
49
+ }
50
+ }
51
+ }
52
+ }
53
+ if (item.skos_relations !== void 0) {
54
+ if (!Array.isArray(item.skos_relations)) {
55
+ errors.push("items[" + index + "].skos_relations must be an array when present");
56
+ } else {
57
+ for (const [relationIndex, relation] of item.skos_relations.entries()) {
58
+ if (!isPlainRecord(relation)) {
59
+ errors.push("items[" + index + "].skos_relations[" + relationIndex + "] must be an object");
60
+ continue;
61
+ }
62
+ if (!hasString(relation.type)) errors.push("items[" + index + "].skos_relations[" + relationIndex + "].type is required");
63
+ if (!hasString(relation.source_id)) errors.push("items[" + index + "].skos_relations[" + relationIndex + "].source_id is required");
64
+ if (!hasString(relation.target_id)) errors.push("items[" + index + "].skos_relations[" + relationIndex + "].target_id is required");
65
+ if (relation.metadata !== void 0 && !isPlainRecord(relation.metadata)) {
66
+ errors.push("items[" + index + "].skos_relations[" + relationIndex + "].metadata must be an object");
67
+ }
68
+ }
69
+ }
70
+ }
71
+ if (item.provenance_events !== void 0) {
72
+ if (!Array.isArray(item.provenance_events)) {
73
+ errors.push("items[" + index + "].provenance_events must be an array when present");
74
+ } else {
75
+ for (const [eventIndex, event] of item.provenance_events.entries()) {
76
+ if (!isPlainRecord(event)) {
77
+ errors.push("items[" + index + "].provenance_events[" + eventIndex + "] must be an object");
78
+ continue;
79
+ }
80
+ if (!hasString(event.activity)) errors.push("items[" + index + "].provenance_events[" + eventIndex + "].activity is required");
81
+ if (event.attributes !== void 0 && !isPlainRecord(event.attributes)) {
82
+ errors.push("items[" + index + "].provenance_events[" + eventIndex + "].attributes must be an object");
83
+ }
84
+ }
85
+ }
86
+ }
87
+ if (Array.isArray(item.relationships)) {
88
+ for (const [relationshipIndex, relationship] of item.relationships.entries()) {
89
+ if (!isPlainRecord(relationship)) {
90
+ errors.push("items[" + index + "].relationships[" + relationshipIndex + "] must be an object");
91
+ continue;
92
+ }
93
+ if (relationship.metadata !== void 0 && !isPlainRecord(relationship.metadata)) {
94
+ errors.push("items[" + index + "].relationships[" + relationshipIndex + "].metadata must be an object");
95
+ }
96
+ if (relationship.direction !== void 0 && relationship.direction !== "upstream" && relationship.direction !== "downstream" && relationship.direction !== "related") {
97
+ errors.push("items[" + index + "].relationships[" + relationshipIndex + "].direction must be upstream, downstream, or related");
98
+ }
99
+ if (relationship.target_path !== void 0 && typeof relationship.target_path !== "string") {
100
+ errors.push("items[" + index + "].relationships[" + relationshipIndex + "].target_path must be a string");
101
+ }
102
+ }
103
+ }
104
+ if (item.search !== void 0) {
105
+ if (!isPlainRecord(item.search)) {
106
+ errors.push("items[" + index + "].search must be an object");
107
+ } else {
108
+ if (!isOptionalStringArray(item.search.triggers)) errors.push("items[" + index + "].search.triggers must be a string array");
109
+ if (!isOptionalStringArray(item.search.aliases)) errors.push("items[" + index + "].search.aliases must be a string array");
110
+ if (!isOptionalStringArray(item.search.tags)) errors.push("items[" + index + "].search.tags must be a string array");
111
+ if (item.search.frontmatter !== void 0 && !isPlainRecord(item.search.frontmatter)) {
112
+ errors.push("items[" + index + "].search.frontmatter must be an object");
113
+ }
114
+ }
115
+ }
116
+ if (item.chunks !== void 0) {
117
+ if (!Array.isArray(item.chunks)) {
118
+ errors.push("items[" + index + "].chunks must be an array when present");
119
+ } else {
120
+ for (const [chunkIndex, chunk] of item.chunks.entries()) {
121
+ if (!isPlainRecord(chunk)) {
122
+ errors.push("items[" + index + "].chunks[" + chunkIndex + "] must be an object");
123
+ continue;
124
+ }
125
+ if (chunk.metadata !== void 0 && !isPlainRecord(chunk.metadata)) {
126
+ errors.push("items[" + index + "].chunks[" + chunkIndex + "].metadata must be an object");
127
+ }
128
+ }
129
+ }
130
+ }
131
+ if (item.embeddings !== void 0) {
132
+ if (!Array.isArray(item.embeddings)) {
133
+ errors.push("items[" + index + "].embeddings must be an array when present");
134
+ } else {
135
+ for (const [embeddingIndex, embedding] of item.embeddings.entries()) {
136
+ if (!isPlainRecord(embedding)) {
137
+ errors.push("items[" + index + "].embeddings[" + embeddingIndex + "] must be an object");
138
+ continue;
139
+ }
140
+ const vector = embedding.embedding ?? embedding.vector;
141
+ if (vector !== void 0 && (!Array.isArray(vector) || !vector.every((entry) => typeof entry === "number"))) {
142
+ errors.push("items[" + index + "].embeddings[" + embeddingIndex + "].embedding/vector must be a number array");
143
+ }
144
+ if (embedding.metadata !== void 0 && !isPlainRecord(embedding.metadata)) {
145
+ errors.push("items[" + index + "].embeddings[" + embeddingIndex + "].metadata must be an object");
146
+ }
147
+ }
148
+ }
149
+ }
150
+ if (item.compatibility !== void 0 && !isPlainRecord(item.compatibility)) {
151
+ errors.push("items[" + index + "].compatibility must be an object");
152
+ }
153
+ }
154
+ function isPrivacyClassification(value) {
155
+ return value === "private" || value === "sanitized" || value === "public";
156
+ }
157
+ function isProvenanceConfidence(value) {
158
+ return value === "source" || value === "candidate" || value === "reviewed" || value === "rejected";
159
+ }
160
+ function validateProvenanceItems(item, index, errors) {
161
+ if (!Array.isArray(item.provenance)) return;
162
+ for (const [provIndex, prov] of item.provenance.entries()) {
163
+ const at = "items[" + index + "].provenance[" + provIndex + "]";
164
+ if (!isPlainRecord(prov)) {
165
+ errors.push(at + " must be an object");
166
+ continue;
167
+ }
168
+ if (!hasString(prov.field)) errors.push(at + ".field is required");
169
+ if (!hasString(prov.source)) errors.push(at + ".source is required");
170
+ if (!hasString(prov.path)) errors.push(at + ".path is required");
171
+ if (!isProvenanceConfidence(prov.confidence)) errors.push(at + ".confidence must be one of source, candidate, reviewed, rejected");
172
+ if (!isPrivacyClassification(prov.privacy)) errors.push(at + ".privacy must be one of private, sanitized, public");
173
+ }
174
+ }
175
+ var V2_ONLY_RECORD_FIELDS = [
176
+ "search",
177
+ "chunks",
178
+ "embeddings",
179
+ "skos_concepts",
180
+ "skos_relations",
181
+ "provenance_events",
182
+ "compatibility"
183
+ ];
184
+ var V2_ONLY_SOURCE_FIELDS = ["origin", "generated", "checksum", "updated_at"];
185
+ var V2_ONLY_RELATIONSHIP_FIELDS = ["target_path", "direction", "metadata"];
186
+ function forbidV2FieldsOnV1Record(item, index, errors) {
187
+ if (item.schema_version !== "aiwg.fortemi.index.record.v1") return;
188
+ const at = "items[" + index + "]";
189
+ const bag = item;
190
+ const v2msg = " is a v2-only field and must be absent on a record.v1 record";
191
+ for (const field of V2_ONLY_RECORD_FIELDS) {
192
+ if (bag[field] !== void 0) errors.push(at + "." + field + v2msg);
193
+ }
194
+ if (isPlainRecord(item.source)) {
195
+ const src = item.source;
196
+ for (const field of V2_ONLY_SOURCE_FIELDS) {
197
+ if (src[field] !== void 0) errors.push(at + ".source." + field + v2msg);
198
+ }
199
+ }
200
+ if (isPlainRecord(item.privacy) && item.privacy.locality !== void 0) {
201
+ errors.push(at + ".privacy.locality" + v2msg);
202
+ }
203
+ if (Array.isArray(item.relationships)) {
204
+ for (const [relIndex, rel] of item.relationships.entries()) {
205
+ if (!isPlainRecord(rel)) continue;
206
+ const relBag = rel;
207
+ for (const field of V2_ONLY_RELATIONSHIP_FIELDS) {
208
+ if (relBag[field] !== void 0) errors.push(at + ".relationships[" + relIndex + "]." + field + v2msg);
209
+ }
210
+ }
211
+ }
212
+ }
213
+ function validateAiwgFortemiIndexExport(value) {
214
+ const errors = [];
215
+ const counts = /* @__PURE__ */ Object.create(null);
216
+ const data = isPlainRecord(value) ? value : {};
217
+ if (!isPlainRecord(value)) errors.push("index export must be an object");
218
+ if (!isSupportedIndexSchemaVersion(data?.schema_version)) {
219
+ errors.push("schema_version must be aiwg.fortemi.index.export.v1 or aiwg.fortemi.index.export.v2");
220
+ }
221
+ if (!hasString(data?.generated_at)) errors.push("generated_at is required");
222
+ if (!hasString(data?.source?.repo)) errors.push("source.repo is required");
223
+ if (!hasString(data?.source?.privacy)) errors.push("source.privacy is required");
224
+ else if (!isPrivacyClassification(data?.source?.privacy)) {
225
+ errors.push("source.privacy must be one of private, sanitized, public");
226
+ }
227
+ if (!Array.isArray(data?.items)) errors.push("items must be an array");
228
+ if (data.compatibility !== void 0 && !isPlainRecord(data.compatibility)) {
229
+ errors.push("compatibility must be an object");
230
+ }
231
+ if (data?.schema_version === "aiwg.fortemi.index.export.v1") {
232
+ if (isPlainRecord(data.source) && data.source.graph !== void 0) {
233
+ errors.push("source.graph is a v2-only field and must be absent on an export.v1 export");
234
+ }
235
+ if (data.compatibility !== void 0) {
236
+ errors.push("compatibility is a v2-only field and must be absent on an export.v1 export");
237
+ }
238
+ }
239
+ const ids = /* @__PURE__ */ new Set();
240
+ let previousId = "";
241
+ const items = Array.isArray(data.items) ? data.items : [];
242
+ for (const [index, item] of items.entries()) {
243
+ if (!isPlainRecord(item)) {
244
+ errors.push("items[" + index + "] must be an object");
245
+ continue;
246
+ }
247
+ for (const field of REQUIRED_RECORD_FIELDS) {
248
+ if (!(field in item)) errors.push("items[" + index + "]." + field + " is required");
249
+ }
250
+ if (!isSupportedRecordSchemaVersion(item.schema_version)) {
251
+ errors.push("items[" + index + "].schema_version must be aiwg.fortemi.index.record.v1 or aiwg.fortemi.index.record.v2");
252
+ }
253
+ if (data.schema_version === "aiwg.fortemi.index.export.v1" && item.schema_version === "aiwg.fortemi.index.record.v2") {
254
+ errors.push("items[" + index + "].schema_version must match aiwg.fortemi.index.export.v1");
255
+ }
256
+ if (!hasString(item.id)) errors.push("items[" + index + "].id is required");
257
+ if (hasString(item.id) && ids.has(item.id)) errors.push("duplicate id: " + item.id);
258
+ if (hasString(item.id)) ids.add(item.id);
259
+ if (previousId && hasString(item.id) && previousId > item.id) {
260
+ errors.push("items must be sorted by id: " + previousId + " before " + item.id);
261
+ }
262
+ if (hasString(item.id)) previousId = item.id;
263
+ if (!hasString(item.type)) errors.push("items[" + index + "].type must be a non-empty string");
264
+ else counts[item.type] = (counts[item.type] ?? 0) + 1;
265
+ if (!hasString(item.source?.path)) errors.push("items[" + index + "].source.path is required");
266
+ if (!hasString(item.source?.repo_relative_path)) errors.push("items[" + index + "].source.repo_relative_path is required");
267
+ if (!hasString(item.source?.locator)) errors.push("items[" + index + "].source.locator is required");
268
+ if (typeof item.title !== "string" && typeof item.search?.title !== "string" && typeof item.search?.name !== "string") {
269
+ errors.push("items[" + index + "].title or search.title/search.name is required");
270
+ }
271
+ if (typeof item.text !== "string" && typeof item.search?.body !== "string" && typeof item.search?.summary !== "string") {
272
+ errors.push("items[" + index + "].text or search.body/search.summary is required");
273
+ }
274
+ if (!Array.isArray(item.tags)) errors.push("items[" + index + "].tags must be an array");
275
+ if (!Array.isArray(item.concepts)) errors.push("items[" + index + "].concepts must be an array");
276
+ if (!Array.isArray(item.relationships)) errors.push("items[" + index + "].relationships must be an array");
277
+ if (!Array.isArray(item.provenance) || item.provenance.length === 0) {
278
+ errors.push("items[" + index + "].provenance must be a non-empty array");
279
+ }
280
+ validateOptionalRichMetadata(item, index, errors);
281
+ validateProvenanceItems(item, index, errors);
282
+ forbidV2FieldsOnV1Record(item, index, errors);
283
+ if (!item.privacy || typeof item.privacy.pii !== "boolean" || !hasString(item.privacy.classification)) {
284
+ errors.push("items[" + index + "].privacy requires classification and pii");
285
+ } else if (!isPrivacyClassification(item.privacy.classification)) {
286
+ errors.push("items[" + index + "].privacy.classification must be one of private, sanitized, public");
287
+ }
288
+ }
289
+ return { valid: errors.length === 0, errors, counts };
290
+ }
291
+
292
+ // src/shard/checksum.ts
293
+ async function sha256Hex(data) {
294
+ const buf = new ArrayBuffer(data.byteLength);
295
+ new Uint8Array(buf).set(data);
296
+ const hashBuffer = await crypto.subtle.digest("SHA-256", buf);
297
+ const hashArray = new Uint8Array(hashBuffer);
298
+ return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
299
+ }
300
+ async function validateChecksums(checksums, files) {
301
+ const failures = [];
302
+ for (const [filename, expectedHash] of Object.entries(checksums)) {
303
+ const fileData = files.get(filename);
304
+ if (!fileData) {
305
+ failures.push(filename);
306
+ continue;
307
+ }
308
+ const actualHash = await sha256Hex(fileData);
309
+ if (actualHash !== expectedHash) {
310
+ failures.push(filename);
311
+ }
312
+ }
313
+ return { valid: failures.length === 0, failures };
314
+ }
315
+
316
+ // schemas/knowledge-shard/1.0.0/core-v1/manifest.schema.json
317
+ var manifest_schema_default = {
318
+ $schema: "https://json-schema.org/draft/2020-12/schema",
319
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.0.0/core-v1/manifest.schema.json",
320
+ title: "Fortemi Knowledge Shard core-v1 manifest",
321
+ type: "object",
322
+ additionalProperties: false,
323
+ required: [
324
+ "version",
325
+ "profile",
326
+ "producer",
327
+ "format",
328
+ "created_at",
329
+ "components",
330
+ "counts",
331
+ "checksums",
332
+ "min_reader_version"
333
+ ],
334
+ properties: {
335
+ version: {
336
+ $ref: "#/$defs/strictSemVer"
337
+ },
338
+ profile: {
339
+ const: "core-v1"
340
+ },
341
+ producer: {
342
+ type: "object",
343
+ additionalProperties: false,
344
+ required: ["name", "version"],
345
+ properties: {
346
+ name: {
347
+ type: "string",
348
+ minLength: 1
349
+ },
350
+ version: {
351
+ type: "string",
352
+ minLength: 1
353
+ },
354
+ revision: {
355
+ type: "string",
356
+ minLength: 1
357
+ }
358
+ }
359
+ },
360
+ matric_version: {
361
+ type: "string",
362
+ minLength: 1,
363
+ deprecated: true
364
+ },
365
+ format: {
366
+ const: "matric-shard"
367
+ },
368
+ created_at: {
369
+ type: "string",
370
+ format: "date-time"
371
+ },
372
+ components: {
373
+ type: "array",
374
+ minItems: 1,
375
+ uniqueItems: true,
376
+ items: {
377
+ enum: ["notes", "collections", "tags", "templates", "links"]
378
+ }
379
+ },
380
+ counts: {
381
+ $ref: "#/$defs/counts"
382
+ },
383
+ checksums: {
384
+ type: "object",
385
+ propertyNames: {
386
+ enum: [
387
+ "notes.jsonl",
388
+ "collections.json",
389
+ "tags.json",
390
+ "templates.json",
391
+ "links.jsonl"
392
+ ]
393
+ },
394
+ additionalProperties: {
395
+ $ref: "#/$defs/sha256"
396
+ }
397
+ },
398
+ min_reader_version: {
399
+ $ref: "#/$defs/strictSemVer"
400
+ },
401
+ migrated_from: {
402
+ $ref: "#/$defs/strictSemVer"
403
+ },
404
+ migration_history: {
405
+ type: "array",
406
+ items: {
407
+ type: "object",
408
+ additionalProperties: false,
409
+ required: [
410
+ "from_version",
411
+ "to_version",
412
+ "migrated_at",
413
+ "migrated_by",
414
+ "changes"
415
+ ],
416
+ properties: {
417
+ from_version: {
418
+ $ref: "#/$defs/strictSemVer"
419
+ },
420
+ to_version: {
421
+ $ref: "#/$defs/strictSemVer"
422
+ },
423
+ migrated_at: {
424
+ type: "string",
425
+ format: "date-time"
426
+ },
427
+ migrated_by: {
428
+ type: "string",
429
+ minLength: 1
430
+ },
431
+ changes: {
432
+ type: "array",
433
+ minItems: 1,
434
+ items: {
435
+ type: "string",
436
+ minLength: 1
437
+ }
438
+ }
439
+ }
440
+ }
441
+ }
442
+ },
443
+ $defs: {
444
+ strictSemVer: {
445
+ type: "string",
446
+ pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
447
+ },
448
+ sha256: {
449
+ type: "string",
450
+ pattern: "^[0-9a-f]{64}$"
451
+ },
452
+ count: {
453
+ type: "integer",
454
+ minimum: 0
455
+ },
456
+ counts: {
457
+ type: "object",
458
+ additionalProperties: false,
459
+ required: [
460
+ "notes",
461
+ "collections",
462
+ "tags",
463
+ "templates",
464
+ "links",
465
+ "embedding_sets",
466
+ "embedding_set_members",
467
+ "embeddings",
468
+ "embedding_configs"
469
+ ],
470
+ properties: {
471
+ notes: {
472
+ $ref: "#/$defs/count"
473
+ },
474
+ collections: {
475
+ $ref: "#/$defs/count"
476
+ },
477
+ tags: {
478
+ $ref: "#/$defs/count"
479
+ },
480
+ templates: {
481
+ $ref: "#/$defs/count"
482
+ },
483
+ links: {
484
+ $ref: "#/$defs/count"
485
+ },
486
+ embedding_sets: {
487
+ const: 0
488
+ },
489
+ embedding_set_members: {
490
+ const: 0
491
+ },
492
+ embeddings: {
493
+ const: 0
494
+ },
495
+ embedding_configs: {
496
+ const: 0
497
+ }
498
+ }
499
+ }
500
+ }
501
+ };
502
+
503
+ // schemas/knowledge-shard/1.0.0/core-v1/note.schema.json
504
+ var note_schema_default = {
505
+ $schema: "https://json-schema.org/draft/2020-12/schema",
506
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.0.0/core-v1/note.schema.json",
507
+ title: "Fortemi Knowledge Shard core-v1 note record",
508
+ type: "object",
509
+ additionalProperties: false,
510
+ required: [
511
+ "id",
512
+ "title",
513
+ "original_content",
514
+ "revised_content",
515
+ "metadata",
516
+ "format",
517
+ "source",
518
+ "starred",
519
+ "archived",
520
+ "collection_id",
521
+ "created_at",
522
+ "updated_at",
523
+ "tags",
524
+ "attachments"
525
+ ],
526
+ properties: {
527
+ id: {
528
+ $ref: "#/$defs/uuid"
529
+ },
530
+ title: {
531
+ type: ["string", "null"]
532
+ },
533
+ original_content: {
534
+ type: "string"
535
+ },
536
+ revised_content: {
537
+ type: "string"
538
+ },
539
+ metadata: true,
540
+ format: {
541
+ type: "string",
542
+ minLength: 1
543
+ },
544
+ source: {
545
+ type: "string",
546
+ minLength: 1
547
+ },
548
+ starred: {
549
+ type: "boolean"
550
+ },
551
+ archived: {
552
+ type: "boolean"
553
+ },
554
+ collection_id: {
555
+ oneOf: [
556
+ {
557
+ $ref: "#/$defs/uuid"
558
+ },
559
+ {
560
+ type: "null"
561
+ }
562
+ ]
563
+ },
564
+ created_at: {
565
+ $ref: "#/$defs/dateTime"
566
+ },
567
+ updated_at: {
568
+ $ref: "#/$defs/dateTime"
569
+ },
570
+ tags: {
571
+ type: "array",
572
+ uniqueItems: true,
573
+ items: {
574
+ type: "string",
575
+ minLength: 1
576
+ }
577
+ },
578
+ attachments: {
579
+ type: "array",
580
+ items: {
581
+ $ref: "#/$defs/attachmentProjection"
582
+ }
583
+ }
584
+ },
585
+ $defs: {
586
+ uuid: {
587
+ type: "string",
588
+ format: "uuid"
589
+ },
590
+ dateTime: {
591
+ type: "string",
592
+ format: "date-time"
593
+ },
594
+ sha256: {
595
+ type: "string",
596
+ pattern: "^blake3:[0-9a-f]{64}$"
597
+ },
598
+ attachmentProjection: {
599
+ type: "object",
600
+ additionalProperties: false,
601
+ required: [
602
+ "extracted_text",
603
+ "extraction_status",
604
+ "reason",
605
+ "attachment"
606
+ ],
607
+ properties: {
608
+ extracted_text: {
609
+ type: ["string", "null"]
610
+ },
611
+ extraction_status: {
612
+ enum: ["extracted", "pending", "failed", "blocked", "deferred"]
613
+ },
614
+ reason: {
615
+ enum: [
616
+ null,
617
+ "extraction_pending",
618
+ "extractor_failed",
619
+ "quarantined",
620
+ "large_binary",
621
+ "unsupported_mime",
622
+ "no_extracted_text"
623
+ ]
624
+ },
625
+ attachment: {
626
+ type: "object",
627
+ additionalProperties: false,
628
+ required: ["id", "path", "mime", "checksum", "bytes"],
629
+ properties: {
630
+ id: {
631
+ $ref: "#/$defs/uuid"
632
+ },
633
+ path: {
634
+ type: "string",
635
+ minLength: 1
636
+ },
637
+ mime: {
638
+ type: "string",
639
+ minLength: 1
640
+ },
641
+ checksum: {
642
+ $ref: "#/$defs/sha256"
643
+ },
644
+ bytes: {
645
+ type: "integer",
646
+ minimum: 0
647
+ }
648
+ }
649
+ }
650
+ }
651
+ }
652
+ }
653
+ };
654
+
655
+ // schemas/knowledge-shard/1.0.0/core-v1/collection.schema.json
656
+ var collection_schema_default = {
657
+ $schema: "https://json-schema.org/draft/2020-12/schema",
658
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.0.0/core-v1/collection.schema.json",
659
+ title: "Fortemi Knowledge Shard core-v1 collection record",
660
+ type: "object",
661
+ additionalProperties: false,
662
+ required: ["id", "name", "description", "parent_id", "created_at", "note_count"],
663
+ properties: {
664
+ id: {
665
+ $ref: "#/$defs/uuid"
666
+ },
667
+ name: {
668
+ type: "string",
669
+ minLength: 1
670
+ },
671
+ description: {
672
+ type: ["string", "null"]
673
+ },
674
+ parent_id: {
675
+ oneOf: [
676
+ {
677
+ $ref: "#/$defs/uuid"
678
+ },
679
+ {
680
+ type: "null"
681
+ }
682
+ ]
683
+ },
684
+ created_at: {
685
+ type: "string",
686
+ format: "date-time"
687
+ },
688
+ note_count: {
689
+ type: "integer",
690
+ minimum: 0
691
+ }
692
+ },
693
+ $defs: {
694
+ uuid: {
695
+ type: "string",
696
+ format: "uuid"
697
+ }
698
+ }
699
+ };
700
+
701
+ // schemas/knowledge-shard/1.0.0/core-v1/tag.schema.json
702
+ var tag_schema_default = {
703
+ $schema: "https://json-schema.org/draft/2020-12/schema",
704
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.0.0/core-v1/tag.schema.json",
705
+ title: "Fortemi Knowledge Shard core-v1 tag record",
706
+ type: "object",
707
+ additionalProperties: false,
708
+ required: ["name", "created_at"],
709
+ properties: {
710
+ name: {
711
+ type: "string",
712
+ minLength: 1
713
+ },
714
+ created_at: {
715
+ type: "string",
716
+ format: "date-time"
717
+ }
718
+ }
719
+ };
720
+
721
+ // schemas/knowledge-shard/1.0.0/core-v1/template.schema.json
722
+ var template_schema_default = {
723
+ $schema: "https://json-schema.org/draft/2020-12/schema",
724
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.0.0/core-v1/template.schema.json",
725
+ title: "Fortemi Knowledge Shard core-v1 template record",
726
+ type: "object",
727
+ additionalProperties: false,
728
+ required: [
729
+ "id",
730
+ "name",
731
+ "description",
732
+ "content",
733
+ "format",
734
+ "default_tags",
735
+ "collection_id",
736
+ "created_at",
737
+ "updated_at"
738
+ ],
739
+ properties: {
740
+ id: {
741
+ $ref: "#/$defs/uuid"
742
+ },
743
+ name: {
744
+ type: "string",
745
+ minLength: 1
746
+ },
747
+ description: {
748
+ type: ["string", "null"]
749
+ },
750
+ content: {
751
+ type: "string"
752
+ },
753
+ format: {
754
+ type: "string",
755
+ minLength: 1
756
+ },
757
+ default_tags: {
758
+ type: "array",
759
+ uniqueItems: true,
760
+ items: {
761
+ type: "string",
762
+ minLength: 1
763
+ }
764
+ },
765
+ collection_id: {
766
+ oneOf: [
767
+ {
768
+ $ref: "#/$defs/uuid"
769
+ },
770
+ {
771
+ type: "null"
772
+ }
773
+ ]
774
+ },
775
+ created_at: {
776
+ type: "string",
777
+ format: "date-time"
778
+ },
779
+ updated_at: {
780
+ type: "string",
781
+ format: "date-time"
782
+ }
783
+ },
784
+ $defs: {
785
+ uuid: {
786
+ type: "string",
787
+ format: "uuid"
788
+ }
789
+ }
790
+ };
791
+
792
+ // schemas/knowledge-shard/1.0.0/core-v1/link.schema.json
793
+ var link_schema_default = {
794
+ $schema: "https://json-schema.org/draft/2020-12/schema",
795
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.0.0/core-v1/link.schema.json",
796
+ title: "Fortemi Knowledge Shard core-v1 link record",
797
+ type: "object",
798
+ additionalProperties: false,
799
+ required: [
800
+ "id",
801
+ "from_note_id",
802
+ "to_note_id",
803
+ "to_url",
804
+ "kind",
805
+ "score",
806
+ "created_at",
807
+ "metadata"
808
+ ],
809
+ properties: {
810
+ id: {
811
+ $ref: "#/$defs/uuid"
812
+ },
813
+ from_note_id: {
814
+ $ref: "#/$defs/uuid"
815
+ },
816
+ to_note_id: {
817
+ oneOf: [
818
+ {
819
+ $ref: "#/$defs/uuid"
820
+ },
821
+ {
822
+ type: "null"
823
+ }
824
+ ]
825
+ },
826
+ to_url: {
827
+ type: ["string", "null"],
828
+ format: "uri"
829
+ },
830
+ kind: {
831
+ type: "string",
832
+ minLength: 1
833
+ },
834
+ score: {
835
+ type: "number"
836
+ },
837
+ created_at: {
838
+ type: "string",
839
+ format: "date-time"
840
+ },
841
+ metadata: true
842
+ },
843
+ oneOf: [
844
+ {
845
+ properties: {
846
+ to_note_id: {
847
+ $ref: "#/$defs/uuid"
848
+ },
849
+ to_url: {
850
+ type: "null"
851
+ }
852
+ }
853
+ },
854
+ {
855
+ properties: {
856
+ to_note_id: {
857
+ type: "null"
858
+ },
859
+ to_url: {
860
+ type: "string",
861
+ format: "uri"
862
+ }
863
+ }
864
+ }
865
+ ],
866
+ $defs: {
867
+ uuid: {
868
+ type: "string",
869
+ format: "uuid"
870
+ }
871
+ }
872
+ };
873
+
874
+ // schemas/knowledge-shard/1.1.0/core-v1/manifest.schema.json
875
+ var manifest_schema_default2 = {
876
+ $schema: "https://json-schema.org/draft/2020-12/schema",
877
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.1.0/core-v1/manifest.schema.json",
878
+ title: "Fortemi Knowledge Shard core-v1 manifest",
879
+ type: "object",
880
+ additionalProperties: false,
881
+ required: [
882
+ "version",
883
+ "profile",
884
+ "producer",
885
+ "format",
886
+ "created_at",
887
+ "components",
888
+ "counts",
889
+ "checksums",
890
+ "min_reader_version"
891
+ ],
892
+ properties: {
893
+ version: {
894
+ const: "1.1.0"
895
+ },
896
+ profile: {
897
+ const: "core-v1"
898
+ },
899
+ producer: {
900
+ type: "object",
901
+ additionalProperties: false,
902
+ required: ["name", "version"],
903
+ properties: {
904
+ name: {
905
+ type: "string",
906
+ minLength: 1
907
+ },
908
+ version: {
909
+ type: "string",
910
+ minLength: 1
911
+ },
912
+ revision: {
913
+ type: "string",
914
+ minLength: 1
915
+ }
916
+ }
917
+ },
918
+ matric_version: {
919
+ type: "string",
920
+ minLength: 1,
921
+ deprecated: true
922
+ },
923
+ format: {
924
+ const: "matric-shard"
925
+ },
926
+ created_at: {
927
+ type: "string",
928
+ format: "date-time"
929
+ },
930
+ components: {
931
+ type: "array",
932
+ minItems: 1,
933
+ uniqueItems: true,
934
+ items: {
935
+ enum: ["notes", "collections", "tags", "templates", "links"]
936
+ }
937
+ },
938
+ counts: {
939
+ $ref: "#/$defs/counts"
940
+ },
941
+ checksums: {
942
+ type: "object",
943
+ propertyNames: {
944
+ enum: [
945
+ "notes.jsonl",
946
+ "collections.json",
947
+ "tags.json",
948
+ "templates.json",
949
+ "links.jsonl"
950
+ ]
951
+ },
952
+ additionalProperties: {
953
+ $ref: "#/$defs/sha256"
954
+ }
955
+ },
956
+ min_reader_version: {
957
+ const: "1.1.0"
958
+ },
959
+ migrated_from: {
960
+ $ref: "#/$defs/strictSemVer"
961
+ },
962
+ migration_history: {
963
+ type: "array",
964
+ items: {
965
+ type: "object",
966
+ additionalProperties: false,
967
+ required: [
968
+ "from_version",
969
+ "to_version",
970
+ "migrated_at",
971
+ "migrated_by",
972
+ "changes"
973
+ ],
974
+ properties: {
975
+ from_version: {
976
+ $ref: "#/$defs/strictSemVer"
977
+ },
978
+ to_version: {
979
+ $ref: "#/$defs/strictSemVer"
980
+ },
981
+ migrated_at: {
982
+ type: "string",
983
+ format: "date-time"
984
+ },
985
+ migrated_by: {
986
+ type: "string",
987
+ minLength: 1
988
+ },
989
+ changes: {
990
+ type: "array",
991
+ minItems: 1,
992
+ items: {
993
+ type: "string",
994
+ minLength: 1
995
+ }
996
+ }
997
+ }
998
+ }
999
+ }
1000
+ },
1001
+ $defs: {
1002
+ strictSemVer: {
1003
+ type: "string",
1004
+ pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
1005
+ },
1006
+ sha256: {
1007
+ type: "string",
1008
+ pattern: "^[0-9a-f]{64}$"
1009
+ },
1010
+ count: {
1011
+ type: "integer",
1012
+ minimum: 0
1013
+ },
1014
+ counts: {
1015
+ type: "object",
1016
+ additionalProperties: false,
1017
+ required: [
1018
+ "notes",
1019
+ "collections",
1020
+ "tags",
1021
+ "templates",
1022
+ "links",
1023
+ "embedding_sets",
1024
+ "embedding_set_members",
1025
+ "embeddings",
1026
+ "embedding_configs"
1027
+ ],
1028
+ properties: {
1029
+ notes: {
1030
+ $ref: "#/$defs/count"
1031
+ },
1032
+ collections: {
1033
+ $ref: "#/$defs/count"
1034
+ },
1035
+ tags: {
1036
+ $ref: "#/$defs/count"
1037
+ },
1038
+ templates: {
1039
+ $ref: "#/$defs/count"
1040
+ },
1041
+ links: {
1042
+ $ref: "#/$defs/count"
1043
+ },
1044
+ embedding_sets: {
1045
+ const: 0
1046
+ },
1047
+ embedding_set_members: {
1048
+ const: 0
1049
+ },
1050
+ embeddings: {
1051
+ const: 0
1052
+ },
1053
+ embedding_configs: {
1054
+ const: 0
1055
+ }
1056
+ }
1057
+ }
1058
+ }
1059
+ };
1060
+
1061
+ // schemas/knowledge-shard/1.2.0/core-v1/manifest.schema.json
1062
+ var manifest_schema_default5 = {
1063
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1064
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.2.0/core-v1/manifest.schema.json",
1065
+ title: "Fortemi Knowledge Shard core-v1 manifest",
1066
+ type: "object",
1067
+ additionalProperties: false,
1068
+ required: [
1069
+ "version",
1070
+ "profile",
1071
+ "producer",
1072
+ "format",
1073
+ "created_at",
1074
+ "components",
1075
+ "counts",
1076
+ "checksums",
1077
+ "min_reader_version"
1078
+ ],
1079
+ properties: {
1080
+ version: {
1081
+ const: "1.2.0"
1082
+ },
1083
+ profile: {
1084
+ const: "core-v1"
1085
+ },
1086
+ producer: {
1087
+ type: "object",
1088
+ additionalProperties: false,
1089
+ required: ["name", "version"],
1090
+ properties: {
1091
+ name: {
1092
+ type: "string",
1093
+ minLength: 1
1094
+ },
1095
+ version: {
1096
+ type: "string",
1097
+ minLength: 1
1098
+ },
1099
+ revision: {
1100
+ type: "string",
1101
+ minLength: 1
1102
+ }
1103
+ }
1104
+ },
1105
+ matric_version: {
1106
+ type: "string",
1107
+ minLength: 1,
1108
+ deprecated: true
1109
+ },
1110
+ format: {
1111
+ const: "matric-shard"
1112
+ },
1113
+ created_at: {
1114
+ type: "string",
1115
+ format: "date-time"
1116
+ },
1117
+ components: {
1118
+ type: "array",
1119
+ minItems: 1,
1120
+ uniqueItems: true,
1121
+ items: {
1122
+ enum: ["notes", "collections", "tags", "templates", "links"]
1123
+ }
1124
+ },
1125
+ counts: {
1126
+ $ref: "#/$defs/counts"
1127
+ },
1128
+ checksums: {
1129
+ type: "object",
1130
+ propertyNames: {
1131
+ enum: [
1132
+ "notes.jsonl",
1133
+ "collections.json",
1134
+ "tags.json",
1135
+ "templates.json",
1136
+ "links.jsonl"
1137
+ ]
1138
+ },
1139
+ additionalProperties: {
1140
+ $ref: "#/$defs/sha256"
1141
+ }
1142
+ },
1143
+ min_reader_version: {
1144
+ const: "1.2.0"
1145
+ },
1146
+ migrated_from: {
1147
+ $ref: "#/$defs/strictSemVer"
1148
+ },
1149
+ migration_history: {
1150
+ type: "array",
1151
+ items: {
1152
+ type: "object",
1153
+ additionalProperties: false,
1154
+ required: [
1155
+ "from_version",
1156
+ "to_version",
1157
+ "migrated_at",
1158
+ "migrated_by",
1159
+ "changes"
1160
+ ],
1161
+ properties: {
1162
+ from_version: {
1163
+ $ref: "#/$defs/strictSemVer"
1164
+ },
1165
+ to_version: {
1166
+ $ref: "#/$defs/strictSemVer"
1167
+ },
1168
+ migrated_at: {
1169
+ type: "string",
1170
+ format: "date-time"
1171
+ },
1172
+ migrated_by: {
1173
+ type: "string",
1174
+ minLength: 1
1175
+ },
1176
+ changes: {
1177
+ type: "array",
1178
+ minItems: 1,
1179
+ items: {
1180
+ type: "string",
1181
+ minLength: 1
1182
+ }
1183
+ }
1184
+ }
1185
+ }
1186
+ }
1187
+ },
1188
+ $defs: {
1189
+ strictSemVer: {
1190
+ type: "string",
1191
+ pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
1192
+ },
1193
+ sha256: {
1194
+ type: "string",
1195
+ pattern: "^[0-9a-f]{64}$"
1196
+ },
1197
+ count: {
1198
+ type: "integer",
1199
+ minimum: 0
1200
+ },
1201
+ counts: {
1202
+ type: "object",
1203
+ additionalProperties: false,
1204
+ required: [
1205
+ "notes",
1206
+ "collections",
1207
+ "tags",
1208
+ "templates",
1209
+ "links",
1210
+ "embedding_sets",
1211
+ "embedding_set_members",
1212
+ "embeddings",
1213
+ "embedding_configs"
1214
+ ],
1215
+ properties: {
1216
+ notes: {
1217
+ $ref: "#/$defs/count"
1218
+ },
1219
+ collections: {
1220
+ $ref: "#/$defs/count"
1221
+ },
1222
+ tags: {
1223
+ $ref: "#/$defs/count"
1224
+ },
1225
+ templates: {
1226
+ $ref: "#/$defs/count"
1227
+ },
1228
+ links: {
1229
+ $ref: "#/$defs/count"
1230
+ },
1231
+ embedding_sets: {
1232
+ const: 0
1233
+ },
1234
+ embedding_set_members: {
1235
+ const: 0
1236
+ },
1237
+ embeddings: {
1238
+ const: 0
1239
+ },
1240
+ embedding_configs: {
1241
+ const: 0
1242
+ }
1243
+ }
1244
+ }
1245
+ }
1246
+ };
1247
+
1248
+ // schemas/knowledge-shard/1.2.0/core-v1/note.schema.json
1249
+ var note_schema_default2 = {
1250
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1251
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.2.0/core-v1/note.schema.json",
1252
+ title: "Fortemi Knowledge Shard core-v1 note record",
1253
+ type: "object",
1254
+ additionalProperties: false,
1255
+ required: [
1256
+ "id",
1257
+ "title",
1258
+ "original_content",
1259
+ "revised_content",
1260
+ "metadata",
1261
+ "format",
1262
+ "source",
1263
+ "starred",
1264
+ "archived",
1265
+ "collection_id",
1266
+ "created_at",
1267
+ "updated_at",
1268
+ "tags",
1269
+ "attachments"
1270
+ ],
1271
+ properties: {
1272
+ id: {
1273
+ $ref: "#/$defs/uuid"
1274
+ },
1275
+ title: {
1276
+ type: ["string", "null"]
1277
+ },
1278
+ original_content: {
1279
+ type: "string"
1280
+ },
1281
+ revised_content: {
1282
+ type: "string"
1283
+ },
1284
+ metadata: true,
1285
+ format: {
1286
+ type: "string",
1287
+ minLength: 1
1288
+ },
1289
+ source: {
1290
+ type: "string",
1291
+ minLength: 1
1292
+ },
1293
+ starred: {
1294
+ type: "boolean"
1295
+ },
1296
+ archived: {
1297
+ type: "boolean"
1298
+ },
1299
+ collection_id: {
1300
+ oneOf: [
1301
+ {
1302
+ $ref: "#/$defs/uuid"
1303
+ },
1304
+ {
1305
+ type: "null"
1306
+ }
1307
+ ]
1308
+ },
1309
+ created_at: {
1310
+ $ref: "#/$defs/dateTime"
1311
+ },
1312
+ updated_at: {
1313
+ $ref: "#/$defs/dateTime"
1314
+ },
1315
+ deleted_at: {
1316
+ oneOf: [
1317
+ {
1318
+ $ref: "#/$defs/dateTime"
1319
+ },
1320
+ {
1321
+ type: "null"
1322
+ }
1323
+ ],
1324
+ default: null
1325
+ },
1326
+ tags: {
1327
+ type: "array",
1328
+ uniqueItems: true,
1329
+ items: {
1330
+ type: "string",
1331
+ minLength: 1
1332
+ }
1333
+ },
1334
+ attachments: {
1335
+ type: "array",
1336
+ items: {
1337
+ $ref: "#/$defs/attachmentProjection"
1338
+ }
1339
+ }
1340
+ },
1341
+ $defs: {
1342
+ uuid: {
1343
+ type: "string",
1344
+ format: "uuid"
1345
+ },
1346
+ dateTime: {
1347
+ type: "string",
1348
+ format: "date-time"
1349
+ },
1350
+ sha256: {
1351
+ type: "string",
1352
+ pattern: "^blake3:[0-9a-f]{64}$"
1353
+ },
1354
+ attachmentProjection: {
1355
+ type: "object",
1356
+ additionalProperties: false,
1357
+ required: [
1358
+ "extracted_text",
1359
+ "extraction_status",
1360
+ "reason",
1361
+ "attachment"
1362
+ ],
1363
+ properties: {
1364
+ extracted_text: {
1365
+ type: ["string", "null"]
1366
+ },
1367
+ extraction_status: {
1368
+ enum: ["extracted", "pending", "failed", "blocked", "deferred"]
1369
+ },
1370
+ reason: {
1371
+ enum: [
1372
+ null,
1373
+ "extraction_pending",
1374
+ "extractor_failed",
1375
+ "quarantined",
1376
+ "large_binary",
1377
+ "unsupported_mime",
1378
+ "no_extracted_text"
1379
+ ]
1380
+ },
1381
+ attachment: {
1382
+ type: "object",
1383
+ additionalProperties: false,
1384
+ required: ["id", "path", "mime", "checksum", "bytes"],
1385
+ properties: {
1386
+ id: {
1387
+ $ref: "#/$defs/uuid"
1388
+ },
1389
+ path: {
1390
+ type: "string",
1391
+ minLength: 1
1392
+ },
1393
+ mime: {
1394
+ type: "string",
1395
+ minLength: 1
1396
+ },
1397
+ checksum: {
1398
+ $ref: "#/$defs/sha256"
1399
+ },
1400
+ bytes: {
1401
+ type: "integer",
1402
+ minimum: 0
1403
+ }
1404
+ }
1405
+ }
1406
+ }
1407
+ }
1408
+ }
1409
+ };
1410
+
1411
+ // schemas/knowledge-shard/1.2.0/core-v1/collection.schema.json
1412
+ var collection_schema_default2 = {
1413
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1414
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.2.0/core-v1/collection.schema.json",
1415
+ title: "Fortemi Knowledge Shard core-v1 collection record",
1416
+ type: "object",
1417
+ additionalProperties: false,
1418
+ required: ["id", "name", "description", "parent_id", "created_at", "note_count"],
1419
+ properties: {
1420
+ id: {
1421
+ $ref: "#/$defs/uuid"
1422
+ },
1423
+ name: {
1424
+ type: "string",
1425
+ minLength: 1
1426
+ },
1427
+ description: {
1428
+ type: ["string", "null"]
1429
+ },
1430
+ parent_id: {
1431
+ oneOf: [
1432
+ {
1433
+ $ref: "#/$defs/uuid"
1434
+ },
1435
+ {
1436
+ type: "null"
1437
+ }
1438
+ ]
1439
+ },
1440
+ created_at: {
1441
+ type: "string",
1442
+ format: "date-time"
1443
+ },
1444
+ note_count: {
1445
+ type: "integer",
1446
+ minimum: 0
1447
+ }
1448
+ },
1449
+ $defs: {
1450
+ uuid: {
1451
+ type: "string",
1452
+ format: "uuid"
1453
+ }
1454
+ }
1455
+ };
1456
+
1457
+ // schemas/knowledge-shard/1.2.0/core-v1/tag.schema.json
1458
+ var tag_schema_default2 = {
1459
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1460
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.2.0/core-v1/tag.schema.json",
1461
+ title: "Fortemi Knowledge Shard core-v1 tag record",
1462
+ type: "object",
1463
+ additionalProperties: false,
1464
+ required: ["name", "created_at"],
1465
+ properties: {
1466
+ name: {
1467
+ type: "string",
1468
+ minLength: 1
1469
+ },
1470
+ created_at: {
1471
+ type: "string",
1472
+ format: "date-time"
1473
+ }
1474
+ }
1475
+ };
1476
+
1477
+ // schemas/knowledge-shard/1.2.0/core-v1/template.schema.json
1478
+ var template_schema_default2 = {
1479
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1480
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.2.0/core-v1/template.schema.json",
1481
+ title: "Fortemi Knowledge Shard core-v1 template record",
1482
+ type: "object",
1483
+ additionalProperties: false,
1484
+ required: [
1485
+ "id",
1486
+ "name",
1487
+ "description",
1488
+ "content",
1489
+ "format",
1490
+ "default_tags",
1491
+ "collection_id",
1492
+ "created_at",
1493
+ "updated_at"
1494
+ ],
1495
+ properties: {
1496
+ id: {
1497
+ $ref: "#/$defs/uuid"
1498
+ },
1499
+ name: {
1500
+ type: "string",
1501
+ minLength: 1
1502
+ },
1503
+ description: {
1504
+ type: ["string", "null"]
1505
+ },
1506
+ content: {
1507
+ type: "string"
1508
+ },
1509
+ format: {
1510
+ type: "string",
1511
+ minLength: 1
1512
+ },
1513
+ default_tags: {
1514
+ type: "array",
1515
+ uniqueItems: true,
1516
+ items: {
1517
+ type: "string",
1518
+ minLength: 1
1519
+ }
1520
+ },
1521
+ collection_id: {
1522
+ oneOf: [
1523
+ {
1524
+ $ref: "#/$defs/uuid"
1525
+ },
1526
+ {
1527
+ type: "null"
1528
+ }
1529
+ ]
1530
+ },
1531
+ created_at: {
1532
+ type: "string",
1533
+ format: "date-time"
1534
+ },
1535
+ updated_at: {
1536
+ type: "string",
1537
+ format: "date-time"
1538
+ }
1539
+ },
1540
+ $defs: {
1541
+ uuid: {
1542
+ type: "string",
1543
+ format: "uuid"
1544
+ }
1545
+ }
1546
+ };
1547
+
1548
+ // schemas/knowledge-shard/1.2.0/core-v1/link.schema.json
1549
+ var link_schema_default2 = {
1550
+ $schema: "https://json-schema.org/draft/2020-12/schema",
1551
+ $id: "https://schemas.fortemi.dev/knowledge-shard/1.2.0/core-v1/link.schema.json",
1552
+ title: "Fortemi Knowledge Shard core-v1 link record",
1553
+ type: "object",
1554
+ additionalProperties: false,
1555
+ required: [
1556
+ "id",
1557
+ "from_note_id",
1558
+ "to_note_id",
1559
+ "to_url",
1560
+ "kind",
1561
+ "score",
1562
+ "created_at",
1563
+ "metadata"
1564
+ ],
1565
+ properties: {
1566
+ id: {
1567
+ $ref: "#/$defs/uuid"
1568
+ },
1569
+ from_note_id: {
1570
+ $ref: "#/$defs/uuid"
1571
+ },
1572
+ to_note_id: {
1573
+ oneOf: [
1574
+ {
1575
+ $ref: "#/$defs/uuid"
1576
+ },
1577
+ {
1578
+ type: "null"
1579
+ }
1580
+ ]
1581
+ },
1582
+ to_url: {
1583
+ type: ["string", "null"],
1584
+ format: "uri"
1585
+ },
1586
+ kind: {
1587
+ type: "string",
1588
+ minLength: 1
1589
+ },
1590
+ score: {
1591
+ type: "number"
1592
+ },
1593
+ created_at: {
1594
+ type: "string",
1595
+ format: "date-time"
1596
+ },
1597
+ metadata: true
1598
+ },
1599
+ oneOf: [
1600
+ {
1601
+ properties: {
1602
+ to_note_id: {
1603
+ $ref: "#/$defs/uuid"
1604
+ },
1605
+ to_url: {
1606
+ type: "null"
1607
+ }
1608
+ }
1609
+ },
1610
+ {
1611
+ properties: {
1612
+ to_note_id: {
1613
+ type: "null"
1614
+ },
1615
+ to_url: {
1616
+ type: "string",
1617
+ format: "uri"
1618
+ }
1619
+ }
1620
+ }
1621
+ ],
1622
+ $defs: {
1623
+ uuid: {
1624
+ type: "string",
1625
+ format: "uuid"
1626
+ }
1627
+ }
1628
+ };
1629
+ var BLOCK_SIZE = 512;
1630
+ var USTAR_MAGIC = "ustar\x0000";
1631
+ function writeString(buf, offset, str, len) {
1632
+ for (let i = 0; i < Math.min(str.length, len); i++) {
1633
+ buf[offset + i] = str.charCodeAt(i);
1634
+ }
1635
+ }
1636
+ function writeOctal(buf, offset, value, len) {
1637
+ const str = value.toString(8).padStart(len - 1, "0");
1638
+ writeString(buf, offset, str, len - 1);
1639
+ }
1640
+ function computeHeaderChecksum(header) {
1641
+ let sum = 0;
1642
+ for (let i = 0; i < BLOCK_SIZE; i++) {
1643
+ sum += i >= 148 && i < 156 ? 32 : header[i];
1644
+ }
1645
+ return sum;
1646
+ }
1647
+ function createTarHeader(filename, size) {
1648
+ const header = new Uint8Array(BLOCK_SIZE);
1649
+ writeString(header, 0, filename, 100);
1650
+ writeOctal(header, 100, 420, 8);
1651
+ writeOctal(header, 108, 0, 8);
1652
+ writeOctal(header, 116, 0, 8);
1653
+ writeOctal(header, 124, size, 12);
1654
+ writeOctal(header, 136, 0, 12);
1655
+ header[156] = 48;
1656
+ writeString(header, 257, USTAR_MAGIC, 8);
1657
+ const checksum = computeHeaderChecksum(header);
1658
+ const csStr = checksum.toString(8).padStart(6, "0");
1659
+ writeString(header, 148, csStr, 6);
1660
+ header[154] = 0;
1661
+ header[155] = 32;
1662
+ return header;
1663
+ }
1664
+ function encodeTar(files) {
1665
+ const blocks = [];
1666
+ for (const [filename, data] of files) {
1667
+ blocks.push(createTarHeader(filename, data.byteLength));
1668
+ blocks.push(data);
1669
+ const remainder = data.byteLength % BLOCK_SIZE;
1670
+ if (remainder > 0) {
1671
+ blocks.push(new Uint8Array(BLOCK_SIZE - remainder));
1672
+ }
1673
+ }
1674
+ blocks.push(new Uint8Array(BLOCK_SIZE * 2));
1675
+ let totalLen = 0;
1676
+ for (const b of blocks) totalLen += b.byteLength;
1677
+ const result = new Uint8Array(totalLen);
1678
+ let offset = 0;
1679
+ for (const b of blocks) {
1680
+ result.set(b, offset);
1681
+ offset += b.byteLength;
1682
+ }
1683
+ return result;
1684
+ }
1685
+ function readString(buf, offset, len) {
1686
+ let end = offset;
1687
+ const limit = offset + len;
1688
+ while (end < limit && buf[end] !== 0) end++;
1689
+ return String.fromCharCode(...buf.slice(offset, end));
1690
+ }
1691
+ function readOctal(buf, offset, len) {
1692
+ const str = readString(buf, offset, len).trim();
1693
+ return str.length > 0 ? parseInt(str, 8) : 0;
1694
+ }
1695
+ function isZeroBlock(buf, offset) {
1696
+ for (let i = 0; i < BLOCK_SIZE; i++) {
1697
+ if (buf[offset + i] !== 0) return false;
1698
+ }
1699
+ return true;
1700
+ }
1701
+ function decodeTar(tarData) {
1702
+ const files = /* @__PURE__ */ new Map();
1703
+ let offset = 0;
1704
+ while (offset + BLOCK_SIZE <= tarData.byteLength) {
1705
+ if (isZeroBlock(tarData, offset)) break;
1706
+ const name = readString(tarData, offset, 100);
1707
+ const size = readOctal(tarData, offset + 124, 12);
1708
+ const typeflag = tarData[offset + 156];
1709
+ offset += BLOCK_SIZE;
1710
+ if (typeflag === 48 || typeflag === 0) {
1711
+ files.set(name, tarData.slice(offset, offset + size));
1712
+ }
1713
+ const dataBlocks = Math.ceil(size / BLOCK_SIZE);
1714
+ offset += dataBlocks * BLOCK_SIZE;
1715
+ }
1716
+ return files;
1717
+ }
1718
+ function packTarGz(files, opts) {
1719
+ const tarData = encodeTar(files);
1720
+ const cap = DEFAULT_MAX_DECOMPRESSED_BYTES;
1721
+ if (tarData.byteLength > cap) {
1722
+ throw new Error(
1723
+ "Refusing to create archive: uncompressed size " + tarData.byteLength + " exceeds cap " + cap + " bytes"
1724
+ );
1725
+ }
1726
+ return gzipSync(tarData, { mtime: 0 });
1727
+ }
1728
+ var DEFAULT_MAX_DECOMPRESSED_BYTES = 256 * 1024 * 1024;
1729
+ function unpackTarGz(data, opts) {
1730
+ const cap = DEFAULT_MAX_DECOMPRESSED_BYTES;
1731
+ if (data.byteLength < 18) {
1732
+ throw new Error("Invalid gzip archive: too short");
1733
+ }
1734
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
1735
+ const declaredSize = view.getUint32(data.byteLength - 4, true);
1736
+ if (declaredSize > cap) {
1737
+ throw new Error(
1738
+ "Refusing to decompress archive: declared size " + declaredSize + " exceeds cap " + cap + " bytes"
1739
+ );
1740
+ }
1741
+ const tarData = gunzipSync(data);
1742
+ if (tarData.byteLength > cap) {
1743
+ throw new Error(
1744
+ "Refusing to decompress archive: decompressed size " + tarData.byteLength + " exceeds cap " + cap + " bytes"
1745
+ );
1746
+ }
1747
+ return decodeTar(tarData);
1748
+ }
1749
+
1750
+ // src/shard/types.ts
1751
+ var CURRENT_SHARD_VERSION = "1.2.0";
1752
+ var SHARD_FORMAT = "matric-shard";
1753
+
1754
+ // src/shard/schema-validator.ts
1755
+ var decoder = new TextDecoder();
1756
+ var CORE_V1_COMPONENT_FILES = {
1757
+ notes: { file: "notes.jsonl", encoding: "jsonl" },
1758
+ collections: { file: "collections.json", encoding: "json-array" },
1759
+ tags: { file: "tags.json", encoding: "json-array" },
1760
+ templates: { file: "templates.json", encoding: "json-array" },
1761
+ links: { file: "links.jsonl", encoding: "jsonl" }
1762
+ };
1763
+ var CORE_V1_SCHEMAS = {
1764
+ "1.0.0": {
1765
+ manifest: manifest_schema_default,
1766
+ notes: note_schema_default,
1767
+ collections: collection_schema_default,
1768
+ tags: tag_schema_default,
1769
+ templates: template_schema_default,
1770
+ links: link_schema_default
1771
+ },
1772
+ "1.1.0": {
1773
+ manifest: manifest_schema_default2,
1774
+ notes: note_schema_default2,
1775
+ collections: collection_schema_default2,
1776
+ tags: tag_schema_default2,
1777
+ templates: template_schema_default2,
1778
+ links: link_schema_default2
1779
+ },
1780
+ "1.2.0": {
1781
+ manifest: manifest_schema_default5,
1782
+ notes: note_schema_default2,
1783
+ collections: collection_schema_default2,
1784
+ tags: tag_schema_default2,
1785
+ templates: template_schema_default2,
1786
+ links: link_schema_default2
1787
+ }
1788
+ };
1789
+ var coreAjvInstance;
1790
+ var coreValidators = /* @__PURE__ */ new Map();
1791
+ function addCanonicalFormats(ajv) {
1792
+ ajv.addFormat("uuid", /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
1793
+ ajv.addFormat("date-time", {
1794
+ type: "string",
1795
+ validate: (value) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && !Number.isNaN(Date.parse(value))
1796
+ });
1797
+ ajv.addFormat("uri", {
1798
+ type: "string",
1799
+ validate: (value) => {
1800
+ try {
1801
+ return Boolean(new URL(value).protocol);
1802
+ } catch {
1803
+ return false;
1804
+ }
1805
+ }
1806
+ });
1807
+ }
1808
+ function getCoreAjv() {
1809
+ if (!coreAjvInstance) {
1810
+ coreAjvInstance = new Ajv2020({
1811
+ allErrors: true,
1812
+ strict: true,
1813
+ validateFormats: true
1814
+ });
1815
+ addCanonicalFormats(coreAjvInstance);
1816
+ const registered = /* @__PURE__ */ new Set();
1817
+ for (const bundle of Object.values(CORE_V1_SCHEMAS)) {
1818
+ for (const schema of Object.values(bundle)) {
1819
+ if (!registered.has(schema.$id)) {
1820
+ coreAjvInstance.addSchema(schema);
1821
+ registered.add(schema.$id);
1822
+ }
1823
+ }
1824
+ }
1825
+ }
1826
+ return coreAjvInstance;
1827
+ }
1828
+ function coreSchemaVersion(value) {
1829
+ return value === "1.0.0" || value === "1.1.0" || value === "1.2.0" ? value : void 0;
1830
+ }
1831
+ function coreValidatorFor(name, version = CURRENT_SHARD_VERSION) {
1832
+ const key = `${version}:${name}`;
1833
+ const cached = coreValidators.get(key);
1834
+ if (cached) return cached;
1835
+ const schema = CORE_V1_SCHEMAS[version][name];
1836
+ const validator = getCoreAjv().getSchema(schema.$id) ?? getCoreAjv().compile(schema);
1837
+ coreValidators.set(key, validator);
1838
+ return validator;
1839
+ }
1840
+ function formatErrors(errors) {
1841
+ return (errors ?? []).map((error) => {
1842
+ const path = error.instancePath || "(root)";
1843
+ return `${path} ${error.message ?? "is invalid"}`;
1844
+ });
1845
+ }
1846
+ function parseJsonArray(bytes, path) {
1847
+ if (!bytes) return { records: [], errors: [] };
1848
+ try {
1849
+ const value = JSON.parse(decoder.decode(bytes));
1850
+ if (!Array.isArray(value)) return { records: [], errors: [`${path} must be a JSON array`] };
1851
+ return { records: value, errors: [] };
1852
+ } catch {
1853
+ return { records: [], errors: [`${path} failed to parse as JSON`] };
1854
+ }
1855
+ }
1856
+ function parseJsonl(bytes, path) {
1857
+ if (!bytes) return { records: [], errors: [] };
1858
+ const text = decoder.decode(bytes).trim();
1859
+ if (!text) return { records: [], errors: [] };
1860
+ const records = [];
1861
+ const errors = [];
1862
+ for (const [index, line] of text.split("\n").entries()) {
1863
+ try {
1864
+ records.push(JSON.parse(line));
1865
+ } catch {
1866
+ errors.push(`${path}:${index + 1} failed to parse as JSON`);
1867
+ }
1868
+ }
1869
+ return { records, errors };
1870
+ }
1871
+ function unpackShardFiles(input) {
1872
+ if (input instanceof Map) return input;
1873
+ return unpackTarGz(input instanceof ArrayBuffer ? new Uint8Array(input) : input);
1874
+ }
1875
+ function parseRecords(bytes, path, encoding) {
1876
+ return encoding === "json-array" ? parseJsonArray(bytes, path) : parseJsonl(bytes, path);
1877
+ }
1878
+ function coreReferenceErrors(records) {
1879
+ const errors = [];
1880
+ const notes = records.get("notes");
1881
+ const collections = records.get("collections");
1882
+ const tags = records.get("tags");
1883
+ const templates = records.get("templates");
1884
+ const links = records.get("links");
1885
+ const noteIds = new Set(notes.map((record) => record.id));
1886
+ const collectionIds = new Set(collections.map((record) => record.id));
1887
+ const tagNames = new Set(tags.map((record) => record.name));
1888
+ for (const [index, collection] of collections.entries()) {
1889
+ if (collection.parent_id !== null && !collectionIds.has(collection.parent_id)) {
1890
+ errors.push(`collections.json[${index}] parent_id does not reference a declared collection`);
1891
+ }
1892
+ }
1893
+ const collectionById = new Map(collections.map((collection) => [collection.id, collection]));
1894
+ const visiting = /* @__PURE__ */ new Set();
1895
+ const visited = /* @__PURE__ */ new Set();
1896
+ const visitCollection = (collection) => {
1897
+ if (visited.has(collection.id)) return;
1898
+ if (visiting.has(collection.id)) {
1899
+ errors.push(`collection hierarchy contains a cycle at ${String(collection.id)}`);
1900
+ return;
1901
+ }
1902
+ visiting.add(collection.id);
1903
+ const parent = collection.parent_id === null ? void 0 : collectionById.get(collection.parent_id);
1904
+ if (parent) visitCollection(parent);
1905
+ visiting.delete(collection.id);
1906
+ visited.add(collection.id);
1907
+ };
1908
+ for (const collection of collections) visitCollection(collection);
1909
+ for (const [index, note] of notes.entries()) {
1910
+ if (note.collection_id !== null && !collectionIds.has(note.collection_id)) {
1911
+ errors.push(`notes.jsonl[${index}] collection_id does not reference a declared collection`);
1912
+ }
1913
+ for (const tag of note.tags) {
1914
+ if (!tagNames.has(tag)) {
1915
+ errors.push(`notes.jsonl[${index}] tag does not reference a declared tag`);
1916
+ }
1917
+ }
1918
+ }
1919
+ for (const [index, template] of templates.entries()) {
1920
+ if (template.collection_id !== null && !collectionIds.has(template.collection_id)) {
1921
+ errors.push(`templates.json[${index}] collection_id does not reference a declared collection`);
1922
+ }
1923
+ for (const tag of template.default_tags) {
1924
+ if (!tagNames.has(tag)) {
1925
+ errors.push(`templates.json[${index}] default tag does not reference a declared tag`);
1926
+ }
1927
+ }
1928
+ }
1929
+ for (const [index, link] of links.entries()) {
1930
+ if (!noteIds.has(link.from_note_id)) {
1931
+ errors.push(`links.jsonl[${index}] from_note_id does not reference a declared note`);
1932
+ }
1933
+ if (link.to_note_id !== null && !noteIds.has(link.to_note_id)) {
1934
+ errors.push(`links.jsonl[${index}] to_note_id does not reference a declared note`);
1935
+ }
1936
+ }
1937
+ return errors;
1938
+ }
1939
+ function validateCoreV1Structure(files, manifest) {
1940
+ const errors = [];
1941
+ const schemaVersion = coreSchemaVersion(manifest.version);
1942
+ if (!schemaVersion) {
1943
+ return ["manifest.json uses an unsupported canonical core-v1 schema version"];
1944
+ }
1945
+ const manifestValidator = coreValidatorFor("manifest", schemaVersion);
1946
+ if (!manifestValidator(manifest)) {
1947
+ return formatErrors(manifestValidator.errors).map((error) => `manifest.json ${error}`);
1948
+ }
1949
+ const components = manifest.components;
1950
+ const expectedFiles = new Set(components.map((component) => CORE_V1_COMPONENT_FILES[component].file));
1951
+ for (const filename of expectedFiles) {
1952
+ if (!files.has(filename)) errors.push(`${filename} is declared but missing`);
1953
+ if (!(filename in manifest.checksums)) errors.push(`${filename} is missing its declared checksum`);
1954
+ }
1955
+ for (const filename of Object.keys(manifest.checksums)) {
1956
+ if (!expectedFiles.has(filename)) {
1957
+ errors.push(`manifest checksum references undeclared file ${filename}`);
1958
+ }
1959
+ }
1960
+ for (const filename of files.keys()) {
1961
+ if (filename !== "manifest.json" && !expectedFiles.has(filename)) {
1962
+ errors.push(`archive contains undeclared file ${filename}`);
1963
+ }
1964
+ }
1965
+ const records = /* @__PURE__ */ new Map();
1966
+ for (const component of components) {
1967
+ const spec = CORE_V1_COMPONENT_FILES[component];
1968
+ const parsed = parseRecords(files.get(spec.file), spec.file, spec.encoding);
1969
+ errors.push(...parsed.errors);
1970
+ const validator = coreValidatorFor(component, schemaVersion);
1971
+ for (const [index, record] of parsed.records.entries()) {
1972
+ if (!validator(record)) {
1973
+ errors.push(
1974
+ ...formatErrors(validator.errors).map((error) => `${spec.file}[${index}] ${error}`)
1975
+ );
1976
+ }
1977
+ }
1978
+ const expectedCount = manifest.counts[component];
1979
+ if (expectedCount !== parsed.records.length) {
1980
+ errors.push(
1981
+ `${spec.file} count mismatch: manifest=${String(expectedCount)} actual=${parsed.records.length}`
1982
+ );
1983
+ }
1984
+ records.set(component, parsed.records);
1985
+ }
1986
+ for (const component of Object.keys(CORE_V1_COMPONENT_FILES)) {
1987
+ if (!records.has(component)) records.set(component, []);
1988
+ }
1989
+ if (errors.length === 0) errors.push(...coreReferenceErrors(records));
1990
+ return errors;
1991
+ }
1992
+ async function validateCoreV1ShardArchive(input) {
1993
+ let files;
1994
+ try {
1995
+ files = unpackShardFiles(input);
1996
+ } catch {
1997
+ return { valid: false, errors: ["archive failed to unpack"] };
1998
+ }
1999
+ const manifestBytes = files.get("manifest.json");
2000
+ if (!manifestBytes) return { valid: false, errors: ["manifest.json is missing"] };
2001
+ let manifest;
2002
+ try {
2003
+ manifest = JSON.parse(decoder.decode(manifestBytes));
2004
+ } catch {
2005
+ return { valid: false, errors: ["manifest.json failed to parse as JSON"] };
2006
+ }
2007
+ const errors = validateCoreV1Structure(files, manifest);
2008
+ if (errors.length > 0) return { valid: false, errors };
2009
+ const checksumResult = await validateChecksums(manifest.checksums, files);
2010
+ if (!checksumResult.valid) {
2011
+ errors.push(...checksumResult.failures.map((filename) => `${filename} checksum mismatch`));
2012
+ }
2013
+ return { valid: errors.length === 0, errors };
2014
+ }
2015
+ var AIWG_SHARD_UUID_NAMESPACE = "7ab5d1f8-29d2-5e35-9e2f-3a45de171a9e";
2016
+ var shardEncoder = new TextEncoder();
2017
+ var shardDecoder = new TextDecoder();
2018
+ function aiwgShardUuid(kind, id) {
2019
+ return v5(`${kind}:${id}`, AIWG_SHARD_UUID_NAMESPACE);
2020
+ }
2021
+ function aiwgShardTimestamp(value, fallback) {
2022
+ if (!value || Number.isNaN(Date.parse(value))) return fallback;
2023
+ return new Date(value).toISOString();
2024
+ }
2025
+ function aiwgRecordTitle(record) {
2026
+ return record.title ?? record.search?.title ?? record.search?.name ?? record.id;
2027
+ }
2028
+ function aiwgRecordContent(record) {
2029
+ if (record.text) return record.text;
2030
+ if (record.search?.body) return record.search.body;
2031
+ const chunks = record.chunks?.map((chunk) => chunk.text ?? chunk.body ?? chunk.summary ?? "").filter(Boolean);
2032
+ if (chunks?.length) return chunks.join("\n\n");
2033
+ return record.search?.summary ?? "";
2034
+ }
2035
+ function aiwgShardMetadata(index, record) {
2036
+ return {
2037
+ aiwg_fortemi_index: {
2038
+ envelope: {
2039
+ schema_version: index.schema_version,
2040
+ generated_at: index.generated_at,
2041
+ source: index.source,
2042
+ ...index.compatibility ? { compatibility: index.compatibility } : {}
2043
+ },
2044
+ record
2045
+ }
2046
+ };
2047
+ }
2048
+ function encodeJsonLines(values) {
2049
+ return shardEncoder.encode(values.map((value) => JSON.stringify(value)).join("\n"));
2050
+ }
2051
+ async function aiwgFortemiIndexToKnowledgeShard(index, options = {}) {
2052
+ if (options.includeNativeRichComponents) {
2053
+ throw new Error(
2054
+ "Native AIWG rich components require the complete full-v1 inventory; use core-v1 metadata preservation until full-v1 conversion is available"
2055
+ );
2056
+ }
2057
+ const validation = validateAiwgFortemiIndexExport(index);
2058
+ if (!validation.valid) {
2059
+ throw new Error(`Invalid AIWG Fortemi index export:
2060
+ ${validation.errors.join("\n")}`);
2061
+ }
2062
+ if (index.schema_version !== "aiwg.fortemi.index.export.v2") {
2063
+ throw new Error("Knowledge Shard conversion requires aiwg.fortemi.index.export.v2");
2064
+ }
2065
+ const createdAt = aiwgShardTimestamp(options.createdAt ?? index.generated_at, (/* @__PURE__ */ new Date()).toISOString());
2066
+ const noteIds = new Map(index.items.map((record) => [record.id, aiwgShardUuid("record", record.id)]));
2067
+ const notes = index.items.map((record) => {
2068
+ const content = aiwgRecordContent(record);
2069
+ return {
2070
+ id: noteIds.get(record.id),
2071
+ title: aiwgRecordTitle(record),
2072
+ original_content: content,
2073
+ revised_content: content,
2074
+ metadata: aiwgShardMetadata(index, record),
2075
+ collection_id: null,
2076
+ attachments: [],
2077
+ format: "markdown",
2078
+ source: "aiwg-index",
2079
+ starred: false,
2080
+ archived: false,
2081
+ tags: [...new Set(record.tags)].sort(),
2082
+ created_at: aiwgShardTimestamp(record.source.updated_at ?? record.updated_at, createdAt),
2083
+ updated_at: aiwgShardTimestamp(record.updated_at, createdAt),
2084
+ deleted_at: null
2085
+ };
2086
+ });
2087
+ const links = [];
2088
+ for (const record of index.items) {
2089
+ for (const [position, relationship] of record.relationships.entries()) {
2090
+ const targetNoteId = noteIds.get(relationship.target_id) ?? null;
2091
+ links.push({
2092
+ id: aiwgShardUuid(
2093
+ "relationship",
2094
+ `${record.id}\0${position}\0${relationship.type}\0${relationship.target_id}`
2095
+ ),
2096
+ from_note_id: noteIds.get(record.id),
2097
+ to_note_id: targetNoteId,
2098
+ to_url: targetNoteId ? null : `aiwg://record/${encodeURIComponent(relationship.target_id)}`,
2099
+ kind: relationship.type,
2100
+ score: relationship.confidence ?? 1,
2101
+ created_at: aiwgShardTimestamp(record.updated_at, createdAt),
2102
+ metadata: {
2103
+ aiwg_fortemi_index: {
2104
+ source_record_id: record.id,
2105
+ target_record_id: relationship.target_id,
2106
+ relationship
2107
+ }
2108
+ }
2109
+ });
2110
+ }
2111
+ }
2112
+ const files = /* @__PURE__ */ new Map();
2113
+ const components = ["notes", "tags"];
2114
+ const counts = {
2115
+ notes: notes.length,
2116
+ tags: [...new Set(notes.flatMap((note) => note.tags))].length
2117
+ };
2118
+ files.set("notes.jsonl", encodeJsonLines(notes));
2119
+ files.set("tags.json", shardEncoder.encode(JSON.stringify(
2120
+ [...new Set(notes.flatMap((note) => note.tags))].sort().map((name) => ({ name, created_at: createdAt }))
2121
+ )));
2122
+ const addComponent = (component, filename, values, jsonLines = true) => {
2123
+ if (values.length === 0) return;
2124
+ components.push(component);
2125
+ counts[component] = values.length;
2126
+ files.set(filename, jsonLines ? encodeJsonLines(values) : shardEncoder.encode(JSON.stringify(values)));
2127
+ };
2128
+ addComponent("links", "links.jsonl", links);
2129
+ const checksums = {};
2130
+ for (const [filename, bytes] of files) checksums[filename] = await sha256Hex(bytes);
2131
+ const manifest = {
2132
+ version: CURRENT_SHARD_VERSION,
2133
+ profile: "core-v1",
2134
+ producer: {
2135
+ name: "fortemi-core-aiwg-index",
2136
+ version: options.matricVersion ?? "fortemi-core"
2137
+ },
2138
+ format: SHARD_FORMAT,
2139
+ created_at: createdAt,
2140
+ components,
2141
+ counts: {
2142
+ notes: 0,
2143
+ collections: 0,
2144
+ tags: 0,
2145
+ templates: 0,
2146
+ links: 0,
2147
+ embedding_sets: 0,
2148
+ embedding_set_members: 0,
2149
+ embeddings: 0,
2150
+ embedding_configs: 0,
2151
+ ...counts
2152
+ },
2153
+ checksums,
2154
+ min_reader_version: CURRENT_SHARD_VERSION
2155
+ };
2156
+ files.set("manifest.json", shardEncoder.encode(JSON.stringify(manifest, null, 2)));
2157
+ const contractValidation = await validateCoreV1ShardArchive(files);
2158
+ if (!contractValidation.valid) {
2159
+ throw new Error(
2160
+ `Generated AIWG core-v1 shard failed canonical validation: ${contractValidation.errors.join("; ")}`
2161
+ );
2162
+ }
2163
+ return packTarGz(files);
2164
+ }
2165
+ function aiwgFortemiIndexFromKnowledgeShard(bytes) {
2166
+ const files = unpackTarGz(bytes);
2167
+ const noteBytes = files.get("notes.jsonl");
2168
+ const notes = (noteBytes ? shardDecoder.decode(noteBytes) : "").split("\n").filter(Boolean).map((line) => JSON.parse(line));
2169
+ if (notes.length === 0) throw new Error("Knowledge Shard contains no AIWG index notes");
2170
+ let envelope;
2171
+ const items = [];
2172
+ for (const note of notes) {
2173
+ const metadata = note.metadata?.aiwg_fortemi_index;
2174
+ if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
2175
+ throw new Error(`Knowledge Shard note ${note.id} has no AIWG index metadata`);
2176
+ }
2177
+ const value = metadata;
2178
+ envelope ??= value.envelope;
2179
+ items.push(value.record);
2180
+ }
2181
+ const restored = {
2182
+ ...envelope,
2183
+ items: items.sort((left, right) => left.id.localeCompare(right.id))
2184
+ };
2185
+ const validation = validateAiwgFortemiIndexExport(restored);
2186
+ if (!validation.valid) {
2187
+ throw new Error(`Knowledge Shard contains invalid AIWG index metadata:
2188
+ ${validation.errors.join("\n")}`);
2189
+ }
2190
+ return restored;
2191
+ }
2192
+
2193
+ export { aiwgFortemiIndexFromKnowledgeShard, aiwgFortemiIndexToKnowledgeShard };
2194
+ //# sourceMappingURL=aiwg-index-shard.js.map
2195
+ //# sourceMappingURL=aiwg-index-shard.js.map