@fortemi/core 2026.7.13 → 2026.7.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7634,6 +7634,164 @@ var knowledge_shard_v2_implementation_receipt_default = {
7634
7634
  schemaBundleSha256: "66dee80876c73fdc8756541c72e96ae189c098113a831c849d619381c4121c02"
7635
7635
  }};
7636
7636
 
7637
+ // schemas/knowledge-shard-v2.cross-repository.receipt.json
7638
+ var knowledge_shard_v2_cross_repository_receipt_default = {
7639
+ cells: [
7640
+ {
7641
+ id: "pglite-full-v1-to-pglite",
7642
+ producer: "react-pglite",
7643
+ consumer: "react-pglite",
7644
+ status: "passed",
7645
+ tests: [
7646
+ "full-v1-store: validates, persists all components and bytes, and converges on re-export",
7647
+ "full-v1-store: produces and converges a complete full-v1 archive from live PGlite state",
7648
+ "full-v1-store: rejects corrupt, incomplete, oversized, and transactional-failure inputs"
7649
+ ],
7650
+ coverage: [
7651
+ "all-33-components",
7652
+ "all-34-count-fields",
7653
+ "attachment-bytes",
7654
+ "signatures",
7655
+ "identities",
7656
+ "relationships",
7657
+ "timestamps",
7658
+ "tombstones",
7659
+ "absent-null-empty-value",
7660
+ "768-dimensional-embeddings",
7661
+ "embedding-contract-lineage",
7662
+ "skos",
7663
+ "provenance",
7664
+ "graph-community",
7665
+ "current-minus-two",
7666
+ "current",
7667
+ "next-major-rejection",
7668
+ "malformed-input",
7669
+ "tampered-input",
7670
+ "resource-limits",
7671
+ "repeated-imports",
7672
+ "zero-mutation-on-rejection"
7673
+ ]
7674
+ },
7675
+ {
7676
+ id: "aiwg-full-v1-to-pglite",
7677
+ producer: "aiwg-index-converter",
7678
+ consumer: "react-pglite",
7679
+ status: "passed",
7680
+ tests: [
7681
+ "aiwg-index-full-shard: verifies the committed source, implementation, archive, and authority receipt",
7682
+ "aiwg-index-full-shard: imports through PGlite and converges on exact logical files",
7683
+ "portable-contract: validates rejection, presence, signature, limit, and mutation invariants"
7684
+ ],
7685
+ coverage: [
7686
+ "all-33-components",
7687
+ "all-34-count-fields",
7688
+ "attachment-bytes",
7689
+ "signatures",
7690
+ "identities",
7691
+ "relationships",
7692
+ "timestamps",
7693
+ "tombstones",
7694
+ "absent-null-empty-value",
7695
+ "768-dimensional-embeddings",
7696
+ "embedding-contract-lineage",
7697
+ "skos",
7698
+ "provenance",
7699
+ "graph-community",
7700
+ "current-minus-two",
7701
+ "current",
7702
+ "next-major-rejection",
7703
+ "malformed-input",
7704
+ "tampered-input",
7705
+ "resource-limits",
7706
+ "repeated-imports",
7707
+ "zero-mutation-on-rejection"
7708
+ ]
7709
+ },
7710
+ {
7711
+ id: "pglite-full-v1-to-fortemi",
7712
+ producer: "react-pglite",
7713
+ consumer: "fortemi-postgresql",
7714
+ status: "passed",
7715
+ tests: [
7716
+ "tests::shard_schema_2_accepts_independent_react_and_aiwg_full_v1_archives",
7717
+ "tests::shard_schema_2_clean_destinations_preserve_independent_full_v1_archives",
7718
+ "tests::shard_schema_2_dispatch_covers_the_complete_authority_field_inventory"
7719
+ ],
7720
+ coverage: [
7721
+ "all-33-components",
7722
+ "all-34-count-fields",
7723
+ "attachment-bytes",
7724
+ "signatures",
7725
+ "identities",
7726
+ "relationships",
7727
+ "timestamps",
7728
+ "tombstones",
7729
+ "absent-null-empty-value",
7730
+ "768-dimensional-embeddings",
7731
+ "embedding-contract-lineage",
7732
+ "skos",
7733
+ "provenance",
7734
+ "graph-community",
7735
+ "current-minus-two",
7736
+ "current",
7737
+ "next-major-rejection",
7738
+ "malformed-input",
7739
+ "tampered-input",
7740
+ "resource-limits",
7741
+ "repeated-imports",
7742
+ "zero-mutation-on-rejection"
7743
+ ]
7744
+ },
7745
+ {
7746
+ id: "aiwg-full-v1-to-fortemi",
7747
+ producer: "aiwg-index-converter",
7748
+ consumer: "fortemi-postgresql",
7749
+ status: "passed",
7750
+ tests: [
7751
+ "tests::shard_schema_2_accepts_independent_react_and_aiwg_full_v1_archives",
7752
+ "tests::shard_schema_2_clean_destinations_preserve_independent_full_v1_archives",
7753
+ "tests::shard_schema_2_dispatch_covers_the_complete_authority_field_inventory"
7754
+ ],
7755
+ coverage: [
7756
+ "all-33-components",
7757
+ "all-34-count-fields",
7758
+ "attachment-bytes",
7759
+ "signatures",
7760
+ "identities",
7761
+ "relationships",
7762
+ "timestamps",
7763
+ "tombstones",
7764
+ "absent-null-empty-value",
7765
+ "768-dimensional-embeddings",
7766
+ "embedding-contract-lineage",
7767
+ "skos",
7768
+ "provenance",
7769
+ "graph-community",
7770
+ "current-minus-two",
7771
+ "current",
7772
+ "next-major-rejection",
7773
+ "malformed-input",
7774
+ "tampered-input",
7775
+ "resource-limits",
7776
+ "repeated-imports",
7777
+ "zero-mutation-on-rejection"
7778
+ ]
7779
+ }
7780
+ ],
7781
+ advertisement: {
7782
+ backend: "pglite",
7783
+ schemaVersion: "2.0.0",
7784
+ profile: "full-v1",
7785
+ operations: [
7786
+ "import",
7787
+ "export"
7788
+ ],
7789
+ enabled: true
7790
+ },
7791
+ claims: {
7792
+ suiteWide: false,
7793
+ recordStoreFullV1: false}};
7794
+
7637
7795
  // src/shard/profile-registry.ts
7638
7796
  var CORE_V1_COMPONENTS = [
7639
7797
  "notes",
@@ -7643,7 +7801,38 @@ var CORE_V1_COMPONENTS = [
7643
7801
  "links"
7644
7802
  ];
7645
7803
  var ALL_PROFILES = ["core-v1", "full-v1", "record-v1"];
7804
+ var FULL_V1_RECEIPT_CELLS = [
7805
+ "pglite-full-v1-to-pglite",
7806
+ "aiwg-full-v1-to-pglite",
7807
+ "pglite-full-v1-to-fortemi",
7808
+ "aiwg-full-v1-to-fortemi"
7809
+ ];
7810
+ var FULL_V1_RECEIPT_COVERAGE = [
7811
+ "all-33-components",
7812
+ "all-34-count-fields",
7813
+ "attachment-bytes",
7814
+ "signatures",
7815
+ "identities",
7816
+ "relationships",
7817
+ "timestamps",
7818
+ "tombstones",
7819
+ "absent-null-empty-value",
7820
+ "768-dimensional-embeddings",
7821
+ "embedding-contract-lineage",
7822
+ "skos",
7823
+ "provenance",
7824
+ "graph-community",
7825
+ "current-minus-two",
7826
+ "current",
7827
+ "next-major-rejection",
7828
+ "malformed-input",
7829
+ "tampered-input",
7830
+ "resource-limits",
7831
+ "repeated-imports",
7832
+ "zero-mutation-on-rejection"
7833
+ ];
7646
7834
  var FULL_V1_IMPLEMENTED = knowledge_shard_v2_implementation_receipt_default.authority.schemaBundleSha256 === knowledge_shard_v2_schema_receipt_default.schemaBundle.sha256;
7835
+ var FULL_V1_ADVERTISEMENT_RECEIPT_PASSED = knowledge_shard_v2_cross_repository_receipt_default.cells.length === FULL_V1_RECEIPT_CELLS.length && knowledge_shard_v2_cross_repository_receipt_default.cells.every((cell, index) => cell.id === FULL_V1_RECEIPT_CELLS[index] && cell.status === "passed" && JSON.stringify(cell.coverage) === JSON.stringify(FULL_V1_RECEIPT_COVERAGE)) && knowledge_shard_v2_cross_repository_receipt_default.advertisement.backend === "pglite" && knowledge_shard_v2_cross_repository_receipt_default.advertisement.schemaVersion === "2.0.0" && knowledge_shard_v2_cross_repository_receipt_default.advertisement.profile === "full-v1" && JSON.stringify(knowledge_shard_v2_cross_repository_receipt_default.advertisement.operations) === JSON.stringify(["import", "export"]) && knowledge_shard_v2_cross_repository_receipt_default.advertisement.enabled === true && knowledge_shard_v2_cross_repository_receipt_default.claims.suiteWide === false && knowledge_shard_v2_cross_repository_receipt_default.claims.recordStoreFullV1 === false;
7647
7836
  var ALL_COMPONENTS = [
7648
7837
  "notes",
7649
7838
  "collections",
@@ -7736,12 +7925,14 @@ function getKnowledgeShardProfileRegistry() {
7736
7925
  }
7737
7926
  function createShardCapabilityReport(input) {
7738
7927
  const requestedSchemaVersion = input.requestedSchemaVersion ?? null;
7739
- const authorityPending = requestedSchemaVersion === "2.0.0";
7740
- const advertisedProfiles = authorityPending ? [] : [...BACKEND_PROFILES[input.backend][input.operation]];
7741
7928
  const requestedProfile = input.requestedProfile;
7742
7929
  const knownProfile = requestedProfile && isKnownProfile(requestedProfile) ? requestedProfile : null;
7743
- const authorityStatus = requestedProfile === null ? "unprofiled" : knownProfile ? authorityPending ? "candidate" : registryEntry(knownProfile).authority_status : "unknown";
7744
- const backendSupported = !authorityPending && knownProfile !== null && advertisedProfiles.includes(knownProfile);
7930
+ const schema2Requested = requestedSchemaVersion === "2.0.0";
7931
+ const receiptBackedSchema2FullV1 = schema2Requested && requestedProfile === "full-v1" && input.backend === "pglite" && FULL_V1_ADVERTISEMENT_RECEIPT_PASSED;
7932
+ const authorityPending = schema2Requested && !receiptBackedSchema2FullV1;
7933
+ const advertisedProfiles = schema2Requested ? receiptBackedSchema2FullV1 ? ["full-v1"] : [] : [...BACKEND_PROFILES[input.backend][input.operation]];
7934
+ const authorityStatus = requestedProfile === null ? "unprofiled" : knownProfile ? receiptBackedSchema2FullV1 ? "supported" : authorityPending ? "candidate" : registryEntry(knownProfile).authority_status : "unknown";
7935
+ const backendSupported = knownProfile !== null && (receiptBackedSchema2FullV1 || !authorityPending && advertisedProfiles.includes(knownProfile));
7745
7936
  const backendComponents = new Set(BACKEND_COMPONENTS[input.backend][input.operation]);
7746
7937
  const profileComponents = knownProfile === "core-v1" ? CORE_V1_COMPONENTS : BACKEND_COMPONENTS[input.backend][input.operation];
7747
7938
  const supportedComponents = profileComponents.filter(
@@ -31143,6 +31334,86 @@ function validateOptionalRichMetadata(item, index, errors) {
31143
31334
  if (item.compatibility !== void 0 && !isPlainRecord(item.compatibility)) {
31144
31335
  errors.push("items[" + index + "].compatibility must be an object");
31145
31336
  }
31337
+ if (item.operational_state !== void 0) {
31338
+ const at = "items[" + index + "].operational_state";
31339
+ if (!isPlainRecord(item.operational_state)) {
31340
+ errors.push(at + " must be an object");
31341
+ } else {
31342
+ const state = item.operational_state;
31343
+ const allowedClassifications = /* @__PURE__ */ new Set([
31344
+ "fresh",
31345
+ "historical",
31346
+ "superseded",
31347
+ "contradicted",
31348
+ "needs-source"
31349
+ ]);
31350
+ const allowedConfidence = /* @__PURE__ */ new Set(["source", "candidate", "reviewed", "rejected"]);
31351
+ const stringFields = [
31352
+ "source_repo",
31353
+ "source_kind",
31354
+ "source_id",
31355
+ "observed_state",
31356
+ "observed_at",
31357
+ "source_updated_at",
31358
+ "evidence_url",
31359
+ "evidence_path",
31360
+ "observer",
31361
+ "stale_after"
31362
+ ];
31363
+ const arrayFields = ["supersedes", "contradicts"];
31364
+ const allowedFields = /* @__PURE__ */ new Set([
31365
+ ...stringFields,
31366
+ ...arrayFields,
31367
+ "classification",
31368
+ "confidence",
31369
+ "current_action_selector"
31370
+ ]);
31371
+ if (!allowedClassifications.has(String(state.classification))) {
31372
+ errors.push(at + ".classification must be fresh, historical, superseded, contradicted, or needs-source");
31373
+ }
31374
+ for (const field of stringFields) {
31375
+ if (state[field] !== void 0 && !hasString(state[field])) {
31376
+ errors.push(at + "." + field + " must be a non-empty string");
31377
+ }
31378
+ }
31379
+ for (const field of ["observed_at", "source_updated_at", "stale_after"]) {
31380
+ if (state[field] !== void 0 && (typeof state[field] !== "string" || Number.isNaN(Date.parse(state[field])))) {
31381
+ errors.push(at + "." + field + " must be a date-time string");
31382
+ }
31383
+ }
31384
+ for (const field of arrayFields) {
31385
+ if (!isOptionalStringArray(state[field])) {
31386
+ errors.push(at + "." + field + " must be a string array");
31387
+ }
31388
+ }
31389
+ if (state.confidence !== void 0 && !allowedConfidence.has(String(state.confidence))) {
31390
+ errors.push(at + ".confidence must be source, candidate, reviewed, or rejected");
31391
+ }
31392
+ if (state.current_action_selector !== void 0 && typeof state.current_action_selector !== "boolean") {
31393
+ errors.push(at + ".current_action_selector must be a boolean");
31394
+ }
31395
+ if (Object.keys(state).some((field) => !allowedFields.has(field))) {
31396
+ errors.push(at + " contains unsupported fields");
31397
+ }
31398
+ }
31399
+ }
31400
+ if (item.state_transfer !== void 0) {
31401
+ const at = "items[" + index + "].state_transfer";
31402
+ if (!isPlainRecord(item.state_transfer)) {
31403
+ errors.push(at + " must be an object");
31404
+ } else {
31405
+ const stateTransfer = item.state_transfer;
31406
+ const deletedAt = stateTransfer.deleted_at;
31407
+ if (!Object.hasOwn(stateTransfer, "deleted_at")) {
31408
+ errors.push(at + ".deleted_at is required");
31409
+ } else if (deletedAt !== null && (typeof deletedAt !== "string" || Number.isNaN(Date.parse(deletedAt)))) {
31410
+ errors.push(at + ".deleted_at must be a date-time string or null");
31411
+ }
31412
+ if (Object.keys(stateTransfer).some((field) => field !== "deleted_at")) {
31413
+ errors.push(at + " contains unsupported fields");
31414
+ }
31415
+ }
31416
+ }
31146
31417
  }
31147
31418
  function isPrivacyClassification(value) {
31148
31419
  return value === "private" || value === "sanitized" || value === "public";
@@ -31172,7 +31443,9 @@ var V2_ONLY_RECORD_FIELDS = [
31172
31443
  "skos_concepts",
31173
31444
  "skos_relations",
31174
31445
  "provenance_events",
31175
- "compatibility"
31446
+ "compatibility",
31447
+ "operational_state",
31448
+ "state_transfer"
31176
31449
  ];
31177
31450
  var V2_ONLY_SOURCE_FIELDS = ["origin", "generated", "checksum", "updated_at"];
31178
31451
  var V2_ONLY_RELATIONSHIP_FIELDS = ["target_path", "direction", "metadata"];
@@ -32762,1180 +33035,235 @@ function communityIdsFor(item, options) {
32762
33035
  if (item.concepts.length > 0) return item.concepts.map((concept) => `concept:${concept}`);
32763
33036
  return [`type:${item.type}`];
32764
33037
  }
32765
- var encoder4 = new TextEncoder();
32766
- var UUID_NAMESPACE = "7ab5d1f8-29d2-5e35-9e2f-3a45de171a9e";
32767
- function uuid(kind, id) {
32768
- return v5(`${kind}:${id}`, UUID_NAMESPACE);
32769
- }
32770
- function own(value, field) {
32771
- return Object.prototype.hasOwnProperty.call(value, field);
32772
- }
32773
- function timestamp(value) {
32774
- if (!value || Number.isNaN(Date.parse(value))) return void 0;
32775
- return new Date(value).toISOString();
32776
- }
32777
- function addLoss(losses, code, message, details = {}) {
32778
- losses.push({ code, message, ...details });
32779
- }
32780
- function encode(values, encoding) {
32781
- return encoder4.encode(encoding === "json-array" ? JSON.stringify(values) : values.map((value) => JSON.stringify(value)).join("\n"));
32782
- }
32783
- function noteTitle(record, losses) {
32784
- if (own(record, "title")) return record.title ?? null;
32785
- const derived = record.search?.title ?? record.search?.name;
32786
- addLoss(losses, "aiwg-title-not-native", derived ? "Title was derived from the AIWG search projection." : "AIWG supplied no title; the nullable destination field is null.", {
32787
- component: "notes",
32788
- record_id: record.id,
32789
- field_path: "/title",
32790
- source_state: "absent",
32791
- destination_capability: "nullable-value",
32792
- action: derived ? "degrade" : "default"
32793
- });
32794
- return derived ?? null;
32795
- }
32796
- function noteContent(record, losses) {
32797
- if (own(record, "text")) return record.text ?? "";
32798
- if (own(record.search ?? {}, "body")) {
32799
- addLoss(
32800
- losses,
32801
- "aiwg-content-search-projection",
32802
- "Content was derived from the AIWG search projection.",
32803
- {
32804
- component: "notes",
32805
- record_id: record.id,
32806
- field_path: "/original_content",
32807
- source_state: "absent",
32808
- destination_capability: "required-string",
32809
- action: "degrade"
33038
+
33039
+ // schemas/aiwg-fortemi-index-export.schema.json
33040
+ var aiwg_fortemi_index_export_schema_default = {
33041
+ $schema: "https://json-schema.org/draft/2020-12/schema",
33042
+ $id: "https://aiwg.io/schemas/aiwg-fortemi-index-export.json",
33043
+ title: "AIWG Fortemi Index Export",
33044
+ type: "object",
33045
+ additionalProperties: false,
33046
+ required: ["schema_version", "generated_at", "source", "items"],
33047
+ properties: {
33048
+ schema_version: {
33049
+ enum: ["aiwg.fortemi.index.export.v1", "aiwg.fortemi.index.export.v2"]
33050
+ },
33051
+ generated_at: {
33052
+ type: "string",
33053
+ format: "date-time"
33054
+ },
33055
+ source: {
33056
+ type: "object",
33057
+ additionalProperties: false,
33058
+ required: ["repo", "privacy"],
33059
+ properties: {
33060
+ repo: {
33061
+ type: "string",
33062
+ minLength: 1
33063
+ },
33064
+ privacy: {
33065
+ $ref: "#/$defs/privacy"
33066
+ },
33067
+ graph: {
33068
+ type: "string",
33069
+ minLength: 1
33070
+ }
33071
+ }
33072
+ },
33073
+ compatibility: {
33074
+ type: "object",
33075
+ additionalProperties: false,
33076
+ required: ["previous_schema_version", "strategy"],
33077
+ properties: {
33078
+ previous_schema_version: {
33079
+ const: "aiwg.fortemi.index.export.v1"
33080
+ },
33081
+ strategy: {
33082
+ const: "supported"
33083
+ }
33084
+ }
33085
+ },
33086
+ items: {
33087
+ type: "array",
33088
+ items: {
33089
+ $ref: "#/$defs/record"
32810
33090
  }
32811
- );
32812
- return record.search?.body ?? "";
32813
- }
32814
- if (record.chunks?.length) {
32815
- addLoss(losses, "aiwg-content-chunk-projection", "Content was assembled from AIWG chunks.", {
32816
- component: "notes",
32817
- record_id: record.id,
32818
- field_path: "/original_content",
32819
- source_state: "absent",
32820
- destination_capability: "required-string",
32821
- action: "degrade"
32822
- });
32823
- return record.chunks.map((chunk) => {
32824
- if (own(chunk, "text")) return chunk.text ?? "";
32825
- if (own(chunk, "body")) return chunk.body ?? "";
32826
- if (own(chunk, "summary")) return chunk.summary ?? "";
32827
- return "";
32828
- }).join("\n\n");
32829
- }
32830
- addLoss(
32831
- losses,
32832
- "aiwg-content-unavailable",
32833
- "AIWG supplied no body; the required destination string is empty.",
32834
- {
32835
- component: "notes",
32836
- record_id: record.id,
32837
- field_path: "/original_content",
32838
- source_state: "absent",
32839
- destination_capability: "required-string",
32840
- action: "default"
32841
33091
  }
32842
- );
32843
- return "";
32844
- }
32845
- function createdAt(record, losses) {
32846
- const source = timestamp(record.source.updated_at);
32847
- if (source) return source;
32848
- addLoss(
32849
- losses,
32850
- "aiwg-created-at-unavailable",
32851
- "AIWG has no distinct creation timestamp; updated_at was used.",
33092
+ },
33093
+ allOf: [
32852
33094
  {
32853
- component: "notes",
32854
- record_id: record.id,
32855
- field_path: "/created_at",
32856
- source_state: "absent",
32857
- destination_capability: "required-date-time",
32858
- action: "default"
32859
- }
32860
- );
32861
- return new Date(record.updated_at).toISOString();
32862
- }
32863
- function safeUri(value) {
32864
- if (!value) return null;
32865
- try {
32866
- return new URL(value).toString();
32867
- } catch {
32868
- return null;
32869
- }
32870
- }
32871
- function schemeName(concept) {
32872
- return concept.scheme && concept.scheme.length > 0 ? concept.scheme : "aiwg";
32873
- }
32874
- async function convertAiwgIndexToFullV1(index, options = {}) {
32875
- const losses = [];
32876
- const exportedAt = timestamp(options.createdAt) ?? new Date(index.generated_at).toISOString();
32877
- const records = [...index.items].sort((a, b) => a.id.localeCompare(b.id));
32878
- const noteIds = new Map(records.map((record) => [record.id, uuid("record", record.id)]));
32879
- const rows = /* @__PURE__ */ new Map();
32880
- for (const component of Object.keys(FULL_V1_COMPONENT_FILES)) rows.set(component, []);
32881
- const tags = /* @__PURE__ */ new Set();
32882
- for (const record of records) {
32883
- const noteId = noteIds.get(record.id);
32884
- const content = noteContent(record, losses);
32885
- const sourceCreatedAt = createdAt(record, losses);
32886
- const updatedAt = new Date(record.updated_at).toISOString();
32887
- const recordTags = [...new Set(record.tags)].sort();
32888
- recordTags.forEach((tag) => tags.add(tag));
32889
- if (record.binary_sources?.length) {
32890
- addLoss(
32891
- losses,
32892
- "aiwg-attachment-bytes-unavailable",
32893
- "Attachment references have no bytes, so full-v1 attachment projections were omitted.",
32894
- {
32895
- component: "notes",
32896
- count: record.binary_sources.length,
32897
- record_id: record.id,
32898
- field_path: "/attachments",
32899
- source_state: "value",
32900
- destination_capability: "mandatory-blob-sidecar",
32901
- action: "omit"
33095
+ if: {
33096
+ properties: {
33097
+ schema_version: {
33098
+ const: "aiwg.fortemi.index.export.v1"
33099
+ }
32902
33100
  }
32903
- );
32904
- }
32905
- const unmappedRecordFields = [
32906
- Object.keys(record.facets).length > 0 ? "facets" : null,
32907
- record.search !== void 0 ? "search" : null,
32908
- record.chunks !== void 0 ? "chunks" : null,
32909
- record.compatibility !== void 0 ? "compatibility" : null
32910
- ].filter((field) => field !== null);
32911
- if (unmappedRecordFields.length > 0) {
32912
- addLoss(
32913
- losses,
32914
- "aiwg-record-fields-unmapped",
32915
- "AIWG fields without a native full-v1 component were not hidden in note metadata.",
32916
- {
32917
- component: "notes",
32918
- record_id: record.id,
32919
- source_state: "value",
32920
- action: "omit",
32921
- destination_capability: "native-full-v1-components",
32922
- reason: unmappedRecordFields.join(",")
33101
+ },
33102
+ then: {
33103
+ not: {
33104
+ required: ["compatibility"]
33105
+ },
33106
+ properties: {
33107
+ source: {
33108
+ not: {
33109
+ required: ["graph"]
33110
+ }
33111
+ },
33112
+ items: {
33113
+ items: {
33114
+ allOf: [
33115
+ {
33116
+ properties: {
33117
+ schema_version: {
33118
+ const: "aiwg.fortemi.index.record.v1"
33119
+ }
33120
+ }
33121
+ },
33122
+ {
33123
+ $ref: "#/$defs/v1RecordCompatibility"
33124
+ }
33125
+ ]
33126
+ }
33127
+ }
32923
33128
  }
32924
- );
32925
- }
32926
- rows.get("notes").push({
32927
- id: noteId,
32928
- title: noteTitle(record, losses),
32929
- original_content: content,
32930
- revised_content: content,
32931
- metadata: { aiwg_source: {
32932
- record_id: record.id,
32933
- record_type: record.type,
32934
- repository: index.source.repo,
32935
- graph: index.source.graph ?? null,
32936
- source: record.source,
32937
- privacy: record.privacy
32938
- } },
32939
- format: "markdown",
32940
- source: "aiwg-index",
32941
- starred: false,
32942
- archived: false,
32943
- collection_id: null,
32944
- created_at: sourceCreatedAt,
32945
- updated_at: updatedAt,
32946
- tags: recordTags,
32947
- attachments: []
32948
- });
32949
- const hash = await sha256Hex(encoder4.encode(content));
32950
- rows.get("note_originals").push({
32951
- id: uuid("note-original", record.id),
32952
- note_id: noteId,
32953
- content,
32954
- hash: `sha256:${hash}`,
32955
- user_created_at: sourceCreatedAt,
32956
- user_last_edited_at: updatedAt,
32957
- version_number: 1
32958
- });
32959
- rows.get("note_revised_current").push({
32960
- note_id: noteId,
32961
- content,
32962
- last_revision_id: null,
32963
- ai_metadata: null
32964
- });
32965
- }
32966
- rows.set("tags", [...tags].sort().map((name) => ({ name, created_at: exportedAt })));
32967
- const relationshipInput = [];
32968
- for (const record of records) {
32969
- for (const [position, relationship] of record.relationships.entries()) {
32970
- const target = noteIds.get(relationship.target_id) ?? null;
32971
- const key = `${record.id}\0${position}\0${relationship.type}\0${relationship.target_id}`;
32972
- rows.get("links").push({
32973
- id: uuid("relationship", key),
32974
- from_note_id: noteIds.get(record.id),
32975
- to_note_id: target,
32976
- to_url: target ? null : `aiwg://record/${encodeURIComponent(relationship.target_id)}`,
32977
- kind: relationship.type,
32978
- score: own(relationship, "confidence") ? relationship.confidence ?? null : null,
32979
- created_at: new Date(record.updated_at).toISOString(),
32980
- metadata: target ? relationship.metadata ?? null : {
32981
- direction: relationship.direction ?? null,
32982
- label: relationship.label ?? null,
32983
- privacy: relationship.privacy ?? null,
32984
- source_path: relationship.source_path ?? null,
32985
- target_path: relationship.target_path ?? null,
32986
- source_metadata: relationship.metadata ?? null
33129
+ }
33130
+ },
33131
+ {
33132
+ if: {
33133
+ properties: {
33134
+ schema_version: {
33135
+ const: "aiwg.fortemi.index.export.v2"
33136
+ }
32987
33137
  }
32988
- });
32989
- relationshipInput.push({ source: record.id, position, relationship });
32990
- if (!target) continue;
32991
- let weight = relationship.confidence;
32992
- if (weight === void 0) {
32993
- weight = 1;
32994
- addLoss(
32995
- losses,
32996
- "aiwg-relationship-weight-unavailable",
32997
- "Graph weight defaulted because relationship confidence is absent.",
32998
- {
32999
- component: "graph_edges",
33000
- record_id: record.id,
33001
- field_path: `/relationships/${position}/confidence`,
33002
- source_state: "absent",
33003
- destination_capability: "required-number",
33004
- action: "default"
33138
+ },
33139
+ then: {
33140
+ required: ["compatibility"],
33141
+ properties: {
33142
+ source: {
33143
+ required: ["graph"]
33144
+ },
33145
+ items: {
33146
+ items: {
33147
+ properties: {
33148
+ schema_version: {
33149
+ const: "aiwg.fortemi.index.record.v2"
33150
+ }
33151
+ }
33152
+ }
33005
33153
  }
33006
- );
33007
- }
33008
- rows.get("graph_edges").push({
33009
- graph_source_id: "aiwg-relationships",
33010
- from_note_id: noteIds.get(record.id),
33011
- to_note_id: target,
33012
- weight,
33013
- kind: "manual",
33014
- rank: position,
33015
- metadata: {
33016
- type: relationship.type,
33017
- direction: relationship.direction ?? null,
33018
- label: relationship.label ?? null,
33019
- privacy: relationship.privacy ?? null,
33020
- source_path: relationship.source_path ?? null,
33021
- target_path: relationship.target_path ?? null,
33022
- source_metadata: relationship.metadata ?? null
33023
33154
  }
33024
- });
33025
- }
33026
- }
33027
- if (rows.get("graph_edges").length) {
33028
- rows.get("graph_sources").push({
33029
- id: "aiwg-relationships",
33030
- name: "AIWG relationships",
33031
- kind: "imported",
33032
- source_table: "manual",
33033
- embedding_set_id: null,
33034
- virtual_set_id: null,
33035
- model: null,
33036
- dimension: null,
33037
- truncate_dimension: null,
33038
- metric: null,
33039
- algorithm: null,
33040
- parameters: null,
33041
- input_hash: `sha256:${await sha256Hex(encoder4.encode(JSON.stringify(relationshipInput)))}`,
33042
- freshness: { status: "fresh", checked_at: exportedAt },
33043
- created_at: exportedAt
33044
- });
33045
- }
33046
- const concepts = /* @__PURE__ */ new Map();
33047
- const conceptMembers = /* @__PURE__ */ new Map();
33048
- for (const record of records) {
33049
- for (const id of record.concepts) {
33050
- conceptMembers.set(id, [...conceptMembers.get(id) ?? [], record]);
33155
+ }
33051
33156
  }
33052
- for (const concept of record.skos_concepts ?? []) {
33053
- const existing = concepts.get(concept.id);
33054
- if (existing && JSON.stringify(existing) !== JSON.stringify(concept)) {
33055
- addLoss(
33056
- losses,
33057
- "aiwg-skos-concept-conflict",
33058
- "Different metadata was supplied for one concept; the first sorted record won.",
33157
+ ],
33158
+ $defs: {
33159
+ privacy: {
33160
+ enum: ["private", "sanitized", "public"]
33161
+ },
33162
+ recordType: {
33163
+ type: "string",
33164
+ minLength: 1
33165
+ },
33166
+ stringArray: {
33167
+ type: "array",
33168
+ items: {
33169
+ type: "string"
33170
+ }
33171
+ },
33172
+ numberArray: {
33173
+ type: "array",
33174
+ items: {
33175
+ type: "number"
33176
+ }
33177
+ },
33178
+ v1RecordCompatibility: {
33179
+ type: "object",
33180
+ not: {
33181
+ anyOf: [
33059
33182
  {
33060
- component: "skos_concepts",
33061
- record_id: concept.id,
33062
- destination_capability: "single-concept-identity",
33063
- action: "degrade"
33183
+ required: ["name"]
33184
+ },
33185
+ {
33186
+ required: ["summary"]
33187
+ },
33188
+ {
33189
+ required: ["search"]
33190
+ },
33191
+ {
33192
+ required: ["chunks"]
33193
+ },
33194
+ {
33195
+ required: ["embeddings"]
33196
+ },
33197
+ {
33198
+ required: ["compatibility"]
33199
+ },
33200
+ {
33201
+ required: ["skos_concepts"]
33202
+ },
33203
+ {
33204
+ required: ["skos_relations"]
33205
+ },
33206
+ {
33207
+ required: ["provenance_events"]
33208
+ },
33209
+ {
33210
+ required: ["operational_state"]
33211
+ },
33212
+ {
33213
+ required: ["state_transfer"]
33064
33214
  }
33065
- );
33066
- } else if (!existing) concepts.set(concept.id, concept);
33067
- }
33068
- }
33069
- for (const id of conceptMembers.keys()) {
33070
- if (!concepts.has(id)) {
33071
- concepts.set(id, { id, prefLabel: id });
33072
- addLoss(
33073
- losses,
33074
- "aiwg-skos-metadata-unavailable",
33075
- "A referenced concept had no SKOS metadata; its id is used as the label.",
33076
- {
33077
- component: "skos_concepts",
33078
- record_id: id,
33079
- field_path: "/prefLabel",
33080
- source_state: "absent",
33081
- destination_capability: "required-label",
33082
- action: "default"
33083
- }
33084
- );
33085
- }
33086
- }
33087
- const schemeIds = new Map(
33088
- [...new Set([...concepts.values()].map(schemeName))].sort().map((name) => [name, uuid("skos-scheme", name)])
33089
- );
33090
- for (const [name, id] of schemeIds) {
33091
- rows.get("skos_schemes").push({
33092
- id,
33093
- uri: null,
33094
- notation: name,
33095
- title: name,
33096
- description: null,
33097
- creator: "aiwg-index",
33098
- publisher: null,
33099
- rights: null,
33100
- version: null,
33101
- is_active: true,
33102
- is_system: false,
33103
- created_at: exportedAt,
33104
- updated_at: exportedAt,
33105
- issued_at: null,
33106
- modified_at: null,
33107
- embedding: null,
33108
- embedding_model: null,
33109
- embedded_at: null
33110
- });
33111
- }
33112
- const conceptIds = new Map([...concepts.keys()].sort().map((id) => [id, uuid("skos-concept", id)]));
33113
- for (const [sourceId, concept] of [...concepts].sort(([a], [b]) => a.localeCompare(b))) {
33114
- const id = conceptIds.get(sourceId);
33115
- const schemeId = schemeIds.get(schemeName(concept));
33116
- const memberCount = conceptMembers.get(sourceId)?.length ?? 0;
33117
- if (concept.uri && !safeUri(concept.uri)) addLoss(
33118
- losses,
33119
- "aiwg-skos-uri-invalid",
33120
- "AIWG concept URI is not a valid authority URI and was mapped to null.",
33121
- {
33122
- component: "skos_concepts",
33123
- record_id: sourceId,
33124
- field_path: "/uri",
33125
- source_state: "value",
33126
- destination_capability: "uri",
33127
- action: "omit"
33128
- }
33129
- );
33130
- const unmappedConceptMetadata = Object.keys(concept.metadata ?? {}).filter((key) => key !== "domain");
33131
- if (unmappedConceptMetadata.length > 0) addLoss(
33132
- losses,
33133
- "aiwg-skos-metadata-unmapped",
33134
- "AIWG concept metadata without a native full-v1 field was omitted.",
33135
- {
33136
- component: "skos_concepts",
33137
- record_id: sourceId,
33138
- source_state: "value",
33139
- action: "omit",
33140
- destination_capability: "native-skos-fields",
33141
- reason: unmappedConceptMetadata.join(",")
33142
- }
33143
- );
33144
- rows.get("skos_concepts").push({
33145
- id,
33146
- primary_scheme_id: schemeId,
33147
- uri: safeUri(concept.uri),
33148
- notation: concept.notation ?? sourceId,
33149
- facet_type: null,
33150
- facet_source: "aiwg-index",
33151
- facet_domain: typeof concept.metadata?.domain === "string" ? concept.metadata.domain : null,
33152
- facet_scope: null,
33153
- status: "candidate",
33154
- promoted_at: null,
33155
- deprecated_at: null,
33156
- deprecation_reason: null,
33157
- replaced_by_id: null,
33158
- note_count: memberCount,
33159
- first_used_at: memberCount ? exportedAt : null,
33160
- last_used_at: memberCount ? exportedAt : null,
33161
- depth: 0,
33162
- broader_count: 0,
33163
- narrower_count: 0,
33164
- related_count: 0,
33165
- antipatterns: null,
33166
- antipattern_checked_at: null,
33167
- created_at: exportedAt,
33168
- updated_at: exportedAt,
33169
- embedding: null,
33170
- embedding_model: null,
33171
- embedded_at: null
33172
- });
33173
- rows.get("skos_scheme_memberships").push({
33174
- concept_id: id,
33175
- scheme_id: schemeId,
33176
- is_top_concept: true,
33177
- added_at: exportedAt
33178
- });
33179
- rows.get("skos_labels").push({
33180
- id: uuid("skos-label", `${sourceId}:pref:${concept.prefLabel}`),
33181
- concept_id: id,
33182
- label_type: "pref_label",
33183
- value: concept.prefLabel,
33184
- language: "und",
33185
- created_at: exportedAt
33186
- });
33187
- for (const label of concept.altLabels ?? []) rows.get("skos_labels").push({
33188
- id: uuid("skos-label", `${sourceId}:alt:${label}`),
33189
- concept_id: id,
33190
- label_type: "alt_label",
33191
- value: label,
33192
- language: "und",
33193
- created_at: exportedAt
33194
- });
33195
- if (concept.definition !== void 0) rows.get("skos_notes").push({
33196
- id: uuid("skos-note", `${sourceId}:definition`),
33197
- concept_id: id,
33198
- note_type: "definition",
33199
- value: concept.definition,
33200
- language: "und",
33201
- author: null,
33202
- source: concept.uri ?? null,
33203
- created_at: exportedAt,
33204
- updated_at: exportedAt
33205
- });
33206
- }
33207
- for (const record of records) {
33208
- for (const [position, sourceId] of record.concepts.entries()) {
33209
- const conceptId = conceptIds.get(sourceId);
33210
- if (conceptId) rows.get("note_skos_tags").push({
33211
- note_id: noteIds.get(record.id),
33212
- concept_id: conceptId,
33213
- source: "aiwg-index",
33214
- confidence: null,
33215
- relevance_score: null,
33216
- is_primary: position === 0,
33217
- created_at: new Date(record.updated_at).toISOString(),
33218
- created_by: "aiwg-index"
33219
- });
33220
- }
33221
- for (const relation of record.skos_relations ?? []) {
33222
- const subject = conceptIds.get(relation.source_id);
33223
- const object = conceptIds.get(relation.target_id);
33224
- if (!subject || !object || !["broader", "narrower", "related"].includes(relation.type)) {
33225
- addLoss(
33226
- losses,
33227
- "aiwg-skos-relation-unrepresentable",
33228
- "SKOS relation could not be mapped to the native full-v1 relation enum.",
33229
- {
33230
- component: "skos_relations",
33231
- record_id: record.id,
33232
- destination_capability: "broader-narrower-related",
33233
- action: "omit"
33215
+ ]
33216
+ },
33217
+ properties: {
33218
+ source: {
33219
+ not: {
33220
+ anyOf: [
33221
+ {
33222
+ required: ["origin"]
33223
+ },
33224
+ {
33225
+ required: ["generated"]
33226
+ },
33227
+ {
33228
+ required: ["checksum"]
33229
+ },
33230
+ {
33231
+ required: ["updated_at"]
33232
+ }
33233
+ ]
33234
33234
  }
33235
- );
33236
- continue;
33237
- }
33238
- const unmappedRelationFields = [
33239
- relation.source_path !== void 0 ? "source_path" : null,
33240
- relation.metadata !== void 0 ? "metadata" : null
33241
- ].filter((field) => field !== null);
33242
- if (unmappedRelationFields.length > 0) {
33243
- addLoss(
33244
- losses,
33245
- "aiwg-skos-relation-fields-unmapped",
33246
- "AIWG SKOS relation fields have no native full-v1 destination fields.",
33247
- {
33248
- component: "skos_relations",
33249
- record_id: record.id,
33250
- source_state: "value",
33251
- destination_capability: "native-skos-relation-fields",
33252
- action: "omit",
33253
- reason: unmappedRelationFields.join(",")
33235
+ },
33236
+ relationships: {
33237
+ items: {
33238
+ not: {
33239
+ anyOf: [
33240
+ {
33241
+ required: ["target_path"]
33242
+ },
33243
+ {
33244
+ required: ["direction"]
33245
+ },
33246
+ {
33247
+ required: ["label"]
33248
+ },
33249
+ {
33250
+ required: ["confidence"]
33251
+ },
33252
+ {
33253
+ required: ["privacy"]
33254
+ },
33255
+ {
33256
+ required: ["metadata"]
33257
+ }
33258
+ ]
33259
+ }
33254
33260
  }
33255
- );
33256
- continue;
33257
- }
33258
- rows.get("skos_relations").push({
33259
- id: uuid("skos-relation", `${relation.source_id}:${relation.type}:${relation.target_id}`),
33260
- subject_id: subject,
33261
- object_id: object,
33262
- relation_type: relation.type,
33263
- inference_score: null,
33264
- is_inferred: false,
33265
- is_validated: false,
33266
- created_at: new Date(record.updated_at).toISOString(),
33267
- created_by: "aiwg-index"
33268
- });
33269
- }
33270
- }
33271
- for (const record of records) {
33272
- for (const [position, event] of (record.provenance_events ?? []).entries()) {
33273
- const start = timestamp(event.started_at);
33274
- if (!start) addLoss(
33275
- losses,
33276
- "aiwg-provenance-start-unavailable",
33277
- "Activity start defaulted to record updated_at.",
33278
- {
33279
- component: "provenance_activities",
33280
- record_id: event.id ?? `${record.id}:${position}`,
33281
- field_path: "/started_at",
33282
- source_state: "absent",
33283
- action: "default"
33284
- }
33285
- );
33286
- rows.get("provenance_activities").push({
33287
- id: uuid("provenance-event", event.id ?? `${record.id}:${position}`),
33288
- note_id: noteIds.get(record.id),
33289
- revision_id: null,
33290
- activity_type: event.activity,
33291
- model_name: event.agent ?? null,
33292
- started_at: start ?? new Date(record.updated_at).toISOString(),
33293
- ended_at: timestamp(event.ended_at) ?? null,
33294
- metadata: {
33295
- source: event.source ?? null,
33296
- path: event.path ?? null,
33297
- confidence: event.confidence ?? null,
33298
- privacy: event.privacy ?? null,
33299
- attributes: event.attributes ?? null
33300
- }
33301
- });
33302
- }
33303
- for (const [position, provenance] of record.provenance.entries()) {
33304
- rows.get("provenance_activities").push({
33305
- id: uuid("provenance-field", `${record.id}:${position}:${provenance.field}`),
33306
- note_id: noteIds.get(record.id),
33307
- revision_id: null,
33308
- activity_type: `source:${provenance.field}`,
33309
- model_name: provenance.source,
33310
- started_at: new Date(record.updated_at).toISOString(),
33311
- ended_at: null,
33312
- metadata: { path: provenance.path, confidence: provenance.confidence, privacy: provenance.privacy }
33313
- });
33314
- }
33315
- }
33316
- const embeddingGroups = /* @__PURE__ */ new Map();
33317
- for (const record of records) {
33318
- for (const [position, embedding] of (record.embeddings ?? []).entries()) {
33319
- const vector = embedding.embedding ?? embedding.vector;
33320
- if (!vector || vector.length !== 768) {
33321
- addLoss(
33322
- losses,
33323
- "aiwg-embedding-dimension-unrepresentable",
33324
- "Only 768-dimensional vectors satisfy the full-v1 authority.",
33325
- {
33326
- component: "embeddings",
33327
- record_id: embedding.id ?? `${record.id}:${position}`,
33328
- field_path: "/vector",
33329
- source_state: vector ? "value" : "absent",
33330
- destination_capability: "768-dimensional-vector",
33331
- action: "omit"
33332
- }
33333
- );
33334
- continue;
33335
- }
33336
- const model = embedding.model ?? "aiwg-unknown";
33337
- if (!embedding.model) addLoss(
33338
- losses,
33339
- "aiwg-embedding-model-unavailable",
33340
- "Embedding model defaulted because AIWG did not supply one.",
33341
- {
33342
- component: "embeddings",
33343
- record_id: embedding.id ?? `${record.id}:${position}`,
33344
- field_path: "/model",
33345
- source_state: "absent",
33346
- action: "default"
33347
- }
33348
- );
33349
- let group = embeddingGroups.get(model);
33350
- if (!group) {
33351
- group = { config: uuid("embedding-config", model), set: uuid("embedding-set", model), count: 0 };
33352
- embeddingGroups.set(model, group);
33353
- }
33354
- group.count += 1;
33355
- const unmappedEmbeddingFields = [
33356
- embedding.granularity !== void 0 ? "granularity" : null,
33357
- embedding.source_path !== void 0 ? "source_path" : null,
33358
- embedding.metadata !== void 0 ? "metadata" : null,
33359
- embedding.input_hash !== void 0 && !/^[0-9a-f]{64}$/.test(embedding.input_hash) ? "input_hash" : null
33360
- ].filter((field) => field !== null);
33361
- if (unmappedEmbeddingFields.length > 0) addLoss(
33362
- losses,
33363
- "aiwg-embedding-fields-unmapped",
33364
- "AIWG embedding fields without a native full-v1 field were omitted.",
33365
- {
33366
- component: "embeddings",
33367
- record_id: embedding.id ?? `${record.id}:${position}`,
33368
- source_state: "value",
33369
- action: "omit",
33370
- destination_capability: "native-embedding-fields",
33371
- reason: unmappedEmbeddingFields.join(",")
33372
- }
33373
- );
33374
- rows.get("embeddings").push({
33375
- id: uuid("embedding", embedding.id ?? `${record.id}:${position}`),
33376
- note_id: noteIds.get(record.id),
33377
- embedding_set_id: group.set,
33378
- chunk_index: position,
33379
- text: record.text ?? "",
33380
- vector,
33381
- model,
33382
- contract_fingerprint: /^[0-9a-f]{64}$/.test(embedding.input_hash ?? "") ? embedding.input_hash : null,
33383
- created_at: new Date(record.updated_at).toISOString()
33384
- });
33385
- }
33386
- }
33387
- for (const [model, group] of [...embeddingGroups].sort(([a], [b]) => a.localeCompare(b))) {
33388
- rows.get("embedding_configs").push({
33389
- id: group.config,
33390
- name: model,
33391
- description: null,
33392
- model,
33393
- dimension: 768,
33394
- chunk_size: 1,
33395
- chunk_overlap: 0,
33396
- hnsw_m: null,
33397
- hnsw_ef_construction: null,
33398
- ivfflat_lists: null,
33399
- is_default: null,
33400
- supports_mrl: null,
33401
- matryoshka_dims: null,
33402
- default_truncate_dim: null,
33403
- provider: null,
33404
- provider_config: null,
33405
- content_types: null,
33406
- strengths: null,
33407
- limitations: null,
33408
- recommended_for: null,
33409
- benchmark_scores: null,
33410
- is_available: null,
33411
- document_composition: {},
33412
- created_at: exportedAt,
33413
- updated_at: exportedAt
33414
- });
33415
- rows.get("embedding_sets").push({
33416
- id: group.set,
33417
- name: model,
33418
- slug: uuid("embedding-slug", model),
33419
- description: null,
33420
- purpose: null,
33421
- usage_hints: null,
33422
- keywords: null,
33423
- set_type: "full",
33424
- mode: "manual",
33425
- criteria: null,
33426
- embedding_config_id: group.config,
33427
- truncate_dim: null,
33428
- auto_embed_rules: null,
33429
- index_status: "ready",
33430
- index_type: null,
33431
- last_indexed_at: exportedAt,
33432
- document_count: null,
33433
- embedding_count: group.count,
33434
- embeddings_current: true,
33435
- index_size_bytes: null,
33436
- is_system: false,
33437
- is_active: true,
33438
- auto_refresh: false,
33439
- refresh_interval: null,
33440
- last_refresh_at: null,
33441
- agent_metadata: null,
33442
- created_at: exportedAt,
33443
- updated_at: exportedAt,
33444
- created_by: "aiwg-index"
33445
- });
33446
- const noteIdSet = new Set(rows.get("embeddings").filter((item) => item.embedding_set_id === group.set).map((item) => item.note_id));
33447
- for (const noteId of [...noteIdSet].sort()) rows.get("embedding_set_members").push({
33448
- embedding_set_id: group.set,
33449
- note_id: noteId,
33450
- membership_type: "materialized",
33451
- added_at: exportedAt,
33452
- added_by: "aiwg-index"
33453
- });
33454
- }
33455
- if (losses.length > 0) {
33456
- return {
33457
- success: false,
33458
- archive: null,
33459
- profile: "full-v1",
33460
- schema_version: "2.0.0",
33461
- lossless: false,
33462
- losses,
33463
- receipt: {
33464
- schema_version: "fortemi.aiwg-full-v1-conversion-receipt.v1",
33465
- source_schema_version: "aiwg.fortemi.index.export.v2",
33466
- authority_repository: knowledge_shard_v2_schema_receipt_default.source.repository,
33467
- authority_commit: knowledge_shard_v2_schema_receipt_default.source.commit,
33468
- authority_contract_sha256: knowledge_shard_v2_schema_receipt_default.source.contractSha256,
33469
- authority_schema_bundle_sha256: knowledge_shard_v2_schema_receipt_default.schemaBundle.sha256,
33470
- manifest_sha256: null,
33471
- component_checksums: {},
33472
- contract_valid: false,
33473
- signed: false
33474
- }
33475
- };
33476
- }
33477
- const files = /* @__PURE__ */ new Map();
33478
- const components = Object.keys(FULL_V1_COMPONENT_FILES);
33479
- const counts = { community_sets: 0 };
33480
- for (const component of components) {
33481
- const spec = FULL_V1_COMPONENT_FILES[component];
33482
- const componentRows = rows.get(component) ?? [];
33483
- files.set(spec.file, encode(componentRows, spec.encoding));
33484
- counts[component] = componentRows.length;
33485
- }
33486
- const checksums = {};
33487
- for (const [file, bytes] of files) checksums[file] = await sha256Hex(bytes);
33488
- const manifest = {
33489
- version: "2.0.0",
33490
- profile: "full-v1",
33491
- producer: { name: "fortemi-core-aiwg-index", version: options.matricVersion ?? "fortemi-core" },
33492
- format: SHARD_FORMAT,
33493
- created_at: exportedAt,
33494
- components,
33495
- counts,
33496
- checksums,
33497
- min_reader_version: "2.0.0"
33498
- };
33499
- const manifestBytes = encoder4.encode(JSON.stringify(manifest, null, 2));
33500
- files.set("manifest.json", manifestBytes);
33501
- const validation = await validateFullV1ShardArchive(files);
33502
- if (!validation.valid) {
33503
- throw new Error(`Generated AIWG full-v1 shard failed authority validation: ${validation.errors.join("; ")}`);
33504
- }
33505
- return {
33506
- success: true,
33507
- archive: packTarGz(files),
33508
- profile: "full-v1",
33509
- schema_version: "2.0.0",
33510
- lossless: losses.length === 0,
33511
- losses,
33512
- receipt: {
33513
- schema_version: "fortemi.aiwg-full-v1-conversion-receipt.v1",
33514
- source_schema_version: "aiwg.fortemi.index.export.v2",
33515
- authority_repository: knowledge_shard_v2_schema_receipt_default.source.repository,
33516
- authority_commit: knowledge_shard_v2_schema_receipt_default.source.commit,
33517
- authority_contract_sha256: knowledge_shard_v2_schema_receipt_default.source.contractSha256,
33518
- authority_schema_bundle_sha256: knowledge_shard_v2_schema_receipt_default.schemaBundle.sha256,
33519
- manifest_sha256: await sha256Hex(manifestBytes),
33520
- component_checksums: checksums,
33521
- contract_valid: true,
33522
- signed: false
33523
- }
33524
- };
33525
- }
33526
-
33527
- // src/aiwg-index-shard.ts
33528
- var AIWG_SHARD_UUID_NAMESPACE = "7ab5d1f8-29d2-5e35-9e2f-3a45de171a9e";
33529
- var shardEncoder = new TextEncoder();
33530
- var shardDecoder = new TextDecoder();
33531
- function aiwgShardUuid(kind, id) {
33532
- return v5(`${kind}:${id}`, AIWG_SHARD_UUID_NAMESPACE);
33533
- }
33534
- function aiwgShardTimestamp(value, fallback) {
33535
- if (!value || Number.isNaN(Date.parse(value))) return fallback;
33536
- return new Date(value).toISOString();
33537
- }
33538
- function aiwgRecordTitle(record) {
33539
- return record.title ?? record.search?.title ?? record.search?.name ?? record.id;
33540
- }
33541
- function aiwgRecordContent(record) {
33542
- if (record.text) return record.text;
33543
- if (record.search?.body) return record.search.body;
33544
- const chunks = record.chunks?.map((chunk) => chunk.text ?? chunk.body ?? chunk.summary ?? "").filter(Boolean);
33545
- if (chunks?.length) return chunks.join("\n\n");
33546
- return record.search?.summary ?? "";
33547
- }
33548
- function aiwgShardMetadata(index, record) {
33549
- return {
33550
- aiwg_fortemi_index: {
33551
- envelope: {
33552
- schema_version: index.schema_version,
33553
- generated_at: index.generated_at,
33554
- source: index.source,
33555
- ...index.compatibility ? { compatibility: index.compatibility } : {}
33556
- },
33557
- record
33558
- }
33559
- };
33560
- }
33561
- function encodeJsonLines(values) {
33562
- return shardEncoder.encode(values.map((value) => JSON.stringify(value)).join("\n"));
33563
- }
33564
- async function aiwgFortemiIndexToKnowledgeShard(index, options = {}) {
33565
- if (options.includeNativeRichComponents) {
33566
- throw new Error(
33567
- "Native AIWG full-v1 conversion requires aiwgFortemiIndexToKnowledgeShardWithReport so semantic losses cannot be discarded"
33568
- );
33569
- }
33570
- const validation = validateAiwgFortemiIndexExport(index);
33571
- if (!validation.valid) {
33572
- throw new Error(`Invalid AIWG Fortemi index export:
33573
- ${validation.errors.join("\n")}`);
33574
- }
33575
- if (index.schema_version !== "aiwg.fortemi.index.export.v2") {
33576
- throw new Error("Knowledge Shard conversion requires aiwg.fortemi.index.export.v2");
33577
- }
33578
- const createdAt2 = aiwgShardTimestamp(options.createdAt ?? index.generated_at, (/* @__PURE__ */ new Date()).toISOString());
33579
- const noteIds = new Map(index.items.map((record) => [record.id, aiwgShardUuid("record", record.id)]));
33580
- const notes = index.items.map((record) => {
33581
- const content = aiwgRecordContent(record);
33582
- return {
33583
- id: noteIds.get(record.id),
33584
- title: aiwgRecordTitle(record),
33585
- original_content: content,
33586
- revised_content: content,
33587
- metadata: aiwgShardMetadata(index, record),
33588
- collection_id: null,
33589
- attachments: [],
33590
- format: "markdown",
33591
- source: "aiwg-index",
33592
- starred: false,
33593
- archived: false,
33594
- tags: [...new Set(record.tags)].sort(),
33595
- created_at: aiwgShardTimestamp(record.source.updated_at ?? record.updated_at, createdAt2),
33596
- updated_at: aiwgShardTimestamp(record.updated_at, createdAt2),
33597
- deleted_at: null
33598
- };
33599
- });
33600
- const links = [];
33601
- for (const record of index.items) {
33602
- for (const [position, relationship] of record.relationships.entries()) {
33603
- const targetNoteId = noteIds.get(relationship.target_id) ?? null;
33604
- links.push({
33605
- id: aiwgShardUuid(
33606
- "relationship",
33607
- `${record.id}\0${position}\0${relationship.type}\0${relationship.target_id}`
33608
- ),
33609
- from_note_id: noteIds.get(record.id),
33610
- to_note_id: targetNoteId,
33611
- to_url: targetNoteId ? null : `aiwg://record/${encodeURIComponent(relationship.target_id)}`,
33612
- kind: relationship.type,
33613
- score: relationship.confidence ?? 1,
33614
- created_at: aiwgShardTimestamp(record.updated_at, createdAt2),
33615
- metadata: {
33616
- aiwg_fortemi_index: {
33617
- source_record_id: record.id,
33618
- target_record_id: relationship.target_id,
33619
- relationship
33620
- }
33621
- }
33622
- });
33623
- }
33624
- }
33625
- const files = /* @__PURE__ */ new Map();
33626
- const components = ["notes", "tags"];
33627
- const counts = {
33628
- notes: notes.length,
33629
- tags: [...new Set(notes.flatMap((note) => note.tags))].length
33630
- };
33631
- files.set("notes.jsonl", encodeJsonLines(notes));
33632
- files.set("tags.json", shardEncoder.encode(JSON.stringify(
33633
- [...new Set(notes.flatMap((note) => note.tags))].sort().map((name) => ({ name, created_at: createdAt2 }))
33634
- )));
33635
- const addComponent = (component, filename, values, jsonLines = true) => {
33636
- if (values.length === 0) return;
33637
- components.push(component);
33638
- counts[component] = values.length;
33639
- files.set(filename, jsonLines ? encodeJsonLines(values) : shardEncoder.encode(JSON.stringify(values)));
33640
- };
33641
- addComponent("links", "links.jsonl", links);
33642
- const checksums = {};
33643
- for (const [filename, bytes] of files) checksums[filename] = await sha256Hex(bytes);
33644
- const manifest = {
33645
- version: CURRENT_SHARD_VERSION,
33646
- profile: "core-v1",
33647
- producer: {
33648
- name: "fortemi-core-aiwg-index",
33649
- version: options.matricVersion ?? "fortemi-core"
33650
- },
33651
- format: SHARD_FORMAT,
33652
- created_at: createdAt2,
33653
- components,
33654
- counts: {
33655
- notes: 0,
33656
- collections: 0,
33657
- tags: 0,
33658
- templates: 0,
33659
- links: 0,
33660
- embedding_sets: 0,
33661
- embedding_set_members: 0,
33662
- embeddings: 0,
33663
- embedding_configs: 0,
33664
- ...counts
33665
- },
33666
- checksums,
33667
- min_reader_version: CURRENT_SHARD_VERSION
33668
- };
33669
- files.set("manifest.json", shardEncoder.encode(JSON.stringify(manifest, null, 2)));
33670
- const contractValidation = await validateCoreV1ShardArchive(files);
33671
- if (!contractValidation.valid) {
33672
- throw new Error(
33673
- `Generated AIWG core-v1 shard failed canonical validation: ${contractValidation.errors.join("; ")}`
33674
- );
33675
- }
33676
- return packTarGz(files);
33677
- }
33678
- async function aiwgFortemiIndexToKnowledgeShardWithReport(index, options = {}) {
33679
- const validation = validateAiwgFortemiIndexExport(index);
33680
- if (!validation.valid) {
33681
- throw new Error(`Invalid AIWG Fortemi index export:
33682
- ${validation.errors.join("\n")}`);
33683
- }
33684
- if (index.schema_version !== "aiwg.fortemi.index.export.v2") {
33685
- throw new Error("Full-v1 Knowledge Shard conversion requires aiwg.fortemi.index.export.v2");
33686
- }
33687
- return convertAiwgIndexToFullV1(index, options);
33688
- }
33689
- function aiwgFortemiIndexFromKnowledgeShard(bytes) {
33690
- const files = unpackTarGz(bytes);
33691
- const noteBytes = files.get("notes.jsonl");
33692
- const notes = (noteBytes ? shardDecoder.decode(noteBytes) : "").split("\n").filter(Boolean).map((line) => JSON.parse(line));
33693
- if (notes.length === 0) throw new Error("Knowledge Shard contains no AIWG index notes");
33694
- let envelope;
33695
- const items = [];
33696
- for (const note of notes) {
33697
- const metadata = note.metadata && typeof note.metadata === "object" && !Array.isArray(note.metadata) ? note.metadata.aiwg_fortemi_index : void 0;
33698
- if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
33699
- throw new Error(`Knowledge Shard note ${note.id} has no AIWG index metadata`);
33700
- }
33701
- const value = metadata;
33702
- envelope ??= value.envelope;
33703
- items.push(value.record);
33704
- }
33705
- const restored = {
33706
- ...envelope,
33707
- items: items.sort((left, right) => left.id.localeCompare(right.id))
33708
- };
33709
- const validation = validateAiwgFortemiIndexExport(restored);
33710
- if (!validation.valid) {
33711
- throw new Error(`Knowledge Shard contains invalid AIWG index metadata:
33712
- ${validation.errors.join("\n")}`);
33713
- }
33714
- return restored;
33715
- }
33716
-
33717
- // schemas/aiwg-fortemi-index-export.schema.json
33718
- var aiwg_fortemi_index_export_schema_default = {
33719
- $schema: "https://json-schema.org/draft/2020-12/schema",
33720
- $id: "https://aiwg.io/schemas/aiwg-fortemi-index-export.json",
33721
- title: "AIWG Fortemi Index Export",
33722
- type: "object",
33723
- additionalProperties: false,
33724
- required: ["schema_version", "generated_at", "source", "items"],
33725
- properties: {
33726
- schema_version: {
33727
- enum: ["aiwg.fortemi.index.export.v1", "aiwg.fortemi.index.export.v2"]
33728
- },
33729
- generated_at: {
33730
- type: "string",
33731
- format: "date-time"
33732
- },
33733
- source: {
33734
- type: "object",
33735
- additionalProperties: false,
33736
- required: ["repo", "privacy"],
33737
- properties: {
33738
- repo: {
33739
- type: "string",
33740
- minLength: 1
33741
- },
33742
- privacy: {
33743
- $ref: "#/$defs/privacy"
33744
- },
33745
- graph: {
33746
- type: "string",
33747
- minLength: 1
33748
- }
33749
- }
33750
- },
33751
- compatibility: {
33752
- type: "object",
33753
- additionalProperties: false,
33754
- required: ["previous_schema_version", "strategy"],
33755
- properties: {
33756
- previous_schema_version: {
33757
- const: "aiwg.fortemi.index.export.v1"
33758
- },
33759
- strategy: {
33760
- const: "supported"
33761
- }
33762
- }
33763
- },
33764
- items: {
33765
- type: "array",
33766
- items: {
33767
- $ref: "#/$defs/record"
33768
- }
33769
- }
33770
- },
33771
- allOf: [
33772
- {
33773
- if: {
33774
- properties: {
33775
- schema_version: {
33776
- const: "aiwg.fortemi.index.export.v1"
33777
- }
33778
- }
33779
- },
33780
- then: {
33781
- not: {
33782
- required: ["compatibility"]
33783
- },
33784
- properties: {
33785
- source: {
33786
- not: {
33787
- required: ["graph"]
33788
- }
33789
- },
33790
- items: {
33791
- items: {
33792
- allOf: [
33793
- {
33794
- properties: {
33795
- schema_version: {
33796
- const: "aiwg.fortemi.index.record.v1"
33797
- }
33798
- }
33799
- },
33800
- {
33801
- $ref: "#/$defs/v1RecordCompatibility"
33802
- }
33803
- ]
33804
- }
33805
- }
33806
- }
33807
- }
33808
- },
33809
- {
33810
- if: {
33811
- properties: {
33812
- schema_version: {
33813
- const: "aiwg.fortemi.index.export.v2"
33814
- }
33815
- }
33816
- },
33817
- then: {
33818
- required: ["compatibility"],
33819
- properties: {
33820
- source: {
33821
- required: ["graph"]
33822
- },
33823
- items: {
33824
- items: {
33825
- properties: {
33826
- schema_version: {
33827
- const: "aiwg.fortemi.index.record.v2"
33828
- }
33829
- }
33830
- }
33831
- }
33832
- }
33833
- }
33834
- }
33835
- ],
33836
- $defs: {
33837
- privacy: {
33838
- enum: ["private", "sanitized", "public"]
33839
- },
33840
- recordType: {
33841
- type: "string",
33842
- minLength: 1
33843
- },
33844
- stringArray: {
33845
- type: "array",
33846
- items: {
33847
- type: "string"
33848
- }
33849
- },
33850
- numberArray: {
33851
- type: "array",
33852
- items: {
33853
- type: "number"
33854
- }
33855
- },
33856
- v1RecordCompatibility: {
33857
- type: "object",
33858
- not: {
33859
- anyOf: [
33860
- {
33861
- required: ["name"]
33862
- },
33863
- {
33864
- required: ["summary"]
33865
- },
33866
- {
33867
- required: ["search"]
33868
- },
33869
- {
33870
- required: ["chunks"]
33871
- },
33872
- {
33873
- required: ["embeddings"]
33874
- },
33875
- {
33876
- required: ["compatibility"]
33877
- },
33878
- {
33879
- required: ["skos_concepts"]
33880
- },
33881
- {
33882
- required: ["skos_relations"]
33883
- },
33884
- {
33885
- required: ["provenance_events"]
33886
- }
33887
- ]
33888
- },
33889
- properties: {
33890
- source: {
33891
- not: {
33892
- anyOf: [
33893
- {
33894
- required: ["origin"]
33895
- },
33896
- {
33897
- required: ["generated"]
33898
- },
33899
- {
33900
- required: ["checksum"]
33901
- },
33902
- {
33903
- required: ["updated_at"]
33904
- }
33905
- ]
33906
- }
33907
- },
33908
- relationships: {
33909
- items: {
33910
- not: {
33911
- anyOf: [
33912
- {
33913
- required: ["target_path"]
33914
- },
33915
- {
33916
- required: ["direction"]
33917
- },
33918
- {
33919
- required: ["label"]
33920
- },
33921
- {
33922
- required: ["confidence"]
33923
- },
33924
- {
33925
- required: ["privacy"]
33926
- },
33927
- {
33928
- required: ["metadata"]
33929
- }
33930
- ]
33931
- }
33932
- }
33933
- },
33934
- privacy: {
33935
- not: {
33936
- required: ["locality"]
33937
- }
33938
- }
33261
+ },
33262
+ privacy: {
33263
+ not: {
33264
+ required: ["locality"]
33265
+ }
33266
+ }
33939
33267
  }
33940
33268
  },
33941
33269
  record: {
@@ -34177,258 +33505,1284 @@ var aiwg_fortemi_index_export_schema_default = {
34177
33505
  summary: {
34178
33506
  type: "string"
34179
33507
  },
34180
- source_path: {
33508
+ source_path: {
33509
+ type: "string"
33510
+ },
33511
+ metadata: {
33512
+ type: "object"
33513
+ },
33514
+ checksum: {
33515
+ type: "string"
33516
+ }
33517
+ }
33518
+ }
33519
+ },
33520
+ embeddings: {
33521
+ type: "array",
33522
+ items: {
33523
+ type: "object",
33524
+ additionalProperties: false,
33525
+ properties: {
33526
+ id: {
33527
+ type: "string"
33528
+ },
33529
+ model: {
33530
+ type: "string"
33531
+ },
33532
+ embedding: {
33533
+ $ref: "#/$defs/numberArray"
33534
+ },
33535
+ vector: {
33536
+ $ref: "#/$defs/numberArray"
33537
+ },
33538
+ granularity: {
33539
+ type: "string"
33540
+ },
33541
+ source_path: {
33542
+ type: "string"
33543
+ },
33544
+ metadata: {
33545
+ type: "object"
33546
+ },
33547
+ chunk_id: {
33548
+ type: "string"
33549
+ },
33550
+ vector_ref: {
33551
+ type: "string"
33552
+ },
33553
+ input_hash: {
33554
+ type: "string"
33555
+ }
33556
+ }
33557
+ }
33558
+ },
33559
+ compatibility: {
33560
+ type: "object"
33561
+ },
33562
+ skos_concepts: {
33563
+ type: "array",
33564
+ items: {
33565
+ type: "object",
33566
+ additionalProperties: false,
33567
+ required: ["id", "prefLabel"],
33568
+ properties: {
33569
+ id: {
33570
+ type: "string",
33571
+ minLength: 1
33572
+ },
33573
+ prefLabel: {
33574
+ type: "string",
33575
+ minLength: 1
33576
+ },
33577
+ definition: {
33578
+ type: "string"
33579
+ },
33580
+ scheme: {
33581
+ type: "string"
33582
+ },
33583
+ notation: {
33584
+ type: "string"
33585
+ },
33586
+ uri: {
33587
+ type: "string"
33588
+ },
33589
+ altLabels: {
33590
+ $ref: "#/$defs/stringArray"
33591
+ },
33592
+ metadata: {
33593
+ type: "object"
33594
+ }
33595
+ }
33596
+ }
33597
+ },
33598
+ skos_relations: {
33599
+ type: "array",
33600
+ items: {
33601
+ type: "object",
33602
+ additionalProperties: false,
33603
+ required: ["type", "source_id", "target_id"],
33604
+ properties: {
33605
+ type: {
33606
+ type: "string",
33607
+ minLength: 1
33608
+ },
33609
+ source_id: {
33610
+ type: "string",
33611
+ minLength: 1
33612
+ },
33613
+ target_id: {
33614
+ type: "string",
33615
+ minLength: 1
33616
+ },
33617
+ source_path: {
33618
+ type: "string"
33619
+ },
33620
+ metadata: {
33621
+ type: "object"
33622
+ }
33623
+ }
33624
+ }
33625
+ },
33626
+ provenance_events: {
33627
+ type: "array",
33628
+ items: {
33629
+ type: "object",
33630
+ additionalProperties: false,
33631
+ required: ["activity"],
33632
+ properties: {
33633
+ id: {
33634
+ type: "string"
33635
+ },
33636
+ activity: {
33637
+ type: "string",
33638
+ minLength: 1
33639
+ },
33640
+ agent: {
33641
+ type: "string"
33642
+ },
33643
+ started_at: {
33644
+ type: "string",
33645
+ format: "date-time"
33646
+ },
33647
+ ended_at: {
33648
+ type: "string",
33649
+ format: "date-time"
33650
+ },
33651
+ source: {
33652
+ type: "string"
33653
+ },
33654
+ path: {
34181
33655
  type: "string"
34182
33656
  },
34183
- metadata: {
34184
- type: "object"
33657
+ confidence: {
33658
+ enum: ["source", "candidate", "reviewed", "rejected"]
34185
33659
  },
34186
- checksum: {
34187
- type: "string"
33660
+ privacy: {
33661
+ $ref: "#/$defs/privacy"
33662
+ },
33663
+ attributes: {
33664
+ type: "object"
34188
33665
  }
34189
33666
  }
34190
33667
  }
34191
- },
34192
- embeddings: {
34193
- type: "array",
34194
- items: {
34195
- type: "object",
34196
- additionalProperties: false,
34197
- properties: {
34198
- id: {
34199
- type: "string"
34200
- },
34201
- model: {
34202
- type: "string"
34203
- },
34204
- embedding: {
34205
- $ref: "#/$defs/numberArray"
34206
- },
34207
- vector: {
34208
- $ref: "#/$defs/numberArray"
34209
- },
34210
- granularity: {
34211
- type: "string"
34212
- },
34213
- source_path: {
34214
- type: "string"
34215
- },
34216
- metadata: {
34217
- type: "object"
34218
- },
34219
- chunk_id: {
34220
- type: "string"
34221
- },
34222
- vector_ref: {
34223
- type: "string"
34224
- },
34225
- input_hash: {
34226
- type: "string"
34227
- }
34228
- }
33668
+ },
33669
+ operational_state: {
33670
+ $ref: "#/$defs/operationalState"
33671
+ },
33672
+ state_transfer: {
33673
+ $ref: "#/$defs/stateTransfer"
33674
+ },
33675
+ updated_at: {
33676
+ type: "string",
33677
+ format: "date-time"
33678
+ }
33679
+ }
33680
+ },
33681
+ operationalState: {
33682
+ type: "object",
33683
+ additionalProperties: false,
33684
+ required: ["classification"],
33685
+ properties: {
33686
+ source_repo: { type: "string", minLength: 1 },
33687
+ source_kind: { type: "string", minLength: 1 },
33688
+ source_id: { type: "string", minLength: 1 },
33689
+ observed_state: { type: "string", minLength: 1 },
33690
+ observed_at: { type: "string", format: "date-time" },
33691
+ source_updated_at: { type: "string", format: "date-time" },
33692
+ evidence_url: { type: "string", format: "uri" },
33693
+ evidence_path: { type: "string", minLength: 1 },
33694
+ observer: { type: "string", minLength: 1 },
33695
+ supersedes: { $ref: "#/$defs/stringArray" },
33696
+ contradicts: { $ref: "#/$defs/stringArray" },
33697
+ stale_after: { type: "string", format: "date-time" },
33698
+ classification: {
33699
+ enum: ["fresh", "historical", "superseded", "contradicted", "needs-source"]
33700
+ },
33701
+ confidence: {
33702
+ enum: ["source", "candidate", "reviewed", "rejected"]
33703
+ },
33704
+ current_action_selector: { type: "boolean" }
33705
+ }
33706
+ },
33707
+ stateTransfer: {
33708
+ type: "object",
33709
+ additionalProperties: false,
33710
+ required: ["deleted_at"],
33711
+ properties: {
33712
+ deleted_at: {
33713
+ type: ["string", "null"],
33714
+ format: "date-time"
33715
+ }
33716
+ }
33717
+ }
33718
+ }
33719
+ };
33720
+
33721
+ // src/aiwg-index-schema.ts
33722
+ var PROJECTED_FIELDS = [
33723
+ "schema_version",
33724
+ "id",
33725
+ "type",
33726
+ "title",
33727
+ "text",
33728
+ "facets",
33729
+ "tags",
33730
+ "concepts",
33731
+ "privacy"
33732
+ ];
33733
+ var ajvInstance;
33734
+ var exportValidator;
33735
+ var projectedRecordValidator;
33736
+ function getAiwgFortemiIndexExportSchema() {
33737
+ return aiwg_fortemi_index_export_schema_default;
33738
+ }
33739
+ function getAjv() {
33740
+ if (!ajvInstance) {
33741
+ ajvInstance = new Ajv2020({
33742
+ allErrors: true,
33743
+ strict: false,
33744
+ validateFormats: false
33745
+ });
33746
+ ajvInstance.addSchema(aiwg_fortemi_index_export_schema_default);
33747
+ }
33748
+ return ajvInstance;
33749
+ }
33750
+ function formatErrors2(errors) {
33751
+ return (errors ?? []).map((error) => {
33752
+ const path = error.instancePath || "(root)";
33753
+ return `${path} ${error.message ?? "is invalid"}`;
33754
+ });
33755
+ }
33756
+ function getExportValidator() {
33757
+ exportValidator ??= getAjv().getSchema(aiwg_fortemi_index_export_schema_default.$id) ?? getAjv().compile(aiwg_fortemi_index_export_schema_default);
33758
+ return exportValidator;
33759
+ }
33760
+ function getProjectedRecordValidator() {
33761
+ if (!projectedRecordValidator) {
33762
+ const properties = Object.fromEntries(Object.keys(aiwg_fortemi_index_export_schema_default.$defs.record.properties).map((field) => [
33763
+ field,
33764
+ { $ref: `${aiwg_fortemi_index_export_schema_default.$id}#/$defs/record/properties/${field}` }
33765
+ ]));
33766
+ projectedRecordValidator = getAjv().compile({
33767
+ type: "object",
33768
+ required: PROJECTED_FIELDS,
33769
+ properties,
33770
+ additionalProperties: true,
33771
+ allOf: [
33772
+ {
33773
+ if: {
33774
+ properties: {
33775
+ schema_version: { const: "aiwg.fortemi.index.record.v1" }
33776
+ }
33777
+ },
33778
+ then: { $ref: `${aiwg_fortemi_index_export_schema_default.$id}#/$defs/v1RecordCompatibility` }
33779
+ }
33780
+ ]
33781
+ });
33782
+ }
33783
+ return projectedRecordValidator;
33784
+ }
33785
+ function validateAiwgFortemiIndexExportSchema(value) {
33786
+ const validate = getExportValidator();
33787
+ const schemaValue = value && typeof value === "object" && Array.isArray(value.items) ? {
33788
+ ...value,
33789
+ items: value.items.map((item) => {
33790
+ if (!item || typeof item !== "object" || Array.isArray(item)) return item;
33791
+ const schemaRecord = { ...item };
33792
+ Reflect.deleteProperty(schemaRecord, "binary_sources");
33793
+ return schemaRecord;
33794
+ })
33795
+ } : value;
33796
+ const valid = validate(schemaValue);
33797
+ return { valid, errors: formatErrors2(validate.errors) };
33798
+ }
33799
+ function validateAiwgFortemiProjectedRecordSchema(value) {
33800
+ const validate = getProjectedRecordValidator();
33801
+ const valid = validate(value);
33802
+ return { valid, errors: formatErrors2(validate.errors) };
33803
+ }
33804
+ var encoder4 = new TextEncoder();
33805
+ var UUID_NAMESPACE = "7ab5d1f8-29d2-5e35-9e2f-3a45de171a9e";
33806
+ function uuid(kind, id) {
33807
+ return v5(`${kind}:${id}`, UUID_NAMESPACE);
33808
+ }
33809
+ function own(value, field) {
33810
+ return Object.prototype.hasOwnProperty.call(value, field);
33811
+ }
33812
+ function timestamp(value) {
33813
+ if (!value || Number.isNaN(Date.parse(value))) return void 0;
33814
+ return new Date(value).toISOString();
33815
+ }
33816
+ function addLoss(losses, code, message, details = {}) {
33817
+ losses.push({ code, message, ...details });
33818
+ }
33819
+ function encode(values, encoding) {
33820
+ return encoder4.encode(encoding === "json-array" ? JSON.stringify(values) : values.map((value) => JSON.stringify(value)).join("\n"));
33821
+ }
33822
+ function noteTitle(record, losses) {
33823
+ if (own(record, "title")) return record.title ?? null;
33824
+ const derived = record.search?.title ?? record.search?.name;
33825
+ addLoss(losses, "aiwg-title-not-native", derived ? "Title was derived from the AIWG search projection." : "AIWG supplied no title; the nullable destination field is null.", {
33826
+ component: "notes",
33827
+ record_id: record.id,
33828
+ field_path: "/title",
33829
+ source_state: "absent",
33830
+ destination_capability: "nullable-value",
33831
+ action: derived ? "degrade" : "default"
33832
+ });
33833
+ return derived ?? null;
33834
+ }
33835
+ function noteContent(record, losses) {
33836
+ if (own(record, "text")) return record.text ?? "";
33837
+ if (own(record.search ?? {}, "body")) {
33838
+ addLoss(
33839
+ losses,
33840
+ "aiwg-content-search-projection",
33841
+ "Content was derived from the AIWG search projection.",
33842
+ {
33843
+ component: "notes",
33844
+ record_id: record.id,
33845
+ field_path: "/original_content",
33846
+ source_state: "absent",
33847
+ destination_capability: "required-string",
33848
+ action: "degrade"
33849
+ }
33850
+ );
33851
+ return record.search?.body ?? "";
33852
+ }
33853
+ if (record.chunks?.length) {
33854
+ addLoss(losses, "aiwg-content-chunk-projection", "Content was assembled from AIWG chunks.", {
33855
+ component: "notes",
33856
+ record_id: record.id,
33857
+ field_path: "/original_content",
33858
+ source_state: "absent",
33859
+ destination_capability: "required-string",
33860
+ action: "degrade"
33861
+ });
33862
+ return record.chunks.map((chunk) => {
33863
+ if (own(chunk, "text")) return chunk.text ?? "";
33864
+ if (own(chunk, "body")) return chunk.body ?? "";
33865
+ if (own(chunk, "summary")) return chunk.summary ?? "";
33866
+ return "";
33867
+ }).join("\n\n");
33868
+ }
33869
+ addLoss(
33870
+ losses,
33871
+ "aiwg-content-unavailable",
33872
+ "AIWG supplied no body; the required destination string is empty.",
33873
+ {
33874
+ component: "notes",
33875
+ record_id: record.id,
33876
+ field_path: "/original_content",
33877
+ source_state: "absent",
33878
+ destination_capability: "required-string",
33879
+ action: "default"
33880
+ }
33881
+ );
33882
+ return "";
33883
+ }
33884
+ function createdAt(record, losses) {
33885
+ const source = timestamp(record.source.updated_at);
33886
+ if (source) return source;
33887
+ addLoss(
33888
+ losses,
33889
+ "aiwg-created-at-unavailable",
33890
+ "AIWG has no distinct creation timestamp; updated_at was used.",
33891
+ {
33892
+ component: "notes",
33893
+ record_id: record.id,
33894
+ field_path: "/created_at",
33895
+ source_state: "absent",
33896
+ destination_capability: "required-date-time",
33897
+ action: "default"
33898
+ }
33899
+ );
33900
+ return new Date(record.updated_at).toISOString();
33901
+ }
33902
+ function safeUri(value) {
33903
+ if (!value) return null;
33904
+ try {
33905
+ return new URL(value).toString();
33906
+ } catch {
33907
+ return null;
33908
+ }
33909
+ }
33910
+ function schemeName(concept) {
33911
+ return concept.scheme && concept.scheme.length > 0 ? concept.scheme : "aiwg";
33912
+ }
33913
+ async function convertAiwgIndexToFullV1(index, options = {}) {
33914
+ const losses = [];
33915
+ const exportedAt = timestamp(options.createdAt) ?? new Date(index.generated_at).toISOString();
33916
+ const records = [...index.items].sort((a, b) => a.id.localeCompare(b.id));
33917
+ const noteIds = new Map(records.map((record) => [record.id, uuid("record", record.id)]));
33918
+ const rows = /* @__PURE__ */ new Map();
33919
+ for (const component of Object.keys(FULL_V1_COMPONENT_FILES)) rows.set(component, []);
33920
+ const tags = /* @__PURE__ */ new Set();
33921
+ for (const record of records) {
33922
+ const noteId = noteIds.get(record.id);
33923
+ const content = noteContent(record, losses);
33924
+ const sourceCreatedAt = createdAt(record, losses);
33925
+ const updatedAt = new Date(record.updated_at).toISOString();
33926
+ const recordTags = [...new Set(record.tags)].sort();
33927
+ recordTags.forEach((tag) => tags.add(tag));
33928
+ if (record.binary_sources?.length) {
33929
+ addLoss(
33930
+ losses,
33931
+ "aiwg-attachment-bytes-unavailable",
33932
+ "Attachment references have no bytes, so full-v1 attachment projections were omitted.",
33933
+ {
33934
+ component: "notes",
33935
+ count: record.binary_sources.length,
33936
+ record_id: record.id,
33937
+ field_path: "/attachments",
33938
+ source_state: "value",
33939
+ destination_capability: "mandatory-blob-sidecar",
33940
+ action: "omit"
33941
+ }
33942
+ );
33943
+ }
33944
+ const unmappedRecordFields = [
33945
+ Object.keys(record.facets).length > 0 ? "facets" : null,
33946
+ record.search !== void 0 ? "search" : null,
33947
+ record.chunks !== void 0 ? "chunks" : null,
33948
+ record.compatibility !== void 0 ? "compatibility" : null
33949
+ ].filter((field) => field !== null);
33950
+ if (unmappedRecordFields.length > 0) {
33951
+ addLoss(
33952
+ losses,
33953
+ "aiwg-record-fields-unmapped",
33954
+ "AIWG fields without a native full-v1 component were not hidden in note metadata.",
33955
+ {
33956
+ component: "notes",
33957
+ record_id: record.id,
33958
+ source_state: "value",
33959
+ action: "omit",
33960
+ destination_capability: "native-full-v1-components",
33961
+ reason: unmappedRecordFields.join(",")
33962
+ }
33963
+ );
33964
+ }
33965
+ rows.get("notes").push({
33966
+ id: noteId,
33967
+ title: noteTitle(record, losses),
33968
+ original_content: content,
33969
+ revised_content: content,
33970
+ metadata: { aiwg_source: {
33971
+ record_id: record.id,
33972
+ record_type: record.type,
33973
+ repository: index.source.repo,
33974
+ graph: index.source.graph ?? null,
33975
+ source: record.source,
33976
+ privacy: record.privacy
33977
+ } },
33978
+ format: "markdown",
33979
+ source: "aiwg-index",
33980
+ starred: false,
33981
+ archived: false,
33982
+ collection_id: null,
33983
+ created_at: sourceCreatedAt,
33984
+ updated_at: updatedAt,
33985
+ tags: recordTags,
33986
+ attachments: []
33987
+ });
33988
+ const hash = await sha256Hex(encoder4.encode(content));
33989
+ rows.get("note_originals").push({
33990
+ id: uuid("note-original", record.id),
33991
+ note_id: noteId,
33992
+ content,
33993
+ hash: `sha256:${hash}`,
33994
+ user_created_at: sourceCreatedAt,
33995
+ user_last_edited_at: updatedAt,
33996
+ version_number: 1
33997
+ });
33998
+ rows.get("note_revised_current").push({
33999
+ note_id: noteId,
34000
+ content,
34001
+ last_revision_id: null,
34002
+ ai_metadata: null
34003
+ });
34004
+ }
34005
+ rows.set("tags", [...tags].sort().map((name) => ({ name, created_at: exportedAt })));
34006
+ const relationshipInput = [];
34007
+ for (const record of records) {
34008
+ for (const [position, relationship] of record.relationships.entries()) {
34009
+ const target = noteIds.get(relationship.target_id) ?? null;
34010
+ const key = `${record.id}\0${position}\0${relationship.type}\0${relationship.target_id}`;
34011
+ rows.get("links").push({
34012
+ id: uuid("relationship", key),
34013
+ from_note_id: noteIds.get(record.id),
34014
+ to_note_id: target,
34015
+ to_url: target ? null : `aiwg://record/${encodeURIComponent(relationship.target_id)}`,
34016
+ kind: relationship.type,
34017
+ score: own(relationship, "confidence") ? relationship.confidence ?? null : null,
34018
+ created_at: new Date(record.updated_at).toISOString(),
34019
+ metadata: target ? relationship.metadata ?? null : {
34020
+ direction: relationship.direction ?? null,
34021
+ label: relationship.label ?? null,
34022
+ privacy: relationship.privacy ?? null,
34023
+ source_path: relationship.source_path ?? null,
34024
+ target_path: relationship.target_path ?? null,
34025
+ source_metadata: relationship.metadata ?? null
34026
+ }
34027
+ });
34028
+ relationshipInput.push({ source: record.id, position, relationship });
34029
+ if (!target) continue;
34030
+ let weight = relationship.confidence;
34031
+ if (weight === void 0) {
34032
+ weight = 1;
34033
+ addLoss(
34034
+ losses,
34035
+ "aiwg-relationship-weight-unavailable",
34036
+ "Graph weight defaulted because relationship confidence is absent.",
34037
+ {
34038
+ component: "graph_edges",
34039
+ record_id: record.id,
34040
+ field_path: `/relationships/${position}/confidence`,
34041
+ source_state: "absent",
34042
+ destination_capability: "required-number",
34043
+ action: "default"
34044
+ }
34045
+ );
34046
+ }
34047
+ rows.get("graph_edges").push({
34048
+ graph_source_id: "aiwg-relationships",
34049
+ from_note_id: noteIds.get(record.id),
34050
+ to_note_id: target,
34051
+ weight,
34052
+ kind: "manual",
34053
+ rank: position,
34054
+ metadata: {
34055
+ type: relationship.type,
34056
+ direction: relationship.direction ?? null,
34057
+ label: relationship.label ?? null,
34058
+ privacy: relationship.privacy ?? null,
34059
+ source_path: relationship.source_path ?? null,
34060
+ target_path: relationship.target_path ?? null,
34061
+ source_metadata: relationship.metadata ?? null
34062
+ }
34063
+ });
34064
+ }
34065
+ }
34066
+ if (rows.get("graph_edges").length) {
34067
+ rows.get("graph_sources").push({
34068
+ id: "aiwg-relationships",
34069
+ name: "AIWG relationships",
34070
+ kind: "imported",
34071
+ source_table: "manual",
34072
+ embedding_set_id: null,
34073
+ virtual_set_id: null,
34074
+ model: null,
34075
+ dimension: null,
34076
+ truncate_dimension: null,
34077
+ metric: null,
34078
+ algorithm: null,
34079
+ parameters: null,
34080
+ input_hash: `sha256:${await sha256Hex(encoder4.encode(JSON.stringify(relationshipInput)))}`,
34081
+ freshness: { status: "fresh", checked_at: exportedAt },
34082
+ created_at: exportedAt
34083
+ });
34084
+ }
34085
+ const concepts = /* @__PURE__ */ new Map();
34086
+ const conceptMembers = /* @__PURE__ */ new Map();
34087
+ for (const record of records) {
34088
+ for (const id of record.concepts) {
34089
+ conceptMembers.set(id, [...conceptMembers.get(id) ?? [], record]);
34090
+ }
34091
+ for (const concept of record.skos_concepts ?? []) {
34092
+ const existing = concepts.get(concept.id);
34093
+ if (existing && JSON.stringify(existing) !== JSON.stringify(concept)) {
34094
+ addLoss(
34095
+ losses,
34096
+ "aiwg-skos-concept-conflict",
34097
+ "Different metadata was supplied for one concept; the first sorted record won.",
34098
+ {
34099
+ component: "skos_concepts",
34100
+ record_id: concept.id,
34101
+ destination_capability: "single-concept-identity",
34102
+ action: "degrade"
34229
34103
  }
34230
- },
34231
- compatibility: {
34232
- type: "object"
34233
- },
34234
- skos_concepts: {
34235
- type: "array",
34236
- items: {
34237
- type: "object",
34238
- additionalProperties: false,
34239
- required: ["id", "prefLabel"],
34240
- properties: {
34241
- id: {
34242
- type: "string",
34243
- minLength: 1
34244
- },
34245
- prefLabel: {
34246
- type: "string",
34247
- minLength: 1
34248
- },
34249
- definition: {
34250
- type: "string"
34251
- },
34252
- scheme: {
34253
- type: "string"
34254
- },
34255
- notation: {
34256
- type: "string"
34257
- },
34258
- uri: {
34259
- type: "string"
34260
- },
34261
- altLabels: {
34262
- $ref: "#/$defs/stringArray"
34263
- },
34264
- metadata: {
34265
- type: "object"
34266
- }
34267
- }
34104
+ );
34105
+ } else if (!existing) concepts.set(concept.id, concept);
34106
+ }
34107
+ }
34108
+ for (const id of conceptMembers.keys()) {
34109
+ if (!concepts.has(id)) {
34110
+ concepts.set(id, { id, prefLabel: id });
34111
+ addLoss(
34112
+ losses,
34113
+ "aiwg-skos-metadata-unavailable",
34114
+ "A referenced concept had no SKOS metadata; its id is used as the label.",
34115
+ {
34116
+ component: "skos_concepts",
34117
+ record_id: id,
34118
+ field_path: "/prefLabel",
34119
+ source_state: "absent",
34120
+ destination_capability: "required-label",
34121
+ action: "default"
34122
+ }
34123
+ );
34124
+ }
34125
+ }
34126
+ const schemeIds = new Map(
34127
+ [...new Set([...concepts.values()].map(schemeName))].sort().map((name) => [name, uuid("skos-scheme", name)])
34128
+ );
34129
+ for (const [name, id] of schemeIds) {
34130
+ rows.get("skos_schemes").push({
34131
+ id,
34132
+ uri: null,
34133
+ notation: name,
34134
+ title: name,
34135
+ description: null,
34136
+ creator: "aiwg-index",
34137
+ publisher: null,
34138
+ rights: null,
34139
+ version: null,
34140
+ is_active: true,
34141
+ is_system: false,
34142
+ created_at: exportedAt,
34143
+ updated_at: exportedAt,
34144
+ issued_at: null,
34145
+ modified_at: null,
34146
+ embedding: null,
34147
+ embedding_model: null,
34148
+ embedded_at: null
34149
+ });
34150
+ }
34151
+ const conceptIds = new Map([...concepts.keys()].sort().map((id) => [id, uuid("skos-concept", id)]));
34152
+ for (const [sourceId, concept] of [...concepts].sort(([a], [b]) => a.localeCompare(b))) {
34153
+ const id = conceptIds.get(sourceId);
34154
+ const schemeId = schemeIds.get(schemeName(concept));
34155
+ const memberCount = conceptMembers.get(sourceId)?.length ?? 0;
34156
+ if (concept.uri && !safeUri(concept.uri)) addLoss(
34157
+ losses,
34158
+ "aiwg-skos-uri-invalid",
34159
+ "AIWG concept URI is not a valid authority URI and was mapped to null.",
34160
+ {
34161
+ component: "skos_concepts",
34162
+ record_id: sourceId,
34163
+ field_path: "/uri",
34164
+ source_state: "value",
34165
+ destination_capability: "uri",
34166
+ action: "omit"
34167
+ }
34168
+ );
34169
+ const unmappedConceptMetadata = Object.keys(concept.metadata ?? {}).filter((key) => key !== "domain");
34170
+ if (unmappedConceptMetadata.length > 0) addLoss(
34171
+ losses,
34172
+ "aiwg-skos-metadata-unmapped",
34173
+ "AIWG concept metadata without a native full-v1 field was omitted.",
34174
+ {
34175
+ component: "skos_concepts",
34176
+ record_id: sourceId,
34177
+ source_state: "value",
34178
+ action: "omit",
34179
+ destination_capability: "native-skos-fields",
34180
+ reason: unmappedConceptMetadata.join(",")
34181
+ }
34182
+ );
34183
+ rows.get("skos_concepts").push({
34184
+ id,
34185
+ primary_scheme_id: schemeId,
34186
+ uri: safeUri(concept.uri),
34187
+ notation: concept.notation ?? sourceId,
34188
+ facet_type: null,
34189
+ facet_source: "aiwg-index",
34190
+ facet_domain: typeof concept.metadata?.domain === "string" ? concept.metadata.domain : null,
34191
+ facet_scope: null,
34192
+ status: "candidate",
34193
+ promoted_at: null,
34194
+ deprecated_at: null,
34195
+ deprecation_reason: null,
34196
+ replaced_by_id: null,
34197
+ note_count: memberCount,
34198
+ first_used_at: memberCount ? exportedAt : null,
34199
+ last_used_at: memberCount ? exportedAt : null,
34200
+ depth: 0,
34201
+ broader_count: 0,
34202
+ narrower_count: 0,
34203
+ related_count: 0,
34204
+ antipatterns: null,
34205
+ antipattern_checked_at: null,
34206
+ created_at: exportedAt,
34207
+ updated_at: exportedAt,
34208
+ embedding: null,
34209
+ embedding_model: null,
34210
+ embedded_at: null
34211
+ });
34212
+ rows.get("skos_scheme_memberships").push({
34213
+ concept_id: id,
34214
+ scheme_id: schemeId,
34215
+ is_top_concept: true,
34216
+ added_at: exportedAt
34217
+ });
34218
+ rows.get("skos_labels").push({
34219
+ id: uuid("skos-label", `${sourceId}:pref:${concept.prefLabel}`),
34220
+ concept_id: id,
34221
+ label_type: "pref_label",
34222
+ value: concept.prefLabel,
34223
+ language: "und",
34224
+ created_at: exportedAt
34225
+ });
34226
+ for (const label of concept.altLabels ?? []) rows.get("skos_labels").push({
34227
+ id: uuid("skos-label", `${sourceId}:alt:${label}`),
34228
+ concept_id: id,
34229
+ label_type: "alt_label",
34230
+ value: label,
34231
+ language: "und",
34232
+ created_at: exportedAt
34233
+ });
34234
+ if (concept.definition !== void 0) rows.get("skos_notes").push({
34235
+ id: uuid("skos-note", `${sourceId}:definition`),
34236
+ concept_id: id,
34237
+ note_type: "definition",
34238
+ value: concept.definition,
34239
+ language: "und",
34240
+ author: null,
34241
+ source: concept.uri ?? null,
34242
+ created_at: exportedAt,
34243
+ updated_at: exportedAt
34244
+ });
34245
+ }
34246
+ for (const record of records) {
34247
+ for (const [position, sourceId] of record.concepts.entries()) {
34248
+ const conceptId = conceptIds.get(sourceId);
34249
+ if (conceptId) rows.get("note_skos_tags").push({
34250
+ note_id: noteIds.get(record.id),
34251
+ concept_id: conceptId,
34252
+ source: "aiwg-index",
34253
+ confidence: null,
34254
+ relevance_score: null,
34255
+ is_primary: position === 0,
34256
+ created_at: new Date(record.updated_at).toISOString(),
34257
+ created_by: "aiwg-index"
34258
+ });
34259
+ }
34260
+ for (const relation of record.skos_relations ?? []) {
34261
+ const subject = conceptIds.get(relation.source_id);
34262
+ const object = conceptIds.get(relation.target_id);
34263
+ if (!subject || !object || !["broader", "narrower", "related"].includes(relation.type)) {
34264
+ addLoss(
34265
+ losses,
34266
+ "aiwg-skos-relation-unrepresentable",
34267
+ "SKOS relation could not be mapped to the native full-v1 relation enum.",
34268
+ {
34269
+ component: "skos_relations",
34270
+ record_id: record.id,
34271
+ destination_capability: "broader-narrower-related",
34272
+ action: "omit"
34268
34273
  }
34269
- },
34270
- skos_relations: {
34271
- type: "array",
34272
- items: {
34273
- type: "object",
34274
- additionalProperties: false,
34275
- required: ["type", "source_id", "target_id"],
34276
- properties: {
34277
- type: {
34278
- type: "string",
34279
- minLength: 1
34280
- },
34281
- source_id: {
34282
- type: "string",
34283
- minLength: 1
34284
- },
34285
- target_id: {
34286
- type: "string",
34287
- minLength: 1
34288
- },
34289
- source_path: {
34290
- type: "string"
34291
- },
34292
- metadata: {
34293
- type: "object"
34294
- }
34295
- }
34274
+ );
34275
+ continue;
34276
+ }
34277
+ const unmappedRelationFields = [
34278
+ relation.source_path !== void 0 ? "source_path" : null,
34279
+ relation.metadata !== void 0 ? "metadata" : null
34280
+ ].filter((field) => field !== null);
34281
+ if (unmappedRelationFields.length > 0) {
34282
+ addLoss(
34283
+ losses,
34284
+ "aiwg-skos-relation-fields-unmapped",
34285
+ "AIWG SKOS relation fields have no native full-v1 destination fields.",
34286
+ {
34287
+ component: "skos_relations",
34288
+ record_id: record.id,
34289
+ source_state: "value",
34290
+ destination_capability: "native-skos-relation-fields",
34291
+ action: "omit",
34292
+ reason: unmappedRelationFields.join(",")
34296
34293
  }
34297
- },
34298
- provenance_events: {
34299
- type: "array",
34300
- items: {
34301
- type: "object",
34302
- additionalProperties: false,
34303
- required: ["activity"],
34304
- properties: {
34305
- id: {
34306
- type: "string"
34307
- },
34308
- activity: {
34309
- type: "string",
34310
- minLength: 1
34311
- },
34312
- agent: {
34313
- type: "string"
34314
- },
34315
- started_at: {
34316
- type: "string",
34317
- format: "date-time"
34318
- },
34319
- ended_at: {
34320
- type: "string",
34321
- format: "date-time"
34322
- },
34323
- source: {
34324
- type: "string"
34325
- },
34326
- path: {
34327
- type: "string"
34328
- },
34329
- confidence: {
34330
- enum: ["source", "candidate", "reviewed", "rejected"]
34331
- },
34332
- privacy: {
34333
- $ref: "#/$defs/privacy"
34334
- },
34335
- attributes: {
34336
- type: "object"
34337
- }
34338
- }
34294
+ );
34295
+ continue;
34296
+ }
34297
+ rows.get("skos_relations").push({
34298
+ id: uuid("skos-relation", `${relation.source_id}:${relation.type}:${relation.target_id}`),
34299
+ subject_id: subject,
34300
+ object_id: object,
34301
+ relation_type: relation.type,
34302
+ inference_score: null,
34303
+ is_inferred: false,
34304
+ is_validated: false,
34305
+ created_at: new Date(record.updated_at).toISOString(),
34306
+ created_by: "aiwg-index"
34307
+ });
34308
+ }
34309
+ }
34310
+ for (const record of records) {
34311
+ for (const [position, event] of (record.provenance_events ?? []).entries()) {
34312
+ const start = timestamp(event.started_at);
34313
+ if (!start) addLoss(
34314
+ losses,
34315
+ "aiwg-provenance-start-unavailable",
34316
+ "Activity start defaulted to record updated_at.",
34317
+ {
34318
+ component: "provenance_activities",
34319
+ record_id: event.id ?? `${record.id}:${position}`,
34320
+ field_path: "/started_at",
34321
+ source_state: "absent",
34322
+ action: "default"
34323
+ }
34324
+ );
34325
+ rows.get("provenance_activities").push({
34326
+ id: uuid("provenance-event", event.id ?? `${record.id}:${position}`),
34327
+ note_id: noteIds.get(record.id),
34328
+ revision_id: null,
34329
+ activity_type: event.activity,
34330
+ model_name: event.agent ?? null,
34331
+ started_at: start ?? new Date(record.updated_at).toISOString(),
34332
+ ended_at: timestamp(event.ended_at) ?? null,
34333
+ metadata: {
34334
+ source: event.source ?? null,
34335
+ path: event.path ?? null,
34336
+ confidence: event.confidence ?? null,
34337
+ privacy: event.privacy ?? null,
34338
+ attributes: event.attributes ?? null
34339
+ }
34340
+ });
34341
+ }
34342
+ for (const [position, provenance] of record.provenance.entries()) {
34343
+ rows.get("provenance_activities").push({
34344
+ id: uuid("provenance-field", `${record.id}:${position}:${provenance.field}`),
34345
+ note_id: noteIds.get(record.id),
34346
+ revision_id: null,
34347
+ activity_type: `source:${provenance.field}`,
34348
+ model_name: provenance.source,
34349
+ started_at: new Date(record.updated_at).toISOString(),
34350
+ ended_at: null,
34351
+ metadata: { path: provenance.path, confidence: provenance.confidence, privacy: provenance.privacy }
34352
+ });
34353
+ }
34354
+ }
34355
+ const embeddingGroups = /* @__PURE__ */ new Map();
34356
+ for (const record of records) {
34357
+ for (const [position, embedding] of (record.embeddings ?? []).entries()) {
34358
+ const vector = embedding.embedding ?? embedding.vector;
34359
+ if (!vector || vector.length !== 768) {
34360
+ addLoss(
34361
+ losses,
34362
+ "aiwg-embedding-dimension-unrepresentable",
34363
+ "Only 768-dimensional vectors satisfy the full-v1 authority.",
34364
+ {
34365
+ component: "embeddings",
34366
+ record_id: embedding.id ?? `${record.id}:${position}`,
34367
+ field_path: "/vector",
34368
+ source_state: vector ? "value" : "absent",
34369
+ destination_capability: "768-dimensional-vector",
34370
+ action: "omit"
34339
34371
  }
34340
- },
34341
- updated_at: {
34342
- type: "string",
34343
- format: "date-time"
34372
+ );
34373
+ continue;
34374
+ }
34375
+ const model = embedding.model ?? "aiwg-unknown";
34376
+ if (!embedding.model) addLoss(
34377
+ losses,
34378
+ "aiwg-embedding-model-unavailable",
34379
+ "Embedding model defaulted because AIWG did not supply one.",
34380
+ {
34381
+ component: "embeddings",
34382
+ record_id: embedding.id ?? `${record.id}:${position}`,
34383
+ field_path: "/model",
34384
+ source_state: "absent",
34385
+ action: "default"
34386
+ }
34387
+ );
34388
+ let group = embeddingGroups.get(model);
34389
+ if (!group) {
34390
+ group = { config: uuid("embedding-config", model), set: uuid("embedding-set", model), count: 0 };
34391
+ embeddingGroups.set(model, group);
34392
+ }
34393
+ group.count += 1;
34394
+ const unmappedEmbeddingFields = [
34395
+ embedding.granularity !== void 0 ? "granularity" : null,
34396
+ embedding.source_path !== void 0 ? "source_path" : null,
34397
+ embedding.metadata !== void 0 ? "metadata" : null,
34398
+ embedding.input_hash !== void 0 && !/^[0-9a-f]{64}$/.test(embedding.input_hash) ? "input_hash" : null
34399
+ ].filter((field) => field !== null);
34400
+ if (unmappedEmbeddingFields.length > 0) addLoss(
34401
+ losses,
34402
+ "aiwg-embedding-fields-unmapped",
34403
+ "AIWG embedding fields without a native full-v1 field were omitted.",
34404
+ {
34405
+ component: "embeddings",
34406
+ record_id: embedding.id ?? `${record.id}:${position}`,
34407
+ source_state: "value",
34408
+ action: "omit",
34409
+ destination_capability: "native-embedding-fields",
34410
+ reason: unmappedEmbeddingFields.join(",")
34344
34411
  }
34412
+ );
34413
+ rows.get("embeddings").push({
34414
+ id: uuid("embedding", embedding.id ?? `${record.id}:${position}`),
34415
+ note_id: noteIds.get(record.id),
34416
+ embedding_set_id: group.set,
34417
+ chunk_index: position,
34418
+ text: record.text ?? "",
34419
+ vector,
34420
+ model,
34421
+ contract_fingerprint: /^[0-9a-f]{64}$/.test(embedding.input_hash ?? "") ? embedding.input_hash : null,
34422
+ created_at: new Date(record.updated_at).toISOString()
34423
+ });
34424
+ }
34425
+ }
34426
+ for (const [model, group] of [...embeddingGroups].sort(([a], [b]) => a.localeCompare(b))) {
34427
+ rows.get("embedding_configs").push({
34428
+ id: group.config,
34429
+ name: model,
34430
+ description: null,
34431
+ model,
34432
+ dimension: 768,
34433
+ chunk_size: 1,
34434
+ chunk_overlap: 0,
34435
+ hnsw_m: null,
34436
+ hnsw_ef_construction: null,
34437
+ ivfflat_lists: null,
34438
+ is_default: null,
34439
+ supports_mrl: null,
34440
+ matryoshka_dims: null,
34441
+ default_truncate_dim: null,
34442
+ provider: null,
34443
+ provider_config: null,
34444
+ content_types: null,
34445
+ strengths: null,
34446
+ limitations: null,
34447
+ recommended_for: null,
34448
+ benchmark_scores: null,
34449
+ is_available: null,
34450
+ document_composition: {},
34451
+ created_at: exportedAt,
34452
+ updated_at: exportedAt
34453
+ });
34454
+ rows.get("embedding_sets").push({
34455
+ id: group.set,
34456
+ name: model,
34457
+ slug: uuid("embedding-slug", model),
34458
+ description: null,
34459
+ purpose: null,
34460
+ usage_hints: null,
34461
+ keywords: null,
34462
+ set_type: "full",
34463
+ mode: "manual",
34464
+ criteria: null,
34465
+ embedding_config_id: group.config,
34466
+ truncate_dim: null,
34467
+ auto_embed_rules: null,
34468
+ index_status: "ready",
34469
+ index_type: null,
34470
+ last_indexed_at: exportedAt,
34471
+ document_count: null,
34472
+ embedding_count: group.count,
34473
+ embeddings_current: true,
34474
+ index_size_bytes: null,
34475
+ is_system: false,
34476
+ is_active: true,
34477
+ auto_refresh: false,
34478
+ refresh_interval: null,
34479
+ last_refresh_at: null,
34480
+ agent_metadata: null,
34481
+ created_at: exportedAt,
34482
+ updated_at: exportedAt,
34483
+ created_by: "aiwg-index"
34484
+ });
34485
+ const noteIdSet = new Set(rows.get("embeddings").filter((item) => item.embedding_set_id === group.set).map((item) => item.note_id));
34486
+ for (const noteId of [...noteIdSet].sort()) rows.get("embedding_set_members").push({
34487
+ embedding_set_id: group.set,
34488
+ note_id: noteId,
34489
+ membership_type: "materialized",
34490
+ added_at: exportedAt,
34491
+ added_by: "aiwg-index"
34492
+ });
34493
+ }
34494
+ if (losses.length > 0) {
34495
+ return {
34496
+ success: false,
34497
+ archive: null,
34498
+ profile: "full-v1",
34499
+ schema_version: "2.0.0",
34500
+ lossless: false,
34501
+ losses,
34502
+ receipt: {
34503
+ schema_version: "fortemi.aiwg-full-v1-conversion-receipt.v1",
34504
+ source_schema_version: "aiwg.fortemi.index.export.v2",
34505
+ authority_repository: knowledge_shard_v2_schema_receipt_default.source.repository,
34506
+ authority_commit: knowledge_shard_v2_schema_receipt_default.source.commit,
34507
+ authority_contract_sha256: knowledge_shard_v2_schema_receipt_default.source.contractSha256,
34508
+ authority_schema_bundle_sha256: knowledge_shard_v2_schema_receipt_default.schemaBundle.sha256,
34509
+ manifest_sha256: null,
34510
+ component_checksums: {},
34511
+ contract_valid: false,
34512
+ signed: false
34345
34513
  }
34514
+ };
34515
+ }
34516
+ const files = /* @__PURE__ */ new Map();
34517
+ const components = Object.keys(FULL_V1_COMPONENT_FILES);
34518
+ const counts = { community_sets: 0 };
34519
+ for (const component of components) {
34520
+ const spec = FULL_V1_COMPONENT_FILES[component];
34521
+ const componentRows = rows.get(component) ?? [];
34522
+ files.set(spec.file, encode(componentRows, spec.encoding));
34523
+ counts[component] = componentRows.length;
34524
+ }
34525
+ const checksums = {};
34526
+ for (const [file, bytes] of files) checksums[file] = await sha256Hex(bytes);
34527
+ const manifest = {
34528
+ version: "2.0.0",
34529
+ profile: "full-v1",
34530
+ producer: { name: "fortemi-core-aiwg-index", version: options.matricVersion ?? "fortemi-core" },
34531
+ format: SHARD_FORMAT,
34532
+ created_at: exportedAt,
34533
+ components,
34534
+ counts,
34535
+ checksums,
34536
+ min_reader_version: "2.0.0"
34537
+ };
34538
+ const manifestBytes = encoder4.encode(JSON.stringify(manifest, null, 2));
34539
+ files.set("manifest.json", manifestBytes);
34540
+ const validation = await validateFullV1ShardArchive(files);
34541
+ if (!validation.valid) {
34542
+ throw new Error(`Generated AIWG full-v1 shard failed authority validation: ${validation.errors.join("; ")}`);
34543
+ }
34544
+ return {
34545
+ success: true,
34546
+ archive: packTarGz(files),
34547
+ profile: "full-v1",
34548
+ schema_version: "2.0.0",
34549
+ lossless: losses.length === 0,
34550
+ losses,
34551
+ receipt: {
34552
+ schema_version: "fortemi.aiwg-full-v1-conversion-receipt.v1",
34553
+ source_schema_version: "aiwg.fortemi.index.export.v2",
34554
+ authority_repository: knowledge_shard_v2_schema_receipt_default.source.repository,
34555
+ authority_commit: knowledge_shard_v2_schema_receipt_default.source.commit,
34556
+ authority_contract_sha256: knowledge_shard_v2_schema_receipt_default.source.contractSha256,
34557
+ authority_schema_bundle_sha256: knowledge_shard_v2_schema_receipt_default.schemaBundle.sha256,
34558
+ manifest_sha256: await sha256Hex(manifestBytes),
34559
+ component_checksums: checksums,
34560
+ contract_valid: true,
34561
+ signed: false
34346
34562
  }
34347
- }
34348
- };
34563
+ };
34564
+ }
34349
34565
 
34350
- // src/aiwg-index-schema.ts
34351
- var PROJECTED_FIELDS = [
34352
- "schema_version",
34353
- "id",
34354
- "type",
34355
- "title",
34356
- "text",
34357
- "facets",
34358
- "tags",
34359
- "concepts",
34360
- "privacy"
34361
- ];
34362
- var ajvInstance;
34363
- var exportValidator;
34364
- var projectedRecordValidator;
34365
- function getAiwgFortemiIndexExportSchema() {
34366
- return aiwg_fortemi_index_export_schema_default;
34566
+ // src/aiwg-index-shard.ts
34567
+ var AIWG_SHARD_UUID_NAMESPACE = "7ab5d1f8-29d2-5e35-9e2f-3a45de171a9e";
34568
+ var shardEncoder = new TextEncoder();
34569
+ var shardDecoder = new TextDecoder();
34570
+ function aiwgShardUuid(kind, id) {
34571
+ return v5(`${kind}:${id}`, AIWG_SHARD_UUID_NAMESPACE);
34367
34572
  }
34368
- function getAjv() {
34369
- if (!ajvInstance) {
34370
- ajvInstance = new Ajv2020({
34371
- allErrors: true,
34372
- strict: false,
34373
- validateFormats: false
34374
- });
34375
- ajvInstance.addSchema(aiwg_fortemi_index_export_schema_default);
34376
- }
34377
- return ajvInstance;
34573
+ function aiwgShardTimestamp(value, fallback) {
34574
+ if (!value || Number.isNaN(Date.parse(value))) return fallback;
34575
+ return new Date(value).toISOString();
34378
34576
  }
34379
- function formatErrors2(errors) {
34380
- return (errors ?? []).map((error) => {
34381
- const path = error.instancePath || "(root)";
34382
- return `${path} ${error.message ?? "is invalid"}`;
34383
- });
34577
+ function aiwgRecordTitle(record) {
34578
+ return record.title ?? record.search?.title ?? record.search?.name ?? record.id;
34384
34579
  }
34385
- function getExportValidator() {
34386
- exportValidator ??= getAjv().getSchema(aiwg_fortemi_index_export_schema_default.$id) ?? getAjv().compile(aiwg_fortemi_index_export_schema_default);
34387
- return exportValidator;
34580
+ function aiwgRecordContent(record) {
34581
+ if (record.text) return record.text;
34582
+ if (record.search?.body) return record.search.body;
34583
+ const chunks = record.chunks?.map((chunk) => chunk.text ?? chunk.body ?? chunk.summary ?? "").filter(Boolean);
34584
+ if (chunks?.length) return chunks.join("\n\n");
34585
+ return record.search?.summary ?? "";
34388
34586
  }
34389
- function getProjectedRecordValidator() {
34390
- if (!projectedRecordValidator) {
34391
- const properties = Object.fromEntries(Object.keys(aiwg_fortemi_index_export_schema_default.$defs.record.properties).map((field) => [
34392
- field,
34393
- { $ref: `${aiwg_fortemi_index_export_schema_default.$id}#/$defs/record/properties/${field}` }
34394
- ]));
34395
- projectedRecordValidator = getAjv().compile({
34396
- type: "object",
34397
- required: PROJECTED_FIELDS,
34398
- properties,
34399
- additionalProperties: true,
34400
- allOf: [
34401
- {
34402
- if: {
34403
- properties: {
34404
- schema_version: { const: "aiwg.fortemi.index.record.v1" }
34405
- }
34406
- },
34407
- then: { $ref: `${aiwg_fortemi_index_export_schema_default.$id}#/$defs/v1RecordCompatibility` }
34587
+ function aiwgRecordCollectionPaths(record) {
34588
+ const segments = record.source.repo_relative_path.split("/").filter((segment) => segment.length > 0 && segment !== ".");
34589
+ const directorySegments = segments.slice(0, -1);
34590
+ return directorySegments.map((_, index) => directorySegments.slice(0, index + 1).join("/"));
34591
+ }
34592
+ function aiwgShardMetadata(index, record) {
34593
+ return {
34594
+ aiwg_fortemi_index: {
34595
+ envelope: {
34596
+ schema_version: index.schema_version,
34597
+ generated_at: index.generated_at,
34598
+ source: index.source,
34599
+ ...index.compatibility ? { compatibility: index.compatibility } : {}
34600
+ },
34601
+ record
34602
+ }
34603
+ };
34604
+ }
34605
+ function encodeJsonLines(values) {
34606
+ return shardEncoder.encode(values.map((value) => JSON.stringify(value)).join("\n"));
34607
+ }
34608
+ function validateAiwgIndexForShard(index) {
34609
+ const contractValidation = validateAiwgFortemiIndexExportSchema(index);
34610
+ const semanticValidation = validateAiwgFortemiIndexExport(index);
34611
+ const errors = [...contractValidation.errors, ...semanticValidation.errors];
34612
+ if (errors.length > 0) {
34613
+ throw new Error(`Invalid AIWG Fortemi index export:
34614
+ ${errors.join("\n")}`);
34615
+ }
34616
+ }
34617
+ async function aiwgFortemiIndexToKnowledgeShard(index, options = {}) {
34618
+ if (options.includeNativeRichComponents) {
34619
+ throw new Error(
34620
+ "Native AIWG full-v1 conversion requires aiwgFortemiIndexToKnowledgeShardWithReport so semantic losses cannot be discarded"
34621
+ );
34622
+ }
34623
+ validateAiwgIndexForShard(index);
34624
+ if (index.schema_version !== "aiwg.fortemi.index.export.v2") {
34625
+ throw new Error("Knowledge Shard conversion requires aiwg.fortemi.index.export.v2");
34626
+ }
34627
+ const createdAt2 = aiwgShardTimestamp(options.createdAt ?? index.generated_at, (/* @__PURE__ */ new Date()).toISOString());
34628
+ const noteIds = new Map(index.items.map((record) => [record.id, aiwgShardUuid("record", record.id)]));
34629
+ const collectionPaths = [...new Set(index.items.flatMap(aiwgRecordCollectionPaths))].sort();
34630
+ const collectionIds = new Map(
34631
+ collectionPaths.map((path) => [path, aiwgShardUuid("collection", path)])
34632
+ );
34633
+ const collectionNoteCounts = /* @__PURE__ */ new Map();
34634
+ for (const record of index.items) {
34635
+ const collectionPath = aiwgRecordCollectionPaths(record).at(-1);
34636
+ if (collectionPath) {
34637
+ collectionNoteCounts.set(collectionPath, (collectionNoteCounts.get(collectionPath) ?? 0) + 1);
34638
+ }
34639
+ }
34640
+ const collections = collectionPaths.map((path) => {
34641
+ const segments = path.split("/");
34642
+ const parentPath = segments.slice(0, -1).join("/");
34643
+ return {
34644
+ id: collectionIds.get(path),
34645
+ name: segments.at(-1),
34646
+ description: null,
34647
+ parent_id: parentPath ? collectionIds.get(parentPath) : null,
34648
+ created_at: createdAt2,
34649
+ note_count: collectionNoteCounts.get(path) ?? 0
34650
+ };
34651
+ });
34652
+ const notes = index.items.map((record) => {
34653
+ const content = aiwgRecordContent(record);
34654
+ const recordCollectionPaths = aiwgRecordCollectionPaths(record);
34655
+ const collectionPath = recordCollectionPaths.at(-1);
34656
+ return {
34657
+ id: noteIds.get(record.id),
34658
+ title: aiwgRecordTitle(record),
34659
+ original_content: content,
34660
+ revised_content: content,
34661
+ metadata: aiwgShardMetadata(index, record),
34662
+ collection_id: collectionPath ? collectionIds.get(collectionPath) : null,
34663
+ attachments: [],
34664
+ format: "markdown",
34665
+ source: "aiwg-index",
34666
+ starred: false,
34667
+ archived: false,
34668
+ tags: [...new Set(record.tags)].sort(),
34669
+ created_at: aiwgShardTimestamp(record.source.updated_at ?? record.updated_at, createdAt2),
34670
+ updated_at: aiwgShardTimestamp(record.updated_at, createdAt2),
34671
+ deleted_at: record.state_transfer?.deleted_at ?? null
34672
+ };
34673
+ });
34674
+ const links = [];
34675
+ for (const record of index.items) {
34676
+ for (const [position, relationship] of record.relationships.entries()) {
34677
+ const targetNoteId = noteIds.get(relationship.target_id) ?? null;
34678
+ links.push({
34679
+ id: aiwgShardUuid(
34680
+ "relationship",
34681
+ `${record.id}\0${position}\0${relationship.type}\0${relationship.target_id}`
34682
+ ),
34683
+ from_note_id: noteIds.get(record.id),
34684
+ to_note_id: targetNoteId,
34685
+ to_url: targetNoteId ? null : `aiwg://record/${encodeURIComponent(relationship.target_id)}`,
34686
+ kind: relationship.type,
34687
+ score: relationship.confidence ?? 1,
34688
+ created_at: aiwgShardTimestamp(record.updated_at, createdAt2),
34689
+ metadata: {
34690
+ aiwg_fortemi_index: {
34691
+ source_record_id: record.id,
34692
+ target_record_id: relationship.target_id,
34693
+ relationship
34694
+ }
34408
34695
  }
34409
- ]
34410
- });
34696
+ });
34697
+ }
34411
34698
  }
34412
- return projectedRecordValidator;
34699
+ const files = /* @__PURE__ */ new Map();
34700
+ const components = ["notes"];
34701
+ const counts = {
34702
+ notes: notes.length
34703
+ };
34704
+ files.set("notes.jsonl", encodeJsonLines(notes));
34705
+ const addComponent = (component, filename, values, jsonLines = true) => {
34706
+ if (values.length === 0) return;
34707
+ components.push(component);
34708
+ counts[component] = values.length;
34709
+ files.set(filename, jsonLines ? encodeJsonLines(values) : shardEncoder.encode(JSON.stringify(values)));
34710
+ };
34711
+ addComponent("collections", "collections.json", collections, false);
34712
+ const tags = [...new Set(notes.flatMap((note) => note.tags))].sort().map((name) => ({ name, created_at: createdAt2 }));
34713
+ components.push("tags");
34714
+ counts.tags = tags.length;
34715
+ files.set("tags.json", shardEncoder.encode(JSON.stringify(tags)));
34716
+ addComponent("links", "links.jsonl", links);
34717
+ const checksums = {};
34718
+ for (const [filename, bytes] of files) checksums[filename] = await sha256Hex(bytes);
34719
+ const manifest = {
34720
+ version: CURRENT_SHARD_VERSION,
34721
+ profile: "core-v1",
34722
+ producer: {
34723
+ name: "fortemi-core-aiwg-index",
34724
+ version: options.matricVersion ?? "fortemi-core"
34725
+ },
34726
+ format: SHARD_FORMAT,
34727
+ created_at: createdAt2,
34728
+ components,
34729
+ counts: {
34730
+ notes: 0,
34731
+ collections: 0,
34732
+ tags: 0,
34733
+ templates: 0,
34734
+ links: 0,
34735
+ embedding_sets: 0,
34736
+ embedding_set_members: 0,
34737
+ embeddings: 0,
34738
+ embedding_configs: 0,
34739
+ ...counts
34740
+ },
34741
+ checksums,
34742
+ min_reader_version: CURRENT_SHARD_VERSION
34743
+ };
34744
+ files.set("manifest.json", shardEncoder.encode(JSON.stringify(manifest, null, 2)));
34745
+ const contractValidation = await validateCoreV1ShardArchive(files);
34746
+ if (!contractValidation.valid) {
34747
+ throw new Error(
34748
+ `Generated AIWG core-v1 shard failed canonical validation: ${contractValidation.errors.join("; ")}`
34749
+ );
34750
+ }
34751
+ return packTarGz(files);
34413
34752
  }
34414
- function validateAiwgFortemiIndexExportSchema(value) {
34415
- const validate = getExportValidator();
34416
- const schemaValue = value && typeof value === "object" && Array.isArray(value.items) ? {
34417
- ...value,
34418
- items: value.items.map((item) => {
34419
- if (!item || typeof item !== "object" || Array.isArray(item)) return item;
34420
- const schemaRecord = { ...item };
34421
- Reflect.deleteProperty(schemaRecord, "binary_sources");
34422
- return schemaRecord;
34423
- })
34424
- } : value;
34425
- const valid = validate(schemaValue);
34426
- return { valid, errors: formatErrors2(validate.errors) };
34753
+ async function aiwgFortemiIndexToKnowledgeShardWithReport(index, options = {}) {
34754
+ validateAiwgIndexForShard(index);
34755
+ if (index.schema_version !== "aiwg.fortemi.index.export.v2") {
34756
+ throw new Error("Full-v1 Knowledge Shard conversion requires aiwg.fortemi.index.export.v2");
34757
+ }
34758
+ return convertAiwgIndexToFullV1(index, options);
34427
34759
  }
34428
- function validateAiwgFortemiProjectedRecordSchema(value) {
34429
- const validate = getProjectedRecordValidator();
34430
- const valid = validate(value);
34431
- return { valid, errors: formatErrors2(validate.errors) };
34760
+ function aiwgFortemiIndexFromKnowledgeShard(bytes) {
34761
+ const files = unpackTarGz(bytes);
34762
+ const noteBytes = files.get("notes.jsonl");
34763
+ const notes = (noteBytes ? shardDecoder.decode(noteBytes) : "").split("\n").filter(Boolean).map((line) => JSON.parse(line));
34764
+ if (notes.length === 0) throw new Error("Knowledge Shard contains no AIWG index notes");
34765
+ let envelope;
34766
+ const items = [];
34767
+ for (const note of notes) {
34768
+ const metadata = note.metadata && typeof note.metadata === "object" && !Array.isArray(note.metadata) ? note.metadata.aiwg_fortemi_index : void 0;
34769
+ if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
34770
+ throw new Error(`Knowledge Shard note ${note.id} has no AIWG index metadata`);
34771
+ }
34772
+ const value = metadata;
34773
+ envelope ??= value.envelope;
34774
+ items.push(value.record);
34775
+ }
34776
+ const restored = {
34777
+ ...envelope,
34778
+ items: items.sort((left, right) => left.id.localeCompare(right.id))
34779
+ };
34780
+ const validation = validateAiwgFortemiIndexExport(restored);
34781
+ if (!validation.valid) {
34782
+ throw new Error(`Knowledge Shard contains invalid AIWG index metadata:
34783
+ ${validation.errors.join("\n")}`);
34784
+ }
34785
+ return restored;
34432
34786
  }
34433
34787
 
34434
34788
  // src/records/types.ts
@@ -36476,7 +36830,7 @@ async function importShardToRecords(store, data, options) {
36476
36830
  }
36477
36831
 
36478
36832
  // src/index.ts
36479
- var VERSION = "2026.7.13";
36833
+ var VERSION = "2026.7.14";
36480
36834
 
36481
36835
  export { AIWG_SCAN_REQUIRED_FIELDS, AllowlistTrustStore, ArchiveManager, AttachmentsRepository, CORE_V1_COMPONENTS, CURRENT_MIGRATION_HEAD, CURRENT_SHARD_VERSION, CanonicalAttachmentsRepository, CanonicalNotesRepository, CapabilityManager, CaptureKnowledgeInputSchema, CollectionsRepository, CommunitiesRepository, DB_SNAPSHOT_SCHEMA_VERSION, DbSnapshotVersionError, EMBED_REQUEST_KIND, EMBED_RESPONSE_KIND, EmbeddingSetsRepository, FORTEMI_COMPATIBILITY_PATH, FORTEMI_COMPATIBILITY_STATES, FORTEMI_REQUIRED_COMPATIBILITY_CAPABILITIES, FallbackRouter, FortemiToolManifest, GetNoteInputSchema, GraphRepository, IdbRecordStore, JOB_CAPABILITIES, JOB_PRIORITIES, JobQueueWorker, LOCAL_ENDPOINTS, LinksRepository, ListNotesInputSchema, ManageArchiveInputSchema, ManageAttachmentsInputSchema, ManageCapabilitiesInputSchema, ManageCollectionsInputSchema, ManageLinksInputSchema, ManageNoteInputSchema, ManageTagsInputSchema, MemoryBlobStore, MemoryRecordStore, MigrationRunner, NotesRepository, OpenAICompatibleProvider, PGliteStorageBackend, PGliteStorageBackendFactory, PGliteWorkerClient, PGliteWorkerStorageBackend, PGliteWorkerStorageBackendFactory, ProvenanceRepository, ProviderRegistry, RECORD_COLLECTIONS, RECORD_SCHEMA_VERSION, RECORD_STORE_CAPABILITIES, SHARD_FORMAT, SIGNATURE_ENTRY, SIGNING_ENVELOPE_VERSION, SUPPORTED_PGLITE_VERSION, SearchInputSchema, SearchRepository, SkosRepository, TagsRepository, TransactionProxy, TypedEventBus, VERSION, aiRevisionHandler, aiwgFortemiIndexFromKnowledgeShard, aiwgFortemiIndexToCommunityGraph, aiwgFortemiIndexToKnowledgeShard, aiwgFortemiIndexToKnowledgeShardWithReport, allMigrations, appendPluginScript, assertAiwgFortemiChunkManifest, assertAiwgFortemiChunkPart, assertAiwgFortemiIndexExport, assertAiwgStaticEmbeddingSet, assertShardComponentRecord, buildAiwgChunkedIndex, buildAiwgStaticEmbeddingSet, buildNoteConditions, buildPluginCsp, captureKnowledge, chunkText, classifyError, classifyModel, clearPrefetchedShard, collectionFromShard, collectionToShard, computeBlobHash, computeHash, computeSri, conceptTaggingHandler, cosineSimilarity, createAiwgFetchChunkLoader, createAiwgFetchDetailLoader, createAiwgIndexController, createAiwgReviewDecisionExport, createBlobStore, createCosineSemanticProvider, createCspReportHandler, createFortemi, createLazyBlobStore, createLegacyProvider, createPGliteBackend, createPGliteInstance, createRecordBackend, createRecordStore, createRemoteBackend, createRoutes, createShardBackend, createShardCapabilityReport, createWorkerEmbedFunction, defaultStorageBackendFactory, detectCommunities, detectGpuCapabilities, detectInferenceCapabilities, discoverLocalProviders, dropAttachmentProjection, dropNoteProjection, dumpDbSnapshot, embeddingConfigToShard, embeddingFromShard, embeddingGenerationHandler, embeddingSetFromShard, embeddingSetMemberToShard, embeddingSetToShard, embeddingToShard, enqueueFullWorkflow, enqueueJob, enqueueNoteCreationJobs, estimateModelFit, estimateVramMB, estimateVramTier, exportShard, exportShardFromRecords, exportShardFromRecordsWithReport, exportShardWithReport, fetchAndValidateFortemiCompatibility, fetchPluginScript, filterAiwgRecordsByPrivacy, findAiwgStaticDuplicatePairs, formatFortemiCompatibilitySummary, fortemiCompatibilityUrl, fortemiManifest, fromPrefetched, generateId, getAiwgFortemiFacets, getAiwgFortemiIndexExportSchema, getEmbedFunction, getFortemiBridge, getFortemiSecretStore, getJobQueueStatus, getKnowledgeShardContractReceipt, getKnowledgeShardProfileRegistry, getKnowledgeShardSchema, getLlmFunction, getNote, getPrefetchedSha256, handleEmbedRequests, hasFortemiSecureSecrets, importShard, importShardToRecords, isPluginScriptAllowed, isShardPrefetched, isShardSigningSupported, linkFromShard, linkToShard, linkingHandler, listNotes, manageArchive, manageAttachments, manageCapabilities, manageCollections, manageLinks, manageNote, manageTags, matchRoute, migrateLegacyBlobStore, noteFromShard, noteSkosTagToShard, noteToShard, openShard, packTarGz, parseCspReport, prefetchShard, profileSupportError, projectAttachments, projectNotes, projectRecords, provenanceEdgeToShard, queryAiwgFortemiIndex, queryAiwgHybridIndex, queryAiwgSemanticIndex, registerLlmCapability, registerSemanticCapability, registerSemanticCapabilityWorker, registerServiceWorker, restoreDbSnapshot, searchTool, selectBackend, selectLlmModel, setEmbedFunction, setLlmFunction, sha256Hex, sidecarBlobDigests, signShard, skosConceptToShard, skosRelationToShard, skosSchemeToShard, suggestTags, tagsToShard, templateToShard, titleGenerationHandler, unpackTarGz, unregisterLlmCapability, unregisterSemanticCapability, urlLinkToShard, validateAiwgFortemiChunkManifest, validateAiwgFortemiChunkPart, validateAiwgFortemiIndexExport, validateAiwgFortemiIndexExportSchema, validateAiwgFortemiProjectedRecordSchema, validateAiwgStaticEmbeddingSet, validateChecksums, validateCoreV1ShardArchive, validateFortemiCompatibilityResponse, validateFullV1ShardArchive, validateRecordV1ShardArchive, validateShardArchive, validateShardComponentRecord, validateShardManifest, verifyDbSnapshotMeta, verifyShardSignature, verifySri };
36482
36836
  //# sourceMappingURL=index.js.map