@fortemi/core 2026.9.4 → 2026.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/dist/index.d.ts +1617 -1486
  2. package/dist/index.js +2310 -438
  3. package/dist/index.js.map +1 -1
  4. package/package.json +5 -3
  5. package/schemas/dataset-execution-capabilities/validation/1.0.1/manifest.json +29 -0
  6. package/schemas/dataset-execution-capabilities/validation/1.0.1/negotiation-vectors.json +127 -0
  7. package/schemas/dataset-execution-capabilities/validation/1.0.1/schema.json +469 -0
  8. package/schemas/dataset-execution-capabilities/validation/1.0.1/wire-vectors.json +681 -0
  9. package/schemas/metadata-search/candidate/1.0.0/README.md +36 -0
  10. package/schemas/metadata-search/candidate/1.0.0/contract.receipt.json +38 -0
  11. package/schemas/metadata-search/candidate/1.0.0/evidence-locator.schema.json +50 -0
  12. package/schemas/metadata-search/candidate/1.0.0/evidence-resolution-vectors.json +355 -0
  13. package/schemas/metadata-search/candidate/1.0.0/evidence-resolution.schema.json +25 -0
  14. package/schemas/metadata-search/candidate/1.0.0/evidence-set-vectors.json +6095 -0
  15. package/schemas/metadata-search/candidate/1.0.0/evidence-set.schema.json +21 -0
  16. package/schemas/metadata-search/candidate/1.0.0/evidence-vectors.json +1603 -0
  17. package/schemas/metadata-search/candidate/1.0.0/predicate-vectors.json +919 -0
  18. package/schemas/metadata-search/candidate/1.0.0/predicates.schema.json +287 -0
  19. package/schemas/metadata-search/candidate/1.0.0/resolution.receipt.json +44 -0
  20. package/schemas/metadata-search/candidate/1.0.0/rest.receipt.json +51 -0
  21. package/schemas/metadata-search/candidate/1.0.0/search-rest-vectors.json +28 -0
  22. package/schemas/metadata-search/candidate/1.0.0/search-rest.schema.json +318 -0
  23. package/schemas/metadata-search/candidate/1.0.0/source.receipt.json +46 -0
  24. package/schemas/metadata-search/candidate/1.0.0/sql-scope-vectors.json +894 -0
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { v7, v5 } from 'uuid';
2
2
  import { sha256 } from '@noble/hashes/sha256';
3
3
  import { blake3 } from '@noble/hashes/blake3';
4
- import { bytesToHex } from '@noble/hashes/utils';
5
- import Ajv20202 from 'ajv/dist/2020.js';
4
+ import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
5
+ import Ajv20206 from 'ajv/dist/2020.js';
6
6
  import { gzipSync, gunzipSync } from 'fflate';
7
7
  import { z } from 'zod';
8
8
 
@@ -24,9 +24,9 @@ var __export = (target, all) => {
24
24
  };
25
25
  var __copyProps = (to, from, except, desc) => {
26
26
  if (from && typeof from === "object" || typeof from === "function") {
27
- for (let key2 of __getOwnPropNames(from))
28
- if (!__hasOwnProp.call(to, key2) && key2 !== except)
29
- __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
27
+ for (let key3 of __getOwnPropNames(from))
28
+ if (!__hasOwnProp.call(to, key3) && key3 !== except)
29
+ __defProp(to, key3, { get: () => from[key3], enumerable: !(desc = __getOwnPropDesc(from, key3)) || desc.enumerable });
30
30
  }
31
31
  return to;
32
32
  };
@@ -1991,19 +1991,19 @@ var require_point = __commonJS({
1991
1991
  var Types = require_types();
1992
1992
  var BinaryWriter = require_binarywriter();
1993
1993
  var ZigZag = require_zigzag();
1994
- function Point2(x, y, z12, m, srid) {
1994
+ function Point2(x, y, z13, m, srid) {
1995
1995
  Geometry2.call(this);
1996
1996
  this.x = x;
1997
1997
  this.y = y;
1998
- this.z = z12;
1998
+ this.z = z13;
1999
1999
  this.m = m;
2000
2000
  this.srid = srid;
2001
2001
  this.hasZ = typeof this.z !== "undefined";
2002
2002
  this.hasM = typeof this.m !== "undefined";
2003
2003
  }
2004
2004
  util.inherits(Point2, Geometry2);
2005
- Point2.Z = function(x, y, z12, srid) {
2006
- var point = new Point2(x, y, z12, void 0, srid);
2005
+ Point2.Z = function(x, y, z13, srid) {
2006
+ var point = new Point2(x, y, z13, void 0, srid);
2007
2007
  point.hasZ = true;
2008
2008
  return point;
2009
2009
  };
@@ -2012,8 +2012,8 @@ var require_point = __commonJS({
2012
2012
  point.hasM = true;
2013
2013
  return point;
2014
2014
  };
2015
- Point2.ZM = function(x, y, z12, m, srid) {
2016
- var point = new Point2(x, y, z12, m, srid);
2015
+ Point2.ZM = function(x, y, z13, m, srid) {
2016
+ var point = new Point2(x, y, z13, m, srid);
2017
2017
  point.hasZ = true;
2018
2018
  point.hasM = true;
2019
2019
  return point;
@@ -2119,17 +2119,17 @@ var require_point = __commonJS({
2119
2119
  Point2.prototype._writeTwkbPoint = function(twkb, precision, previousPoint) {
2120
2120
  var x = this.x * precision.xyFactor;
2121
2121
  var y = this.y * precision.xyFactor;
2122
- var z12 = this.z * precision.zFactor;
2122
+ var z13 = this.z * precision.zFactor;
2123
2123
  var m = this.m * precision.mFactor;
2124
2124
  twkb.writeVarInt(ZigZag.encode(x - previousPoint.x));
2125
2125
  twkb.writeVarInt(ZigZag.encode(y - previousPoint.y));
2126
2126
  if (this.hasZ)
2127
- twkb.writeVarInt(ZigZag.encode(z12 - previousPoint.z));
2127
+ twkb.writeVarInt(ZigZag.encode(z13 - previousPoint.z));
2128
2128
  if (this.hasM)
2129
2129
  twkb.writeVarInt(ZigZag.encode(m - previousPoint.m));
2130
2130
  previousPoint.x = x;
2131
2131
  previousPoint.y = y;
2132
- previousPoint.z = z12;
2132
+ previousPoint.z = z13;
2133
2133
  previousPoint.m = m;
2134
2134
  };
2135
2135
  Point2.prototype._getWkbSize = function() {
@@ -3615,14 +3615,14 @@ var MemoryDatasetIngestStore = class {
3615
3615
  receipts: /* @__PURE__ */ new Map()
3616
3616
  };
3617
3617
  const draft = {
3618
- records: new Map([...existing.records].map(([key2, value]) => [key2, clone(value)])),
3619
- receipts: new Map([...existing.receipts].map(([key2, value]) => [key2, clone(value)])),
3618
+ records: new Map([...existing.records].map(([key3, value]) => [key3, clone(value)])),
3619
+ receipts: new Map([...existing.receipts].map(([key3, value]) => [key3, clone(value)])),
3620
3620
  ...existing.checkpoint ? { checkpoint: clone(existing.checkpoint) } : {}
3621
3621
  };
3622
3622
  const transaction = {
3623
3623
  getRecord: (id) => draft.records.get(id),
3624
3624
  setRecord: (record) => draft.records.set(record.logicalId, clone(record)),
3625
- getReceipt: (key2) => draft.receipts.get(key2),
3625
+ getReceipt: (key3) => draft.receipts.get(key3),
3626
3626
  setReceipt: (receipt) => draft.receipts.set(receipt.idempotencyKey, clone(receipt)),
3627
3627
  getCheckpoint: () => draft.checkpoint,
3628
3628
  setCheckpoint: (checkpoint) => {
@@ -3650,7 +3650,7 @@ var MemoryDatasetIngestStore = class {
3650
3650
  function canonicalJson(value) {
3651
3651
  if (value === null || typeof value !== "object") return JSON.stringify(value);
3652
3652
  if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
3653
- return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key2, item]) => `${JSON.stringify(key2)}:${canonicalJson(item)}`).join(",")}}`;
3653
+ return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key3, item]) => `${JSON.stringify(key3)}:${canonicalJson(item)}`).join(",")}}`;
3654
3654
  }
3655
3655
  function digest(value) {
3656
3656
  return computeHash(new TextEncoder().encode(canonicalJson(value)));
@@ -3819,11 +3819,11 @@ var DatasetIngestExecutor = class {
3819
3819
  return this.store.getReceipt(datasetDestinationScopeKey(plan.destination), deriveDatasetIngestIdempotencyKey(plan, batch));
3820
3820
  }
3821
3821
  status(scope, expectedSourceRevision) {
3822
- const key2 = datasetDestinationScopeKey(scope);
3823
- const lastSuccessful = this.successes.get(key2);
3822
+ const key3 = datasetDestinationScopeKey(scope);
3823
+ const lastSuccessful = this.successes.get(key3);
3824
3824
  return {
3825
3825
  scope: clone(scope),
3826
- ...this.attempts.get(key2) ? { lastAttempt: clone(this.attempts.get(key2)) } : {},
3826
+ ...this.attempts.get(key3) ? { lastAttempt: clone(this.attempts.get(key3)) } : {},
3827
3827
  ...lastSuccessful ? { lastSuccessful: clone(lastSuccessful) } : {},
3828
3828
  freshness: lastSuccessful ? expectedSourceRevision && expectedSourceRevision !== lastSuccessful.sourceRevision ? "stale" : "current" : "never"
3829
3829
  };
@@ -3877,7 +3877,7 @@ function canonicalJson2(value) {
3877
3877
  if (value === null || typeof value !== "object") return JSON.stringify(value);
3878
3878
  if (Array.isArray(value)) return `[${value.map(canonicalJson2).join(",")}]`;
3879
3879
  const entries = Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right));
3880
- return `{${entries.map(([key2, item]) => `${JSON.stringify(key2)}:${canonicalJson2(item)}`).join(",")}}`;
3880
+ return `{${entries.map(([key3, item]) => `${JSON.stringify(key3)}:${canonicalJson2(item)}`).join(",")}}`;
3881
3881
  }
3882
3882
  function computeLineageDigest(value) {
3883
3883
  return computeHash(new TextEncoder().encode(canonicalJson2(value)));
@@ -3957,9 +3957,9 @@ var DatasetLineageLedger = class _DatasetLineageLedger {
3957
3957
  if (item.payload !== void 0 && computeLineageDigest(item.payload) !== item.digest) {
3958
3958
  throw new LineageValidationError("EVIDENCE_DIGEST_MISMATCH", `Evidence ${item.id} payload does not match ${item.digest}`);
3959
3959
  }
3960
- const key2 = `${item.id}@${item.revision}`;
3961
- this.ensureUnique(this.evidence, key2, "evidence revision");
3962
- return this.append(this.evidence, key2, item);
3960
+ const key3 = `${item.id}@${item.revision}`;
3961
+ this.ensureUnique(this.evidence, key3, "evidence revision");
3962
+ return this.append(this.evidence, key3, item);
3963
3963
  }
3964
3964
  appendAssertion(assertion) {
3965
3965
  requireIdentity(assertion.id, "assertion.id");
@@ -3995,13 +3995,13 @@ var DatasetLineageLedger = class _DatasetLineageLedger {
3995
3995
  if (item.digest !== reference.digest) throw new LineageValidationError("EVIDENCE_DIGEST_MISMATCH", `Evidence reference digest differs for ${reference.evidenceId}`);
3996
3996
  if (reference.locator && reference.locator !== item.locator) throw new LineageValidationError("EVIDENCE_DIGEST_MISMATCH", `Evidence locator differs for ${reference.evidenceId}`);
3997
3997
  }
3998
- const key2 = `${assertion.id}@${assertion.revision}`;
3999
- if (this.assertions.has(key2)) throw new LineageValidationError("IDENTITY_DUPLICATE", `Duplicate assertion revision ${key2}`);
3998
+ const key3 = `${assertion.id}@${assertion.revision}`;
3999
+ if (this.assertions.has(key3)) throw new LineageValidationError("IDENTITY_DUPLICATE", `Duplicate assertion revision ${key3}`);
4000
4000
  const prior = [...this.assertions.values()].some((entry) => entry.value.id === assertion.id);
4001
4001
  if (prior && !this.hasReplacementPermission(assertion.id, assertion.revision)) {
4002
4002
  throw new LineageValidationError("CORRECTION_INVALID", `Assertion ${assertion.id} can only receive revision ${assertion.revision} after an explicit correction`);
4003
4003
  }
4004
- return this.append(this.assertions, key2, assertion);
4004
+ return this.append(this.assertions, key3, assertion);
4005
4005
  }
4006
4006
  appendCorrection(correction) {
4007
4007
  requireIdentity(correction.id, "correction.id");
@@ -4116,10 +4116,10 @@ var DatasetLineageLedger = class _DatasetLineageLedger {
4116
4116
  const correction = pending.splice(index, 1)[0];
4117
4117
  ledger.appendCorrection(correction);
4118
4118
  if (correction.replacementAssertionId && correction.replacementRevision) {
4119
- const key2 = `${correction.replacementAssertionId}@${correction.replacementRevision}`;
4120
- if (!ledger.assertions.has(key2)) {
4121
- const replacement = archive.assertions.find((item) => `${item.id}@${item.revision}` === key2);
4122
- if (!replacement) throw new LineageValidationError("IDENTITY_DANGLING", `Missing replacement assertion ${key2}`);
4119
+ const key3 = `${correction.replacementAssertionId}@${correction.replacementRevision}`;
4120
+ if (!ledger.assertions.has(key3)) {
4121
+ const replacement = archive.assertions.find((item) => `${item.id}@${item.revision}` === key3);
4122
+ if (!replacement) throw new LineageValidationError("IDENTITY_DANGLING", `Missing replacement assertion ${key3}`);
4123
4123
  ledger.appendAssertion(replacement);
4124
4124
  }
4125
4125
  }
@@ -4167,19 +4167,19 @@ var DatasetLineageLedger = class _DatasetLineageLedger {
4167
4167
  }
4168
4168
  });
4169
4169
  }
4170
- append(map, key2, value) {
4170
+ append(map, key3, value) {
4171
4171
  this.sequence += 1;
4172
- map.set(key2, { sequence: this.sequence, value: clone2(value) });
4172
+ map.set(key3, { sequence: this.sequence, value: clone2(value) });
4173
4173
  return this.sequence;
4174
4174
  }
4175
- ensureUnique(map, key2, label) {
4176
- if (map.has(key2)) throw new LineageValidationError("IDENTITY_DUPLICATE", `Duplicate ${label} identity ${key2}`);
4175
+ ensureUnique(map, key3, label) {
4176
+ if (map.has(key3)) throw new LineageValidationError("IDENTITY_DUPLICATE", `Duplicate ${label} identity ${key3}`);
4177
4177
  }
4178
4178
  visibleAt(map, snapshot) {
4179
- return new Map([...map].filter(([, entry]) => entry.sequence <= snapshot).map(([key2, entry]) => [key2, clone2(entry.value)]));
4179
+ return new Map([...map].filter(([, entry]) => entry.sequence <= snapshot).map(([key3, entry]) => [key3, clone2(entry.value)]));
4180
4180
  }
4181
- sorted(map, key2 = (item) => item.id) {
4182
- return [...map.values()].sort((left, right) => key2(left).localeCompare(key2(right))).map(clone2);
4181
+ sorted(map, key3 = (item) => item.id) {
4182
+ return [...map.values()].sort((left, right) => key3(left).localeCompare(key3(right))).map(clone2);
4183
4183
  }
4184
4184
  hasReplacementPermission(assertionId, revision) {
4185
4185
  return [...this.corrections.values()].some((entry) => entry.value.action === "correct" && entry.value.replacementAssertionId === assertionId && entry.value.replacementRevision === revision);
@@ -4215,6 +4215,479 @@ function compareAssertions(left, right) {
4215
4215
 
4216
4216
  // src/dataset-execution-capabilities.ts
4217
4217
  init_geometry_buffer();
4218
+
4219
+ // schemas/dataset-execution-capabilities/validation/1.0.1/schema.json
4220
+ var schema_default = {
4221
+ $schema: "https://json-schema.org/draft/2020-12/schema",
4222
+ $id: "https://fortemi.dev/schemas/dataset-execution-capabilities/validation/1.0.1.schema.json",
4223
+ title: "Dataset Capability Validation Revision 1.0.1 (v1 wire)",
4224
+ oneOf: [
4225
+ {
4226
+ $ref: "#/$defs/descriptor"
4227
+ },
4228
+ {
4229
+ $ref: "#/$defs/request"
4230
+ },
4231
+ {
4232
+ $ref: "#/$defs/result"
4233
+ }
4234
+ ],
4235
+ $defs: {
4236
+ capabilityId: {
4237
+ enum: [
4238
+ "ingest.full",
4239
+ "ingest.snapshot",
4240
+ "ingest.incremental",
4241
+ "ingest.stream",
4242
+ "schema.inspect",
4243
+ "identity.stable-revision",
4244
+ "identity.record",
4245
+ "mutation.upsert",
4246
+ "mutation.tombstone",
4247
+ "mutation.reconcile",
4248
+ "checkpoint.read",
4249
+ "checkpoint.write",
4250
+ "execution.cancel",
4251
+ "rejection.record",
4252
+ "index.lexical",
4253
+ "index.chunk",
4254
+ "index.vector",
4255
+ "index.hybrid",
4256
+ "index.rerank",
4257
+ "index.graph",
4258
+ "index.community",
4259
+ "lineage.dataset",
4260
+ "lineage.record",
4261
+ "lineage.field",
4262
+ "lineage.relationship-evidence",
4263
+ "transaction.atomic-batch",
4264
+ "privacy.pre-materialization-filter",
4265
+ "pagination.cursor",
4266
+ "ordering.deterministic"
4267
+ ]
4268
+ },
4269
+ semver: {
4270
+ type: "string",
4271
+ maxLength: 256,
4272
+ pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-((?:0|[1-9][0-9]*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\\+([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?$(?![\\s\\S])"
4273
+ },
4274
+ digest: {
4275
+ type: "string",
4276
+ pattern: "^[a-z0-9]+:[a-f0-9]+$"
4277
+ },
4278
+ limits: {
4279
+ type: "object",
4280
+ additionalProperties: false,
4281
+ properties: {
4282
+ maxInputBytes: {
4283
+ type: "integer",
4284
+ minimum: 0,
4285
+ maximum: 9007199254740991
4286
+ },
4287
+ maxRecordBytes: {
4288
+ type: "integer",
4289
+ minimum: 0,
4290
+ maximum: 9007199254740991
4291
+ },
4292
+ maxBatchRecords: {
4293
+ type: "integer",
4294
+ minimum: 0,
4295
+ maximum: 9007199254740991
4296
+ },
4297
+ maxConcurrency: {
4298
+ type: "integer",
4299
+ minimum: 0,
4300
+ maximum: 9007199254740991
4301
+ },
4302
+ maxPageSize: {
4303
+ type: "integer",
4304
+ minimum: 0,
4305
+ maximum: 9007199254740991
4306
+ },
4307
+ maxTraversalDepth: {
4308
+ type: "integer",
4309
+ minimum: 0,
4310
+ maximum: 9007199254740991
4311
+ }
4312
+ }
4313
+ },
4314
+ evidence: {
4315
+ type: "object",
4316
+ additionalProperties: false,
4317
+ required: [
4318
+ "id",
4319
+ "kind",
4320
+ "uri"
4321
+ ],
4322
+ properties: {
4323
+ id: {
4324
+ type: "string",
4325
+ minLength: 1
4326
+ },
4327
+ kind: {
4328
+ enum: [
4329
+ "fixture",
4330
+ "conformance-report",
4331
+ "live-qualification"
4332
+ ]
4333
+ },
4334
+ uri: {
4335
+ type: "string",
4336
+ minLength: 1
4337
+ },
4338
+ digest: {
4339
+ $ref: "#/$defs/digest"
4340
+ }
4341
+ }
4342
+ },
4343
+ capability: {
4344
+ type: "object",
4345
+ additionalProperties: false,
4346
+ required: [
4347
+ "id",
4348
+ "version",
4349
+ "status",
4350
+ "evidence"
4351
+ ],
4352
+ properties: {
4353
+ id: {
4354
+ $ref: "#/$defs/capabilityId"
4355
+ },
4356
+ version: {
4357
+ $ref: "#/$defs/semver"
4358
+ },
4359
+ status: {
4360
+ enum: [
4361
+ "supported",
4362
+ "experimental",
4363
+ "unsupported"
4364
+ ]
4365
+ },
4366
+ limits: {
4367
+ $ref: "#/$defs/limits"
4368
+ },
4369
+ evidence: {
4370
+ type: "array",
4371
+ items: {
4372
+ type: "string",
4373
+ minLength: 1
4374
+ },
4375
+ uniqueItems: true
4376
+ }
4377
+ }
4378
+ },
4379
+ runtime: {
4380
+ type: "object",
4381
+ additionalProperties: false,
4382
+ required: [
4383
+ "id",
4384
+ "version",
4385
+ "plane",
4386
+ "dataClass",
4387
+ "maturity"
4388
+ ],
4389
+ properties: {
4390
+ id: {
4391
+ type: "string",
4392
+ minLength: 1
4393
+ },
4394
+ version: {
4395
+ $ref: "#/$defs/semver"
4396
+ },
4397
+ plane: {
4398
+ enum: [
4399
+ "browser-local-archive",
4400
+ "static-cache",
4401
+ "portable-shard",
4402
+ "server-process",
4403
+ "live-remote-persistence"
4404
+ ]
4405
+ },
4406
+ dataClass: {
4407
+ enum: [
4408
+ "canonical",
4409
+ "regenerable-index",
4410
+ "static-cache",
4411
+ "portable-projection",
4412
+ "remote-persistence"
4413
+ ]
4414
+ },
4415
+ maturity: {
4416
+ enum: [
4417
+ "experimental",
4418
+ "alpha",
4419
+ "beta",
4420
+ "stable"
4421
+ ]
4422
+ }
4423
+ }
4424
+ },
4425
+ guarantees: {
4426
+ type: "object",
4427
+ additionalProperties: false,
4428
+ required: [
4429
+ "transaction",
4430
+ "isolation",
4431
+ "durability",
4432
+ "availability",
4433
+ "ordering"
4434
+ ],
4435
+ properties: {
4436
+ transaction: {
4437
+ enum: [
4438
+ "none",
4439
+ "single-record",
4440
+ "atomic-batch"
4441
+ ]
4442
+ },
4443
+ isolation: {
4444
+ enum: [
4445
+ "none",
4446
+ "snapshot",
4447
+ "serializable"
4448
+ ]
4449
+ },
4450
+ durability: {
4451
+ enum: [
4452
+ "process",
4453
+ "memory",
4454
+ "filesystem",
4455
+ "wal",
4456
+ "replicated"
4457
+ ]
4458
+ },
4459
+ availability: {
4460
+ enum: [
4461
+ "local-process",
4462
+ "single-host",
4463
+ "remote-service"
4464
+ ]
4465
+ },
4466
+ ordering: {
4467
+ enum: [
4468
+ "unspecified",
4469
+ "stable-identity",
4470
+ "backend-cursor"
4471
+ ]
4472
+ }
4473
+ }
4474
+ },
4475
+ descriptor: {
4476
+ type: "object",
4477
+ additionalProperties: false,
4478
+ required: [
4479
+ "contract",
4480
+ "schemaVersion",
4481
+ "runtime",
4482
+ "guarantees",
4483
+ "capabilities",
4484
+ "evidence"
4485
+ ],
4486
+ properties: {
4487
+ contract: {
4488
+ const: "fortemi.dataset-execution-capabilities/v1"
4489
+ },
4490
+ schemaVersion: {
4491
+ $ref: "#/$defs/semver"
4492
+ },
4493
+ runtime: {
4494
+ $ref: "#/$defs/runtime"
4495
+ },
4496
+ guarantees: {
4497
+ $ref: "#/$defs/guarantees"
4498
+ },
4499
+ capabilities: {
4500
+ type: "array",
4501
+ items: {
4502
+ $ref: "#/$defs/capability"
4503
+ }
4504
+ },
4505
+ evidence: {
4506
+ type: "array",
4507
+ items: {
4508
+ $ref: "#/$defs/evidence"
4509
+ }
4510
+ }
4511
+ }
4512
+ },
4513
+ requirement: {
4514
+ type: "object",
4515
+ additionalProperties: false,
4516
+ required: [
4517
+ "id"
4518
+ ],
4519
+ properties: {
4520
+ id: {
4521
+ $ref: "#/$defs/capabilityId"
4522
+ },
4523
+ minimumVersion: {
4524
+ $ref: "#/$defs/semver"
4525
+ },
4526
+ minimumLimits: {
4527
+ $ref: "#/$defs/limits"
4528
+ }
4529
+ }
4530
+ },
4531
+ optionalRequirement: {
4532
+ type: "object",
4533
+ additionalProperties: false,
4534
+ required: [
4535
+ "id"
4536
+ ],
4537
+ properties: {
4538
+ id: {
4539
+ $ref: "#/$defs/capabilityId"
4540
+ },
4541
+ minimumVersion: {
4542
+ $ref: "#/$defs/semver"
4543
+ },
4544
+ minimumLimits: {
4545
+ $ref: "#/$defs/limits"
4546
+ },
4547
+ fallback: {
4548
+ type: "array",
4549
+ items: {
4550
+ $ref: "#/$defs/capabilityId"
4551
+ },
4552
+ uniqueItems: true
4553
+ }
4554
+ }
4555
+ },
4556
+ request: {
4557
+ type: "object",
4558
+ additionalProperties: false,
4559
+ required: [
4560
+ "contract",
4561
+ "required"
4562
+ ],
4563
+ properties: {
4564
+ contract: {
4565
+ const: "fortemi.dataset-execution-capabilities/v1"
4566
+ },
4567
+ required: {
4568
+ type: "array",
4569
+ items: {
4570
+ $ref: "#/$defs/requirement"
4571
+ }
4572
+ },
4573
+ optional: {
4574
+ type: "array",
4575
+ items: {
4576
+ $ref: "#/$defs/optionalRequirement"
4577
+ }
4578
+ }
4579
+ }
4580
+ },
4581
+ diagnostic: {
4582
+ type: "object",
4583
+ additionalProperties: false,
4584
+ required: [
4585
+ "code",
4586
+ "message"
4587
+ ],
4588
+ properties: {
4589
+ code: {
4590
+ enum: [
4591
+ "CONTRACT_MAJOR_UNSUPPORTED",
4592
+ "SCHEMA_VERSION_UNSUPPORTED",
4593
+ "DESCRIPTOR_INVALID",
4594
+ "CAPABILITY_DUPLICATE",
4595
+ "CAPABILITY_INCONSISTENT",
4596
+ "REQUIRED_CAPABILITY_MISSING",
4597
+ "CAPABILITY_VERSION_INSUFFICIENT",
4598
+ "CAPABILITY_LIMIT_INSUFFICIENT"
4599
+ ]
4600
+ },
4601
+ capability: {
4602
+ $ref: "#/$defs/capabilityId"
4603
+ },
4604
+ path: {
4605
+ type: "string"
4606
+ },
4607
+ message: {
4608
+ type: "string",
4609
+ minLength: 1
4610
+ }
4611
+ }
4612
+ },
4613
+ degradation: {
4614
+ type: "object",
4615
+ additionalProperties: false,
4616
+ required: [
4617
+ "requested",
4618
+ "reason",
4619
+ "changedGuarantees"
4620
+ ],
4621
+ properties: {
4622
+ requested: {
4623
+ $ref: "#/$defs/capabilityId"
4624
+ },
4625
+ selected: {
4626
+ $ref: "#/$defs/capabilityId"
4627
+ },
4628
+ reason: {
4629
+ enum: [
4630
+ "unsupported",
4631
+ "version-insufficient",
4632
+ "limit-insufficient"
4633
+ ]
4634
+ },
4635
+ changedGuarantees: {
4636
+ type: "array",
4637
+ minItems: 1,
4638
+ items: {
4639
+ type: "string",
4640
+ minLength: 1
4641
+ }
4642
+ }
4643
+ }
4644
+ },
4645
+ result: {
4646
+ type: "object",
4647
+ additionalProperties: false,
4648
+ required: [
4649
+ "contract",
4650
+ "accepted",
4651
+ "runtime",
4652
+ "selected",
4653
+ "degradations",
4654
+ "diagnostics"
4655
+ ],
4656
+ properties: {
4657
+ contract: {
4658
+ const: "fortemi.dataset-execution-capabilities/v1"
4659
+ },
4660
+ accepted: {
4661
+ type: "boolean"
4662
+ },
4663
+ runtime: {
4664
+ $ref: "#/$defs/runtime"
4665
+ },
4666
+ selected: {
4667
+ type: "array",
4668
+ items: {
4669
+ $ref: "#/$defs/capabilityId"
4670
+ },
4671
+ uniqueItems: true
4672
+ },
4673
+ degradations: {
4674
+ type: "array",
4675
+ items: {
4676
+ $ref: "#/$defs/degradation"
4677
+ }
4678
+ },
4679
+ diagnostics: {
4680
+ type: "array",
4681
+ items: {
4682
+ $ref: "#/$defs/diagnostic"
4683
+ }
4684
+ }
4685
+ }
4686
+ }
4687
+ }
4688
+ };
4689
+
4690
+ // src/dataset-execution-capabilities.ts
4218
4691
  var DATASET_EXECUTION_CONTRACT = "fortemi.dataset-execution-capabilities/v1";
4219
4692
  var DATASET_EXECUTION_SCHEMA_VERSION = "1.0.0";
4220
4693
  var DATASET_EXECUTION_CAPABILITY_IDS = [
@@ -4250,27 +4723,64 @@ var DATASET_EXECUTION_CAPABILITY_IDS = [
4250
4723
  ];
4251
4724
  var ID_SET = new Set(DATASET_EXECUTION_CAPABILITY_IDS);
4252
4725
  var LIMIT_KEYS = ["maxInputBytes", "maxRecordBytes", "maxBatchRecords", "maxConcurrency", "maxPageSize", "maxTraversalDepth"];
4726
+ var versionPattern = new RegExp(schema_default.$defs.semver.pattern);
4727
+ var ajv = new Ajv20206({ strict: true, allErrors: false });
4728
+ ajv.addSchema(schema_default);
4729
+ var descriptorStructure = ajv.compile({ $ref: schema_default.$id + "#/$defs/descriptor" });
4730
+ var requestStructure = ajv.compile({ $ref: schema_default.$id + "#/$defs/request" });
4731
+ function parseVersion(value) {
4732
+ if (typeof value !== "string" || value.length > 256) return null;
4733
+ const match = versionPattern.exec(value);
4734
+ if (!match || match[0] !== value) return null;
4735
+ const core = match.slice(1, 4).map(Number);
4736
+ if (!core.every(Number.isSafeInteger)) return null;
4737
+ return { core, prerelease: match[4]?.split(".") ?? [] };
4738
+ }
4253
4739
  function major(version) {
4254
- const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(version);
4255
- return match ? Number(match[1]) : null;
4740
+ const parsed = parseVersion(version);
4741
+ return parsed && parsed.prerelease.length === 0 ? parsed.core[0] : null;
4256
4742
  }
4257
4743
  function compareVersions(left, right) {
4258
- const parse = (value) => {
4259
- const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(value);
4260
- return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
4261
- };
4262
- const a = parse(left);
4263
- const b = parse(right);
4744
+ const a = parseVersion(left);
4745
+ const b = parseVersion(right);
4264
4746
  if (!a || !b) return null;
4265
4747
  for (let index = 0; index < 3; index++) {
4266
- if (a[index] !== b[index]) return a[index] > b[index] ? 1 : -1;
4748
+ if (a.core[index] !== b.core[index]) return a.core[index] > b.core[index] ? 1 : -1;
4749
+ }
4750
+ if (!a.prerelease.length || !b.prerelease.length) {
4751
+ return a.prerelease.length ? -1 : b.prerelease.length ? 1 : 0;
4752
+ }
4753
+ for (let index = 0; index < Math.max(a.prerelease.length, b.prerelease.length); index++) {
4754
+ const leftPart = a.prerelease[index];
4755
+ const rightPart = b.prerelease[index];
4756
+ if (leftPart === rightPart) continue;
4757
+ if (leftPart === void 0) return -1;
4758
+ if (rightPart === void 0) return 1;
4759
+ const leftNumeric = /^[0-9]+$/.test(leftPart);
4760
+ const rightNumeric = /^[0-9]+$/.test(rightPart);
4761
+ if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;
4762
+ if (leftNumeric && leftPart.length !== rightPart.length) return leftPart.length > rightPart.length ? 1 : -1;
4763
+ return leftPart > rightPart ? 1 : -1;
4267
4764
  }
4268
4765
  return 0;
4269
4766
  }
4270
4767
  function isSupported(capability) {
4271
- return capability !== void 0 && capability.status !== "unsupported";
4768
+ return capability !== void 0 && (capability.status === "supported" || capability.status === "experimental");
4769
+ }
4770
+ function structuralDiagnostics(validate4, prefix = "") {
4771
+ return (validate4.errors ?? []).slice(0, 8).map((error) => ({
4772
+ code: "DESCRIPTOR_INVALID",
4773
+ path: (prefix + error.instancePath).slice(0, 256),
4774
+ message: "Invalid capability wire structure: " + error.keyword
4775
+ }));
4272
4776
  }
4273
4777
  function validateDatasetExecutionDescriptor(descriptor) {
4778
+ if (!descriptorStructure(descriptor)) {
4779
+ if (descriptor && typeof descriptor === "object" && "contract" in descriptor && descriptor.contract !== DATASET_EXECUTION_CONTRACT) {
4780
+ return [{ code: "CONTRACT_MAJOR_UNSUPPORTED", path: "/contract", message: "Unsupported descriptor contract" }];
4781
+ }
4782
+ return structuralDiagnostics(descriptorStructure);
4783
+ }
4274
4784
  const diagnostics = [];
4275
4785
  if (descriptor.contract !== DATASET_EXECUTION_CONTRACT) {
4276
4786
  diagnostics.push({ code: "CONTRACT_MAJOR_UNSUPPORTED", path: "/contract", message: `Unsupported contract ${String(descriptor.contract)}` });
@@ -4278,6 +4788,9 @@ function validateDatasetExecutionDescriptor(descriptor) {
4278
4788
  if (major(descriptor.schemaVersion) !== 1) {
4279
4789
  diagnostics.push({ code: "SCHEMA_VERSION_UNSUPPORTED", path: "/schemaVersion", message: `Unsupported descriptor schema version ${descriptor.schemaVersion}` });
4280
4790
  }
4791
+ if (!parseVersion(descriptor.runtime.version)) {
4792
+ diagnostics.push({ code: "DESCRIPTOR_INVALID", path: "/runtime/version", message: "Invalid runtime semantic version" });
4793
+ }
4281
4794
  const capabilities = /* @__PURE__ */ new Map();
4282
4795
  descriptor.capabilities.forEach((capability, index) => {
4283
4796
  if (!ID_SET.has(capability.id) || compareVersions(capability.version, capability.version) === null) {
@@ -4288,10 +4801,10 @@ function validateDatasetExecutionDescriptor(descriptor) {
4288
4801
  diagnostics.push({ code: "CAPABILITY_DUPLICATE", capability: capability.id, path: `/capabilities/${index}/id`, message: `Capability ${capability.id} is declared more than once` });
4289
4802
  }
4290
4803
  capabilities.set(capability.id, capability);
4291
- for (const key2 of LIMIT_KEYS) {
4292
- const value = capability.limits?.[key2];
4804
+ for (const key3 of LIMIT_KEYS) {
4805
+ const value = capability.limits?.[key3];
4293
4806
  if (value !== void 0 && (!Number.isSafeInteger(value) || value < 0)) {
4294
- diagnostics.push({ code: "DESCRIPTOR_INVALID", capability: capability.id, path: `/capabilities/${index}/limits/${key2}`, message: `${key2} must be a non-negative safe integer` });
4807
+ diagnostics.push({ code: "DESCRIPTOR_INVALID", capability: capability.id, path: `/capabilities/${index}/limits/${key3}`, message: `${key3} must be a non-negative safe integer` });
4295
4808
  }
4296
4809
  }
4297
4810
  if (capability.status !== "unsupported" && capability.evidence.length === 0) {
@@ -4299,7 +4812,7 @@ function validateDatasetExecutionDescriptor(descriptor) {
4299
4812
  }
4300
4813
  for (const evidenceId of capability.evidence) {
4301
4814
  if (!descriptor.evidence.some((evidence) => evidence.id === evidenceId)) {
4302
- diagnostics.push({ code: "DESCRIPTOR_INVALID", capability: capability.id, path: `/capabilities/${index}/evidence`, message: `Unknown evidence ${evidenceId}` });
4815
+ diagnostics.push({ code: "DESCRIPTOR_INVALID", capability: capability.id, path: `/capabilities/${index}/evidence`, message: "Capability references undeclared evidence" });
4303
4816
  }
4304
4817
  }
4305
4818
  });
@@ -4326,31 +4839,53 @@ function validateDatasetExecutionDescriptor(descriptor) {
4326
4839
  }
4327
4840
  return diagnostics;
4328
4841
  }
4842
+ function validateDatasetExecutionRequest(request) {
4843
+ if (!requestStructure(request)) {
4844
+ if (request && typeof request === "object" && "contract" in request && request.contract !== DATASET_EXECUTION_CONTRACT) {
4845
+ return [{ code: "CONTRACT_MAJOR_UNSUPPORTED", path: "/request/contract", message: "Unsupported request contract" }];
4846
+ }
4847
+ return structuralDiagnostics(requestStructure, "/request");
4848
+ }
4849
+ const diagnostics = [];
4850
+ for (const [group, requirements] of [["required", request.required], ["optional", request.optional ?? []]]) {
4851
+ requirements.forEach((requirement, index) => {
4852
+ if (requirement.minimumVersion !== void 0 && !parseVersion(requirement.minimumVersion)) {
4853
+ diagnostics.push({ code: "DESCRIPTOR_INVALID", path: "/request/" + group + "/" + index + "/minimumVersion", message: "Invalid required semantic version" });
4854
+ }
4855
+ });
4856
+ }
4857
+ return diagnostics;
4858
+ }
4859
+ function negotiateDatasetExecutionCapabilitiesFromWire(descriptor, request) {
4860
+ const diagnostics = [...validateDatasetExecutionDescriptor(descriptor), ...validateDatasetExecutionRequest(request)];
4861
+ if (diagnostics.length) return { valid: false, diagnostics };
4862
+ return {
4863
+ valid: true,
4864
+ result: negotiateDatasetExecutionCapabilities(descriptor, request)
4865
+ };
4866
+ }
4329
4867
  function assessRequirement(requirement, capabilities) {
4330
4868
  const capability = capabilities.get(requirement.id);
4331
4869
  if (!isSupported(capability)) {
4332
4870
  return { ok: false, reason: "unsupported", diagnostics: [{ code: "REQUIRED_CAPABILITY_MISSING", capability: requirement.id, message: `Capability ${requirement.id} is unsupported` }] };
4333
4871
  }
4334
- if (requirement.minimumVersion) {
4872
+ if (requirement.minimumVersion !== void 0) {
4335
4873
  const comparison = compareVersions(capability.version, requirement.minimumVersion);
4336
4874
  if (comparison === null || comparison < 0) {
4337
4875
  return { ok: false, reason: "version-insufficient", diagnostics: [{ code: "CAPABILITY_VERSION_INSUFFICIENT", capability: requirement.id, message: `${capability.version} does not satisfy ${requirement.minimumVersion}` }] };
4338
4876
  }
4339
4877
  }
4340
- for (const key2 of LIMIT_KEYS) {
4341
- const required = requirement.minimumLimits?.[key2];
4342
- if (required !== void 0 && (capability.limits?.[key2] ?? -1) < required) {
4343
- return { ok: false, reason: "limit-insufficient", diagnostics: [{ code: "CAPABILITY_LIMIT_INSUFFICIENT", capability: requirement.id, path: `/minimumLimits/${key2}`, message: `${key2} does not satisfy ${required}` }] };
4878
+ for (const key3 of LIMIT_KEYS) {
4879
+ const required = requirement.minimumLimits?.[key3];
4880
+ if (required !== void 0 && (capability.limits?.[key3] ?? -1) < required) {
4881
+ return { ok: false, reason: "limit-insufficient", diagnostics: [{ code: "CAPABILITY_LIMIT_INSUFFICIENT", capability: requirement.id, path: `/minimumLimits/${key3}`, message: `${key3} does not satisfy ${required}` }] };
4344
4882
  }
4345
4883
  }
4346
4884
  return { ok: true, diagnostics: [] };
4347
4885
  }
4348
4886
  function negotiateDatasetExecutionCapabilities(descriptor, request) {
4349
- const diagnostics = validateDatasetExecutionDescriptor(descriptor);
4350
- if (request.contract !== DATASET_EXECUTION_CONTRACT) {
4351
- diagnostics.push({ code: "CONTRACT_MAJOR_UNSUPPORTED", path: "/contract", message: `Unsupported request contract ${String(request.contract)}` });
4352
- }
4353
- const capabilities = new Map(descriptor.capabilities.map((capability) => [capability.id, capability]));
4887
+ const diagnostics = [...validateDatasetExecutionDescriptor(descriptor), ...validateDatasetExecutionRequest(request)];
4888
+ const capabilities = new Map(diagnostics.length ? [] : descriptor.capabilities.map((capability) => [capability.id, capability]));
4354
4889
  const selected = [];
4355
4890
  const degradations = [];
4356
4891
  if (diagnostics.length === 0) {
@@ -4378,7 +4913,7 @@ function negotiateDatasetExecutionCapabilities(descriptor, request) {
4378
4913
  return {
4379
4914
  contract: DATASET_EXECUTION_CONTRACT,
4380
4915
  accepted: diagnostics.length === 0,
4381
- runtime: { ...descriptor.runtime },
4916
+ runtime: { ...descriptor?.runtime },
4382
4917
  selected: [...new Set(selected)],
4383
4918
  degradations,
4384
4919
  diagnostics
@@ -4451,7 +4986,7 @@ var encoder = new TextEncoder();
4451
4986
  function canonicalJson3(value) {
4452
4987
  if (value === null || typeof value !== "object") return JSON.stringify(value);
4453
4988
  if (Array.isArray(value)) return `[${value.map(canonicalJson3).join(",")}]`;
4454
- return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key2, item]) => `${JSON.stringify(key2)}:${canonicalJson3(item)}`).join(",")}}`;
4989
+ return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key3, item]) => `${JSON.stringify(key3)}:${canonicalJson3(item)}`).join(",")}}`;
4455
4990
  }
4456
4991
  function digestDatasetMaterializationValue(value) {
4457
4992
  return computeHash(encoder.encode(canonicalJson3(value)));
@@ -4542,7 +5077,7 @@ async function executeDatasetMaterialization(request, runtime, adapter, authoriz
4542
5077
  }
4543
5078
  const selected = [request.profile, ...options.fallbackProfiles ?? []].find((item) => item.id === negotiation.selectedProfile);
4544
5079
  try {
4545
- const validateConfiguration = new Ajv20202({ strict: true, allErrors: true }).compile(selected.configurationSchema);
5080
+ const validateConfiguration = new Ajv20206({ strict: true, allErrors: true }).compile(selected.configurationSchema);
4546
5081
  if (!validateConfiguration(request.configuration)) {
4547
5082
  throw new DatasetMaterializationError("CONFIGURATION_INVALID", `Configuration does not satisfy ${selected.id}: ${JSON.stringify(validateConfiguration.errors)}`);
4548
5083
  }
@@ -6342,7 +6877,7 @@ function nativeIdentityKey(spec, row) {
6342
6877
  // src/migrations/0031_native_shard_lineage.ts
6343
6878
  var triggers = Object.entries(nativeIdentities).flatMap(([component, spec]) => (component === "links" ? ["link", "link_url_target"] : [spec.table]).map((table) => `
6344
6879
  CREATE TRIGGER native_lineage_delete AFTER DELETE ON ${table} FOR EACH ROW
6345
- EXECUTE FUNCTION delete_native_record_lineage('${component}', ${spec.keys.map((key2) => `'${key2}'`).join(", ")});`)).join("\n");
6880
+ EXECUTE FUNCTION delete_native_record_lineage('${component}', ${spec.keys.map((key3) => `'${key3}'`).join(", ")});`)).join("\n");
6346
6881
  var migration0031 = {
6347
6882
  version: 31,
6348
6883
  name: "0031_native_shard_lineage",
@@ -6388,6 +6923,58 @@ var migration0032 = {
6388
6923
  `
6389
6924
  };
6390
6925
 
6926
+ // src/migrations/0033_typed_metadata_search.ts
6927
+ init_geometry_buffer();
6928
+ var migration0033 = {
6929
+ version: 33,
6930
+ name: "0033_typed_metadata_search",
6931
+ sql: `
6932
+ CREATE FUNCTION public.metadata_search_order_key_v1(value jsonb)
6933
+ RETURNS numeric LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
6934
+ SET search_path = pg_catalog
6935
+ AS $function$
6936
+ SELECT CASE jsonb_typeof(value)
6937
+ WHEN 'number' THEN trunc(greatest(-1e16::numeric,
6938
+ least(1e16::numeric, (value #>> '{}')::numeric)), 18)
6939
+ WHEN 'boolean' THEN CASE WHEN value = 'true'::jsonb THEN 1::numeric ELSE 0::numeric END
6940
+ ELSE NULL::numeric
6941
+ END
6942
+ $function$;
6943
+
6944
+ CREATE FUNCTION public.metadata_search_text_key_v1(value jsonb)
6945
+ RETURNS text LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE
6946
+ SET search_path = pg_catalog
6947
+ AS $function$
6948
+ SELECT CASE WHEN jsonb_typeof(value) = 'string'
6949
+ THEN left(value #>> '{}', 256) ELSE NULL::text END
6950
+ $function$;
6951
+
6952
+ DO $metadata_indexes$
6953
+ DECLARE metadata_path text;
6954
+ BEGIN
6955
+ FOREACH metadata_path IN ARRAY ARRAY['provider', 'model', 'role', 'event_kind', 'sensitivity']
6956
+ LOOP
6957
+ -- Superseded unbounded indexes can reject large values before query rechecks.
6958
+ EXECUTE format('DROP INDEX %I', 'idx_note_metadata_' || metadata_path);
6959
+ EXECUTE format('DROP INDEX %I', 'idx_note_native_metadata_' || metadata_path);
6960
+ EXECUTE format(
6961
+ 'CREATE INDEX %I ON note (
6962
+ (jsonb_typeof(metadata -> %L)),
6963
+ (public.metadata_search_order_key_v1(metadata -> %L)),
6964
+ (public.metadata_search_text_key_v1(metadata -> %L) COLLATE "C"))',
6965
+ 'idx_note_metadata_' || metadata_path || '_v1', metadata_path, metadata_path, metadata_path);
6966
+ END LOOP;
6967
+ END
6968
+ $metadata_indexes$;
6969
+
6970
+ CREATE INDEX idx_source_identity_metadata_run_v1 ON source_identity
6971
+ (tenant_id, import_run_id COLLATE "C", note_id);
6972
+ CREATE INDEX idx_source_identity_metadata_note_v1 ON source_identity (tenant_id, note_id);
6973
+ UPDATE metadata_index_path SET value_type = 'json-scalar-v1', indexed_at = now()
6974
+ WHERE path IN ('provider', 'model', 'role', 'event_kind', 'sensitivity');
6975
+ `
6976
+ };
6977
+
6391
6978
  // src/migrations/index.ts
6392
6979
  var allMigrations = [
6393
6980
  migration0001,
@@ -6421,7 +7008,8 @@ var allMigrations = [
6421
7008
  migration0029,
6422
7009
  migration0030,
6423
7010
  migration0031,
6424
- migration0032
7011
+ migration0032,
7012
+ migration0033
6425
7013
  ];
6426
7014
 
6427
7015
  // src/data-archive.ts
@@ -7023,6 +7611,137 @@ var NotesRepository = class {
7023
7611
  // src/repositories/search-repository.ts
7024
7612
  init_geometry_buffer();
7025
7613
 
7614
+ // src/repositories/search-evidence-repository.ts
7615
+ init_geometry_buffer();
7616
+
7617
+ // src/search-evidence.ts
7618
+ init_geometry_buffer();
7619
+
7620
+ // schemas/metadata-search/candidate/1.0.0/evidence-locator.schema.json
7621
+ var evidence_locator_schema_default = {
7622
+ $schema: "https://json-schema.org/draft/2020-12/schema",
7623
+ $id: "https://fortemi.com/contracts/metadata-search/candidate/1.0.0/evidence-locator.schema.json",
7624
+ title: "Candidate search evidence locator",
7625
+ type: "object",
7626
+ additionalProperties: false,
7627
+ required: ["version", "note_id", "unit", "content_digest", "span"],
7628
+ properties: {
7629
+ version: { const: "1.0.0" },
7630
+ note_id: { $ref: "#/$defs/identifier" },
7631
+ unit: {
7632
+ type: "object",
7633
+ additionalProperties: false,
7634
+ required: ["kind", "id", "index"],
7635
+ properties: {
7636
+ kind: { enum: ["current", "title", "embedding", "attachment"] },
7637
+ id: { $ref: "#/$defs/identifier" },
7638
+ index: { type: "integer", minimum: 0, maximum: 2147483647 }
7639
+ },
7640
+ if: { properties: { kind: { enum: ["current", "title", "attachment"] } } },
7641
+ then: { properties: { index: { const: 0 } } }
7642
+ },
7643
+ content_digest: { $ref: "#/$defs/digest" },
7644
+ span: {
7645
+ type: "object",
7646
+ additionalProperties: false,
7647
+ required: ["unit", "start", "end"],
7648
+ properties: {
7649
+ unit: { const: "utf8-bytes" },
7650
+ start: { type: "integer", minimum: 0, maximum: 16777216 },
7651
+ end: { type: "integer", minimum: 0, maximum: 16777216 }
7652
+ }
7653
+ },
7654
+ source: {
7655
+ type: "object",
7656
+ additionalProperties: false,
7657
+ required: ["namespace", "external_id_hash", "import_run_id", "schema_version"],
7658
+ properties: {
7659
+ namespace: { $ref: "#/$defs/identifier" },
7660
+ external_id_hash: { $ref: "#/$defs/digest" },
7661
+ import_run_id: { $ref: "#/$defs/identifier" },
7662
+ schema_version: { $ref: "#/$defs/identifier" }
7663
+ }
7664
+ }
7665
+ },
7666
+ $defs: {
7667
+ identifier: { type: "string", minLength: 1, maxLength: 200, pattern: "^[^\\u0000]+$" },
7668
+ digest: { type: "string", pattern: "^sha256:[a-f0-9]{64}$" }
7669
+ }
7670
+ };
7671
+
7672
+ // src/search-evidence.ts
7673
+ var MAX_EVIDENCE_BYTES = 16 * 1024 * 1024;
7674
+ var validateSchema = new Ajv20206({ strict: true, allErrors: false, ownProperties: true }).compile(evidence_locator_schema_default);
7675
+ var encoder2 = new TextEncoder();
7676
+ var decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
7677
+ var invalid = () => new Error("SEARCH_EVIDENCE_INVALID");
7678
+ var unavailable = () => new Error("SEARCH_EVIDENCE_UNAVAILABLE");
7679
+ function wellFormed(value) {
7680
+ for (let i = 0; i < value.length; i++) {
7681
+ const code = value.charCodeAt(i);
7682
+ if (code >= 55296 && code <= 56319) {
7683
+ const next = value.charCodeAt(++i);
7684
+ if (!(next >= 56320 && next <= 57343)) return false;
7685
+ } else if (code >= 56320 && code <= 57343) return false;
7686
+ }
7687
+ return true;
7688
+ }
7689
+ function parseSearchEvidenceLocator(value) {
7690
+ if (!validateSchema(value)) throw invalid();
7691
+ const locator = value;
7692
+ const strings = [locator.note_id, locator.unit.id, ...Object.values(locator.source ?? {})];
7693
+ if (!strings.every(wellFormed) || locator.span.start > locator.span.end) throw invalid();
7694
+ if ((locator.unit.kind === "current" || locator.unit.kind === "title") && locator.unit.id !== locator.note_id) throw invalid();
7695
+ const copy = {
7696
+ version: locator.version,
7697
+ note_id: locator.note_id,
7698
+ unit: Object.freeze({ kind: locator.unit.kind, id: locator.unit.id, index: locator.unit.index }),
7699
+ content_digest: locator.content_digest,
7700
+ span: Object.freeze({ unit: locator.span.unit, start: locator.span.start, end: locator.span.end }),
7701
+ ...locator.source === void 0 ? {} : { source: Object.freeze({ ...locator.source }) }
7702
+ };
7703
+ return Object.freeze(copy);
7704
+ }
7705
+ function textBytes(content) {
7706
+ if (typeof content !== "string" || content.length > MAX_EVIDENCE_BYTES || !wellFormed(content)) return null;
7707
+ const bytes = encoder2.encode(content);
7708
+ return bytes.length <= MAX_EVIDENCE_BYTES ? bytes : null;
7709
+ }
7710
+ function spanText(bytes, start, end) {
7711
+ if (!Number.isInteger(start) || !Number.isInteger(end) || start < 0 || start > end || end > bytes.length) return null;
7712
+ if (start < bytes.length && (bytes[start] & 192) === 128 || end < bytes.length && (bytes[end] & 192) === 128) return null;
7713
+ try {
7714
+ return decoder.decode(bytes.subarray(start, end));
7715
+ } catch {
7716
+ return null;
7717
+ }
7718
+ }
7719
+ function bindSearchEvidence(text, start, end) {
7720
+ const bytes = textBytes(text.content);
7721
+ if (!bytes || spanText(bytes, start, end) === null) throw invalid();
7722
+ return parseSearchEvidenceLocator({
7723
+ version: "1.0.0",
7724
+ note_id: text.note_id,
7725
+ unit: text.unit,
7726
+ content_digest: computeHash(bytes),
7727
+ span: { unit: "utf8-bytes", start, end },
7728
+ ...text.source === void 0 ? {} : { source: text.source }
7729
+ });
7730
+ }
7731
+ function sameSource(a, b) {
7732
+ if (!a || !b) return a === b;
7733
+ return a.namespace === b.namespace && a.external_id_hash === b.external_id_hash && a.import_run_id === b.import_run_id && a.schema_version === b.schema_version;
7734
+ }
7735
+ function resolveSearchEvidence(value, text) {
7736
+ const locator = parseSearchEvidenceLocator(value);
7737
+ if (!text || locator.note_id !== text.note_id || locator.unit.kind !== text.unit.kind || locator.unit.id !== text.unit.id || locator.unit.index !== text.unit.index || !sameSource(locator.source, text.source)) throw unavailable();
7738
+ const bytes = textBytes(text.content);
7739
+ if (!bytes || computeHash(bytes) !== locator.content_digest) throw unavailable();
7740
+ const result = spanText(bytes, locator.span.start, locator.span.end);
7741
+ if (result === null) throw unavailable();
7742
+ return result;
7743
+ }
7744
+
7026
7745
  // src/repositories/condition-builder.ts
7027
7746
  init_geometry_buffer();
7028
7747
  function buildNoteConditions(options, startIdx, includeDeleted = false) {
@@ -7038,6 +7757,11 @@ function buildNoteConditions(options, startIdx, includeDeleted = false) {
7038
7757
  );
7039
7758
  params.push(options.tags);
7040
7759
  }
7760
+ if (options.tagsAll?.length) {
7761
+ conditions.push(`NOT EXISTS (SELECT 1 FROM unnest($${idx++}::text[]) wanted(tag)
7762
+ WHERE NOT EXISTS (SELECT 1 FROM note_tag nt WHERE nt.note_id = n.id AND nt.tag = wanted.tag))`);
7763
+ params.push(options.tagsAll);
7764
+ }
7041
7765
  if (options.collection_id) {
7042
7766
  conditions.push(
7043
7767
  `EXISTS (SELECT 1 FROM collection_note cn WHERE cn.note_id = n.id AND cn.collection_id = $${idx++})`
@@ -7068,6 +7792,10 @@ function buildNoteConditions(options, startIdx, includeDeleted = false) {
7068
7792
  conditions.push(`n.source = $${idx++}`);
7069
7793
  params.push(options.source);
7070
7794
  }
7795
+ if (options.sources?.length) {
7796
+ conditions.push(`n.source = ANY($${idx++}::text[])`);
7797
+ params.push(options.sources);
7798
+ }
7071
7799
  if (options.visibility) {
7072
7800
  conditions.push(`n.visibility = $${idx++}`);
7073
7801
  params.push(options.visibility);
@@ -7075,6 +7803,657 @@ function buildNoteConditions(options, startIdx, includeDeleted = false) {
7075
7803
  return { conditions, params, nextIdx: idx };
7076
7804
  }
7077
7805
 
7806
+ // src/repositories/metadata-predicates.ts
7807
+ init_geometry_buffer();
7808
+
7809
+ // schemas/metadata-search/candidate/1.0.0/predicates.schema.json
7810
+ var predicates_schema_default = {
7811
+ $schema: "https://json-schema.org/draft/2020-12/schema",
7812
+ $id: "https://fortemi.dev/schemas/metadata-search/candidate/1.0.0/predicates.schema.json",
7813
+ title: "Candidate typed metadata predicates",
7814
+ type: "array",
7815
+ maxItems: 8,
7816
+ items: {
7817
+ $ref: "#/$defs/predicate"
7818
+ },
7819
+ $defs: {
7820
+ scalar: {
7821
+ oneOf: [
7822
+ {
7823
+ type: "string",
7824
+ maxLength: 256,
7825
+ pattern: "^[^\\u0000]*$"
7826
+ },
7827
+ {
7828
+ type: "number",
7829
+ minimum: -9007199254740991,
7830
+ maximum: 9007199254740991
7831
+ },
7832
+ {
7833
+ type: "boolean"
7834
+ },
7835
+ {
7836
+ type: "null"
7837
+ }
7838
+ ]
7839
+ },
7840
+ bound: {
7841
+ oneOf: [
7842
+ {
7843
+ type: "string",
7844
+ maxLength: 256,
7845
+ pattern: "^[^\\u0000]*$"
7846
+ },
7847
+ {
7848
+ type: "number",
7849
+ minimum: -9007199254740991,
7850
+ maximum: 9007199254740991
7851
+ }
7852
+ ]
7853
+ },
7854
+ predicate: {
7855
+ oneOf: [
7856
+ {
7857
+ type: "object",
7858
+ additionalProperties: false,
7859
+ required: [
7860
+ "path",
7861
+ "op",
7862
+ "value"
7863
+ ],
7864
+ properties: {
7865
+ path: {
7866
+ enum: [
7867
+ "provider",
7868
+ "model",
7869
+ "role",
7870
+ "event_kind",
7871
+ "sensitivity",
7872
+ "import_run_id"
7873
+ ]
7874
+ },
7875
+ op: {
7876
+ const: "eq"
7877
+ },
7878
+ value: {
7879
+ $ref: "#/$defs/scalar"
7880
+ }
7881
+ },
7882
+ allOf: [
7883
+ {
7884
+ if: {
7885
+ properties: {
7886
+ path: {
7887
+ const: "import_run_id"
7888
+ }
7889
+ }
7890
+ },
7891
+ then: {
7892
+ properties: {
7893
+ value: {
7894
+ type: "string",
7895
+ maxLength: 200,
7896
+ pattern: "^[^\\u0000]*$",
7897
+ minLength: 1
7898
+ }
7899
+ }
7900
+ }
7901
+ }
7902
+ ]
7903
+ },
7904
+ {
7905
+ type: "object",
7906
+ additionalProperties: false,
7907
+ required: [
7908
+ "path",
7909
+ "op",
7910
+ "value"
7911
+ ],
7912
+ properties: {
7913
+ path: {
7914
+ enum: [
7915
+ "provider",
7916
+ "model",
7917
+ "role",
7918
+ "event_kind",
7919
+ "sensitivity",
7920
+ "import_run_id"
7921
+ ]
7922
+ },
7923
+ op: {
7924
+ const: "in"
7925
+ },
7926
+ value: {
7927
+ type: "array",
7928
+ maxItems: 32,
7929
+ items: {
7930
+ $ref: "#/$defs/scalar"
7931
+ }
7932
+ }
7933
+ },
7934
+ allOf: [
7935
+ {
7936
+ if: {
7937
+ properties: {
7938
+ path: {
7939
+ const: "import_run_id"
7940
+ }
7941
+ }
7942
+ },
7943
+ then: {
7944
+ properties: {
7945
+ value: {
7946
+ type: "array",
7947
+ items: {
7948
+ type: "string",
7949
+ maxLength: 200,
7950
+ pattern: "^[^\\u0000]*$",
7951
+ minLength: 1
7952
+ }
7953
+ }
7954
+ }
7955
+ }
7956
+ }
7957
+ ]
7958
+ },
7959
+ {
7960
+ type: "object",
7961
+ additionalProperties: false,
7962
+ required: [
7963
+ "path",
7964
+ "op"
7965
+ ],
7966
+ properties: {
7967
+ path: {
7968
+ enum: [
7969
+ "provider",
7970
+ "model",
7971
+ "role",
7972
+ "event_kind",
7973
+ "sensitivity",
7974
+ "import_run_id"
7975
+ ]
7976
+ },
7977
+ op: {
7978
+ const: "range"
7979
+ },
7980
+ gte: {
7981
+ $ref: "#/$defs/bound"
7982
+ },
7983
+ lte: {
7984
+ $ref: "#/$defs/bound"
7985
+ }
7986
+ },
7987
+ anyOf: [
7988
+ {
7989
+ properties: {
7990
+ gte: {
7991
+ $ref: "#/$defs/bound"
7992
+ }
7993
+ },
7994
+ required: [
7995
+ "gte"
7996
+ ]
7997
+ },
7998
+ {
7999
+ properties: {
8000
+ lte: {
8001
+ $ref: "#/$defs/bound"
8002
+ }
8003
+ },
8004
+ required: [
8005
+ "lte"
8006
+ ]
8007
+ }
8008
+ ],
8009
+ oneOf: [
8010
+ {
8011
+ properties: {
8012
+ gte: {
8013
+ type: "string",
8014
+ maxLength: 256,
8015
+ pattern: "^[^\\u0000]*$"
8016
+ },
8017
+ lte: {
8018
+ type: "string",
8019
+ maxLength: 256,
8020
+ pattern: "^[^\\u0000]*$"
8021
+ }
8022
+ }
8023
+ },
8024
+ {
8025
+ properties: {
8026
+ gte: {
8027
+ type: "number",
8028
+ minimum: -9007199254740991,
8029
+ maximum: 9007199254740991
8030
+ },
8031
+ lte: {
8032
+ type: "number",
8033
+ minimum: -9007199254740991,
8034
+ maximum: 9007199254740991
8035
+ }
8036
+ }
8037
+ }
8038
+ ],
8039
+ allOf: [
8040
+ {
8041
+ if: {
8042
+ properties: {
8043
+ path: {
8044
+ const: "import_run_id"
8045
+ }
8046
+ }
8047
+ },
8048
+ then: {
8049
+ properties: {
8050
+ gte: {
8051
+ type: "string",
8052
+ maxLength: 200,
8053
+ pattern: "^[^\\u0000]*$",
8054
+ minLength: 1
8055
+ },
8056
+ lte: {
8057
+ type: "string",
8058
+ maxLength: 200,
8059
+ pattern: "^[^\\u0000]*$",
8060
+ minLength: 1
8061
+ }
8062
+ }
8063
+ }
8064
+ }
8065
+ ]
8066
+ },
8067
+ {
8068
+ type: "object",
8069
+ additionalProperties: false,
8070
+ required: [
8071
+ "path",
8072
+ "op"
8073
+ ],
8074
+ properties: {
8075
+ path: {
8076
+ enum: [
8077
+ "provider",
8078
+ "model",
8079
+ "role",
8080
+ "event_kind",
8081
+ "sensitivity",
8082
+ "import_run_id"
8083
+ ]
8084
+ },
8085
+ op: {
8086
+ const: "exists"
8087
+ },
8088
+ value: {
8089
+ type: "boolean"
8090
+ }
8091
+ }
8092
+ }
8093
+ ]
8094
+ }
8095
+ }
8096
+ };
8097
+
8098
+ // src/repositories/metadata-predicates.ts
8099
+ var REGISTERED_METADATA_PATHS = [
8100
+ "provider",
8101
+ "model",
8102
+ "role",
8103
+ "event_kind",
8104
+ "sensitivity",
8105
+ "import_run_id"
8106
+ ];
8107
+ var validateSchema2 = new Ajv20206({ strict: true, allErrors: false, ownProperties: true }).compile(predicates_schema_default);
8108
+ function compareStrings(left, right) {
8109
+ const a = Array.from(left, (char) => char.codePointAt(0));
8110
+ const b = Array.from(right, (char) => char.codePointAt(0));
8111
+ for (let i = 0; i < Math.min(a.length, b.length); i++) {
8112
+ if (a[i] !== b[i]) return a[i] - b[i];
8113
+ }
8114
+ return a.length - b.length;
8115
+ }
8116
+ function validateMetadataPredicates(value) {
8117
+ if (!validateSchema2(value)) throw new Error("METADATA_PREDICATES_INVALID");
8118
+ const predicates = value;
8119
+ for (const predicate of predicates) {
8120
+ const values = predicate.op === "range" ? [predicate.gte, predicate.lte] : predicate.op === "in" ? predicate.value : [predicate.value];
8121
+ for (const scalar of values) {
8122
+ if (typeof scalar === "string" && Array.from(scalar).some((char) => {
8123
+ const code = char.codePointAt(0);
8124
+ return code >= 55296 && code <= 57343;
8125
+ })) throw new Error("METADATA_PREDICATES_INVALID");
8126
+ }
8127
+ }
8128
+ for (const predicate of predicates) {
8129
+ if (predicate.op !== "range" || predicate.gte === void 0 || predicate.lte === void 0) continue;
8130
+ const reversed = typeof predicate.gte === "string" ? compareStrings(predicate.gte, predicate.lte) > 0 : predicate.gte > predicate.lte;
8131
+ if (reversed) throw new Error("METADATA_RANGE_INVALID");
8132
+ }
8133
+ }
8134
+ function predicateSql(predicate, compare, exists) {
8135
+ switch (predicate.op) {
8136
+ case "eq":
8137
+ return compare(predicate.value, "=");
8138
+ case "in":
8139
+ return predicate.value.length ? `(${predicate.value.map((value) => compare(value, "=")).join(" OR ")})` : "FALSE";
8140
+ case "range":
8141
+ return `(${[
8142
+ predicate.gte === void 0 ? null : compare(predicate.gte, ">="),
8143
+ predicate.lte === void 0 ? null : compare(predicate.lte, "<=")
8144
+ ].filter(Boolean).join(" AND ")})`;
8145
+ case "exists":
8146
+ return predicate.value === false ? `NOT (${exists})` : exists;
8147
+ }
8148
+ }
8149
+ function buildMetadataSourceConditions(options, startIdx) {
8150
+ const predicates = options.metadataPredicates === void 0 ? [] : options.metadataPredicates;
8151
+ validateMetadataPredicates(predicates);
8152
+ const params = [options.tenant_id ?? "default"];
8153
+ let idx = startIdx + 1;
8154
+ const conditions = [
8155
+ `si.note_id = n.id`,
8156
+ `si.tenant_id = $${startIdx}`,
8157
+ "si.archive_id IS NOT DISTINCT FROM n.archive_id",
8158
+ "si.import_run_id IS NOT NULL"
8159
+ ];
8160
+ for (const predicate of predicates.filter((p) => p.path === "import_run_id")) {
8161
+ conditions.push(predicateSql(predicate, (value, op) => {
8162
+ params.push(value);
8163
+ return `si.import_run_id COLLATE "C" ${op} $${idx++}::text COLLATE "C"`;
8164
+ }, "si.import_run_id IS NOT NULL"));
8165
+ }
8166
+ return { conditions, joins: [], params, nextIdx: idx };
8167
+ }
8168
+ function buildMetadataPredicateConditions(options, startIdx) {
8169
+ const predicates = options.metadataPredicates === void 0 ? [] : options.metadataPredicates;
8170
+ validateMetadataPredicates(predicates);
8171
+ const conditions = [];
8172
+ const params = [];
8173
+ const joins = [];
8174
+ let idx = startIdx;
8175
+ if (options.archive_id !== void 0) {
8176
+ conditions.push(`n.archive_id IS NOT DISTINCT FROM $${idx++}::text`);
8177
+ params.push(options.archive_id);
8178
+ }
8179
+ if (options.tenant_id !== void 0) {
8180
+ const source = buildMetadataSourceConditions({ ...options, metadataPredicates: [] }, idx);
8181
+ const native = options.tenant_id === "default" ? " OR NOT EXISTS (SELECT 1 FROM source_identity si WHERE si.note_id = n.id)" : "";
8182
+ conditions.push(`(EXISTS (SELECT 1 FROM source_identity si WHERE ${source.conditions.join(" AND ")})${native})`);
8183
+ params.push(...source.params);
8184
+ idx = source.nextIdx;
8185
+ }
8186
+ for (const predicate of predicates) {
8187
+ if (predicate.path === "import_run_id") continue;
8188
+ const lhs = `(n.metadata -> '${predicate.path}')`;
8189
+ conditions.push(predicateSql(predicate, (value, op) => {
8190
+ if (value === null) return `jsonb_typeof(${lhs}) = 'null'`;
8191
+ const rhs = `$${idx++}::jsonb`;
8192
+ params.push(JSON.stringify(value));
8193
+ const type = typeof value;
8194
+ if (type === "string") {
8195
+ return `(jsonb_typeof(${lhs}) = 'string'
8196
+ AND public.metadata_search_order_key_v1(${lhs}) IS NULL
8197
+ AND public.metadata_search_text_key_v1(${lhs}) COLLATE "C" ${op} public.metadata_search_text_key_v1(${rhs}) COLLATE "C"
8198
+ AND (${lhs} #>> '{}') COLLATE "C" ${op} (${rhs} #>> '{}') COLLATE "C")`;
8199
+ }
8200
+ return `(jsonb_typeof(${lhs}) = '${type}'
8201
+ AND public.metadata_search_order_key_v1(${lhs}) ${op} public.metadata_search_order_key_v1(${rhs})
8202
+ AND ${lhs} ${op} ${rhs})`;
8203
+ }, `jsonb_typeof(${lhs}) IS NOT NULL`));
8204
+ }
8205
+ const runs = predicates.filter((p) => p.path === "import_run_id");
8206
+ if (runs.length) {
8207
+ const positive = runs.filter((p) => !(p.op === "exists" && p.value === false));
8208
+ for (const [selected, negated] of [[positive, false], [[], true]]) {
8209
+ if (negated ? !runs.some((p) => p.op === "exists" && p.value === false) : !positive.length) continue;
8210
+ const source = buildMetadataSourceConditions({ ...options, metadataPredicates: selected }, idx);
8211
+ conditions.push(`${negated ? "NOT " : ""}EXISTS (SELECT 1 FROM source_identity si WHERE ${source.conditions.join(" AND ")})`);
8212
+ params.push(...source.params);
8213
+ idx = source.nextIdx;
8214
+ }
8215
+ }
8216
+ return { conditions, joins, params, nextIdx: idx };
8217
+ }
8218
+
8219
+ // src/repositories/search-evidence-repository.ts
8220
+ function validateScope(scope) {
8221
+ if (!scope || typeof scope !== "object" || Array.isArray(scope) || ![Object.prototype, null].includes(Object.getPrototypeOf(scope)) || Object.keys(scope).some((key3) => !["tenant_id", "archive_id", "visibility", "metadataPredicates"].includes(key3))) {
8222
+ throw new Error("SEARCH_EVIDENCE_INVALID");
8223
+ }
8224
+ for (const key3 of ["tenant_id", "archive_id", "visibility"]) {
8225
+ const value = scope[key3];
8226
+ if (value === void 0 || key3 === "archive_id" && value === null) continue;
8227
+ if (typeof value !== "string" || value.length === 0 || value.includes("\0") || Array.from(value).some((char) => {
8228
+ const code = char.codePointAt(0);
8229
+ return code >= 55296 && code <= 57343;
8230
+ })) throw new Error("SEARCH_EVIDENCE_INVALID");
8231
+ }
8232
+ }
8233
+ async function resolveStoredSearchEvidence(db, value, scope = {}) {
8234
+ const locator = parseSearchEvidenceLocator(value);
8235
+ validateScope(scope);
8236
+ const options = { ...scope, tenant_id: scope.tenant_id ?? "default" };
8237
+ const notes = buildNoteConditions(options, 5);
8238
+ const metadata2 = buildMetadataPredicateConditions(options, notes.nextIdx);
8239
+ const params = [
8240
+ locator.note_id,
8241
+ locator.unit.id,
8242
+ locator.unit.index,
8243
+ MAX_EVIDENCE_BYTES,
8244
+ ...notes.params,
8245
+ ...metadata2.params
8246
+ ];
8247
+ const conditions = ["n.id = $1", ...notes.conditions, ...metadata2.conditions];
8248
+ let joins;
8249
+ let content;
8250
+ switch (locator.unit.kind) {
8251
+ case "current":
8252
+ joins = "JOIN note_revised_current c ON c.note_id = n.id";
8253
+ content = "c.content";
8254
+ conditions.push("n.id = $2", "$3::integer = 0");
8255
+ break;
8256
+ case "title":
8257
+ joins = "";
8258
+ content = "n.title";
8259
+ conditions.push("n.id = $2", "$3::integer = 0");
8260
+ break;
8261
+ case "embedding":
8262
+ joins = "JOIN embedding e ON e.note_id = n.id";
8263
+ content = "e.text";
8264
+ conditions.push("e.id = $2", "e.chunk_index = $3");
8265
+ break;
8266
+ case "attachment":
8267
+ joins = "JOIN attachment a ON a.note_id = n.id";
8268
+ content = "a.extracted_text";
8269
+ conditions.push("a.id = $2", "$3::integer = 0", "a.status = 'completed'", "a.deleted_at IS NULL");
8270
+ break;
8271
+ }
8272
+ if (locator.source) {
8273
+ const source = buildMetadataSourceConditions(options, metadata2.nextIdx);
8274
+ let idx = source.nextIdx;
8275
+ conditions.push(`EXISTS (SELECT 1 FROM source_identity si
8276
+ WHERE ${source.conditions.join(" AND ")}
8277
+ AND si.namespace = $${idx++} AND si.external_id_hash = $${idx++}
8278
+ AND si.import_run_id = $${idx++} AND si.source_schema_version = $${idx++})`);
8279
+ params.push(
8280
+ ...source.params,
8281
+ locator.source.namespace,
8282
+ locator.source.external_id_hash,
8283
+ locator.source.import_run_id,
8284
+ locator.source.schema_version
8285
+ );
8286
+ }
8287
+ const result = await db.query(
8288
+ `SELECT CASE WHEN octet_length(${content}) <= $4
8289
+ THEN encode(convert_to(${content}, 'UTF8'), 'hex') ELSE NULL END AS content_hex
8290
+ FROM note n ${joins} ${metadata2.joins.join(" ")}
8291
+ WHERE ${conditions.join(" AND ")} LIMIT 1`,
8292
+ params
8293
+ );
8294
+ const row = result.rows[0];
8295
+ return resolveSearchEvidence(locator, row?.content_hex == null ? null : {
8296
+ note_id: locator.note_id,
8297
+ unit: locator.unit,
8298
+ content: new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(hexToBytes(row.content_hex)),
8299
+ ...locator.source === void 0 ? {} : { source: locator.source }
8300
+ });
8301
+ }
8302
+
8303
+ // src/repositories/search-evidence-projection.ts
8304
+ init_geometry_buffer();
8305
+
8306
+ // src/search-evidence-set.ts
8307
+ init_geometry_buffer();
8308
+
8309
+ // schemas/metadata-search/candidate/1.0.0/evidence-set.schema.json
8310
+ var evidence_set_schema_default = {
8311
+ $schema: "https://json-schema.org/draft/2020-12/schema",
8312
+ $id: "https://fortemi.com/contracts/metadata-search/candidate/1.0.0/evidence-set.schema.json",
8313
+ title: "Candidate per-hit search evidence envelope",
8314
+ type: "object",
8315
+ additionalProperties: false,
8316
+ required: ["version", "locators", "omissions"],
8317
+ properties: {
8318
+ version: { const: "1.0.0" },
8319
+ locators: {
8320
+ type: "array",
8321
+ maxItems: 64,
8322
+ uniqueItems: true,
8323
+ items: { $ref: "evidence-locator.schema.json" }
8324
+ },
8325
+ omissions: {
8326
+ type: "array",
8327
+ maxItems: 2,
8328
+ uniqueItems: true,
8329
+ items: { enum: ["unavailable-unit", "locator-limit"] }
8330
+ }
8331
+ },
8332
+ if: { properties: { locators: { type: "array", maxItems: 0 } } },
8333
+ then: { properties: { omissions: { type: "array", minItems: 1 } } }
8334
+ };
8335
+
8336
+ // src/search-evidence-set.ts
8337
+ var MAX_SEARCH_LOCATORS = 64;
8338
+ var EVIDENCE_OMISSIONS = ["unavailable-unit", "locator-limit"];
8339
+ var validate = new Ajv20206({ strict: true, allErrors: false, ownProperties: true }).addSchema(evidence_locator_schema_default).compile(evidence_set_schema_default);
8340
+ var invalid2 = () => new Error("SEARCH_EVIDENCE_INVALID");
8341
+ var priorities = { embedding: 0, title: 1, current: 2, attachment: 3 };
8342
+ function scalarCompare(left, right) {
8343
+ const a = Array.from(left, (char) => char.codePointAt(0));
8344
+ const b = Array.from(right, (char) => char.codePointAt(0));
8345
+ for (let i = 0; i < Math.min(a.length, b.length); i++) if (a[i] !== b[i]) return a[i] - b[i];
8346
+ return a.length - b.length;
8347
+ }
8348
+ function key(locator) {
8349
+ return [
8350
+ priorities[locator.unit.kind],
8351
+ locator.unit.id,
8352
+ locator.unit.index,
8353
+ locator.content_digest,
8354
+ locator.span.start,
8355
+ locator.span.end,
8356
+ locator.source ? 1 : 0,
8357
+ locator.source?.namespace ?? "",
8358
+ locator.source?.external_id_hash ?? "",
8359
+ locator.source?.import_run_id ?? "",
8360
+ locator.source?.schema_version ?? ""
8361
+ ];
8362
+ }
8363
+ function compareSearchEvidence(left, right) {
8364
+ const a = key(left), b = key(right);
8365
+ for (let i = 0; i < a.length; i++) {
8366
+ const cmp = typeof a[i] === "number" ? a[i] - b[i] : scalarCompare(a[i], b[i]);
8367
+ if (cmp !== 0) return cmp;
8368
+ }
8369
+ return 0;
8370
+ }
8371
+ function parseSearchEvidenceSet(value, noteId) {
8372
+ if (!validate(value)) throw invalid2();
8373
+ const locators = value.locators.map(parseSearchEvidenceLocator);
8374
+ if (locators.some((locator, i) => locator.note_id !== noteId || i > 0 && compareSearchEvidence(locators[i - 1], locator) >= 0)) throw invalid2();
8375
+ if (value.omissions.some((reason, i) => i > 0 && EVIDENCE_OMISSIONS.indexOf(value.omissions[i - 1]) >= EVIDENCE_OMISSIONS.indexOf(reason))) throw invalid2();
8376
+ return Object.freeze({ version: "1.0.0", locators: Object.freeze(locators), omissions: Object.freeze([...value.omissions]) });
8377
+ }
8378
+ function createSearchEvidenceSet(noteId, values, omissions = []) {
8379
+ const parsed = values.map(parseSearchEvidenceLocator);
8380
+ if (parsed.some((locator) => locator.note_id !== noteId) || omissions.some((reason) => !EVIDENCE_OMISSIONS.includes(reason))) throw invalid2();
8381
+ const locators = parsed.sort(compareSearchEvidence).filter((locator, i, all) => i === 0 || compareSearchEvidence(all[i - 1], locator) !== 0);
8382
+ const reasons = new Set(omissions);
8383
+ if (locators.length > MAX_SEARCH_LOCATORS) reasons.add("locator-limit");
8384
+ if (locators.length === 0) reasons.add("unavailable-unit");
8385
+ return parseSearchEvidenceSet({
8386
+ version: "1.0.0",
8387
+ locators: locators.slice(0, MAX_SEARCH_LOCATORS),
8388
+ omissions: EVIDENCE_OMISSIONS.filter((reason) => reasons.has(reason))
8389
+ }, noteId);
8390
+ }
8391
+ function mergeSearchEvidenceSets(noteId, sets) {
8392
+ const checked2 = sets.map((set) => parseSearchEvidenceSet(set, noteId));
8393
+ return createSearchEvidenceSet(noteId, checked2.flatMap((set) => [...set.locators]), checked2.flatMap((set) => [...set.omissions]));
8394
+ }
8395
+
8396
+ // src/repositories/search-evidence-projection.ts
8397
+ function buildSearchEvidenceProjection(options, startIdx, match) {
8398
+ const source = buildMetadataSourceConditions(options, startIdx);
8399
+ const scope = buildMetadataPredicateConditions({ tenant_id: options.tenant_id ?? "default", archive_id: options.archive_id }, source.nextIdx);
8400
+ const units = [];
8401
+ if (match.lexical) {
8402
+ const query = `${match.lexical.fn}('english', $${match.lexical.parameter})`;
8403
+ units.push(`SELECT 1 AS priority, 'title'::text AS kind, n.id AS id, 0 AS index, n.title AS content
8404
+ WHERE to_tsvector('english', n.title) @@ ${query}`);
8405
+ units.push(`SELECT 2, 'current', n.id, 0, c.content
8406
+ WHERE to_tsvector('english', c.content) @@ ${query}`);
8407
+ units.push(`SELECT 3, 'attachment', a.id, 0, a.extracted_text FROM attachment a
8408
+ WHERE a.note_id = n.id AND a.deleted_at IS NULL AND a.status = 'completed'
8409
+ AND to_tsvector('english', a.extracted_text) @@ ${query}`);
8410
+ }
8411
+ if (match.embedding) units.push("SELECT 0, 'embedding'::text, e.id, e.chunk_index, NULLIF(e.text, '')");
8412
+ if (units.length === 0) throw new Error("SEARCH_EVIDENCE_INVALID");
8413
+ return {
8414
+ params: [...source.params, ...scope.params],
8415
+ nextIdx: scope.nextIdx,
8416
+ sql: `(WITH units(priority, kind, id, index, content) AS (${units.join(" UNION ALL ")}),
8417
+ sources AS (
8418
+ SELECT DISTINCT si.namespace COLLATE "C" AS namespace, si.external_id_hash COLLATE "C" AS external_id_hash,
8419
+ si.import_run_id COLLATE "C" AS import_run_id, si.source_schema_version COLLATE "C" AS source_schema_version
8420
+ FROM source_identity si WHERE ${source.conditions.join(" AND ")}
8421
+ ORDER BY si.namespace COLLATE "C", si.external_id_hash COLLATE "C",
8422
+ si.import_run_id COLLATE "C", si.source_schema_version COLLATE "C"
8423
+ LIMIT ${MAX_SEARCH_LOCATORS + 1}
8424
+ ), candidates AS MATERIALIZED (
8425
+ SELECT u.*, s.namespace, s.external_id_hash, s.import_run_id, s.source_schema_version
8426
+ FROM units u LEFT JOIN sources s ON true
8427
+ ORDER BY u.priority, u.id COLLATE "C", u.index, s.namespace COLLATE "C",
8428
+ s.external_id_hash COLLATE "C", s.import_run_id COLLATE "C", s.source_schema_version COLLATE "C"
8429
+ LIMIT ${MAX_SEARCH_LOCATORS + 1}
8430
+ ), bound AS (
8431
+ SELECT CASE WHEN ${scope.conditions.join(" AND ")}
8432
+ AND char_length(n.id) BETWEEN 1 AND 200 AND char_length(id) BETWEEN 1 AND 200
8433
+ AND index BETWEEN 0 AND 2147483647 AND octet_length(content) <= ${MAX_EVIDENCE_BYTES}
8434
+ AND (namespace IS NULL OR (char_length(namespace) BETWEEN 1 AND 200
8435
+ AND external_id_hash ~ '^sha256:[a-f0-9]{64}$'
8436
+ AND char_length(import_run_id) BETWEEN 1 AND 200
8437
+ AND char_length(source_schema_version) BETWEEN 1 AND 200))
8438
+ THEN jsonb_build_object('version', '1.0.0', 'note_id', n.id,
8439
+ 'unit', jsonb_build_object('kind', kind, 'id', id, 'index', index),
8440
+ 'content_digest', 'sha256:' || encode(sha256(convert_to(content, 'UTF8')), 'hex'),
8441
+ 'span', jsonb_build_object('unit', 'utf8-bytes', 'start', 0, 'end', octet_length(content)))
8442
+ || CASE WHEN namespace IS NULL THEN '{}'::jsonb ELSE jsonb_build_object('source',
8443
+ jsonb_build_object('namespace', namespace, 'external_id_hash', external_id_hash,
8444
+ 'import_run_id', import_run_id, 'schema_version', source_schema_version)) END
8445
+ ELSE NULL END AS locator FROM candidates
8446
+ ) SELECT jsonb_build_object('locators', coalesce(jsonb_agg(locator), '[]'::jsonb),
8447
+ 'limited', count(*) > ${MAX_SEARCH_LOCATORS}) FROM bound)`
8448
+ };
8449
+ }
8450
+ function projectedSearchEvidence(noteId, value) {
8451
+ return createSearchEvidenceSet(noteId, value.locators.filter((locator) => locator !== null), [
8452
+ ...value.locators.some((locator) => locator === null) ? ["unavailable-unit"] : [],
8453
+ ...value.limited ? ["locator-limit"] : []
8454
+ ]);
8455
+ }
8456
+
7078
8457
  // src/repositories/embedding-sets-repository.ts
7079
8458
  init_geometry_buffer();
7080
8459
  var ATTACHMENT_TEXT_JOIN = `
@@ -7654,91 +9033,6 @@ var EmbeddingSetsRepository = class {
7654
9033
  }
7655
9034
  };
7656
9035
 
7657
- // src/repositories/metadata-predicates.ts
7658
- init_geometry_buffer();
7659
- var REGISTERED_METADATA_PATHS = [
7660
- "provider",
7661
- "model",
7662
- "role",
7663
- "event_kind",
7664
- "sensitivity",
7665
- "import_run_id"
7666
- ];
7667
- var REGISTERED_SET = new Set(REGISTERED_METADATA_PATHS);
7668
- var MAX_PREDICATES = 8;
7669
- var MAX_IN_VALUES = 32;
7670
- var MAX_VALUE_LENGTH = 256;
7671
- function assertRegisteredPath(path) {
7672
- if (!REGISTERED_SET.has(path) || path.includes(".") || path.includes("/")) {
7673
- throw new Error(`Unsupported metadata predicate path: ${path}`);
7674
- }
7675
- }
7676
- function assertBoundedValue(value) {
7677
- if (typeof value === "string" && value.length > MAX_VALUE_LENGTH) {
7678
- throw new Error("Metadata predicate value exceeds the 256 character bound");
7679
- }
7680
- }
7681
- function jsonAccessor(path) {
7682
- if (path === "import_run_id") return "si.import_run_id";
7683
- return `n.metadata ->> '${path}'`;
7684
- }
7685
- function buildMetadataPredicateConditions(options, startIdx) {
7686
- const predicates = options.metadataPredicates ?? [];
7687
- if (predicates.length > MAX_PREDICATES) {
7688
- throw new Error(`Metadata predicate count exceeds the ${MAX_PREDICATES} predicate bound`);
7689
- }
7690
- const conditions = [];
7691
- const params = [];
7692
- const joins = [];
7693
- let idx = startIdx;
7694
- let needsSourceJoin = options.tenant_id !== void 0 || options.archive_id !== void 0;
7695
- if (options.tenant_id !== void 0) {
7696
- conditions.push(`COALESCE(si.tenant_id, 'default') = $${idx++}`);
7697
- params.push(options.tenant_id);
7698
- }
7699
- if (options.archive_id !== void 0) {
7700
- conditions.push(`si.archive_id IS NOT DISTINCT FROM $${idx++}`);
7701
- params.push(options.archive_id);
7702
- }
7703
- for (const predicate of predicates) {
7704
- assertRegisteredPath(predicate.path);
7705
- const lhs = jsonAccessor(predicate.path);
7706
- if (predicate.path === "import_run_id") needsSourceJoin = true;
7707
- if (predicate.op === "eq") {
7708
- assertBoundedValue(predicate.value);
7709
- conditions.push(`${lhs} IS NOT DISTINCT FROM $${idx++}`);
7710
- params.push(predicate.value == null ? null : String(predicate.value));
7711
- } else if (predicate.op === "in") {
7712
- if (predicate.value.length > MAX_IN_VALUES) {
7713
- throw new Error(`Metadata predicate membership exceeds the ${MAX_IN_VALUES} value bound`);
7714
- }
7715
- for (const value of predicate.value) assertBoundedValue(value);
7716
- conditions.push(`${lhs} = ANY($${idx++})`);
7717
- params.push(predicate.value.map((value) => value == null ? null : String(value)));
7718
- } else if (predicate.op === "range") {
7719
- if (predicate.gte === void 0 && predicate.lte === void 0) {
7720
- throw new Error("Metadata range predicate requires gte or lte");
7721
- }
7722
- if (predicate.gte !== void 0) {
7723
- assertBoundedValue(predicate.gte);
7724
- conditions.push(`${lhs} >= $${idx++}`);
7725
- params.push(String(predicate.gte));
7726
- }
7727
- if (predicate.lte !== void 0) {
7728
- assertBoundedValue(predicate.lte);
7729
- conditions.push(`${lhs} <= $${idx++}`);
7730
- params.push(String(predicate.lte));
7731
- }
7732
- } else {
7733
- conditions.push(predicate.value === false ? `${lhs} IS NULL` : `${lhs} IS NOT NULL`);
7734
- }
7735
- }
7736
- if (needsSourceJoin) {
7737
- joins.push("LEFT JOIN source_identity si ON si.note_id = n.id");
7738
- }
7739
- return { conditions, joins, params, nextIdx: idx };
7740
- }
7741
-
7742
9036
  // src/repositories/search-repository.ts
7743
9037
  var ATTACHMENT_TEXT_JOIN2 = `
7744
9038
  LEFT JOIN (
@@ -7760,6 +9054,10 @@ var SearchRepository = class {
7760
9054
  this.db = db;
7761
9055
  this.semanticAvailable = semanticAvailable;
7762
9056
  }
9057
+ /** Candidate citation resolution with fresh local scope and content checks. */
9058
+ async resolveEvidence(locator, scope = {}) {
9059
+ return resolveStoredSearchEvidence(this.db, locator, scope);
9060
+ }
7763
9061
  tsqueryFn(query) {
7764
9062
  return query.includes('"') ? "phraseto_tsquery" : "plainto_tsquery";
7765
9063
  }
@@ -7769,7 +9067,7 @@ var SearchRepository = class {
7769
9067
  const setFilter = embeddingSetId ? " AND embedding_set_id = $2" : "";
7770
9068
  if (embeddingSetId) params.push(embeddingSetId);
7771
9069
  const result = await this.db.query(
7772
- "SELECT note_id FROM embedding WHERE vector IS NOT NULL AND note_id = ANY($1)" + setFilter,
9070
+ "SELECT to_jsonb(note_id) AS note_id FROM embedding WHERE vector IS NOT NULL AND note_id = ANY($1)" + setFilter,
7773
9071
  params
7774
9072
  );
7775
9073
  return new Set(result.rows.map((r) => r.note_id));
@@ -7813,15 +9111,17 @@ var SearchRepository = class {
7813
9111
  attachEmbeddingStatus(results, embeddingSet) {
7814
9112
  return results.map((r) => ({ ...r, has_embedding: embeddingSet.has(r.id) }));
7815
9113
  }
7816
- async fetchLocatorMap(noteIds, metadataPaths = []) {
9114
+ async fetchLocatorMap(noteIds, options) {
7817
9115
  const locators = /* @__PURE__ */ new Map();
7818
9116
  if (noteIds.length === 0) return locators;
9117
+ const metadataPaths = this.metadataPaths(options);
9118
+ const source = buildMetadataSourceConditions(options, 2);
7819
9119
  const result = await this.db.query(
7820
- `SELECT note_id, namespace, external_id_hash, import_run_id, source_schema_version
7821
- FROM source_identity
7822
- WHERE note_id = ANY($1)
7823
- ORDER BY created_at ASC`,
7824
- [noteIds]
9120
+ `SELECT to_jsonb(si.note_id) AS note_id, si.namespace, si.external_id_hash, si.import_run_id, si.source_schema_version
9121
+ FROM source_identity si JOIN note n ON n.id = si.note_id
9122
+ WHERE n.id = ANY($1) AND ${source.conditions.join(" AND ")}
9123
+ ORDER BY si.created_at ASC, si.id ASC`,
9124
+ [noteIds, ...source.params]
7825
9125
  );
7826
9126
  for (const row of result.rows) {
7827
9127
  const existing = locators.get(row.note_id) ?? [];
@@ -7849,6 +9149,7 @@ var SearchRepository = class {
7849
9149
  return [...new Set((options.metadataPredicates ?? []).map((predicate) => predicate.path))];
7850
9150
  }
7851
9151
  async search(query, options = {}, queryEmbedding) {
9152
+ validateMetadataPredicates(options.metadataPredicates === void 0 ? [] : options.metadataPredicates);
7852
9153
  const { limit = 20, offset = 0 } = options;
7853
9154
  const mode = options.mode ?? "auto";
7854
9155
  if (mode === "text") {
@@ -7894,9 +9195,11 @@ var SearchRepository = class {
7894
9195
  allParams
7895
9196
  );
7896
9197
  const total = parseInt(countResult.rows[0].count, 10);
7897
- const searchParams = [...allParams, limit, offset];
9198
+ const evidence = buildSearchEvidenceProjection(options, paramIdx, { lexical: { fn: tsqFn, parameter: 1 } });
9199
+ paramIdx = evidence.nextIdx;
9200
+ const searchParams = [...allParams, ...evidence.params, limit, offset];
7898
9201
  const result = await this.db.query(
7899
- `SELECT n.id, n.title, n.created_at, n.updated_at,
9202
+ `SELECT to_jsonb(n.id) AS id, n.title, n.created_at, n.updated_at, ${evidence.sql} AS evidence_projection,
7900
9203
  ts_rank(
7901
9204
  setweight(n.tsv, 'A') || setweight(${COMBINED_TEXT_VECTOR_SQL2}, 'B'),
7902
9205
  ${tsqFn}('english', $1)
@@ -7924,7 +9227,7 @@ var SearchRepository = class {
7924
9227
  let facets;
7925
9228
  if (options.include_facets) {
7926
9229
  const idsResult = await this.db.query(
7927
- `SELECT n.id FROM note n
9230
+ `SELECT to_jsonb(n.id) AS id FROM note n
7928
9231
  LEFT JOIN note_revised_current c ON c.note_id = n.id
7929
9232
  ${metadata2.joins.join("\n")}
7930
9233
  ${ATTACHMENT_TEXT_JOIN2}
@@ -7933,7 +9236,7 @@ var SearchRepository = class {
7933
9236
  );
7934
9237
  facets = await this.fetchFacets(idsResult.rows.map((r) => r.id));
7935
9238
  }
7936
- const locatorMap = await this.fetchLocatorMap(resultIds, this.metadataPaths(options));
9239
+ const locatorMap = await this.fetchLocatorMap(resultIds, options);
7937
9240
  const baseResults = result.rows.map((r) => ({
7938
9241
  id: r.id,
7939
9242
  title: r.title,
@@ -7942,7 +9245,8 @@ var SearchRepository = class {
7942
9245
  created_at: r.created_at,
7943
9246
  updated_at: r.updated_at,
7944
9247
  tags: tagMap.get(r.id) ?? [],
7945
- locators: locatorMap.get(r.id) ?? []
9248
+ locators: locatorMap.get(r.id) ?? [],
9249
+ evidence: projectedSearchEvidence(r.id, r.evidence_projection)
7946
9250
  }));
7947
9251
  return {
7948
9252
  results: this.attachEmbeddingStatus(baseResults, embeddingSet),
@@ -7956,6 +9260,7 @@ var SearchRepository = class {
7956
9260
  };
7957
9261
  }
7958
9262
  async semanticSearch(queryEmbedding, options = {}) {
9263
+ validateMetadataPredicates(options.metadataPredicates === void 0 ? [] : options.metadataPredicates);
7959
9264
  const { limit = 20, offset = 0 } = options;
7960
9265
  const vector = vectorColumn(queryEmbedding);
7961
9266
  const vectorStr = `[${queryEmbedding.join(",")}]`;
@@ -7977,11 +9282,14 @@ var SearchRepository = class {
7977
9282
  params
7978
9283
  );
7979
9284
  const total = parseInt(countResult.rows[0].count, 10);
9285
+ const evidence = buildSearchEvidenceProjection(options, paramIdx, { embedding: true });
9286
+ paramIdx = evidence.nextIdx;
7980
9287
  const vecIdx = paramIdx++;
7981
9288
  const limIdx = paramIdx++;
7982
9289
  const offIdx = paramIdx++;
7983
9290
  const result = await this.db.query(
7984
- `SELECT * FROM (SELECT DISTINCT ON (n.id) n.id, n.title, n.created_at, n.updated_at,
9291
+ `SELECT * FROM (SELECT DISTINCT ON (n.id) to_jsonb(n.id) AS id, n.title, n.created_at, n.updated_at,
9292
+ ${evidence.sql} AS evidence_projection,
7985
9293
  (${vector} <=> $${vecIdx}::vector) as distance,
7986
9294
  LEFT(${COMBINED_TEXT_SQL}, 200) as snippet
7987
9295
  FROM embedding e
@@ -7993,11 +9301,11 @@ var SearchRepository = class {
7993
9301
  ORDER BY n.id, ${vector} <=> $${vecIdx}::vector ASC, e.id) AS best_chunks
7994
9302
  ORDER BY distance ASC, id
7995
9303
  LIMIT $${limIdx} OFFSET $${offIdx}`,
7996
- [...params, vectorStr, limit, offset]
9304
+ [...params, ...evidence.params, vectorStr, limit, offset]
7997
9305
  );
7998
9306
  const tagMap = await this.fetchTagMap(result.rows.map((r) => r.id));
7999
9307
  const facets = options.include_facets ? await this.fetchFacets((await this.db.query(
8000
- `SELECT n.id
9308
+ `SELECT to_jsonb(n.id) AS id
8001
9309
  FROM embedding e
8002
9310
  JOIN note n ON n.id = e.note_id
8003
9311
  LEFT JOIN note_revised_current c ON c.note_id = n.id
@@ -8005,7 +9313,7 @@ var SearchRepository = class {
8005
9313
  WHERE ${where}`,
8006
9314
  params
8007
9315
  )).rows.map((r) => r.id)) : void 0;
8008
- const locatorMap = await this.fetchLocatorMap(result.rows.map((r) => r.id), this.metadataPaths(options));
9316
+ const locatorMap = await this.fetchLocatorMap(result.rows.map((r) => r.id), options);
8009
9317
  return {
8010
9318
  results: result.rows.map((r) => ({
8011
9319
  id: r.id,
@@ -8016,7 +9324,8 @@ var SearchRepository = class {
8016
9324
  updated_at: r.updated_at,
8017
9325
  tags: tagMap.get(r.id) ?? [],
8018
9326
  has_embedding: true,
8019
- locators: locatorMap.get(r.id) ?? []
9327
+ locators: locatorMap.get(r.id) ?? [],
9328
+ evidence: projectedSearchEvidence(r.id, r.evidence_projection)
8020
9329
  })),
8021
9330
  total,
8022
9331
  query: "",
@@ -8028,6 +9337,7 @@ var SearchRepository = class {
8028
9337
  };
8029
9338
  }
8030
9339
  async hybridSearch(query, queryEmbedding, options = {}) {
9340
+ validateMetadataPredicates(options.metadataPredicates === void 0 ? [] : options.metadataPredicates);
8031
9341
  const { limit = 20, offset = 0 } = options;
8032
9342
  const vectorStr = `[${queryEmbedding.join(",")}]`;
8033
9343
  const k = 60;
@@ -8042,11 +9352,12 @@ var SearchRepository = class {
8042
9352
  ${COMBINED_TEXT_VECTOR_SQL2} @@ ${tsqFn}('english', $1))`
8043
9353
  ];
8044
9354
  textCond.params.push(...textMeta.params);
8045
- this.scopeToResolvedEmbeddingSet(textConditions, textCond.params, textMeta.nextIdx, resolvedEmbeddingSet);
9355
+ const textNextIdx = this.scopeToResolvedEmbeddingSet(textConditions, textCond.params, textMeta.nextIdx, resolvedEmbeddingSet);
8046
9356
  const textWhere = textConditions.join(" AND ");
8047
- const textParams = [query, ...textCond.params];
9357
+ const textEvidence = buildSearchEvidenceProjection(options, textNextIdx, { lexical: { fn: tsqFn, parameter: 1 } });
9358
+ const textParams = [query, ...textCond.params, ...textEvidence.params];
8048
9359
  const textResult = await this.db.query(
8049
- `SELECT n.id,
9360
+ `SELECT to_jsonb(n.id) AS id, ${textEvidence.sql} AS evidence_projection,
8050
9361
  ts_rank(
8051
9362
  setweight(n.tsv, 'A') || setweight(${COMBINED_TEXT_VECTOR_SQL2}, 'B'),
8052
9363
  ${tsqFn}('english', $1)
@@ -8068,9 +9379,11 @@ var SearchRepository = class {
8068
9379
  const vector = vectorColumn(queryEmbedding);
8069
9380
  vecCond.conditions.push(`vector_dims(e.vector) = ${queryEmbedding.length}`);
8070
9381
  const vecWhere = vecCond.conditions.join(" AND ");
8071
- const vecVecIdx = vecCond.nextIdx;
9382
+ const vectorEvidence = buildSearchEvidenceProjection(options, vecCond.nextIdx, { embedding: true });
9383
+ const vecVecIdx = vectorEvidence.nextIdx;
8072
9384
  const vectorResult = await this.db.query(
8073
- `SELECT * FROM (SELECT DISTINCT ON (n.id) n.id, (${vector} <=> $${vecVecIdx}::vector) as distance
9385
+ `SELECT * FROM (SELECT DISTINCT ON (n.id) to_jsonb(n.id) AS id, ${vectorEvidence.sql} AS evidence_projection,
9386
+ (${vector} <=> $${vecVecIdx}::vector) as distance
8074
9387
  FROM embedding e
8075
9388
  JOIN note n ON n.id = e.note_id
8076
9389
  LEFT JOIN note_revised_current c ON c.note_id = n.id
@@ -8079,9 +9392,15 @@ var SearchRepository = class {
8079
9392
  ORDER BY n.id, ${vector} <=> $${vecVecIdx}::vector ASC, e.id) AS best_chunks
8080
9393
  ORDER BY distance ASC, id
8081
9394
  LIMIT 100`,
8082
- [...vecCond.params, vectorStr]
9395
+ [...vecCond.params, ...vectorEvidence.params, vectorStr]
8083
9396
  );
8084
9397
  const rrfScores = /* @__PURE__ */ new Map();
9398
+ const evidenceMap = /* @__PURE__ */ new Map();
9399
+ for (const row of [...textResult.rows, ...vectorResult.rows]) {
9400
+ const existing = evidenceMap.get(row.id) ?? [];
9401
+ existing.push(projectedSearchEvidence(row.id, row.evidence_projection));
9402
+ evidenceMap.set(row.id, existing);
9403
+ }
8085
9404
  textResult.rows.forEach((row, idx) => {
8086
9405
  rrfScores.set(row.id, (rrfScores.get(row.id) ?? 0) + 1 / (k + idx + 1));
8087
9406
  });
@@ -8094,21 +9413,24 @@ var SearchRepository = class {
8094
9413
  if (pageIds.length === 0) {
8095
9414
  return { results: [], total, query, mode: "hybrid", semantic_available: this.semanticAvailable, limit, offset };
8096
9415
  }
9416
+ const displayConditions = buildNoteConditions(options, 2);
9417
+ const displayMetadata = buildMetadataPredicateConditions(options, displayConditions.nextIdx);
8097
9418
  const noteResult = await this.db.query(
8098
- `SELECT n.id, n.title, n.created_at, n.updated_at,
9419
+ `SELECT to_jsonb(n.id) AS id, n.title, n.created_at, n.updated_at,
8099
9420
  LEFT(${COMBINED_TEXT_SQL}, 200) as snippet
8100
9421
  FROM note n
8101
9422
  LEFT JOIN note_revised_current c ON c.note_id = n.id
8102
9423
  ${ATTACHMENT_TEXT_JOIN2}
8103
- WHERE n.id = ANY($1)`,
8104
- [pageIds]
9424
+ ${displayMetadata.joins.join("\n")}
9425
+ WHERE n.id = ANY($1) AND ${[...displayConditions.conditions, ...displayMetadata.conditions].join(" AND ")}`,
9426
+ [pageIds, ...displayConditions.params, ...displayMetadata.params]
8105
9427
  );
8106
9428
  const noteMap = new Map(noteResult.rows.map((r) => [r.id, r]));
8107
9429
  const [tagMap, embeddingSet] = await Promise.all([
8108
9430
  this.fetchTagMap(pageIds),
8109
9431
  this.fetchEmbeddingStatus(pageIds, resolvedEmbeddingSet, options.embeddingSetId)
8110
9432
  ]);
8111
- const locatorMap = await this.fetchLocatorMap(pageIds, this.metadataPaths(options));
9433
+ const locatorMap = await this.fetchLocatorMap(pageIds, options);
8112
9434
  const facets = options.include_facets ? await this.fetchFacets(sortedIds) : void 0;
8113
9435
  return {
8114
9436
  results: pageIds.map((id) => {
@@ -8123,7 +9445,8 @@ var SearchRepository = class {
8123
9445
  updated_at: r.updated_at,
8124
9446
  tags: tagMap.get(id) ?? [],
8125
9447
  has_embedding: embeddingSet.has(id),
8126
- locators: locatorMap.get(id) ?? []
9448
+ locators: locatorMap.get(id) ?? [],
9449
+ evidence: mergeSearchEvidenceSets(id, evidenceMap.get(id) ?? [])
8127
9450
  };
8128
9451
  }).filter((r) => r !== null),
8129
9452
  total,
@@ -8155,7 +9478,7 @@ var SearchRepository = class {
8155
9478
  const total = parseInt(countResult.rows[0].count, 10);
8156
9479
  const listParams = [...params, limit, offset];
8157
9480
  const result = await this.db.query(
8158
- `SELECT n.id, n.title, n.created_at, n.updated_at,
9481
+ `SELECT to_jsonb(n.id) AS id, n.title, n.created_at, n.updated_at,
8159
9482
  LEFT(${COMBINED_TEXT_SQL}, 200) as snippet
8160
9483
  FROM note n
8161
9484
  LEFT JOIN note_revised_current c ON c.note_id = n.id
@@ -8168,7 +9491,7 @@ var SearchRepository = class {
8168
9491
  );
8169
9492
  const resultIds = result.rows.map((r) => r.id);
8170
9493
  const embeddingSet = await this.fetchEmbeddingStatus(resultIds, resolvedEmbeddingSet, options.embeddingSetId);
8171
- const locatorMap = await this.fetchLocatorMap(resultIds, this.metadataPaths(options));
9494
+ const locatorMap = await this.fetchLocatorMap(resultIds, options);
8172
9495
  return {
8173
9496
  results: result.rows.map((r) => ({
8174
9497
  id: r.id,
@@ -8213,7 +9536,7 @@ var SearchRepository = class {
8213
9536
  const tagMap = /* @__PURE__ */ new Map();
8214
9537
  if (noteIds.length === 0) return tagMap;
8215
9538
  const tagsResult = await this.db.query(
8216
- `SELECT note_id, tag FROM note_tag WHERE note_id = ANY($1) ORDER BY tag`,
9539
+ `SELECT to_jsonb(note_id) AS note_id, tag FROM note_tag WHERE note_id = ANY($1) ORDER BY tag`,
8217
9540
  [noteIds]
8218
9541
  );
8219
9542
  for (const row of tagsResult.rows) {
@@ -8457,7 +9780,7 @@ init_geometry_buffer();
8457
9780
  // src/shard/full-v1-references.ts
8458
9781
  init_geometry_buffer();
8459
9782
  var uuid2 = (value) => typeof value === "string" ? value.toLowerCase() : value;
8460
- var key = (...values) => JSON.stringify(values);
9783
+ var key2 = (...values) => JSON.stringify(values);
8461
9784
  var present = (value) => value !== null && value !== void 0;
8462
9785
  function fullV1ReferenceErrors(records) {
8463
9786
  const errors = [];
@@ -8515,7 +9838,7 @@ function fullV1ReferenceErrors(records) {
8515
9838
  const id = uuid2(attachment.id);
8516
9839
  check(!attachmentIds.has(id), "notes", index, "duplicate attachment identity");
8517
9840
  attachmentIds.add(id);
8518
- const declaration = key(attachment.bytes, attachment.mime);
9841
+ const declaration = key2(attachment.bytes, attachment.mime);
8519
9842
  check(
8520
9843
  !digests.has(attachment.checksum) || digests.get(attachment.checksum) === declaration,
8521
9844
  "notes",
@@ -8541,7 +9864,7 @@ function fullV1ReferenceErrors(records) {
8541
9864
  }
8542
9865
  });
8543
9866
  ids2("note_original_history");
8544
- unique2("note_original_history", (row) => key(uuid2(row.note_id), row.version_number));
9867
+ unique2("note_original_history", (row) => key2(uuid2(row.note_id), row.version_number));
8545
9868
  rows("note_original_history").forEach((row, index) => {
8546
9869
  ref(row, "note_id", notes, "note_original_history", index);
8547
9870
  const current = originals.get(uuid2(row.note_id));
@@ -8553,7 +9876,7 @@ function fullV1ReferenceErrors(records) {
8553
9876
  );
8554
9877
  });
8555
9878
  const revisionIds = ids2("note_revisions");
8556
- unique2("note_revisions", (row) => key(uuid2(row.note_id), row.revision_number));
9879
+ unique2("note_revisions", (row) => key2(uuid2(row.note_id), row.revision_number));
8557
9880
  const revisions = new Map(rows("note_revisions").map((row) => [uuid2(row.id), row]));
8558
9881
  rows("note_revisions").forEach((row, index) => {
8559
9882
  ref(row, "note_id", notes, "note_revisions", index);
@@ -8608,7 +9931,7 @@ function fullV1ReferenceErrors(records) {
8608
9931
  ref(row, "named_location_id", namedLocations, "provenance_locations", index, true);
8609
9932
  });
8610
9933
  const devices = ids2("provenance_devices");
8611
- unique2("provenance_devices", (row) => key(row.device_make, row.device_model, uuid2(row.owner_id)));
9934
+ unique2("provenance_devices", (row) => key2(row.device_make, row.device_model, uuid2(row.owner_id)));
8612
9935
  ids2("provenance_records");
8613
9936
  unique2("provenance_records", (row) => uuid2(row.note_id));
8614
9937
  rows("provenance_records").forEach((row, index) => {
@@ -8640,13 +9963,13 @@ function fullV1ReferenceErrors(records) {
8640
9963
  const config = configRows.get(uuid2(row.embedding_config_id));
8641
9964
  if (config) dimensions.set(uuid2(row.id), Number(row.truncate_dim ?? config.dimension));
8642
9965
  });
8643
- unique2("embedding_set_members", (row) => key(uuid2(row.embedding_set_id), uuid2(row.note_id)));
9966
+ unique2("embedding_set_members", (row) => key2(uuid2(row.embedding_set_id), uuid2(row.note_id)));
8644
9967
  rows("embedding_set_members").forEach((row, index) => {
8645
9968
  ref(row, "embedding_set_id", sets, "embedding_set_members", index);
8646
9969
  ref(row, "note_id", notes, "embedding_set_members", index);
8647
9970
  });
8648
9971
  ids2("embeddings");
8649
- unique2("embeddings", (row) => present(row.note_id) && present(row.embedding_set_id) ? key(uuid2(row.note_id), uuid2(row.embedding_set_id), row.chunk_index) : null);
9972
+ unique2("embeddings", (row) => present(row.note_id) && present(row.embedding_set_id) ? key2(uuid2(row.note_id), uuid2(row.embedding_set_id), row.chunk_index) : null);
8650
9973
  rows("embeddings").forEach((row, index) => {
8651
9974
  ref(row, "note_id", notes, "embeddings", index, true);
8652
9975
  ref(row, "embedding_set_id", sets, "embeddings", index, true);
@@ -8664,34 +9987,34 @@ function fullV1ReferenceErrors(records) {
8664
9987
  unique2("skos_schemes", (row) => row.uri);
8665
9988
  const concepts = ids2("skos_concepts");
8666
9989
  unique2("skos_concepts", (row) => row.uri);
8667
- unique2("skos_concepts", (row) => present(row.notation) ? key(uuid2(row.primary_scheme_id), row.notation) : null);
9990
+ unique2("skos_concepts", (row) => present(row.notation) ? key2(uuid2(row.primary_scheme_id), row.notation) : null);
8668
9991
  rows("skos_concepts").forEach((row, index) => {
8669
9992
  ref(row, "primary_scheme_id", schemes, "skos_concepts", index);
8670
9993
  ref(row, "replaced_by_id", concepts, "skos_concepts", index, true);
8671
9994
  check(uuid2(row.replaced_by_id) !== uuid2(row.id), "skos_concepts", index, "concept replaces itself");
8672
9995
  });
8673
9996
  ids2("skos_labels");
8674
- unique2("skos_labels", (row) => key(uuid2(row.concept_id), row.label_type, row.language, row.value));
8675
- unique2("skos_labels", (row) => row.label_type === "pref_label" ? key(uuid2(row.concept_id), row.language) : null);
9997
+ unique2("skos_labels", (row) => key2(uuid2(row.concept_id), row.label_type, row.language, row.value));
9998
+ unique2("skos_labels", (row) => row.label_type === "pref_label" ? key2(uuid2(row.concept_id), row.language) : null);
8676
9999
  rows("skos_labels").forEach((row, index) => ref(row, "concept_id", concepts, "skos_labels", index));
8677
10000
  ids2("skos_notes");
8678
10001
  rows("skos_notes").forEach((row, index) => ref(row, "concept_id", concepts, "skos_notes", index));
8679
10002
  ids2("skos_relations");
8680
- unique2("skos_relations", (row) => key(uuid2(row.subject_id), uuid2(row.object_id), row.relation_type));
10003
+ unique2("skos_relations", (row) => key2(uuid2(row.subject_id), uuid2(row.object_id), row.relation_type));
8681
10004
  rows("skos_relations").forEach((row, index) => {
8682
10005
  ref(row, "subject_id", concepts, "skos_relations", index);
8683
10006
  ref(row, "object_id", concepts, "skos_relations", index);
8684
10007
  check(uuid2(row.subject_id) !== uuid2(row.object_id), "skos_relations", index, "self relation is invalid");
8685
10008
  });
8686
10009
  ids2("skos_mapping_relations");
8687
- unique2("skos_mapping_relations", (row) => key(uuid2(row.concept_id), row.target_uri, row.relation_type));
10010
+ unique2("skos_mapping_relations", (row) => key2(uuid2(row.concept_id), row.target_uri, row.relation_type));
8688
10011
  rows("skos_mapping_relations").forEach((row, index) => ref(row, "concept_id", concepts, "skos_mapping_relations", index));
8689
- unique2("skos_scheme_memberships", (row) => key(uuid2(row.concept_id), uuid2(row.scheme_id)));
10012
+ unique2("skos_scheme_memberships", (row) => key2(uuid2(row.concept_id), uuid2(row.scheme_id)));
8690
10013
  rows("skos_scheme_memberships").forEach((row, index) => {
8691
10014
  ref(row, "concept_id", concepts, "skos_scheme_memberships", index);
8692
10015
  ref(row, "scheme_id", schemes, "skos_scheme_memberships", index);
8693
10016
  });
8694
- unique2("note_skos_tags", (row) => key(uuid2(row.note_id), uuid2(row.concept_id)));
10017
+ unique2("note_skos_tags", (row) => key2(uuid2(row.note_id), uuid2(row.concept_id)));
8695
10018
  rows("note_skos_tags").forEach((row, index) => {
8696
10019
  ref(row, "note_id", notes, "note_skos_tags", index);
8697
10020
  ref(row, "concept_id", concepts, "note_skos_tags", index);
@@ -8699,7 +10022,7 @@ function fullV1ReferenceErrors(records) {
8699
10022
  const skosCollections = ids2("skos_collections");
8700
10023
  unique2("skos_collections", (row) => row.uri);
8701
10024
  rows("skos_collections").forEach((row, index) => ref(row, "scheme_id", schemes, "skos_collections", index, true));
8702
- unique2("skos_collection_members", (row) => key(uuid2(row.collection_id), uuid2(row.concept_id)));
10025
+ unique2("skos_collection_members", (row) => key2(uuid2(row.collection_id), uuid2(row.concept_id)));
8703
10026
  rows("skos_collection_members").forEach((row, index) => {
8704
10027
  ref(row, "collection_id", skosCollections, "skos_collection_members", index);
8705
10028
  ref(row, "concept_id", concepts, "skos_collection_members", index);
@@ -8715,7 +10038,7 @@ function fullV1ReferenceErrors(records) {
8715
10038
  );
8716
10039
  }
8717
10040
  });
8718
- unique2("graph_edges", (row) => key(row.graph_source_id, uuid2(row.from_note_id), uuid2(row.to_note_id), row.kind));
10041
+ unique2("graph_edges", (row) => key2(row.graph_source_id, uuid2(row.from_note_id), uuid2(row.to_note_id), row.kind));
8719
10042
  rows("graph_edges").forEach((row, index) => {
8720
10043
  ref(row, "graph_source_id", sources, "graph_edges", index, false, false);
8721
10044
  ref(row, "from_note_id", notes, "graph_edges", index);
@@ -8727,7 +10050,7 @@ function fullV1ReferenceErrors(records) {
8727
10050
  rows("communities").forEach((row, index) => {
8728
10051
  ref(row, "graph_source_id", sources, "communities", index, false, false);
8729
10052
  for (const community of row.communities) {
8730
- const id = key(row.id, community.id);
10053
+ const id = key2(row.id, community.id);
8731
10054
  check(!communities.has(id), "communities", index, "duplicate community identity within set");
8732
10055
  communities.add(id);
8733
10056
  const representatives = /* @__PURE__ */ new Set();
@@ -8742,10 +10065,10 @@ function fullV1ReferenceErrors(records) {
8742
10065
  }
8743
10066
  }
8744
10067
  });
8745
- unique2("community_assignments", (row) => key(row.community_set_id, uuid2(row.note_id)));
10068
+ unique2("community_assignments", (row) => key2(row.community_set_id, uuid2(row.note_id)));
8746
10069
  rows("community_assignments").forEach((row, index) => {
8747
10070
  check(
8748
- communities.has(key(row.community_set_id, row.community_id)),
10071
+ communities.has(key2(row.community_set_id, row.community_id)),
8749
10072
  "community_assignments",
8750
10073
  index,
8751
10074
  "community does not belong to the declared set"
@@ -18704,15 +20027,15 @@ init_geometry_buffer();
18704
20027
  var CURRENT_SHARD_VERSION = "1.2.0";
18705
20028
  var MAX_SHARD_READER_VERSION = "2.0.0";
18706
20029
  var SHARD_FORMAT = "matric-shard";
18707
- function parseVersion(value) {
20030
+ function parseVersion2(value) {
18708
20031
  return value.split(".").map((segment) => {
18709
20032
  const match = segment.match(/^\d+/);
18710
20033
  return match ? Number.parseInt(match[0], 10) : 0;
18711
20034
  });
18712
20035
  }
18713
20036
  function compareShardVersions(left, right) {
18714
- const leftParts = parseVersion(left);
18715
- const rightParts = parseVersion(right);
20037
+ const leftParts = parseVersion2(left);
20038
+ const rightParts = parseVersion2(right);
18716
20039
  const length = Math.max(leftParts.length, rightParts.length);
18717
20040
  for (let index = 0; index < length; index += 1) {
18718
20041
  const leftValue = leftParts[index] ?? 0;
@@ -18748,7 +20071,7 @@ function collectSidecarBlobs(files) {
18748
20071
  }
18749
20072
 
18750
20073
  // src/shard/schema-validator.ts
18751
- var decoder = new TextDecoder();
20074
+ var decoder2 = new TextDecoder();
18752
20075
  var LEGACY_COMPONENT_SCHEMA_DEFS = {
18753
20076
  notes: "note",
18754
20077
  collections: "collection",
@@ -19004,13 +20327,13 @@ function getKnowledgeShardSchema() {
19004
20327
  function getKnowledgeShardContractReceipt() {
19005
20328
  return knowledge_shard_schema_receipt_default;
19006
20329
  }
19007
- function addCanonicalFormats(ajv) {
19008
- ajv.addFormat("uuid", /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
19009
- ajv.addFormat("date-time", {
20330
+ function addCanonicalFormats(ajv3) {
20331
+ ajv3.addFormat("uuid", /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
20332
+ ajv3.addFormat("date-time", {
19010
20333
  type: "string",
19011
20334
  validate: (value) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && !Number.isNaN(Date.parse(value))
19012
20335
  });
19013
- ajv.addFormat("uri", {
20336
+ ajv3.addFormat("uri", {
19014
20337
  type: "string",
19015
20338
  validate: (value) => {
19016
20339
  try {
@@ -19023,7 +20346,7 @@ function addCanonicalFormats(ajv) {
19023
20346
  }
19024
20347
  function getLegacyAjv() {
19025
20348
  if (!legacyAjvInstance) {
19026
- legacyAjvInstance = new Ajv20202({
20349
+ legacyAjvInstance = new Ajv20206({
19027
20350
  allErrors: true,
19028
20351
  strict: true,
19029
20352
  validateFormats: false
@@ -19034,7 +20357,7 @@ function getLegacyAjv() {
19034
20357
  }
19035
20358
  function getCoreAjv() {
19036
20359
  if (!coreAjvInstance) {
19037
- coreAjvInstance = new Ajv20202({
20360
+ coreAjvInstance = new Ajv20206({
19038
20361
  allErrors: true,
19039
20362
  strict: true,
19040
20363
  validateFormats: true
@@ -19054,7 +20377,7 @@ function getCoreAjv() {
19054
20377
  }
19055
20378
  function getRecordAjv() {
19056
20379
  if (!recordAjvInstance) {
19057
- recordAjvInstance = new Ajv20202({
20380
+ recordAjvInstance = new Ajv20206({
19058
20381
  allErrors: true,
19059
20382
  strict: true,
19060
20383
  validateFormats: true
@@ -19074,7 +20397,7 @@ function getRecordAjv() {
19074
20397
  }
19075
20398
  function getFullAjv() {
19076
20399
  if (!fullAjvInstance) {
19077
- fullAjvInstance = new Ajv20202({
20400
+ fullAjvInstance = new Ajv20206({
19078
20401
  allErrors: true,
19079
20402
  strict: true,
19080
20403
  validateFormats: true
@@ -19109,30 +20432,30 @@ function fullSchemaVersion(value) {
19109
20432
  return value === "1.1.0" || value === "1.2.0" || value === "2.0.0" ? value : void 0;
19110
20433
  }
19111
20434
  function coreValidatorFor(name, version = CURRENT_SHARD_VERSION) {
19112
- const key2 = `${version}:${name}`;
19113
- const cached = coreValidators.get(key2);
20435
+ const key3 = `${version}:${name}`;
20436
+ const cached = coreValidators.get(key3);
19114
20437
  if (cached) return cached;
19115
20438
  const schema = CORE_V1_SCHEMAS[version][name];
19116
20439
  const validator = getCoreAjv().getSchema(schema.$id) ?? getCoreAjv().compile(schema);
19117
- coreValidators.set(key2, validator);
20440
+ coreValidators.set(key3, validator);
19118
20441
  return validator;
19119
20442
  }
19120
20443
  function recordValidatorFor(name, version = CURRENT_SHARD_VERSION) {
19121
- const key2 = `${version}:${name}`;
19122
- const cached = recordValidators.get(key2);
20444
+ const key3 = `${version}:${name}`;
20445
+ const cached = recordValidators.get(key3);
19123
20446
  if (cached) return cached;
19124
20447
  const schema = RECORD_V1_SCHEMAS[version][name];
19125
20448
  const validator = getRecordAjv().getSchema(schema.$id) ?? getRecordAjv().compile(schema);
19126
- recordValidators.set(key2, validator);
20449
+ recordValidators.set(key3, validator);
19127
20450
  return validator;
19128
20451
  }
19129
20452
  function fullValidatorFor(name, version = CURRENT_SHARD_VERSION) {
19130
- const key2 = `${version}:${name}`;
19131
- const cached = fullValidators.get(key2);
20453
+ const key3 = `${version}:${name}`;
20454
+ const cached = fullValidators.get(key3);
19132
20455
  if (cached) return cached;
19133
20456
  const schema = FULL_V1_SCHEMAS[version][name];
19134
20457
  const validator = getFullAjv().getSchema(schema.$id) ?? getFullAjv().compile(schema);
19135
- fullValidators.set(key2, validator);
20458
+ fullValidators.set(key3, validator);
19136
20459
  return validator;
19137
20460
  }
19138
20461
  function formatErrors(errors) {
@@ -19147,7 +20470,7 @@ function profileOf(value) {
19147
20470
  return typeof profile === "string" ? profile : void 0;
19148
20471
  }
19149
20472
  function validateShardManifest(value) {
19150
- let validate3;
20473
+ let validate4;
19151
20474
  const profile = profileOf(value);
19152
20475
  if (profile === "core-v1") {
19153
20476
  const version = value && typeof value === "object" && !Array.isArray(value) ? coreSchemaVersion(String(value.version ?? "")) : void 0;
@@ -19157,7 +20480,7 @@ function validateShardManifest(value) {
19157
20480
  errors: ["(root) uses an unsupported canonical core-v1 schema version"]
19158
20481
  };
19159
20482
  }
19160
- validate3 = coreValidatorFor("manifest", version);
20483
+ validate4 = coreValidatorFor("manifest", version);
19161
20484
  } else if (profile === "record-v1") {
19162
20485
  const version = value && typeof value === "object" && !Array.isArray(value) ? recordSchemaVersion(String(value.version ?? "")) : void 0;
19163
20486
  if (!version) {
@@ -19166,7 +20489,7 @@ function validateShardManifest(value) {
19166
20489
  errors: ["(root) uses an unsupported canonical record-v1 schema version"]
19167
20490
  };
19168
20491
  }
19169
- validate3 = recordValidatorFor("manifest", version);
20492
+ validate4 = recordValidatorFor("manifest", version);
19170
20493
  } else if (profile === "full-v1") {
19171
20494
  const version = value && typeof value === "object" && !Array.isArray(value) ? fullSchemaVersion(String(value.version ?? "")) : void 0;
19172
20495
  if (!version) {
@@ -19175,17 +20498,17 @@ function validateShardManifest(value) {
19175
20498
  errors: ["(root) uses an unsupported canonical full-v1 schema version"]
19176
20499
  };
19177
20500
  }
19178
- validate3 = fullValidatorFor("manifest", version);
20501
+ validate4 = fullValidatorFor("manifest", version);
19179
20502
  } else {
19180
- validate3 = legacyValidatorFor("manifest");
20503
+ validate4 = legacyValidatorFor("manifest");
19181
20504
  }
19182
- const valid = validate3(value);
19183
- return { valid, errors: formatErrors(validate3.errors) };
20505
+ const valid = validate4(value);
20506
+ return { valid, errors: formatErrors(validate4.errors) };
19184
20507
  }
19185
20508
  function parseJsonArray(bytes, path) {
19186
20509
  if (!bytes) return { records: [], errors: [] };
19187
20510
  try {
19188
- const value = JSON.parse(decoder.decode(bytes));
20511
+ const value = JSON.parse(decoder2.decode(bytes));
19189
20512
  if (!Array.isArray(value)) return { records: [], errors: [`${path} must be a JSON array`] };
19190
20513
  return { records: value, errors: [] };
19191
20514
  } catch {
@@ -19194,7 +20517,7 @@ function parseJsonArray(bytes, path) {
19194
20517
  }
19195
20518
  function parseJsonl(bytes, path) {
19196
20519
  if (!bytes) return { records: [], errors: [] };
19197
- const text = decoder.decode(bytes).trim();
20520
+ const text = decoder2.decode(bytes).trim();
19198
20521
  if (!text) return { records: [], errors: [] };
19199
20522
  const records = [];
19200
20523
  const errors = [];
@@ -19438,7 +20761,7 @@ function validateFullV1Structure(files, manifest) {
19438
20761
  const signatureBytes = files.get("signature.json");
19439
20762
  if (signatureBytes) {
19440
20763
  try {
19441
- const signature = JSON.parse(decoder.decode(signatureBytes));
20764
+ const signature = JSON.parse(decoder2.decode(signatureBytes));
19442
20765
  const signatureValidator = fullValidatorFor("signature", schemaVersion);
19443
20766
  if (!signatureValidator(signature)) {
19444
20767
  errors.push(
@@ -19534,7 +20857,7 @@ function validateShardArchive(input) {
19534
20857
  if (!manifestBytes) return { valid: false, errors: ["manifest.json is missing"] };
19535
20858
  let manifest;
19536
20859
  try {
19537
- manifest = JSON.parse(decoder.decode(manifestBytes));
20860
+ manifest = JSON.parse(decoder2.decode(manifestBytes));
19538
20861
  } catch {
19539
20862
  return { valid: false, errors: ["manifest.json failed to parse as JSON"] };
19540
20863
  }
@@ -19553,7 +20876,7 @@ async function validateCoreV1ShardArchive(input) {
19553
20876
  if (!manifestBytes) return { valid: false, errors: ["manifest.json is missing"] };
19554
20877
  let manifest;
19555
20878
  try {
19556
- manifest = JSON.parse(decoder.decode(manifestBytes));
20879
+ manifest = JSON.parse(decoder2.decode(manifestBytes));
19557
20880
  } catch {
19558
20881
  return { valid: false, errors: ["manifest.json failed to parse as JSON"] };
19559
20882
  }
@@ -19576,7 +20899,7 @@ async function validateRecordV1ShardArchive(input) {
19576
20899
  if (!manifestBytes) return { valid: false, errors: ["manifest.json is missing"] };
19577
20900
  let manifest;
19578
20901
  try {
19579
- manifest = JSON.parse(decoder.decode(manifestBytes));
20902
+ manifest = JSON.parse(decoder2.decode(manifestBytes));
19580
20903
  } catch {
19581
20904
  return { valid: false, errors: ["manifest.json failed to parse as JSON"] };
19582
20905
  }
@@ -19599,7 +20922,7 @@ async function validateFullV1ShardArchive(input) {
19599
20922
  if (!manifestBytes) return { valid: false, errors: ["manifest.json is missing"] };
19600
20923
  let manifest;
19601
20924
  try {
19602
- manifest = JSON.parse(decoder.decode(manifestBytes));
20925
+ manifest = JSON.parse(decoder2.decode(manifestBytes));
19603
20926
  } catch {
19604
20927
  return { valid: false, errors: ["manifest.json failed to parse as JSON"] };
19605
20928
  }
@@ -19628,9 +20951,9 @@ async function validateFullV1ShardArchive(input) {
19628
20951
  return { valid: errors.length === 0, errors };
19629
20952
  }
19630
20953
  function validateShardComponentRecord(component, value, profile, version = CURRENT_SHARD_VERSION) {
19631
- let validate3;
20954
+ let validate4;
19632
20955
  if (profile === "core-v1" && component in CORE_V1_COMPONENT_FILES) {
19633
- validate3 = coreValidatorFor(component, version);
20956
+ validate4 = coreValidatorFor(component, version);
19634
20957
  } else if (profile === "record-v1" && component in RECORD_V1_COMPONENT_FILES) {
19635
20958
  const canonicalVersion = recordSchemaVersion(version);
19636
20959
  if (!canonicalVersion) {
@@ -19639,7 +20962,7 @@ function validateShardComponentRecord(component, value, profile, version = CURRE
19639
20962
  errors: [`(root) uses an unsupported canonical record-v1 schema version ${version}`]
19640
20963
  };
19641
20964
  }
19642
- validate3 = recordValidatorFor(component, canonicalVersion);
20965
+ validate4 = recordValidatorFor(component, canonicalVersion);
19643
20966
  } else if (profile === "full-v1" && component in FULL_V1_COMPONENT_FILES) {
19644
20967
  const canonicalVersion = fullSchemaVersion(version);
19645
20968
  if (!canonicalVersion) {
@@ -19648,7 +20971,7 @@ function validateShardComponentRecord(component, value, profile, version = CURRE
19648
20971
  errors: [`(root) uses an unsupported canonical full-v1 schema version ${version}`]
19649
20972
  };
19650
20973
  }
19651
- validate3 = fullValidatorFor(component, canonicalVersion);
20974
+ validate4 = fullValidatorFor(component, canonicalVersion);
19652
20975
  } else {
19653
20976
  const legacyDef = LEGACY_COMPONENT_SCHEMA_DEFS[component];
19654
20977
  if (!legacyDef) {
@@ -19657,10 +20980,10 @@ function validateShardComponentRecord(component, value, profile, version = CURRE
19657
20980
  errors: [`(root) component '${component}' requires an explicit full-v1 profile`]
19658
20981
  };
19659
20982
  }
19660
- validate3 = legacyValidatorFor(legacyDef);
20983
+ validate4 = legacyValidatorFor(legacyDef);
19661
20984
  }
19662
- const valid = validate3(value);
19663
- return { valid, errors: formatErrors(validate3.errors) };
20985
+ const valid = validate4(value);
20986
+ return { valid, errors: formatErrors(validate4.errors) };
19664
20987
  }
19665
20988
  function assertShardComponentRecord(component, value, profile, version = CURRENT_SHARD_VERSION) {
19666
20989
  const result = validateShardComponentRecord(component, value, profile, version);
@@ -19977,6 +21300,12 @@ var ManageNoteInputSchema = z.object({
19977
21300
  });
19978
21301
  var SearchInputSchema = z.object({
19979
21302
  query: z.string(),
21303
+ metadataPredicates: z.unknown().transform((value) => {
21304
+ validateMetadataPredicates(value);
21305
+ return value;
21306
+ }).optional(),
21307
+ tenant_id: z.string().min(1).optional(),
21308
+ archive_id: z.string().min(1).nullable().optional(),
19980
21309
  mode: z.enum(["text", "semantic", "hybrid", "auto"]).default("text"),
19981
21310
  query_embedding: z.array(z.number()).optional(),
19982
21311
  embeddingSetId: z.string().optional(),
@@ -20041,6 +21370,366 @@ async function manageNote(db, rawInput, events) {
20041
21370
 
20042
21371
  // src/remote-contract.ts
20043
21372
  init_geometry_buffer();
21373
+
21374
+ // src/remote-search-schema.ts
21375
+ init_geometry_buffer();
21376
+
21377
+ // schemas/metadata-search/candidate/1.0.0/search-rest.schema.json
21378
+ var search_rest_schema_default = {
21379
+ $schema: "https://json-schema.org/draft/2020-12/schema",
21380
+ $id: "https://fortemi.com/contracts/metadata-search/candidate/1.0.0/search-rest.schema.json",
21381
+ title: "Candidate canonical GET search request and response",
21382
+ description: "Producer authority candidate. Schema validation is supplemented by same-note/canonical evidence binding, exact returned totals, strict-filter aggregate count and metadata range semantics. No auth grant or complete capability promotion.",
21383
+ $defs: {
21384
+ StrictSearchFilterInput: {
21385
+ type: "object",
21386
+ description: "Decoded strict_filter JSON. Unknown keys retain legacy ignored behavior. Sum of the five list lengths must not exceed 1000; name resolution still requires current authorized storage.",
21387
+ additionalProperties: true,
21388
+ properties: {
21389
+ required_tags: {
21390
+ type: "array",
21391
+ maxItems: 1e3,
21392
+ items: {
21393
+ type: "string"
21394
+ },
21395
+ default: []
21396
+ },
21397
+ any_tags: {
21398
+ type: "array",
21399
+ maxItems: 1e3,
21400
+ items: {
21401
+ type: "string"
21402
+ },
21403
+ default: []
21404
+ },
21405
+ excluded_tags: {
21406
+ type: "array",
21407
+ maxItems: 1e3,
21408
+ items: {
21409
+ type: "string"
21410
+ },
21411
+ default: []
21412
+ },
21413
+ required_schemes: {
21414
+ type: "array",
21415
+ maxItems: 1e3,
21416
+ items: {
21417
+ type: "string"
21418
+ },
21419
+ default: []
21420
+ },
21421
+ excluded_schemes: {
21422
+ type: "array",
21423
+ maxItems: 1e3,
21424
+ items: {
21425
+ type: "string"
21426
+ },
21427
+ default: []
21428
+ },
21429
+ min_tag_count: {
21430
+ type: ["integer", "null"],
21431
+ minimum: -2147483648,
21432
+ maximum: 2147483647
21433
+ },
21434
+ include_untagged: {
21435
+ type: "boolean",
21436
+ default: true
21437
+ }
21438
+ }
21439
+ },
21440
+ SearchRestRequest: {
21441
+ type: "object",
21442
+ description: "Decoded GET query parameters. JSON-content parameters are decoded to JSON values before this schema is applied. This is not a POST request body. Unknown query keys retain legacy ignored behavior and cannot grant tenant/archive authorization.",
21443
+ required: [
21444
+ "q"
21445
+ ],
21446
+ additionalProperties: true,
21447
+ properties: {
21448
+ q: {
21449
+ type: "string",
21450
+ description: "Search expression. Empty text remains accepted."
21451
+ },
21452
+ limit: {
21453
+ type: "integer",
21454
+ minimum: 0,
21455
+ maximum: 1e3,
21456
+ default: 20
21457
+ },
21458
+ filters: {
21459
+ type: "string",
21460
+ description: "Legacy filter expression; combined with comma-separated tags."
21461
+ },
21462
+ mode: {
21463
+ type: "string",
21464
+ default: "hybrid",
21465
+ description: "fts selects lexical search, semantic selects vector search. hybrid, absent and other legacy values select hybrid; failures have explicit FTS degradation."
21466
+ },
21467
+ set: {
21468
+ type: "string",
21469
+ description: "Embedding-set slug resolved within the authorized memory and tenant."
21470
+ },
21471
+ created_after: {
21472
+ type: "string",
21473
+ format: "date-time"
21474
+ },
21475
+ created_before: {
21476
+ type: "string",
21477
+ format: "date-time"
21478
+ },
21479
+ updated_after: {
21480
+ type: "string",
21481
+ format: "date-time"
21482
+ },
21483
+ updated_before: {
21484
+ type: "string",
21485
+ format: "date-time"
21486
+ },
21487
+ since: {
21488
+ type: "string",
21489
+ description: "Relative created-after time; explicit created_after wins. Unrecognized relative text retains legacy ignored behavior."
21490
+ },
21491
+ tags: {
21492
+ type: "string",
21493
+ description: "Comma-separated tags; trimmed nonempty entries are AND requirements."
21494
+ },
21495
+ strict_filter: {
21496
+ $ref: "#/$defs/StrictSearchFilterInput",
21497
+ "x-fortemi-query-content": "application/json"
21498
+ },
21499
+ metadata_predicates: {
21500
+ $ref: "predicates.schema.json",
21501
+ "x-fortemi-query-content": "application/json",
21502
+ "x-fortemi-max-encoded-utf8-bytes": 1048576
21503
+ },
21504
+ diversity: {
21505
+ type: "number",
21506
+ minimum: -34028234663852886e22,
21507
+ maximum: 34028234663852886e22,
21508
+ description: "Finite f32 input, clamped to [0,1] before MMR; zero is pure relevance."
21509
+ }
21510
+ }
21511
+ },
21512
+ SearchHitFields: {
21513
+ type: "object",
21514
+ required: [
21515
+ "note_id",
21516
+ "score",
21517
+ "snippet"
21518
+ ],
21519
+ properties: {
21520
+ note_id: {
21521
+ type: "string",
21522
+ format: "uuid"
21523
+ },
21524
+ score: {
21525
+ type: "number",
21526
+ description: "Finite retrieval/fusion score, not a probability."
21527
+ },
21528
+ snippet: {
21529
+ type: [
21530
+ "string",
21531
+ "null"
21532
+ ],
21533
+ description: "Display only; not citation text or coordinates."
21534
+ },
21535
+ title: {
21536
+ type: "string"
21537
+ },
21538
+ tags: {
21539
+ type: "array",
21540
+ items: {
21541
+ type: "string"
21542
+ }
21543
+ },
21544
+ embedding_status: {
21545
+ enum: [
21546
+ "ready",
21547
+ "pending",
21548
+ "failed",
21549
+ "none"
21550
+ ]
21551
+ },
21552
+ evidence: {
21553
+ $ref: "evidence-set.schema.json"
21554
+ }
21555
+ }
21556
+ },
21557
+ SearchHit: {
21558
+ type: "object",
21559
+ allOf: [
21560
+ {
21561
+ $ref: "#/$defs/SearchHitFields"
21562
+ }
21563
+ ],
21564
+ unevaluatedProperties: false
21565
+ },
21566
+ ChainSearchInfo: {
21567
+ type: "object",
21568
+ additionalProperties: false,
21569
+ required: [
21570
+ "chain_id",
21571
+ "original_title",
21572
+ "chunks_matched",
21573
+ "best_chunk_sequence",
21574
+ "total_chunks"
21575
+ ],
21576
+ description: "Legacy display aggregation. Index/count fields are currently heuristic, not native citation coordinates; use evidence for exact unit identity.",
21577
+ properties: {
21578
+ chain_id: {
21579
+ type: "string",
21580
+ format: "uuid"
21581
+ },
21582
+ original_title: {
21583
+ type: "string"
21584
+ },
21585
+ chunks_matched: {
21586
+ type: "integer",
21587
+ minimum: 0
21588
+ },
21589
+ best_chunk_sequence: {
21590
+ type: "integer",
21591
+ minimum: 0,
21592
+ maximum: 4294967295
21593
+ },
21594
+ total_chunks: {
21595
+ type: "integer",
21596
+ minimum: 0,
21597
+ maximum: 4294967295
21598
+ }
21599
+ }
21600
+ },
21601
+ EnhancedSearchHit: {
21602
+ type: "object",
21603
+ allOf: [
21604
+ {
21605
+ $ref: "#/$defs/SearchHitFields"
21606
+ },
21607
+ {
21608
+ type: "object",
21609
+ properties: {
21610
+ chain_info: {
21611
+ $ref: "#/$defs/ChainSearchInfo"
21612
+ }
21613
+ }
21614
+ }
21615
+ ],
21616
+ unevaluatedProperties: false
21617
+ },
21618
+ SearchDegradation: {
21619
+ type: "object",
21620
+ additionalProperties: false,
21621
+ required: [
21622
+ "code",
21623
+ "effective_mode"
21624
+ ],
21625
+ properties: {
21626
+ code: {
21627
+ type: "string",
21628
+ pattern: "^[a-z][a-z0-9_]{0,63}$"
21629
+ },
21630
+ effective_mode: {
21631
+ const: "fts"
21632
+ }
21633
+ }
21634
+ },
21635
+ SearchRestResponse: {
21636
+ type: "object",
21637
+ additionalProperties: false,
21638
+ required: [
21639
+ "results",
21640
+ "query",
21641
+ "total",
21642
+ "degraded"
21643
+ ],
21644
+ properties: {
21645
+ results: {
21646
+ type: "array",
21647
+ maxItems: 1e3,
21648
+ items: {
21649
+ $ref: "#/$defs/EnhancedSearchHit"
21650
+ }
21651
+ },
21652
+ query: {
21653
+ type: "string"
21654
+ },
21655
+ total: {
21656
+ type: "integer",
21657
+ minimum: 0,
21658
+ maximum: 1e3,
21659
+ description: "Returned hit count, exactly results.length; not total matches in storage."
21660
+ },
21661
+ degraded: {
21662
+ type: "boolean"
21663
+ },
21664
+ degradation: {
21665
+ $ref: "#/$defs/SearchDegradation"
21666
+ }
21667
+ },
21668
+ if: {
21669
+ properties: {
21670
+ degraded: {
21671
+ const: true
21672
+ }
21673
+ }
21674
+ },
21675
+ then: {
21676
+ properties: {
21677
+ degradation: {}
21678
+ },
21679
+ required: [
21680
+ "degradation"
21681
+ ]
21682
+ },
21683
+ else: {
21684
+ not: {
21685
+ properties: {
21686
+ degradation: {}
21687
+ },
21688
+ required: [
21689
+ "degradation"
21690
+ ]
21691
+ }
21692
+ }
21693
+ }
21694
+ }
21695
+ };
21696
+
21697
+ // schemas/metadata-search/candidate/1.0.0/evidence-resolution.schema.json
21698
+ var evidence_resolution_schema_default = {
21699
+ $schema: "https://json-schema.org/draft/2020-12/schema",
21700
+ $id: "https://fortemi.com/contracts/metadata-search/candidate/1.0.0/evidence-resolution.schema.json",
21701
+ title: "Candidate current-storage evidence resolution",
21702
+ $defs: {
21703
+ SearchEvidenceResolveRequest: {
21704
+ type: "object",
21705
+ additionalProperties: false,
21706
+ required: ["locator"],
21707
+ properties: {
21708
+ locator: { $ref: "evidence-locator.schema.json" },
21709
+ metadata_predicates: { $ref: "predicates.schema.json" },
21710
+ include_archived: { type: "boolean", default: false }
21711
+ }
21712
+ },
21713
+ SearchEvidenceResolveResponse: {
21714
+ type: "object",
21715
+ additionalProperties: false,
21716
+ required: ["text"],
21717
+ properties: {
21718
+ text: { type: "string", maxLength: 16777216 }
21719
+ }
21720
+ }
21721
+ }
21722
+ };
21723
+
21724
+ // src/remote-search-schema.ts
21725
+ var timestamp = z.string().datetime({ offset: true });
21726
+ var ajv2 = new Ajv20206({ strict: true, allErrors: false, ownProperties: true }).addFormat("uuid", /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i).addFormat("date-time", { type: "string", validate: (value) => timestamp.safeParse(value).success }).addKeyword({ keyword: "x-fortemi-query-content", schemaType: "string", valid: true }).addKeyword({ keyword: "x-fortemi-max-encoded-utf8-bytes", schemaType: "number", valid: true }).addSchema([search_rest_schema_default, evidence_locator_schema_default, evidence_set_schema_default, evidence_resolution_schema_default]).addSchema(predicates_schema_default, new URL("predicates.schema.json", search_rest_schema_default.$id).href);
21727
+ var isSearchRestRequest = ajv2.compile({ $ref: search_rest_schema_default.$id + "#/$defs/SearchRestRequest" });
21728
+ var isSearchRestResponse = ajv2.compile({ $ref: search_rest_schema_default.$id + "#/$defs/SearchRestResponse" });
21729
+ var isEvidenceResolveRequest = ajv2.compile({ $ref: evidence_resolution_schema_default.$id + "#/$defs/SearchEvidenceResolveRequest" });
21730
+ var isEvidenceResolveResponse = ajv2.compile({ $ref: evidence_resolution_schema_default.$id + "#/$defs/SearchEvidenceResolveResponse" });
21731
+
21732
+ // src/remote-contract.ts
20044
21733
  var uuid3 = z.string().uuid().transform((value) => value.toLowerCase());
20045
21734
  var metadata = z.object({
20046
21735
  id: uuid3,
@@ -20083,7 +21772,7 @@ function parseRemoteNoteDetail(value) {
20083
21772
  return { ...projectNote({ ...result.note, tags: result.tags }), content: result.revised.content };
20084
21773
  });
20085
21774
  }
20086
- var timestamp = z.string().datetime({ offset: true });
21775
+ var timestamp2 = z.string().datetime({ offset: true });
20087
21776
  function remoteNoteId(value) {
20088
21777
  const parsed = uuid3.safeParse(value);
20089
21778
  if (!parsed.success) throw new RemoteBackendError("invalid-request");
@@ -20096,7 +21785,7 @@ var link = z.object({
20096
21785
  to_url: z.string().nullable(),
20097
21786
  kind: z.string(),
20098
21787
  score: z.number().finite(),
20099
- created_at_utc: timestamp,
21788
+ created_at_utc: timestamp2,
20100
21789
  snippet: z.string().nullable(),
20101
21790
  metadata: z.unknown().refine((value) => value !== void 0)
20102
21791
  });
@@ -20135,7 +21824,7 @@ var conceptAssignment = z.tuple([
20135
21824
  source: z.string(),
20136
21825
  relevance_score: z.number().finite(),
20137
21826
  is_primary: z.boolean(),
20138
- created_at: timestamp,
21827
+ created_at: timestamp2,
20139
21828
  confidence: z.number().finite().optional(),
20140
21829
  created_by: z.string().optional()
20141
21830
  }),
@@ -20143,8 +21832,8 @@ var conceptAssignment = z.tuple([
20143
21832
  id: uuid3,
20144
21833
  primary_scheme_id: uuid3,
20145
21834
  pref_label: z.string(),
20146
- created_at: timestamp,
20147
- updated_at: timestamp
21835
+ created_at: timestamp2,
21836
+ updated_at: timestamp2
20148
21837
  })
20149
21838
  ]);
20150
21839
  function parseRemoteConcepts(value, noteId) {
@@ -20179,8 +21868,8 @@ var provenanceActivity = z.object({
20179
21868
  revision_id: uuid3.nullable(),
20180
21869
  activity_type: z.string(),
20181
21870
  model_name: z.string().nullable(),
20182
- started_at: timestamp,
20183
- ended_at: timestamp.nullable(),
21871
+ started_at: timestamp2,
21872
+ ended_at: timestamp2.nullable(),
20184
21873
  metadata: z.unknown().refine((value) => value !== void 0)
20185
21874
  });
20186
21875
  var provenanceEdge = z.object({
@@ -20189,7 +21878,7 @@ var provenanceEdge = z.object({
20189
21878
  source_note_id: uuid3.nullable(),
20190
21879
  source_url: z.string().nullable(),
20191
21880
  relation: z.string(),
20192
- created_at_utc: timestamp
21881
+ created_at_utc: timestamp2
20193
21882
  });
20194
21883
  var provenanceChain = z.object({
20195
21884
  note_id: uuid3,
@@ -20227,12 +21916,14 @@ function remoteSearchParameters(query, options) {
20227
21916
  if (typeof query !== "string" || !parsed.success) throw new RemoteBackendError("invalid-request");
20228
21917
  const value = parsed.data;
20229
21918
  if ((value.offset ?? 0) !== 0 || (value.source?.length ?? 0) > 0) throw new RemoteBackendError("unsupported-operation");
20230
- return {
21919
+ const parameters = {
20231
21920
  q: query,
20232
21921
  mode: value.mode,
20233
21922
  limit: value.limit,
20234
21923
  ...value.tags?.length ? { tags: value.tags.join(",") } : {}
20235
21924
  };
21925
+ if (!isSearchRestRequest(parameters)) throw new RemoteBackendError("invalid-request");
21926
+ return parameters;
20236
21927
  }
20237
21928
  var searchHit = z.object({
20238
21929
  note_id: uuid3,
@@ -20241,6 +21932,7 @@ var searchHit = z.object({
20241
21932
  title: z.string().optional(),
20242
21933
  tags: z.array(z.string()).optional(),
20243
21934
  embedding_status: z.enum(["ready", "pending", "failed", "none"]).optional(),
21935
+ evidence: z.unknown().optional(),
20244
21936
  chain_info: z.object({
20245
21937
  chain_id: uuid3,
20246
21938
  original_title: z.string(),
@@ -20248,10 +21940,13 @@ var searchHit = z.object({
20248
21940
  best_chunk_sequence: z.number().int().nonnegative(),
20249
21941
  total_chunks: z.number().int().nonnegative()
20250
21942
  }).optional()
20251
- });
21943
+ }).transform(({ evidence, ...hit }) => ({
21944
+ ...hit,
21945
+ ...evidence === void 0 ? {} : { evidence: parseSearchEvidenceSet(evidence, hit.note_id) }
21946
+ }));
20252
21947
  var searchDegradation = z.object({
20253
21948
  code: z.string().regex(/^[a-z][a-z0-9_]{0,63}$/),
20254
- effective_mode: searchMode
21949
+ effective_mode: z.literal("fts")
20255
21950
  });
20256
21951
  var searchResponse = z.object({
20257
21952
  query: z.string(),
@@ -20262,8 +21957,10 @@ var searchResponse = z.object({
20262
21957
  });
20263
21958
  function parseRemoteSearch(value, query, limit) {
20264
21959
  return remoteProjection(() => {
21960
+ if (!isSearchRestResponse(value)) throw new Error("Invalid search schema");
20265
21961
  const result = searchResponse.parse(value);
20266
21962
  if (result.query !== query || result.total !== result.results.length || result.results.length > limit || result.degraded !== (result.degradation !== void 0)) throw new Error("Invalid search envelope");
21963
+ if (result.results.some((hit) => hit.chain_info && hit.chain_info.chain_id !== hit.note_id)) throw new Error("Invalid chain identity");
20267
21964
  return result;
20268
21965
  });
20269
21966
  }
@@ -20299,6 +21996,135 @@ function parseRemoteRestored(value, id) {
20299
21996
  });
20300
21997
  }
20301
21998
 
21999
+ // src/backend-search-options.ts
22000
+ init_geometry_buffer();
22001
+ function validateBackendSearchOptions(options, support) {
22002
+ if (options?.metadataPredicates !== void 0) {
22003
+ validateMetadataPredicates(options.metadataPredicates);
22004
+ if (!support.metadata) throw new Error("BACKEND_METADATA_PREDICATES_UNSUPPORTED");
22005
+ }
22006
+ if (options?.tenant_id !== void 0 || options?.archive_id !== void 0) {
22007
+ if (!support.scope) throw new Error("BACKEND_SEARCH_SCOPE_UNSUPPORTED");
22008
+ if (options.tenant_id !== void 0 && (typeof options.tenant_id !== "string" || !options.tenant_id.length) || options.archive_id !== void 0 && options.archive_id !== null && (typeof options.archive_id !== "string" || !options.archive_id.length)) {
22009
+ throw new Error("BACKEND_SEARCH_SCOPE_INVALID");
22010
+ }
22011
+ }
22012
+ if (options?.mode !== void 0 && support.modes && !support.modes.includes(options.mode)) {
22013
+ throw new Error("BACKEND_SEARCH_MODE_UNSUPPORTED");
22014
+ }
22015
+ }
22016
+
22017
+ // src/remote-evidence-resolution.ts
22018
+ init_geometry_buffer();
22019
+ var encoder3 = new TextEncoder();
22020
+ var decoder3 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
22021
+ var invalidRequest = () => new RemoteBackendError("invalid-request");
22022
+ var invalidResponse = () => new RemoteBackendError("invalid-response");
22023
+ function prepare(value, options = {}) {
22024
+ try {
22025
+ if (!options || typeof options !== "object" || Array.isArray(options) || ![Object.prototype, null].includes(Object.getPrototypeOf(options)) || Reflect.ownKeys(options).some((key3) => !["metadataPredicates", "includeArchived", "signal"].includes(String(key3)))) throw invalidRequest();
22026
+ const locator = parseSearchEvidenceLocator(value);
22027
+ if (locator.span.end > MAX_EVIDENCE_BYTES) throw invalidRequest();
22028
+ const metadata2 = Object.hasOwn(options, "metadataPredicates") ? options.metadataPredicates : void 0;
22029
+ const archived = Object.hasOwn(options, "includeArchived") ? options.includeArchived : void 0;
22030
+ const signal = Object.hasOwn(options, "signal") ? options.signal : void 0;
22031
+ if (signal !== void 0 && !(signal instanceof AbortSignal)) throw invalidRequest();
22032
+ if (metadata2 !== void 0) validateMetadataPredicates(metadata2);
22033
+ const request = {
22034
+ locator,
22035
+ ...metadata2 === void 0 ? {} : { metadata_predicates: metadata2 },
22036
+ ...archived === void 0 ? {} : { include_archived: archived }
22037
+ };
22038
+ if (!isEvidenceResolveRequest(request)) throw invalidRequest();
22039
+ const body = JSON.stringify(request);
22040
+ if (encoder3.encode(body).length > 65536) throw invalidRequest();
22041
+ const wire = JSON.parse(body);
22042
+ if (!isEvidenceResolveRequest(wire)) throw invalidRequest();
22043
+ const encoded = wire;
22044
+ parseSearchEvidenceLocator(encoded.locator);
22045
+ if (encoded.metadata_predicates !== void 0) validateMetadataPredicates(encoded.metadata_predicates);
22046
+ return { body, signal, length: locator.span.end - locator.span.start };
22047
+ } catch {
22048
+ throw invalidRequest();
22049
+ }
22050
+ }
22051
+ async function resolveRemoteEvidence(value, options, send) {
22052
+ const prepared = prepare(value, options);
22053
+ if (prepared.signal?.aborted) throw new RemoteBackendError("aborted");
22054
+ const controller = new AbortController();
22055
+ const abort = () => controller.abort();
22056
+ prepared.signal?.addEventListener("abort", abort, { once: true });
22057
+ const timer = setTimeout(abort, 3e4);
22058
+ let reader;
22059
+ let completed = false;
22060
+ let rejectAbort = () => {
22061
+ };
22062
+ const aborted = new Promise((_resolve, reject) => {
22063
+ rejectAbort = () => reject(new RemoteBackendError("aborted"));
22064
+ });
22065
+ controller.signal.addEventListener("abort", rejectAbort, { once: true });
22066
+ async function perform() {
22067
+ const response = await send(prepared.body, controller.signal);
22068
+ if (controller.signal.aborted) {
22069
+ void response.body?.cancel().catch(() => {
22070
+ });
22071
+ throw new RemoteBackendError("aborted");
22072
+ }
22073
+ reader = response.body?.getReader();
22074
+ if (!response.ok) throw new RemoteBackendError("http", response.status);
22075
+ if (response.status !== 200 || !reader || response.headers.get("content-type")?.split(";")[0].trim().toLowerCase() !== "application/json" || !response.headers.get("cache-control")?.split(",").some((part) => part.trim().toLowerCase() === "no-store")) throw invalidResponse();
22076
+ const maximum = prepared.length * 6 + 64;
22077
+ const advertised = response.headers.get("content-length");
22078
+ if (advertised !== null && (!/^\d+$/.test(advertised) || Number(advertised) > maximum)) throw invalidResponse();
22079
+ let bytes = new Uint8Array(Math.min(maximum, 4096));
22080
+ let length = 0;
22081
+ while (true) {
22082
+ const { done, value: chunk } = await reader.read();
22083
+ if (done) {
22084
+ completed = true;
22085
+ break;
22086
+ }
22087
+ const nextLength = length + chunk.byteLength;
22088
+ if (nextLength > maximum) throw invalidResponse();
22089
+ if (nextLength > bytes.length) {
22090
+ const grown = new Uint8Array(Math.min(maximum, Math.max(nextLength, bytes.length * 2)));
22091
+ grown.set(bytes.subarray(0, length));
22092
+ bytes = grown;
22093
+ }
22094
+ bytes.set(chunk, length);
22095
+ length = nextLength;
22096
+ }
22097
+ let data;
22098
+ try {
22099
+ data = JSON.parse(decoder3.decode(bytes.subarray(0, length)));
22100
+ } catch {
22101
+ throw invalidResponse();
22102
+ }
22103
+ if (!isEvidenceResolveResponse(data)) throw invalidResponse();
22104
+ const text = data.text;
22105
+ if (text.length > prepared.length) throw invalidResponse();
22106
+ const textBytes2 = encoder3.encode(text);
22107
+ if (textBytes2.length !== prepared.length || decoder3.decode(textBytes2) !== text) throw invalidResponse();
22108
+ return text;
22109
+ }
22110
+ try {
22111
+ return await Promise.race([perform(), aborted]);
22112
+ } catch (error) {
22113
+ if (error instanceof RemoteBackendError) throw error;
22114
+ throw new RemoteBackendError(controller.signal.aborted || error instanceof Error && error.name === "AbortError" ? "aborted" : "transport");
22115
+ } finally {
22116
+ clearTimeout(timer);
22117
+ prepared.signal?.removeEventListener("abort", abort);
22118
+ controller.signal.removeEventListener("abort", rejectAbort);
22119
+ controller.abort();
22120
+ if (reader) {
22121
+ if (!completed) void reader.cancel().catch(() => {
22122
+ });
22123
+ reader.releaseLock();
22124
+ }
22125
+ }
22126
+ }
22127
+
20302
22128
  // src/data-backend.ts
20303
22129
  var SEMANTIC_RANK = {
20304
22130
  none: 0,
@@ -20313,6 +22139,8 @@ var STARTUP_RANK = {
20313
22139
  };
20314
22140
  function missingFor(request, caps) {
20315
22141
  const missing = [];
22142
+ if (request.typedMetadataPredicates && !caps.typedMetadataPredicates) missing.push("typedMetadataPredicates");
22143
+ if (request.evidenceLocators && !caps.evidenceLocators) missing.push("evidenceLocators");
20316
22144
  if (request.read && !caps.read) missing.push("read");
20317
22145
  if (request.write && !caps.write) missing.push("write");
20318
22146
  if (request.merge && !caps.merge) missing.push("merge");
@@ -20436,9 +22264,45 @@ function shardProvenanceToBackend(edge) {
20436
22264
  }
20437
22265
  function createPGliteBackend(db, options = {}) {
20438
22266
  const semanticAvailable = options.semanticAvailable ?? false;
22267
+ const embedQuery = options.embedQuery;
22268
+ const canEmbed = semanticAvailable && typeof embedQuery === "function";
20439
22269
  const notes = new NotesRepository(db);
20440
22270
  const search = new SearchRepository(db, semanticAvailable);
20441
22271
  const links = new LinksRepository(db);
22272
+ async function searchNotes(query, o) {
22273
+ validateBackendSearchOptions(o, {
22274
+ metadata: true,
22275
+ scope: true,
22276
+ modes: canEmbed ? ["fts", "semantic", "hybrid"] : ["fts"]
22277
+ });
22278
+ const mode = o?.mode ?? "fts";
22279
+ const vector = mode === "fts" ? void 0 : await embedQuery(query);
22280
+ if (mode !== "fts" && (!Array.isArray(vector) || !vector.length || !Array.from(vector).every((value) => typeof value === "number" && Number.isFinite(value)))) {
22281
+ throw new Error("BACKEND_QUERY_EMBEDDING_INVALID");
22282
+ }
22283
+ const r = await search.search(query, {
22284
+ limit: o?.limit,
22285
+ offset: o?.offset,
22286
+ tagsAll: o?.tags,
22287
+ sources: o?.source,
22288
+ mode: mode === "fts" ? "text" : mode,
22289
+ metadataPredicates: o?.metadataPredicates,
22290
+ tenant_id: o?.tenant_id,
22291
+ archive_id: o?.archive_id,
22292
+ include_facets: true
22293
+ }, vector);
22294
+ return {
22295
+ hits: r.results.map((res) => ({
22296
+ note: searchResultToBackend(res),
22297
+ rank: res.rank,
22298
+ snippet: res.snippet,
22299
+ locators: res.locators,
22300
+ evidence: res.evidence
22301
+ })),
22302
+ total: r.total,
22303
+ facets: r.facets ? { tags: Object.fromEntries(r.facets.tags.map((t) => [t.tag, t.count])) } : void 0
22304
+ };
22305
+ }
20442
22306
  async function linksOf(id) {
20443
22307
  const result = await links.listForNote(id);
20444
22308
  const urlLinks = await db.query(
@@ -20479,7 +22343,9 @@ function createPGliteBackend(db, options = {}) {
20479
22343
  write: true,
20480
22344
  merge: true,
20481
22345
  multiUser: false,
20482
- semantic: semanticAvailable ? "ann-full" : "none",
22346
+ typedMetadataPredicates: true,
22347
+ evidenceLocators: false,
22348
+ semantic: canEmbed ? "ann-full" : "none",
20483
22349
  startupCost: "index-build"
20484
22350
  },
20485
22351
  async listNotes(o) {
@@ -20494,24 +22360,8 @@ function createPGliteBackend(db, options = {}) {
20494
22360
  return null;
20495
22361
  }
20496
22362
  },
20497
- async search(query, o) {
20498
- const r = await search.search(query, {
20499
- limit: o?.limit,
20500
- offset: o?.offset,
20501
- tags: o?.tags,
20502
- source: o?.source?.[0],
20503
- include_facets: true
20504
- });
20505
- const hits = r.results.map((res) => ({
20506
- note: searchResultToBackend(res),
20507
- rank: res.rank,
20508
- snippet: res.snippet
20509
- }));
20510
- const facets = r.facets ? {
20511
- tags: Object.fromEntries(r.facets.tags.map((t) => [t.tag, t.count]))
20512
- } : void 0;
20513
- return { hits, total: r.total, facets };
20514
- },
22363
+ search: searchNotes,
22364
+ ...canEmbed ? { semantic: async (query, k) => (await searchNotes(query, { mode: "semantic", limit: k })).hits } : {},
20515
22365
  async getNoteFull(id) {
20516
22366
  try {
20517
22367
  const f = await notes.get(id);
@@ -20537,6 +22387,7 @@ var DEFAULT_REMOTE_PATHS = {
20537
22387
  notes: "/api/v1/notes",
20538
22388
  note: "/api/v1/notes/:id",
20539
22389
  search: "/api/v1/search",
22390
+ resolveEvidence: "/api/v1/search/evidence/resolve",
20540
22391
  links: "/api/v1/notes/:id/links",
20541
22392
  concepts: "/api/v1/notes/:id/concepts",
20542
22393
  provenance: "/api/v1/notes/:id/provenance",
@@ -20547,12 +22398,12 @@ function remotePath(template, id) {
20547
22398
  }
20548
22399
  function remoteUrl(baseUrl, path, params) {
20549
22400
  const url = new URL(path, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
20550
- for (const [key2, value] of Object.entries(params ?? {})) {
22401
+ for (const [key3, value] of Object.entries(params ?? {})) {
20551
22402
  if (value === void 0) continue;
20552
22403
  if (Array.isArray(value)) {
20553
- for (const item of value) url.searchParams.append(key2, String(item));
22404
+ for (const item of value) url.searchParams.append(key3, String(item));
20554
22405
  } else {
20555
- url.searchParams.set(key2, String(value));
22406
+ url.searchParams.set(key3, String(value));
20556
22407
  }
20557
22408
  }
20558
22409
  return url.toString();
@@ -20608,6 +22459,7 @@ function createRemoteBackend(config) {
20608
22459
  return note;
20609
22460
  }
20610
22461
  async function searchRemote(query, options, requireSemantic = false) {
22462
+ validateBackendSearchOptions(options, { metadata: false, scope: false });
20611
22463
  const params = remoteSearchParameters(query, options);
20612
22464
  const result = parseRemoteSearch(await getJson(paths.search, params), query, params.limit);
20613
22465
  if (requireSemantic && result.degraded) throw new RemoteBackendError("degraded-search");
@@ -20632,6 +22484,7 @@ function createRemoteBackend(config) {
20632
22484
  },
20633
22485
  rank: hit.score,
20634
22486
  ...hit.snippet === null ? {} : { snippet: hit.snippet },
22487
+ ...hit.evidence === void 0 ? {} : { evidence: hit.evidence },
20635
22488
  remoteSearch: {
20636
22489
  ...hit.title === void 0 ? {} : { title: hit.title },
20637
22490
  ...hit.tags === void 0 ? {} : { tags: hit.tags },
@@ -20688,6 +22541,8 @@ function createRemoteBackend(config) {
20688
22541
  merge: false,
20689
22542
  multiUser: true,
20690
22543
  semantic: "server",
22544
+ typedMetadataPredicates: false,
22545
+ evidenceLocators: false,
20691
22546
  startupCost: "network"
20692
22547
  },
20693
22548
  async listNotes(o) {
@@ -20715,6 +22570,20 @@ function createRemoteBackend(config) {
20715
22570
  }
20716
22571
  },
20717
22572
  search: searchRemote,
22573
+ async resolveEvidence(locator, options) {
22574
+ return resolveRemoteEvidence(locator, options, async (body, signal) => {
22575
+ const headers = await remoteHeaders(config, true);
22576
+ signal.throwIfAborted();
22577
+ return (config.fetchImpl ?? globalThis.fetch)(remoteUrl(config.baseUrl, paths.resolveEvidence ?? DEFAULT_REMOTE_PATHS.resolveEvidence), {
22578
+ method: "POST",
22579
+ headers,
22580
+ body,
22581
+ signal,
22582
+ cache: "no-store",
22583
+ redirect: "error"
22584
+ });
22585
+ });
22586
+ },
20718
22587
  getNoteFull,
20719
22588
  linksOf,
20720
22589
  conceptsOf,
@@ -20784,6 +22653,8 @@ function createShardBackend(reader, options = {}) {
20784
22653
  merge: false,
20785
22654
  multiUser: false,
20786
22655
  semantic,
22656
+ typedMetadataPredicates: false,
22657
+ evidenceLocators: false,
20787
22658
  startupCost: "instant"
20788
22659
  },
20789
22660
  async listNotes(o) {
@@ -20795,6 +22666,7 @@ function createShardBackend(reader, options = {}) {
20795
22666
  return n ? shardNoteToBackend(n) : null;
20796
22667
  },
20797
22668
  async search(query, o) {
22669
+ validateBackendSearchOptions(o, { metadata: false, scope: false, modes: ["fts"] });
20798
22670
  const r = await reader.search(query, { ...o, rank: true, snippets: true });
20799
22671
  const hits = r.rankedItems ? r.rankedItems.map((it) => ({
20800
22672
  note: shardNoteToBackend(it.note),
@@ -21338,26 +23210,26 @@ function isRecord(value) {
21338
23210
  function isSupportedState(value) {
21339
23211
  return typeof value === "string" && FORTEMI_COMPATIBILITY_STATES.includes(value);
21340
23212
  }
21341
- function requireRecord(parent, key2, errors) {
21342
- const value = parent[key2];
23213
+ function requireRecord(parent, key3, errors) {
23214
+ const value = parent[key3];
21343
23215
  if (!isRecord(value)) {
21344
- errors.push(`${key2} must be an object`);
23216
+ errors.push(`${key3} must be an object`);
21345
23217
  return null;
21346
23218
  }
21347
23219
  return value;
21348
23220
  }
21349
- function requireString(parent, key2, path, errors) {
21350
- const value = parent[key2];
23221
+ function requireString(parent, key3, path, errors) {
23222
+ const value = parent[key3];
21351
23223
  if (typeof value !== "string" || value.length === 0) {
21352
- errors.push(`${path}.${key2} must be a non-empty string`);
23224
+ errors.push(`${path}.${key3} must be a non-empty string`);
21353
23225
  return null;
21354
23226
  }
21355
23227
  return value;
21356
23228
  }
21357
- function requireBoolean(parent, key2, path, errors) {
21358
- const value = parent[key2];
23229
+ function requireBoolean(parent, key3, path, errors) {
23230
+ const value = parent[key3];
21359
23231
  if (typeof value !== "boolean") {
21360
- errors.push(`${path}.${key2} must be a boolean`);
23232
+ errors.push(`${path}.${key3} must be a boolean`);
21361
23233
  return null;
21362
23234
  }
21363
23235
  return value;
@@ -21407,24 +23279,24 @@ function validateFortemiCompatibilityResponse(raw) {
21407
23279
  }
21408
23280
  const capabilities = requireRecord(raw, "capabilities", errors);
21409
23281
  if (capabilities) {
21410
- for (const key2 of FORTEMI_REQUIRED_COMPATIBILITY_CAPABILITIES) {
21411
- if (!isRecord(capabilities[key2])) {
21412
- errors.push(`capabilities.${key2} must be present as an object`);
23282
+ for (const key3 of FORTEMI_REQUIRED_COMPATIBILITY_CAPABILITIES) {
23283
+ if (!isRecord(capabilities[key3])) {
23284
+ errors.push(`capabilities.${key3} must be present as an object`);
21413
23285
  }
21414
23286
  }
21415
- for (const [key2, value] of Object.entries(capabilities)) {
23287
+ for (const [key3, value] of Object.entries(capabilities)) {
21416
23288
  if (!isRecord(value)) {
21417
- errors.push(`capabilities.${key2} must be an object`);
23289
+ errors.push(`capabilities.${key3} must be an object`);
21418
23290
  continue;
21419
23291
  }
21420
23292
  if (!isSupportedState(value.state)) {
21421
- errors.push(`capabilities.${key2}.state must be one of ${FORTEMI_COMPATIBILITY_STATES.join(", ")}`);
23293
+ errors.push(`capabilities.${key3}.state must be one of ${FORTEMI_COMPATIBILITY_STATES.join(", ")}`);
21422
23294
  }
21423
23295
  if ("reason_code" in value && typeof value.reason_code !== "string") {
21424
- errors.push(`capabilities.${key2}.reason_code must be a string when present`);
23296
+ errors.push(`capabilities.${key3}.reason_code must be a string when present`);
21425
23297
  }
21426
23298
  if (value.state !== "available" && !value.reason_code) {
21427
- warnings.push(`capabilities.${key2} is ${String(value.state)} without reason_code`);
23299
+ warnings.push(`capabilities.${key3} is ${String(value.state)} without reason_code`);
21428
23300
  }
21429
23301
  }
21430
23302
  }
@@ -21443,7 +23315,7 @@ function validateFortemiCompatibilityResponse(raw) {
21443
23315
  };
21444
23316
  }
21445
23317
  function formatFortemiCompatibilitySummary(response) {
21446
- const capabilitySummary = Object.entries(response.capabilities).map(([key2, value]) => `${key2}=${value.state}`).sort().join(", ");
23318
+ const capabilitySummary = Object.entries(response.capabilities).map(([key3, value]) => `${key3}=${value.state}`).sort().join(", ");
21447
23319
  return [
21448
23320
  `Fortemi compatibility ${response.contract_revision}`,
21449
23321
  `api=${response.api.name}@${response.api.version}`,
@@ -23756,7 +25628,7 @@ var CollectionsRepository = class {
23756
25628
 
23757
25629
  // src/repositories/templates-repository.ts
23758
25630
  init_geometry_buffer();
23759
- function validate(record) {
25631
+ function validate2(record) {
23760
25632
  if (!validateShardComponentRecord("templates", record, "full-v1", "2.0.0").valid) throw new Error("Invalid native template");
23761
25633
  }
23762
25634
  var TemplatesRepository = class {
@@ -23774,7 +25646,7 @@ var TemplatesRepository = class {
23774
25646
  async create(input) {
23775
25647
  const id = generateId();
23776
25648
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
23777
- validate({
25649
+ validate2({
23778
25650
  id,
23779
25651
  name: input.name,
23780
25652
  content: input.content,
@@ -23794,13 +25666,13 @@ var TemplatesRepository = class {
23794
25666
  }
23795
25667
  async update(id, input) {
23796
25668
  const current = await this.get(id);
23797
- validate({ ...current, ...Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0)) });
25669
+ validate2({ ...current, ...Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0)) });
23798
25670
  const values = [];
23799
25671
  const assignments = ["updated_at = now()"];
23800
- for (const key2 of ["name", "content", "description", "format", "default_tags", "collection_id"]) {
23801
- if (input[key2] === void 0) continue;
23802
- values.push(key2 === "default_tags" ? JSON.stringify(input[key2]) : input[key2]);
23803
- assignments.push(`${key2} = $${values.length}${key2 === "default_tags" ? "::jsonb" : ""}`);
25672
+ for (const key3 of ["name", "content", "description", "format", "default_tags", "collection_id"]) {
25673
+ if (input[key3] === void 0) continue;
25674
+ values.push(key3 === "default_tags" ? JSON.stringify(input[key3]) : input[key3]);
25675
+ assignments.push(`${key3} = $${values.length}${key3 === "default_tags" ? "::jsonb" : ""}`);
23804
25676
  }
23805
25677
  values.push(id);
23806
25678
  await this.db.query(`UPDATE template SET ${assignments.join(", ")} WHERE id = $${values.length}`, values);
@@ -23961,8 +25833,8 @@ async function removeOmittedNativeSkos(tx, state, selectedNoteIds3) {
23961
25833
  await tx.query(
23962
25834
  `DELETE FROM ${table} existing WHERE existing.${owner} = ANY($1::text[])
23963
25835
  AND NOT EXISTS (SELECT 1 FROM UNNEST(${keys.map((_, index) => `$${index + 2}::text[]`).join(", ")}) incoming(${keys.join(", ")})
23964
- WHERE ${keys.map((key2) => `incoming.${key2} = existing.${key2}`).join(" AND ")})`,
23965
- [selected, ...keys.map((key2) => incoming.map((row) => nativeUuid(row[key2])))]
25836
+ WHERE ${keys.map((key3) => `incoming.${key3} = existing.${key3}`).join(" AND ")})`,
25837
+ [selected, ...keys.map((key3) => incoming.map((row) => nativeUuid(row[key3])))]
23966
25838
  );
23967
25839
  }
23968
25840
  }
@@ -24501,8 +26373,8 @@ async function captureKnowledge(db, rawInput, events) {
24501
26373
  if (!input.template) throw new Error("template is required for from_template action");
24502
26374
  let content = input.template;
24503
26375
  if (input.variables) {
24504
- for (const [key2, value] of Object.entries(input.variables)) {
24505
- content = content.replaceAll(`{{${key2}}}`, value);
26376
+ for (const [key3, value] of Object.entries(input.variables)) {
26377
+ content = content.replaceAll(`{{${key3}}}`, value);
24506
26378
  }
24507
26379
  }
24508
26380
  const note = await repo.create({
@@ -24528,6 +26400,9 @@ async function searchTool(db, rawInput) {
24528
26400
  }
24529
26401
  const repo = new SearchRepository(db, semanticAvailable);
24530
26402
  return repo.search(input.query, {
26403
+ metadataPredicates: input.metadataPredicates,
26404
+ tenant_id: input.tenant_id,
26405
+ archive_id: input.archive_id,
24531
26406
  limit: input.limit,
24532
26407
  offset: input.offset,
24533
26408
  mode: input.mode,
@@ -24552,10 +26427,10 @@ function zodToJsonSchema(schema) {
24552
26427
  const shape = schema.shape;
24553
26428
  const properties = {};
24554
26429
  const required = [];
24555
- for (const [key2, value] of Object.entries(shape)) {
24556
- properties[key2] = resolvePropertySchema(value);
26430
+ for (const [key3, value] of Object.entries(shape)) {
26431
+ properties[key3] = resolvePropertySchema(value);
24557
26432
  if (!(value instanceof z.ZodOptional) && !(value instanceof z.ZodDefault)) {
24558
- required.push(key2);
26433
+ required.push(key3);
24559
26434
  }
24560
26435
  }
24561
26436
  return {
@@ -26619,13 +28494,13 @@ var OpenAICompatibleProvider = class {
26619
28494
  throw new Error("Streaming not supported: response body is null");
26620
28495
  }
26621
28496
  const reader = response.body.getReader();
26622
- const decoder8 = new TextDecoder();
28497
+ const decoder10 = new TextDecoder();
26623
28498
  let buffer = "";
26624
28499
  try {
26625
28500
  while (true) {
26626
28501
  const { done, value } = await reader.read();
26627
28502
  if (done) break;
26628
- buffer += decoder8.decode(value, { stream: true });
28503
+ buffer += decoder10.decode(value, { stream: true });
26629
28504
  const lines = buffer.split("\n");
26630
28505
  buffer = lines.pop() ?? "";
26631
28506
  for (const line of lines) {
@@ -27686,8 +29561,8 @@ var AllowlistTrustStore = class {
27686
29561
  }
27687
29562
  /** Mark a key revoked without removing it (still resolvable, verdict `revoked`). */
27688
29563
  revoke(keyId) {
27689
- const key2 = this.keys.get(keyId);
27690
- if (key2) this.keys.set(keyId, { ...key2, revoked: true });
29564
+ const key3 = this.keys.get(keyId);
29565
+ if (key3) this.keys.set(keyId, { ...key3, revoked: true });
27691
29566
  }
27692
29567
  };
27693
29568
  function base64urlToBytes(s) {
@@ -27775,7 +29650,7 @@ async function verifyShardSignature(input) {
27775
29650
  };
27776
29651
  let signatureValid = false;
27777
29652
  try {
27778
- const key2 = await globalThis.crypto.subtle.importKey(
29653
+ const key3 = await globalThis.crypto.subtle.importKey(
27779
29654
  "raw",
27780
29655
  toBufferSource(base64urlToBytes(trusted.public_key)),
27781
29656
  { name: "Ed25519" },
@@ -27785,7 +29660,7 @@ async function verifyShardSignature(input) {
27785
29660
  const digest2 = await sha256Hex(canonicalPayloadBytes(payload));
27786
29661
  signatureValid = await globalThis.crypto.subtle.verify(
27787
29662
  "Ed25519",
27788
- key2,
29663
+ key3,
27789
29664
  toBufferSource(base64urlToBytes(envelope.signature)),
27790
29665
  toBufferSource(new TextEncoder().encode(digest2))
27791
29666
  );
@@ -36398,8 +38273,8 @@ function classifyPresenceValue(value) {
36398
38273
  function classifyOwnProperty(document2, pointer) {
36399
38274
  const resolved = parentAndKey(document2, pointer, false);
36400
38275
  if (!resolved) return "absent";
36401
- const { parent, key: key2 } = resolved;
36402
- return Object.hasOwn(parent, key2) ? classifyPresenceValue(parent[key2]) : "absent";
38276
+ const { parent, key: key3 } = resolved;
38277
+ return Object.hasOwn(parent, key3) ? classifyPresenceValue(parent[key3]) : "absent";
36403
38278
  }
36404
38279
  function capturePresence(document2, pointers) {
36405
38280
  return Object.fromEntries(pointers.flatMap(
@@ -36451,14 +38326,14 @@ function restoreStoredPresence(document2, presence) {
36451
38326
  for (const [pointer, stored] of Object.entries(presence)) {
36452
38327
  const resolved = parentAndKey(restored, pointer);
36453
38328
  if (!resolved) throw new Error(`JSON Pointer '${pointer}' parent is not an object`);
36454
- const { parent, key: key2 } = resolved;
38329
+ const { parent, key: key3 } = resolved;
36455
38330
  if (stored === "legacy-indeterminate") {
36456
38331
  throw new Error(`Cannot emit schema 2.0 with legacy-indeterminate state at ${pointer}`);
36457
38332
  }
36458
38333
  if (stored === "absent") {
36459
- delete parent[key2];
38334
+ delete parent[key3];
36460
38335
  } else if (stored === "null") {
36461
- parent[key2] = null;
38336
+ parent[key3] = null;
36462
38337
  } else if (classifyOwnProperty(restored, pointer) !== stored) {
36463
38338
  throw new Error(`Stored ${stored} state at ${pointer} does not match the persisted value`);
36464
38339
  }
@@ -36777,7 +38652,7 @@ var rowKey = (component, row) => nativeIdentityKey(nativeIdentities[component],
36777
38652
  function canonical(value) {
36778
38653
  if (Array.isArray(value)) return value.map(canonical);
36779
38654
  if (value !== null && typeof value === "object") return Object.fromEntries(
36780
- Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key2, item]) => [key2, canonical(item)])
38655
+ Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key3, item]) => [key3, canonical(item)])
36781
38656
  );
36782
38657
  return value;
36783
38658
  }
@@ -36839,7 +38714,7 @@ async function readNativeLineage(tx, state) {
36839
38714
 
36840
38715
  // src/shard/live-full-v1.ts
36841
38716
  var components2 = Object.keys(FULL_V1_COMPONENT_FILES);
36842
- var encoder2 = new TextEncoder();
38717
+ var encoder4 = new TextEncoder();
36843
38718
  var scoped = (values) => values ? [...values] : void 0;
36844
38719
  var ids = (rows) => new Set(rows.map((row) => row.id));
36845
38720
  var nullableIn = (set, value) => value === null || set.has(value);
@@ -37175,7 +39050,7 @@ async function exportLiveFullV1(db, options) {
37175
39050
  for (const component of components2) {
37176
39051
  const spec = FULL_V1_COMPONENT_FILES[component];
37177
39052
  const rows = state[component];
37178
- const bytes = encoder2.encode(spec.encoding === "json-array" ? JSON.stringify(rows) : rows.map((row) => JSON.stringify(row)).join("\n"));
39053
+ const bytes = encoder4.encode(spec.encoding === "json-array" ? JSON.stringify(rows) : rows.map((row) => JSON.stringify(row)).join("\n"));
37179
39054
  files.set(spec.file, bytes);
37180
39055
  counts[component] = rows.length;
37181
39056
  checksums[spec.file] = await sha256Hex(bytes);
@@ -37214,7 +39089,7 @@ async function exportLiveFullV1(db, options) {
37214
39089
  capability = { ...capability, losses: manifestLosses };
37215
39090
  return failure2("Generated live full-v1 manifest violates presence authority.");
37216
39091
  }
37217
- files.set("manifest.json", encoder2.encode(JSON.stringify(manifest, null, 2)));
39092
+ files.set("manifest.json", encoder4.encode(JSON.stringify(manifest, null, 2)));
37218
39093
  for (const note of state.notes) for (const { attachment } of note.attachments) {
37219
39094
  const path = sidecarEntryName(attachment.checksum);
37220
39095
  if (files.has(path)) continue;
@@ -37237,7 +39112,7 @@ async function exportLiveFullV1(db, options) {
37237
39112
  }
37238
39113
 
37239
39114
  // src/shard/shard-export.ts
37240
- var encoder3 = new TextEncoder();
39115
+ var encoder5 = new TextEncoder();
37241
39116
  var CORE_V1_FILES = /* @__PURE__ */ new Set([
37242
39117
  "notes.jsonl",
37243
39118
  "collections.json",
@@ -37643,11 +39518,11 @@ async function exportShardBytes(db, options, mode) {
37643
39518
  const slice = shardNotes.slice(offset, offset + clusterSize);
37644
39519
  const href = `notes/${String(offset).padStart(6, "0")}.jsonl`;
37645
39520
  clusters.push({ href, offset });
37646
- files.set(href, encoder3.encode(slice.map((n) => JSON.stringify(n)).join("\n")));
39521
+ files.set(href, encoder5.encode(slice.map((n) => JSON.stringify(n)).join("\n")));
37647
39522
  }
37648
39523
  layout = { clusters: { notes: clusters } };
37649
39524
  } else {
37650
- files.set("notes.jsonl", encoder3.encode(shardNotes.map((n) => JSON.stringify(n)).join("\n")));
39525
+ files.set("notes.jsonl", encoder5.encode(shardNotes.map((n) => JSON.stringify(n)).join("\n")));
37651
39526
  }
37652
39527
  components4.push("notes");
37653
39528
  counts.notes = notes.length;
@@ -37675,7 +39550,7 @@ async function exportShardBytes(db, options, mode) {
37675
39550
  mode?.nativeSchema2Presence
37676
39551
  );
37677
39552
  }
37678
- files.set("collections.json", encoder3.encode(JSON.stringify(shardCollections)));
39553
+ files.set("collections.json", encoder5.encode(JSON.stringify(shardCollections)));
37679
39554
  components4.push("collections");
37680
39555
  counts.collections = shardCollections.length;
37681
39556
  const allTagRows = await db.query(
@@ -37691,7 +39566,7 @@ async function exportShardBytes(db, options, mode) {
37691
39566
  const shardTags = tagsToShard(
37692
39567
  relevantTags.map((r) => ({ name: r.tag, created_at: r.created_at }))
37693
39568
  );
37694
- files.set("tags.json", encoder3.encode(JSON.stringify(shardTags)));
39569
+ files.set("tags.json", encoder5.encode(JSON.stringify(shardTags)));
37695
39570
  components4.push("tags");
37696
39571
  counts.tags = shardTags.length;
37697
39572
  const templateRows = await db.query(`SELECT * FROM template ORDER BY created_at, id`);
@@ -37707,7 +39582,7 @@ async function exportShardBytes(db, options, mode) {
37707
39582
  mode?.nativeSchema2Presence
37708
39583
  );
37709
39584
  }
37710
- files.set("templates.json", encoder3.encode(JSON.stringify(shardTemplates)));
39585
+ files.set("templates.json", encoder5.encode(JSON.stringify(shardTemplates)));
37711
39586
  components4.push("templates");
37712
39587
  counts.templates = shardTemplates.length;
37713
39588
  }
@@ -37732,7 +39607,7 @@ async function exportShardBytes(db, options, mode) {
37732
39607
  );
37733
39608
  }
37734
39609
  const linksJsonl = shardLinks.map((l) => JSON.stringify(l)).join("\n");
37735
- files.set("links.jsonl", encoder3.encode(linksJsonl));
39610
+ files.set("links.jsonl", encoder5.encode(linksJsonl));
37736
39611
  components4.push("links");
37737
39612
  counts.links = shardLinks.length;
37738
39613
  const allNoteSkosRows = await db.query(`SELECT * FROM note_skos_tag ORDER BY created_at`);
@@ -37749,25 +39624,25 @@ async function exportShardBytes(db, options, mode) {
37749
39624
  (row) => exportedConceptIds.has(row.source_concept_id) && exportedConceptIds.has(row.target_concept_id)
37750
39625
  ) : allRelationRows.rows;
37751
39626
  const shardSkosSchemes = filteredSchemeRows.map(skosSchemeToShard);
37752
- files.set("skos_schemes.json", encoder3.encode(JSON.stringify(shardSkosSchemes)));
39627
+ files.set("skos_schemes.json", encoder5.encode(JSON.stringify(shardSkosSchemes)));
37753
39628
  components4.push("skos_schemes");
37754
39629
  counts.skos_schemes = shardSkosSchemes.length;
37755
39630
  const shardSkosConcepts = filteredConceptRows.map(skosConceptToShard);
37756
- files.set("skos_concepts.json", encoder3.encode(JSON.stringify(shardSkosConcepts)));
39631
+ files.set("skos_concepts.json", encoder5.encode(JSON.stringify(shardSkosConcepts)));
37757
39632
  components4.push("skos_concepts");
37758
39633
  counts.skos_concepts = shardSkosConcepts.length;
37759
39634
  const skosRelationsJsonl = filteredRelationRows.map((row) => JSON.stringify(skosRelationToShard(row))).join("\n");
37760
- files.set("skos_relations.jsonl", encoder3.encode(skosRelationsJsonl));
39635
+ files.set("skos_relations.jsonl", encoder5.encode(skosRelationsJsonl));
37761
39636
  components4.push("skos_relations");
37762
39637
  counts.skos_relations = filteredRelationRows.length;
37763
39638
  const noteSkosJsonl = filteredNoteSkosRows.map((row) => JSON.stringify(noteSkosTagToShard(row))).join("\n");
37764
- files.set("note_skos_tags.jsonl", encoder3.encode(noteSkosJsonl));
39639
+ files.set("note_skos_tags.jsonl", encoder5.encode(noteSkosJsonl));
37765
39640
  components4.push("note_skos_tags");
37766
39641
  counts.note_skos_tags = filteredNoteSkosRows.length;
37767
39642
  const provenanceRows = await db.query(`SELECT * FROM provenance_edge ORDER BY started_at`);
37768
39643
  const filteredProvenanceRows = isFiltered ? provenanceRows.rows.filter((row) => row.entity_type !== "note" || exportedNoteIds.has(row.entity_id)) : provenanceRows.rows;
37769
39644
  const provenanceJsonl = filteredProvenanceRows.map((row) => JSON.stringify(provenanceEdgeToShard(row))).join("\n");
37770
- files.set("provenance_edges.jsonl", encoder3.encode(provenanceJsonl));
39645
+ files.set("provenance_edges.jsonl", encoder5.encode(provenanceJsonl));
37771
39646
  components4.push("provenance_edges");
37772
39647
  counts.provenance_edges = filteredProvenanceRows.length;
37773
39648
  if (options?.includeEmbeddings) {
@@ -37807,7 +39682,7 @@ async function exportShardBytes(db, options, mode) {
37807
39682
  freshness_json: { status: "unknown" }
37808
39683
  } : row
37809
39684
  ));
37810
- files.set("embedding_sets.json", encoder3.encode(JSON.stringify(shardEmbSets)));
39685
+ files.set("embedding_sets.json", encoder5.encode(JSON.stringify(shardEmbSets)));
37811
39686
  components4.push("embedding_sets");
37812
39687
  counts.embedding_sets = shardEmbSets.length;
37813
39688
  const embeddingConfigRows = await db.query(
@@ -37817,7 +39692,7 @@ async function exportShardBytes(db, options, mode) {
37817
39692
  );
37818
39693
  if (embeddingConfigRows.rows.length > 0) {
37819
39694
  const shardEmbeddingConfigs = embeddingConfigRows.rows.map((row) => embeddingConfigToShard(row));
37820
- files.set("embedding_configs.json", encoder3.encode(JSON.stringify(shardEmbeddingConfigs)));
39695
+ files.set("embedding_configs.json", encoder5.encode(JSON.stringify(shardEmbeddingConfigs)));
37821
39696
  components4.push("embedding_configs");
37822
39697
  counts.embedding_configs = shardEmbeddingConfigs.length;
37823
39698
  }
@@ -37830,7 +39705,7 @@ async function exportShardBytes(db, options, mode) {
37830
39705
  (member) => exportedSetIds.has(member.embedding_set_id) && exportedNoteIds.has(member.note_id) && (includeMaterializedSelectors || !virtualSetIds.has(member.embedding_set_id))
37831
39706
  );
37832
39707
  const membersJsonl = scopedEmbMemberRows.map((m) => JSON.stringify(embeddingSetMemberToShard(m))).join("\n");
37833
- files.set("embedding_set_members.jsonl", encoder3.encode(membersJsonl));
39708
+ files.set("embedding_set_members.jsonl", encoder5.encode(membersJsonl));
37834
39709
  components4.push("embedding_set_members");
37835
39710
  counts.embedding_set_members = scopedEmbMemberRows.length;
37836
39711
  const embRows = await db.query(
@@ -37856,7 +39731,7 @@ async function exportShardBytes(db, options, mode) {
37856
39731
  (embedding) => exportedSetIds.has(embedding.embedding_set_id) && exportedNoteIds.has(embedding.note_id) && (memberEmbeddingIds.size === 0 || memberEmbeddingIds.has(embedding.id))
37857
39732
  );
37858
39733
  const embJsonl = scopedEmbRows.map((e) => JSON.stringify(embeddingToShard(e))).join("\n");
37859
- files.set("embeddings.jsonl", encoder3.encode(embJsonl));
39734
+ files.set("embeddings.jsonl", encoder5.encode(embJsonl));
37860
39735
  components4.push("embeddings");
37861
39736
  counts.embeddings = scopedEmbRows.length;
37862
39737
  }
@@ -37882,7 +39757,7 @@ async function exportShardBytes(db, options, mode) {
37882
39757
  freshness: jsonObject3(row.freshness_json) ?? { status: "unknown" },
37883
39758
  created_at: iso2(row.created_at)
37884
39759
  }));
37885
- files.set("graph_sources.json", encoder3.encode(JSON.stringify(shardGraphSources)));
39760
+ files.set("graph_sources.json", encoder5.encode(JSON.stringify(shardGraphSources)));
37886
39761
  components4.push("graph_sources");
37887
39762
  counts.graph_sources = shardGraphSources.length;
37888
39763
  }
@@ -37898,7 +39773,7 @@ async function exportShardBytes(db, options, mode) {
37898
39773
  rank: row.rank,
37899
39774
  metadata: jsonObject3(row.metadata_json)
37900
39775
  })).join("\n");
37901
- files.set("graph_edges.jsonl", encoder3.encode(graphEdgesJsonl));
39776
+ files.set("graph_edges.jsonl", encoder5.encode(graphEdgesJsonl));
37902
39777
  components4.push("graph_edges");
37903
39778
  counts.graph_edges = scopedGraphEdgeRows.length;
37904
39779
  }
@@ -37934,7 +39809,7 @@ async function exportShardBytes(db, options, mode) {
37934
39809
  })),
37935
39810
  created_at: iso2(row.created_at)
37936
39811
  }));
37937
- files.set("communities.json", encoder3.encode(JSON.stringify(shardCommunitySets)));
39812
+ files.set("communities.json", encoder5.encode(JSON.stringify(shardCommunitySets)));
37938
39813
  components4.push("communities");
37939
39814
  counts.community_sets = shardCommunitySets.length;
37940
39815
  counts.communities = scopedCommunityRows.length;
@@ -37950,7 +39825,7 @@ async function exportShardBytes(db, options, mode) {
37950
39825
  source_type: row.source_type,
37951
39826
  metadata: jsonObject3(row.metadata_json)
37952
39827
  })).join("\n");
37953
- files.set("community_assignments.jsonl", encoder3.encode(assignmentsJsonl));
39828
+ files.set("community_assignments.jsonl", encoder5.encode(assignmentsJsonl));
37954
39829
  components4.push("community_assignments");
37955
39830
  counts.community_assignments = scopedAssignmentRows.length;
37956
39831
  }
@@ -37973,10 +39848,10 @@ async function exportShardBytes(db, options, mode) {
37973
39848
  const coreTags = [...tagsByName.values()].sort(
37974
39849
  (left, right) => left.name.localeCompare(right.name)
37975
39850
  );
37976
- files.set("tags.json", encoder3.encode(JSON.stringify(coreTags)));
39851
+ files.set("tags.json", encoder5.encode(JSON.stringify(coreTags)));
37977
39852
  components4.splice(0, components4.length, ...CORE_V1_COMPONENTS);
37978
- for (const key2 of Object.keys(counts)) {
37979
- if (!CORE_V1_COMPONENTS.includes(key2)) delete counts[key2];
39853
+ for (const key3 of Object.keys(counts)) {
39854
+ if (!CORE_V1_COMPONENTS.includes(key3)) delete counts[key3];
37980
39855
  }
37981
39856
  Object.assign(counts, {
37982
39857
  notes: shardNotes.length,
@@ -38013,7 +39888,7 @@ async function exportShardBytes(db, options, mode) {
38013
39888
  ...!coreV1 ? { migrated_from: null } : {},
38014
39889
  ...!coreV1 && layout ? { layout } : {}
38015
39890
  };
38016
- files.set("manifest.json", encoder3.encode(JSON.stringify(manifest, null, 2)));
39891
+ files.set("manifest.json", encoder5.encode(JSON.stringify(manifest, null, 2)));
38017
39892
  if (options?.includeBlobs && options.blobStore) {
38018
39893
  const packed = /* @__PURE__ */ new Set();
38019
39894
  for (const row of attachmentRows.rows) {
@@ -38038,14 +39913,14 @@ init_geometry_buffer();
38038
39913
 
38039
39914
  // src/shard/parse.ts
38040
39915
  init_geometry_buffer();
38041
- var decoder2 = new TextDecoder();
39916
+ var decoder4 = new TextDecoder();
38042
39917
  function parseJsonlBytes(data) {
38043
39918
  if (!data || data.byteLength === 0) return [];
38044
- return decoder2.decode(data).split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
39919
+ return decoder4.decode(data).split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
38045
39920
  }
38046
39921
  function parseJsonArrayBytes(data) {
38047
39922
  if (!data || data.byteLength === 0) return [];
38048
- return JSON.parse(decoder2.decode(data));
39923
+ return JSON.parse(decoder4.decode(data));
38049
39924
  }
38050
39925
 
38051
39926
  // src/shard/blob-staging.ts
@@ -38109,8 +39984,8 @@ async function promoteBlobs(blobStore, blobs) {
38109
39984
  init_geometry_buffer();
38110
39985
  function instant(value) {
38111
39986
  if (value === null || value === void 0) return Number.NEGATIVE_INFINITY;
38112
- const timestamp3 = value instanceof Date ? value.getTime() : Date.parse(value);
38113
- return Number.isNaN(timestamp3) ? Number.NEGATIVE_INFINITY : timestamp3;
39987
+ const timestamp4 = value instanceof Date ? value.getTime() : Date.parse(value);
39988
+ return Number.isNaN(timestamp4) ? Number.NEGATIVE_INFINITY : timestamp4;
38114
39989
  }
38115
39990
  function shouldApplyReplacement(existing, incoming) {
38116
39991
  const existingDeleted = instant(existing.deleted_at);
@@ -38470,7 +40345,7 @@ async function importNativeFullV1(db, data, options = {}) {
38470
40345
  }
38471
40346
 
38472
40347
  // src/shard/shard-import.ts
38473
- var decoder3 = new TextDecoder();
40348
+ var decoder5 = new TextDecoder();
38474
40349
  var DEFAULT_BATCH_SIZE = 250;
38475
40350
  function emptyCounts2() {
38476
40351
  return {
@@ -38607,7 +40482,7 @@ async function importShard(db, data, options) {
38607
40482
  }
38608
40483
  let manifest;
38609
40484
  try {
38610
- manifest = JSON.parse(decoder3.decode(manifestData));
40485
+ manifest = JSON.parse(decoder5.decode(manifestData));
38611
40486
  if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
38612
40487
  throw new Error("manifest must be a JSON object");
38613
40488
  }
@@ -38911,11 +40786,11 @@ async function importShard(db, data, options) {
38911
40786
  }
38912
40787
  }
38913
40788
  }
38914
- const skipExisting = async (key2, sql, params) => {
40789
+ const skipExisting = async (key3, sql, params) => {
38915
40790
  if (strategy !== "skip") return false;
38916
40791
  const existing = await tx.query(sql, params);
38917
40792
  if (existing.rows.length === 0) return false;
38918
- skipped[key2] = (skipped[key2] ?? 0) + 1;
40793
+ skipped[key3] = (skipped[key3] ?? 0) + 1;
38919
40794
  return true;
38920
40795
  };
38921
40796
  const storePresence = async (component, recordId, record) => {
@@ -39839,8 +41714,8 @@ function slugifyServerEmbeddingSet(value) {
39839
41714
 
39840
41715
  // src/shard/full-v1-store.ts
39841
41716
  init_geometry_buffer();
39842
- var decoder4 = new TextDecoder();
39843
- var encoder4 = new TextEncoder();
41717
+ var decoder6 = new TextDecoder();
41718
+ var encoder6 = new TextEncoder();
39844
41719
  function emptyCounts3() {
39845
41720
  return {
39846
41721
  notes: 0,
@@ -39894,12 +41769,12 @@ function componentRecords(component, bytes) {
39894
41769
  function canonicalJson4(value) {
39895
41770
  if (Array.isArray(value)) return `[${value.map(canonicalJson4).join(",")}]`;
39896
41771
  if (value && typeof value === "object") {
39897
- return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key2, item]) => `${JSON.stringify(key2)}:${canonicalJson4(item)}`).join(",")}}`;
41772
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key3, item]) => `${JSON.stringify(key3)}:${canonicalJson4(item)}`).join(",")}}`;
39898
41773
  }
39899
41774
  return JSON.stringify(value);
39900
41775
  }
39901
41776
  function encodeComponentRecords(component, records) {
39902
- return encoder4.encode(FULL_V1_COMPONENT_FILES[component].encoding === "json-array" ? JSON.stringify(records) : records.map((record) => JSON.stringify(record)).join("\n"));
41777
+ return encoder6.encode(FULL_V1_COMPONENT_FILES[component].encoding === "json-array" ? JSON.stringify(records) : records.map((record) => JSON.stringify(record)).join("\n"));
39903
41778
  }
39904
41779
  function attachmentBlobReferences(files) {
39905
41780
  const refs = /* @__PURE__ */ new Map();
@@ -39936,7 +41811,7 @@ async function importFullV1Snapshot(db, data, options) {
39936
41811
  files = unpackTarGz(bytes);
39937
41812
  const manifestBytes = files.get("manifest.json");
39938
41813
  if (!manifestBytes) throw new Error("Missing manifest");
39939
- const parsed2 = JSON.parse(decoder4.decode(manifestBytes));
41814
+ const parsed2 = JSON.parse(decoder6.decode(manifestBytes));
39940
41815
  if (!parsed2 || typeof parsed2 !== "object" || Array.isArray(parsed2)) {
39941
41816
  throw new Error("Manifest is not an object");
39942
41817
  }
@@ -40190,7 +42065,7 @@ async function exportFullV1Snapshot(db, blobStore) {
40190
42065
  name: "fortemi-react-full-v1-store",
40191
42066
  version: manifest.producer?.version ?? "unknown"
40192
42067
  };
40193
- files.set("manifest.json", encoder4.encode(JSON.stringify(manifest, null, 2)));
42068
+ files.set("manifest.json", encoder6.encode(JSON.stringify(manifest, null, 2)));
40194
42069
  files.delete("signature.json");
40195
42070
  blobRefs = attachmentBlobReferences(files);
40196
42071
  } else {
@@ -40217,7 +42092,7 @@ async function exportFullV1Snapshot(db, blobStore) {
40217
42092
 
40218
42093
  // src/shard/shard-reader.ts
40219
42094
  init_geometry_buffer();
40220
- var decoder5 = new TextDecoder();
42095
+ var decoder7 = new TextDecoder();
40221
42096
  function assertSafeComponentName(filename) {
40222
42097
  if (filename.length === 0 || filename.startsWith("/") || filename.includes("\\") || filename.includes("\0") || filename.includes(":") || filename.split("/").some((segment) => segment === "..")) {
40223
42098
  throw new Error(`Refusing to read unsafe shard component path: ${JSON.stringify(filename)}`);
@@ -40319,7 +42194,7 @@ async function resolveStore(source, maxComponentBytes) {
40319
42194
  const files = unpackTarGz(bytes);
40320
42195
  const manifestBytes = files.get("manifest.json");
40321
42196
  if (!manifestBytes) throw new Error("Missing manifest.json in shard archive");
40322
- const manifest = JSON.parse(decoder5.decode(manifestBytes));
42197
+ const manifest = JSON.parse(decoder7.decode(manifestBytes));
40323
42198
  return new PackedComponentStore(files, manifest);
40324
42199
  }
40325
42200
  function tokenize(query) {
@@ -40456,14 +42331,14 @@ var ShardReaderImpl = class {
40456
42331
  weights: { ...DEFAULT_WEIGHTS, ...options.weights }
40457
42332
  });
40458
42333
  }
40459
- cacheMatches(key2, notes) {
40460
- this.matchCache.delete(key2);
40461
- this.matchCache.set(key2, notes);
42334
+ cacheMatches(key3, notes) {
42335
+ this.matchCache.delete(key3);
42336
+ this.matchCache.set(key3, notes);
40462
42337
  let total = 0;
40463
42338
  for (const set of this.matchCache.values()) total += set.length;
40464
42339
  while (total > this.maxCachedMatches && this.matchCache.size > 1) {
40465
42340
  const oldest = this.matchCache.keys().next().value;
40466
- if (oldest === void 0 || oldest === key2) break;
42341
+ if (oldest === void 0 || oldest === key3) break;
40467
42342
  total -= this.matchCache.get(oldest)?.length ?? 0;
40468
42343
  this.matchCache.delete(oldest);
40469
42344
  }
@@ -40473,12 +42348,12 @@ var ShardReaderImpl = class {
40473
42348
  const weights = { ...DEFAULT_WEIGHTS, ...options.weights };
40474
42349
  const offset = options.offset ?? 0;
40475
42350
  const limit = options.limit ?? Number.MAX_SAFE_INTEGER;
40476
- const key2 = this.matchKey(query, options);
40477
- let matched = this.matchCache.get(key2);
42351
+ const key3 = this.matchKey(query, options);
42352
+ let matched = this.matchCache.get(key3);
40478
42353
  let fetchedClusters = 0;
40479
42354
  if (matched) {
40480
- this.matchCache.delete(key2);
40481
- this.matchCache.set(key2, matched);
42355
+ this.matchCache.delete(key3);
42356
+ this.matchCache.set(key3, matched);
40482
42357
  } else {
40483
42358
  const { notes, fetched } = await this.loadAllNotes();
40484
42359
  fetchedClusters = fetched;
@@ -40486,7 +42361,7 @@ var ShardReaderImpl = class {
40486
42361
  if (tokens.length > 0 && options.rank !== false) {
40487
42362
  matched = [...matched].sort((a, b) => rankNote(b, tokens, weights) - rankNote(a, tokens, weights));
40488
42363
  }
40489
- this.cacheMatches(key2, matched);
42364
+ this.cacheMatches(key3, matched);
40490
42365
  }
40491
42366
  const page = matched.slice(offset, offset + limit);
40492
42367
  const result = {
@@ -40605,7 +42480,7 @@ async function openShard(source, options = {}) {
40605
42480
 
40606
42481
  // src/shard/semantic-providers.ts
40607
42482
  init_geometry_buffer();
40608
- var decoder6 = new TextDecoder();
42483
+ var decoder8 = new TextDecoder();
40609
42484
  function cosine(a, b) {
40610
42485
  let dot = 0;
40611
42486
  let normA = 0;
@@ -40629,7 +42504,7 @@ function createCosineSemanticProvider(options) {
40629
42504
  vectors = [];
40630
42505
  return;
40631
42506
  }
40632
- vectors = decoder6.decode(bytes).split("\n").filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
42507
+ vectors = decoder8.decode(bytes).split("\n").filter((line) => line.trim().length > 0).map((line) => JSON.parse(line));
40633
42508
  },
40634
42509
  async search(query, k) {
40635
42510
  const queryVector = await options.embedQuery(query);
@@ -42165,14 +44040,14 @@ function matchSetCacheKey(q, options) {
42165
44040
  weights: { ...DEFAULT_QUERY_WEIGHTS, ...options.weights }
42166
44041
  });
42167
44042
  }
42168
- function cacheMatchEntries(runtime, key2, entries) {
42169
- runtime.matchCache.delete(key2);
42170
- runtime.matchCache.set(key2, entries);
44043
+ function cacheMatchEntries(runtime, key3, entries) {
44044
+ runtime.matchCache.delete(key3);
44045
+ runtime.matchCache.set(key3, entries);
42171
44046
  let total = 0;
42172
44047
  for (const set of runtime.matchCache.values()) total += set.length;
42173
44048
  while (total > runtime.maxCachedMatches && runtime.matchCache.size > 1) {
42174
44049
  const oldest = runtime.matchCache.keys().next().value;
42175
- if (oldest === void 0 || oldest === key2) break;
44050
+ if (oldest === void 0 || oldest === key3) break;
42176
44051
  total -= runtime.matchCache.get(oldest)?.length ?? 0;
42177
44052
  runtime.matchCache.delete(oldest);
42178
44053
  }
@@ -42185,15 +44060,15 @@ function getPartsForRange(manifest, offset, limit) {
42185
44060
  return manifest.parts.filter((part) => part.count > 0 && part.offset < end && part.offset + part.count > offset);
42186
44061
  }
42187
44062
  async function loadChunkPart(runtime, part) {
42188
- const key2 = chunkPartCacheKey(part);
42189
- const cached = runtime.partCache.get(key2);
44063
+ const key3 = chunkPartCacheKey(part);
44064
+ const cached = runtime.partCache.get(key3);
42190
44065
  if (cached) {
42191
- runtime.partCache.delete(key2);
42192
- runtime.partCache.set(key2, cached);
44066
+ runtime.partCache.delete(key3);
44067
+ runtime.partCache.set(key3, cached);
42193
44068
  return { part: cached, fetched: false };
42194
44069
  }
42195
44070
  const parsed = assertAiwgFortemiChunkPart(await runtime.loader(part, runtime.manifest), part, runtime.manifest);
42196
- runtime.partCache.set(key2, parsed);
44071
+ runtime.partCache.set(key3, parsed);
42197
44072
  while (runtime.partCache.size > runtime.maxCachedParts) {
42198
44073
  const oldest = runtime.partCache.keys().next().value;
42199
44074
  if (oldest === void 0) break;
@@ -42618,10 +44493,10 @@ function aiwgFortemiIndexToCommunityGraph(index, options = {}) {
42618
44493
  const kind = relationship.type;
42619
44494
  const configuredWeight = Object.prototype.hasOwnProperty.call(relationshipWeights, kind) ? relationshipWeights[kind] : void 0;
42620
44495
  const baseWeight = typeof configuredWeight === "number" && Number.isFinite(configuredWeight) ? configuredWeight : 1;
42621
- const key2 = `${item.id}\0${relationship.target_id}\0${kind}`;
42622
- const existing = edgeCounts.get(key2);
44496
+ const key3 = `${item.id}\0${relationship.target_id}\0${kind}`;
44497
+ const existing = edgeCounts.get(key3);
42623
44498
  if (existing) existing.weight += baseWeight;
42624
- else edgeCounts.set(key2, { source: item.id, target: relationship.target_id, kind, weight: baseWeight });
44499
+ else edgeCounts.set(key3, { source: item.id, target: relationship.target_id, kind, weight: baseWeight });
42625
44500
  }
42626
44501
  }
42627
44502
  const communities = /* @__PURE__ */ new Map();
@@ -43361,7 +45236,7 @@ function getAiwgFortemiIndexExportSchema() {
43361
45236
  }
43362
45237
  function getAjv() {
43363
45238
  if (!ajvInstance) {
43364
- ajvInstance = new Ajv20202({
45239
+ ajvInstance = new Ajv20206({
43365
45240
  allErrors: true,
43366
45241
  strict: false,
43367
45242
  validateFormats: false
@@ -43406,7 +45281,7 @@ function getProjectedRecordValidator() {
43406
45281
  return projectedRecordValidator;
43407
45282
  }
43408
45283
  function validateAiwgFortemiIndexExportSchema(value) {
43409
- const validate3 = getExportValidator();
45284
+ const validate4 = getExportValidator();
43410
45285
  const schemaValue = value && typeof value === "object" && Array.isArray(value.items) ? {
43411
45286
  ...value,
43412
45287
  items: value.items.map((item) => {
@@ -43416,18 +45291,18 @@ function validateAiwgFortemiIndexExportSchema(value) {
43416
45291
  return schemaRecord;
43417
45292
  })
43418
45293
  } : value;
43419
- const valid = validate3(schemaValue);
43420
- return { valid, errors: formatErrors2(validate3.errors) };
45294
+ const valid = validate4(schemaValue);
45295
+ return { valid, errors: formatErrors2(validate4.errors) };
43421
45296
  }
43422
45297
  function validateAiwgFortemiProjectedRecordSchema(value) {
43423
- const validate3 = getProjectedRecordValidator();
43424
- const valid = validate3(value);
43425
- return { valid, errors: formatErrors2(validate3.errors) };
45298
+ const validate4 = getProjectedRecordValidator();
45299
+ const valid = validate4(value);
45300
+ return { valid, errors: formatErrors2(validate4.errors) };
43426
45301
  }
43427
45302
 
43428
45303
  // src/aiwg-index-full-shard.ts
43429
45304
  init_geometry_buffer();
43430
- var encoder5 = new TextEncoder();
45305
+ var encoder7 = new TextEncoder();
43431
45306
  var UUID_NAMESPACE = "7ab5d1f8-29d2-5e35-9e2f-3a45de171a9e";
43432
45307
  function uuid5(kind, id) {
43433
45308
  return v5(`${kind}:${id}`, UUID_NAMESPACE);
@@ -43435,7 +45310,7 @@ function uuid5(kind, id) {
43435
45310
  function own(value, field) {
43436
45311
  return Object.prototype.hasOwnProperty.call(value, field);
43437
45312
  }
43438
- function timestamp2(value) {
45313
+ function timestamp3(value) {
43439
45314
  if (!value || Number.isNaN(Date.parse(value))) return void 0;
43440
45315
  return new Date(value).toISOString();
43441
45316
  }
@@ -43443,7 +45318,7 @@ function addLoss(losses, code, message, details = {}) {
43443
45318
  losses.push({ code, message, ...details });
43444
45319
  }
43445
45320
  function encode(values, encoding) {
43446
- return encoder5.encode(encoding === "json-array" ? JSON.stringify(values) : values.map((value) => JSON.stringify(value)).join("\n"));
45321
+ return encoder7.encode(encoding === "json-array" ? JSON.stringify(values) : values.map((value) => JSON.stringify(value)).join("\n"));
43447
45322
  }
43448
45323
  function noteTitle(record, losses) {
43449
45324
  if (own(record, "title")) return record.title ?? null;
@@ -43508,7 +45383,7 @@ function noteContent(record, losses) {
43508
45383
  return "";
43509
45384
  }
43510
45385
  function createdAt(record, losses) {
43511
- const source = timestamp2(record.source.updated_at);
45386
+ const source = timestamp3(record.source.updated_at);
43512
45387
  if (source) return source;
43513
45388
  addLoss(
43514
45389
  losses,
@@ -43538,7 +45413,7 @@ function schemeName(concept) {
43538
45413
  }
43539
45414
  async function convertAiwgIndexToFullV1(index, options = {}) {
43540
45415
  const losses = [];
43541
- const exportedAt = timestamp2(options.createdAt) ?? new Date(index.generated_at).toISOString();
45416
+ const exportedAt = timestamp3(options.createdAt) ?? new Date(index.generated_at).toISOString();
43542
45417
  const records = [...index.items].sort((a, b) => a.id.localeCompare(b.id));
43543
45418
  const noteIds = new Map(records.map((record) => [record.id, uuid5("record", record.id)]));
43544
45419
  const rows = /* @__PURE__ */ new Map();
@@ -43611,7 +45486,7 @@ async function convertAiwgIndexToFullV1(index, options = {}) {
43611
45486
  tags: recordTags,
43612
45487
  attachments: []
43613
45488
  });
43614
- const hash = await sha256Hex(encoder5.encode(content));
45489
+ const hash = await sha256Hex(encoder7.encode(content));
43615
45490
  rows.get("note_originals").push({
43616
45491
  id: uuid5("note-original", record.id),
43617
45492
  note_id: noteId,
@@ -43633,9 +45508,9 @@ async function convertAiwgIndexToFullV1(index, options = {}) {
43633
45508
  for (const record of records) {
43634
45509
  for (const [position, relationship] of record.relationships.entries()) {
43635
45510
  const target = noteIds.get(relationship.target_id) ?? null;
43636
- const key2 = `${record.id}\0${position}\0${relationship.type}\0${relationship.target_id}`;
45511
+ const key3 = `${record.id}\0${position}\0${relationship.type}\0${relationship.target_id}`;
43637
45512
  rows.get("links").push({
43638
- id: uuid5("relationship", key2),
45513
+ id: uuid5("relationship", key3),
43639
45514
  from_note_id: noteIds.get(record.id),
43640
45515
  to_note_id: target,
43641
45516
  to_url: target ? null : `aiwg://record/${encodeURIComponent(relationship.target_id)}`,
@@ -43703,7 +45578,7 @@ async function convertAiwgIndexToFullV1(index, options = {}) {
43703
45578
  metric: null,
43704
45579
  algorithm: null,
43705
45580
  parameters: null,
43706
- input_hash: `sha256:${await sha256Hex(encoder5.encode(JSON.stringify(relationshipInput)))}`,
45581
+ input_hash: `sha256:${await sha256Hex(encoder7.encode(JSON.stringify(relationshipInput)))}`,
43707
45582
  freshness: { status: "fresh", checked_at: exportedAt },
43708
45583
  created_at: exportedAt
43709
45584
  });
@@ -43792,7 +45667,7 @@ async function convertAiwgIndexToFullV1(index, options = {}) {
43792
45667
  action: "omit"
43793
45668
  }
43794
45669
  );
43795
- const unmappedConceptMetadata = Object.keys(concept.metadata ?? {}).filter((key2) => key2 !== "domain");
45670
+ const unmappedConceptMetadata = Object.keys(concept.metadata ?? {}).filter((key3) => key3 !== "domain");
43796
45671
  if (unmappedConceptMetadata.length > 0) addLoss(
43797
45672
  losses,
43798
45673
  "aiwg-skos-metadata-unmapped",
@@ -43935,7 +45810,7 @@ async function convertAiwgIndexToFullV1(index, options = {}) {
43935
45810
  }
43936
45811
  for (const record of records) {
43937
45812
  for (const [position, event] of (record.provenance_events ?? []).entries()) {
43938
- const start = timestamp2(event.started_at);
45813
+ const start = timestamp3(event.started_at);
43939
45814
  if (!start) addLoss(
43940
45815
  losses,
43941
45816
  "aiwg-provenance-start-unavailable",
@@ -43955,7 +45830,7 @@ async function convertAiwgIndexToFullV1(index, options = {}) {
43955
45830
  activity_type: event.activity,
43956
45831
  model_name: event.agent ?? null,
43957
45832
  started_at: start ?? new Date(record.updated_at).toISOString(),
43958
- ended_at: timestamp2(event.ended_at) ?? null,
45833
+ ended_at: timestamp3(event.ended_at) ?? null,
43959
45834
  metadata: {
43960
45835
  source: event.source ?? null,
43961
45836
  path: event.path ?? null,
@@ -44161,7 +46036,7 @@ async function convertAiwgIndexToFullV1(index, options = {}) {
44161
46036
  checksums,
44162
46037
  min_reader_version: "2.0.0"
44163
46038
  };
44164
- const manifestBytes = encoder5.encode(JSON.stringify(manifest, null, 2));
46039
+ const manifestBytes = encoder7.encode(JSON.stringify(manifest, null, 2));
44165
46040
  files.set("manifest.json", manifestBytes);
44166
46041
  const validation = await validateFullV1ShardArchive(files);
44167
46042
  if (!validation.valid) {
@@ -44441,7 +46316,7 @@ var RECORD_STORE_CAPABILITIES = {
44441
46316
  sourceAddressedUpsert: true,
44442
46317
  deletionReceipts: true,
44443
46318
  typedMetadataPredicates: false,
44444
- evidenceLocators: true,
46319
+ evidenceLocators: false,
44445
46320
  fullTextSearch: false,
44446
46321
  vectorSearch: false,
44447
46322
  sqlJoins: false
@@ -44828,7 +46703,7 @@ var CanonicalNotesRepository = class {
44828
46703
  * Bounded substring scan over title + revised content (case-insensitive).
44829
46704
  * This is deliberately not ranked FTS — see `store.capabilities`.
44830
46705
  */
44831
- async searchText(query, limit = 20) {
46706
+ async searchText(query, limit = 20, accept) {
44832
46707
  const needle = query.toLowerCase();
44833
46708
  const revised = new Map(
44834
46709
  (await this.store.list("note_revised_current")).map((r) => [r.id, r.content])
@@ -44836,6 +46711,7 @@ var CanonicalNotesRepository = class {
44836
46711
  const hits = [];
44837
46712
  for (const note of await this.store.list("note")) {
44838
46713
  if (note.deleted_at !== null) continue;
46714
+ if (accept && !accept(note)) continue;
44839
46715
  const haystack = `${note.title ?? ""}
44840
46716
  ${revised.get(note.id) ?? ""}`.toLowerCase();
44841
46717
  if (haystack.includes(needle)) {
@@ -45351,6 +47227,8 @@ function createRecordBackend(store, options = {}) {
45351
47227
  // via importShardToRecords (record-shard.ts)
45352
47228
  multiUser: false,
45353
47229
  semantic: "none",
47230
+ typedMetadataPredicates: false,
47231
+ evidenceLocators: false,
45354
47232
  startupCost: "instant"
45355
47233
  },
45356
47234
  async listNotes(o) {
@@ -45370,17 +47248,11 @@ function createRecordBackend(store, options = {}) {
45370
47248
  return noteToBackend(view.note, view.tags);
45371
47249
  },
45372
47250
  async search(query, o) {
47251
+ validateBackendSearchOptions(o, { metadata: false, scope: false, modes: ["fts"] });
45373
47252
  const offset = o?.offset ?? 0;
45374
47253
  const limit = o?.limit ?? 20;
45375
- let matched = await notes.searchText(query, offset + limit);
45376
- if (o?.tags?.length) {
45377
- const tags2 = await tagsByNote();
45378
- matched = matched.filter((n) => o.tags.every((t) => (tags2.get(n.id) ?? []).includes(t)));
45379
- }
45380
- if (o?.source?.length) {
45381
- matched = matched.filter((n) => o.source.includes(n.source));
45382
- }
45383
47254
  const tags = await tagsByNote();
47255
+ const matched = await notes.searchText(query, offset + limit, (n) => (!o?.tags?.length || o.tags.every((t) => (tags.get(n.id) ?? []).includes(t))) && (!o?.source?.length || o.source.includes(n.source)));
45384
47256
  const hits = matched.slice(offset, offset + limit).map((n) => ({ note: noteToBackend(n, tags.get(n.id) ?? []) }));
45385
47257
  return { hits, total: matched.length };
45386
47258
  },
@@ -45438,8 +47310,8 @@ function createRecordBackend(store, options = {}) {
45438
47310
 
45439
47311
  // src/records/record-shard.ts
45440
47312
  init_geometry_buffer();
45441
- var encoder6 = new TextEncoder();
45442
- var decoder7 = new TextDecoder();
47313
+ var encoder8 = new TextEncoder();
47314
+ var decoder9 = new TextDecoder();
45443
47315
  function emptyCounts4() {
45444
47316
  return {
45445
47317
  notes: 0,
@@ -45696,11 +47568,11 @@ async function buildRecordShardArchive(store, options, profile) {
45696
47568
  const slice = shardNotes.slice(offset, offset + clusterSize);
45697
47569
  const href = `notes/${String(offset).padStart(6, "0")}.jsonl`;
45698
47570
  clusters.push({ href, offset });
45699
- files.set(href, encoder6.encode(slice.map((n) => JSON.stringify(n)).join("\n")));
47571
+ files.set(href, encoder8.encode(slice.map((n) => JSON.stringify(n)).join("\n")));
45700
47572
  }
45701
47573
  layout = { clusters: { notes: clusters } };
45702
47574
  } else {
45703
- files.set("notes.jsonl", encoder6.encode(shardNotes.map((n) => JSON.stringify(n)).join("\n")));
47575
+ files.set("notes.jsonl", encoder8.encode(shardNotes.map((n) => JSON.stringify(n)).join("\n")));
45704
47576
  }
45705
47577
  components4.push("notes");
45706
47578
  counts.notes = shardNotes.length;
@@ -45728,7 +47600,7 @@ async function buildRecordShardArchive(store, options, profile) {
45728
47600
  note_count: mapped.note_count ?? 0
45729
47601
  };
45730
47602
  });
45731
- files.set("collections.json", encoder6.encode(JSON.stringify(shardCollections)));
47603
+ files.set("collections.json", encoder8.encode(JSON.stringify(shardCollections)));
45732
47604
  components4.push("collections");
45733
47605
  counts.collections = shardCollections.length;
45734
47606
  const distinctTags = [...new Set(
@@ -45745,7 +47617,7 @@ async function buildRecordShardArchive(store, options, profile) {
45745
47617
  created_at: tagCreatedAt.get(name) ?? (/* @__PURE__ */ new Date(0)).toISOString()
45746
47618
  }))
45747
47619
  );
45748
- files.set("tags.json", encoder6.encode(JSON.stringify(shardTags)));
47620
+ files.set("tags.json", encoder8.encode(JSON.stringify(shardTags)));
45749
47621
  components4.push("tags");
45750
47622
  counts.tags = shardTags.length;
45751
47623
  const links = await store.list("link");
@@ -45767,7 +47639,7 @@ async function buildRecordShardArchive(store, options, profile) {
45767
47639
  }
45768
47640
  return shard;
45769
47641
  });
45770
- files.set("links.jsonl", encoder6.encode(shardLinks.map((l) => JSON.stringify(l)).join("\n")));
47642
+ files.set("links.jsonl", encoder8.encode(shardLinks.map((l) => JSON.stringify(l)).join("\n")));
45771
47643
  components4.push("links");
45772
47644
  counts.links = shardLinks.length;
45773
47645
  const checksums = {};
@@ -45897,7 +47769,7 @@ async function buildRecordShardArchive(store, options, profile) {
45897
47769
  );
45898
47770
  }
45899
47771
  }
45900
- files.set("manifest.json", encoder6.encode(JSON.stringify(manifest, null, 2)));
47772
+ files.set("manifest.json", encoder8.encode(JSON.stringify(manifest, null, 2)));
45901
47773
  if (options?.includeBlobs && options.blobStore) {
45902
47774
  const packed = /* @__PURE__ */ new Set();
45903
47775
  for (const checksum of exportedBlobChecksums) {
@@ -45977,7 +47849,7 @@ async function importShardToRecords(store, data, options) {
45977
47849
  }
45978
47850
  let manifest;
45979
47851
  try {
45980
- manifest = JSON.parse(decoder7.decode(manifestData));
47852
+ manifest = JSON.parse(decoder9.decode(manifestData));
45981
47853
  if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
45982
47854
  throw new Error("manifest must be a JSON object");
45983
47855
  }
@@ -46114,8 +47986,8 @@ async function importShardToRecords(store, data, options) {
46114
47986
  for (const component of manifest.components ?? []) {
46115
47987
  if (UNSUPPORTED_COMPONENTS.includes(component)) {
46116
47988
  const count2 = manifest.counts?.[component];
46117
- const key2 = component === "communities" ? "communities" : component;
46118
- skipped[key2] = (skipped[key2] ?? 0) + (typeof count2 === "number" ? count2 : 0);
47989
+ const key3 = component === "communities" ? "communities" : component;
47990
+ skipped[key3] = (skipped[key3] ?? 0) + (typeof count2 === "number" ? count2 : 0);
46119
47991
  warnings.push(
46120
47992
  `Shard component '${component}' is not supported by the canonical record tier and was skipped. Import into a PGlite-backed store to preserve it.`
46121
47993
  );
@@ -46283,7 +48155,7 @@ async function importShardToRecords(store, data, options) {
46283
48155
  id: existingOriginal?.id ?? generateId(),
46284
48156
  note_id: note.id,
46285
48157
  content: note.original_content,
46286
- content_hash: computeHash(encoder6.encode(note.original_content)),
48158
+ content_hash: computeHash(encoder8.encode(note.original_content)),
46287
48159
  created_at: createdAt2
46288
48160
  };
46289
48161
  mutations.push({ op: "put", collection: "note_original", record: originalRecord });
@@ -46590,7 +48462,7 @@ async function upsertRecordStoreSources(store, items, options = {}) {
46590
48462
  const requestDigest = sourceRequestDigest(items, options);
46591
48463
  const batchId = options.batchId ?? deriveSourceBatchId(requestDigest);
46592
48464
  const batchReason = batchId.length === 0 || batchId.length > 200 ? "invalid_batch_metadata" : JSON.stringify(options.checkpoint ?? {}).length > 65536 ? "checkpoint_too_large" : void 0;
46593
- const validation = validate2(items, options.maxItems ?? 500, batchReason);
48465
+ const validation = validate3(items, options.maxItems ?? 500, batchReason);
46594
48466
  if (validation) return finish2(importRunId, batchId, options.dryRun === true, "rejected", validation, options.checkpoint);
46595
48467
  const batches = await store.list("source_import_batch");
46596
48468
  const prior = batches.find((batch2) => batch2.tenant_id === (items[0].source.tenant_id ?? "default") && batch2.archive_id === (items[0].source.archive_id ?? null) && batch2.namespace === items[0].source.namespace && batch2.batch_id === batchId);
@@ -46774,7 +48646,7 @@ function addUpdateMutations(mutations, item, identity, note, current, original,
46774
48646
  mutations.push({ op: "put", collection: "note_revision", record: revision });
46775
48647
  }
46776
48648
  }
46777
- function validate2(items, maxItems, initialReason) {
48649
+ function validate3(items, maxItems, initialReason) {
46778
48650
  let reason = initialReason ?? (items.length === 0 || items.length > maxItems ? "batch_size_out_of_bounds" : null);
46779
48651
  const seen = /* @__PURE__ */ new Set();
46780
48652
  const stableIds = /* @__PURE__ */ new Set();
@@ -46783,9 +48655,9 @@ function validate2(items, maxItems, initialReason) {
46783
48655
  if ((item.source.source_id?.length ?? 0) > 500 || item.source.source_id === "" || (item.source.workspace_id?.length ?? 0) > 500 || item.source.workspace_id === "") reason ??= "invalid_batch_metadata";
46784
48656
  if ((item.format ?? "markdown").length > 100 || (item.title?.length ?? 0) > 2e3 || JSON.stringify(item.metadata ?? {}).length > 262144) reason ??= "invalid_item";
46785
48657
  if (item.content_digest && item.content_digest !== sourceContentDigest(item.content)) reason ??= "content_digest_mismatch";
46786
- const key2 = `${item.source.tenant_id}\0${item.source.archive_id ?? ""}\0${item.source.namespace}\0${item.source.external_id}`;
46787
- if (seen.has(key2)) reason ??= "duplicate_external_id_in_batch";
46788
- seen.add(key2);
48658
+ const key3 = `${item.source.tenant_id}\0${item.source.archive_id ?? ""}\0${item.source.namespace}\0${item.source.external_id}`;
48659
+ if (seen.has(key3)) reason ??= "duplicate_external_id_in_batch";
48660
+ seen.add(key3);
46789
48661
  if (item.source.caller_stable_id && stableIds.has(item.source.caller_stable_id)) reason ??= "caller_stable_id_conflict";
46790
48662
  if (item.source.caller_stable_id) stableIds.add(item.source.caller_stable_id);
46791
48663
  }
@@ -46917,7 +48789,7 @@ async function purgeRecordStoreGraph(store, selector, operationKey) {
46917
48789
  }
46918
48790
 
46919
48791
  // src/index.ts
46920
- var VERSION = "2026.9.4";
48792
+ var VERSION = "2026.9.6";
46921
48793
  /*! Bundled license information:
46922
48794
 
46923
48795
  ieee754/index.js:
@@ -46932,6 +48804,6 @@ buffer/index.js:
46932
48804
  *)
46933
48805
  */
46934
48806
 
46935
- export { AIWG_SCAN_REQUIRED_FIELDS, AllowlistTrustStore, ArchiveManager, AttachmentsRepository, BridgeInferenceProvider, CORE_V1_COMPONENTS, CURRENT_MIGRATION_HEAD, CURRENT_SHARD_VERSION, CanonicalAttachmentsRepository, CanonicalNotesRepository, CapabilityManager, CaptureKnowledgeInputSchema, CollectionsRepository, CommunitiesRepository, DATASET_EXECUTION_CAPABILITY_IDS, DATASET_EXECUTION_CONTRACT, DATASET_EXECUTION_SCHEMA_VERSION, DATASET_INGEST_CONTRACT, DATASET_INGEST_SCHEMA_VERSION, DATASET_LINEAGE_CONTRACT, DATASET_LINEAGE_SCHEMA_VERSION, DATASET_MATERIALIZATION_CONTRACT, DATASET_MATERIALIZATION_KINDS, DATASET_MATERIALIZATION_SCHEMA_VERSION, DB_SNAPSHOT_SCHEMA_VERSION, DEFAULT_LARGE_DOCUMENT_CHARS, DEFAULT_LARGE_DOCUMENT_CHUNKS, DatasetIngestError, DatasetIngestExecutor, DatasetLineageLedger, DatasetMaterializationError, DbSnapshotVersionError, EMBED_REQUEST_KIND, EMBED_RESPONSE_KIND, EmbeddingSetsRepository, FORTEMI_BROWSER_LOCAL_DATASET_EXECUTION_DESCRIPTOR, FORTEMI_COMPATIBILITY_PATH, FORTEMI_COMPATIBILITY_STATES, FORTEMI_PORTABLE_SHARD_DATASET_EXECUTION_DESCRIPTOR, FORTEMI_REQUIRED_COMPATIBILITY_CAPABILITIES, FORTEMI_SERVER_COMPATIBILITY_REVISION, FORTEMI_STATIC_CACHE_DATASET_EXECUTION_DESCRIPTOR, FallbackRouter, FortemiToolManifest, GetNoteInputSchema, GraphRepository, IdbRecordStore, JOB_CAPABILITIES, JOB_PRIORITIES, JobQueueWorker, LINEAGE_ENTITY_KINDS, LINEAGE_RELATIONSHIP_KINDS, LOCAL_ENDPOINTS, LifecyclePurgeRepository, LineageValidationError, LinksRepository, ListNotesInputSchema, ManageArchiveInputSchema, ManageAttachmentsInputSchema, ManageCapabilitiesInputSchema, ManageCollectionsInputSchema, ManageLinksInputSchema, ManageNoteInputSchema, ManageTagsInputSchema, MemoryBlobStore, MemoryDatasetIngestStore, MemoryRecordStore, MigrationRunner, NotesRepository, OpenAICompatibleProvider, PGliteStorageBackend, PGliteStorageBackendFactory, PGliteWorkerClient, PGliteWorkerStorageBackend, PGliteWorkerStorageBackendFactory, ProvenanceRepository, ProviderRegistry, RECORD_COLLECTIONS, RECORD_SCHEMA_VERSION, RECORD_STORE_CAPABILITIES, REGISTERED_METADATA_PATHS, RemoteBackendError, SHARD_FORMAT, SIGNATURE_ENTRY, SIGNING_ENVELOPE_VERSION, SOURCE_UPSERT_CONTRACT_VERSION, SOURCE_UPSERT_MAX_ITEMS, SUPPORTED_PGLITE_VERSION, SearchInputSchema, SearchRepository, SkosRepository, SourceUpsertRepository, TagsRepository, TemplatesRepository, TransactionProxy, TypedEventBus, VERSION, aiRevisionHandler, aiwgFortemiIndexFromKnowledgeShard, aiwgFortemiIndexToCommunityGraph, aiwgFortemiIndexToKnowledgeShard, aiwgFortemiIndexToKnowledgeShardWithReport, allMigrations, appendPluginScript, assertAiwgFortemiChunkManifest, assertAiwgFortemiChunkPart, assertAiwgFortemiIndexExport, assertAiwgStaticEmbeddingSet, assertShardComponentRecord, buildAiwgChunkedIndex, buildAiwgStaticEmbeddingSet, buildMetadataPredicateConditions, buildNoteConditions, buildPluginCsp, captureKnowledge, chunkText, classifyError, classifyModel, clearPrefetchedShard, collectionFromShard, collectionToShard, compareDatasetIncrementalParity, computeBlobHash, computeHash, computeLineageDigest, computeSri, conceptTaggingHandler, configureInferenceRuntime, cosineSimilarity, createAiwgFetchChunkLoader, createAiwgFetchDetailLoader, createAiwgIndexController, createAiwgReviewDecisionExport, createBlobStore, createBridgeInferenceProviders, createCosineSemanticProvider, createCspReportHandler, createFortemi, createLazyBlobStore, createLegacyProvider, createLocalProviderProfile, createPGliteBackend, createPGliteInstance, createRecordBackend, createRecordStore, createRemoteBackend, createRoutes, createShardBackend, createShardCapabilityReport, createWorkerEmbedFunction, datasetDestinationScopeKey, defaultStorageBackendFactory, defineInferenceProvider, defineInferenceRuntime, defineLegacyInferenceProvider, defineOpenAICompatibleProvider, deriveDatasetIngestIdempotencyKey, detectCommunities, detectGpuCapabilities, detectInferenceCapabilities, digestDatasetMaterializationValue, discoverLocalProviders, dropAttachmentProjection, dropNoteProjection, dumpDbSnapshot, embeddingConfigToShard, embeddingFromShard, embeddingGenerationHandler, embeddingSetFromShard, embeddingSetMemberToShard, embeddingSetToShard, embeddingToShard, enqueueFullWorkflow, enqueueJob, enqueueNoteCreationJobs, estimateModelFit, estimateVramMB, estimateVramTier, executeDatasetMaterialization, executeDatasetRetrieval, exportFullV1Snapshot, exportShard, exportShardFromRecords, exportShardFromRecordsWithReport, exportShardWithReport, fetchAndValidateFortemiCompatibility, fetchPluginScript, filterAiwgRecordsByPrivacy, findAiwgStaticDuplicatePairs, formatFortemiCompatibilitySummary, fortemiCompatibilityUrl, fortemiManifest, fromPrefetched, generateId, getAiwgFortemiFacets, getAiwgFortemiIndexExportSchema, getConfiguredInferenceProviderId, getEmbedFunction, getEmbeddingTaskSelectionOptions, getFortemiBridge, getFortemiSecretStore, getJobQueueStatus, getKnowledgeShardContractReceipt, getKnowledgeShardProfileRegistry, getKnowledgeShardSchema, getLlmFunction, getNote, getPrefetchedSha256, getProviderRouteRequirementIssue, handleEmbedRequests, hasFortemiSecureSecrets, importFullV1Snapshot, importShard, importShardToRecords, inferInferenceTaskCapability, inferLocalEmbeddingDimensions, isPluginScriptAllowed, isShardPrefetched, isShardSigningSupported, linkFromShard, linkToShard, linkingHandler, listNotes, manageArchive, manageAttachments, manageCapabilities, manageCollections, manageLinks, manageNote, manageTags, matchRoute, mergeInferenceRuntimeConfigs, migrateLegacyBlobStore, negotiateDatasetExecutionCapabilities, negotiateDatasetMaterializationProfile, noteFromShard, noteSkosTagToShard, noteToShard, openShard, packTarGz, parseCspReport, prefetchShard, previewRecordStorePurge, profileSupportError, projectAttachments, projectNotes, projectRecords, provenanceEdgeToShard, providerSatisfiesRouteRequirements, purgeRecordStoreGraph, queryAiwgFortemiIndex, queryAiwgHybridIndex, queryAiwgSemanticIndex, registerLlmCapability, registerSemanticCapability, registerSemanticCapabilityWorker, registerServiceWorker, restoreDbSnapshot, searchTool, selectBackend, selectEmbeddingTask, selectLlmModel, setEmbedFunction, setEmbeddingTaskSelectionOptions, setLlmFunction, sha256Hex, sidecarBlobDigests, signShard, skosConceptToShard, skosRelationToShard, skosSchemeToShard, suggestTags, tagsToShard, templateToShard, titleGenerationHandler, unpackTarGz, unregisterLlmCapability, unregisterSemanticCapability, upsertRecordStoreRequest, upsertRecordStoreSources, urlLinkToShard, validateAiwgFortemiChunkManifest, validateAiwgFortemiChunkPart, validateAiwgFortemiIndexExport, validateAiwgFortemiIndexExportSchema, validateAiwgFortemiProjectedRecordSchema, validateAiwgStaticEmbeddingSet, validateChecksums, validateCoreV1ShardArchive, validateDatasetBenchmarkEvidence, validateDatasetExecutionDescriptor, validateFortemiCompatibilityResponse, validateFullV1ShardArchive, validateProviderRoute, validateRecordV1ShardArchive, validateShardArchive, validateShardComponentRecord, validateShardManifest, verifyDbSnapshotMeta, verifyShardSignature, verifySri };
48807
+ export { AIWG_SCAN_REQUIRED_FIELDS, AllowlistTrustStore, ArchiveManager, AttachmentsRepository, BridgeInferenceProvider, CORE_V1_COMPONENTS, CURRENT_MIGRATION_HEAD, CURRENT_SHARD_VERSION, CanonicalAttachmentsRepository, CanonicalNotesRepository, CapabilityManager, CaptureKnowledgeInputSchema, CollectionsRepository, CommunitiesRepository, DATASET_EXECUTION_CAPABILITY_IDS, DATASET_EXECUTION_CONTRACT, DATASET_EXECUTION_SCHEMA_VERSION, DATASET_INGEST_CONTRACT, DATASET_INGEST_SCHEMA_VERSION, DATASET_LINEAGE_CONTRACT, DATASET_LINEAGE_SCHEMA_VERSION, DATASET_MATERIALIZATION_CONTRACT, DATASET_MATERIALIZATION_KINDS, DATASET_MATERIALIZATION_SCHEMA_VERSION, DB_SNAPSHOT_SCHEMA_VERSION, DEFAULT_LARGE_DOCUMENT_CHARS, DEFAULT_LARGE_DOCUMENT_CHUNKS, DatasetIngestError, DatasetIngestExecutor, DatasetLineageLedger, DatasetMaterializationError, DbSnapshotVersionError, EMBED_REQUEST_KIND, EMBED_RESPONSE_KIND, EmbeddingSetsRepository, FORTEMI_BROWSER_LOCAL_DATASET_EXECUTION_DESCRIPTOR, FORTEMI_COMPATIBILITY_PATH, FORTEMI_COMPATIBILITY_STATES, FORTEMI_PORTABLE_SHARD_DATASET_EXECUTION_DESCRIPTOR, FORTEMI_REQUIRED_COMPATIBILITY_CAPABILITIES, FORTEMI_SERVER_COMPATIBILITY_REVISION, FORTEMI_STATIC_CACHE_DATASET_EXECUTION_DESCRIPTOR, FallbackRouter, FortemiToolManifest, GetNoteInputSchema, GraphRepository, IdbRecordStore, JOB_CAPABILITIES, JOB_PRIORITIES, JobQueueWorker, LINEAGE_ENTITY_KINDS, LINEAGE_RELATIONSHIP_KINDS, LOCAL_ENDPOINTS, LifecyclePurgeRepository, LineageValidationError, LinksRepository, ListNotesInputSchema, ManageArchiveInputSchema, ManageAttachmentsInputSchema, ManageCapabilitiesInputSchema, ManageCollectionsInputSchema, ManageLinksInputSchema, ManageNoteInputSchema, ManageTagsInputSchema, MemoryBlobStore, MemoryDatasetIngestStore, MemoryRecordStore, MigrationRunner, NotesRepository, OpenAICompatibleProvider, PGliteStorageBackend, PGliteStorageBackendFactory, PGliteWorkerClient, PGliteWorkerStorageBackend, PGliteWorkerStorageBackendFactory, ProvenanceRepository, ProviderRegistry, RECORD_COLLECTIONS, RECORD_SCHEMA_VERSION, RECORD_STORE_CAPABILITIES, REGISTERED_METADATA_PATHS, RemoteBackendError, SHARD_FORMAT, SIGNATURE_ENTRY, SIGNING_ENVELOPE_VERSION, SOURCE_UPSERT_CONTRACT_VERSION, SOURCE_UPSERT_MAX_ITEMS, SUPPORTED_PGLITE_VERSION, SearchInputSchema, SearchRepository, SkosRepository, SourceUpsertRepository, TagsRepository, TemplatesRepository, TransactionProxy, TypedEventBus, VERSION, aiRevisionHandler, aiwgFortemiIndexFromKnowledgeShard, aiwgFortemiIndexToCommunityGraph, aiwgFortemiIndexToKnowledgeShard, aiwgFortemiIndexToKnowledgeShardWithReport, allMigrations, appendPluginScript, assertAiwgFortemiChunkManifest, assertAiwgFortemiChunkPart, assertAiwgFortemiIndexExport, assertAiwgStaticEmbeddingSet, assertShardComponentRecord, bindSearchEvidence, buildAiwgChunkedIndex, buildAiwgStaticEmbeddingSet, buildMetadataPredicateConditions, buildNoteConditions, buildPluginCsp, captureKnowledge, chunkText, classifyError, classifyModel, clearPrefetchedShard, collectionFromShard, collectionToShard, compareDatasetIncrementalParity, computeBlobHash, computeHash, computeLineageDigest, computeSri, conceptTaggingHandler, configureInferenceRuntime, cosineSimilarity, createAiwgFetchChunkLoader, createAiwgFetchDetailLoader, createAiwgIndexController, createAiwgReviewDecisionExport, createBlobStore, createBridgeInferenceProviders, createCosineSemanticProvider, createCspReportHandler, createFortemi, createLazyBlobStore, createLegacyProvider, createLocalProviderProfile, createPGliteBackend, createPGliteInstance, createRecordBackend, createRecordStore, createRemoteBackend, createRoutes, createSearchEvidenceSet, createShardBackend, createShardCapabilityReport, createWorkerEmbedFunction, datasetDestinationScopeKey, defaultStorageBackendFactory, defineInferenceProvider, defineInferenceRuntime, defineLegacyInferenceProvider, defineOpenAICompatibleProvider, deriveDatasetIngestIdempotencyKey, detectCommunities, detectGpuCapabilities, detectInferenceCapabilities, digestDatasetMaterializationValue, discoverLocalProviders, dropAttachmentProjection, dropNoteProjection, dumpDbSnapshot, embeddingConfigToShard, embeddingFromShard, embeddingGenerationHandler, embeddingSetFromShard, embeddingSetMemberToShard, embeddingSetToShard, embeddingToShard, enqueueFullWorkflow, enqueueJob, enqueueNoteCreationJobs, estimateModelFit, estimateVramMB, estimateVramTier, executeDatasetMaterialization, executeDatasetRetrieval, exportFullV1Snapshot, exportShard, exportShardFromRecords, exportShardFromRecordsWithReport, exportShardWithReport, fetchAndValidateFortemiCompatibility, fetchPluginScript, filterAiwgRecordsByPrivacy, findAiwgStaticDuplicatePairs, formatFortemiCompatibilitySummary, fortemiCompatibilityUrl, fortemiManifest, fromPrefetched, generateId, getAiwgFortemiFacets, getAiwgFortemiIndexExportSchema, getConfiguredInferenceProviderId, getEmbedFunction, getEmbeddingTaskSelectionOptions, getFortemiBridge, getFortemiSecretStore, getJobQueueStatus, getKnowledgeShardContractReceipt, getKnowledgeShardProfileRegistry, getKnowledgeShardSchema, getLlmFunction, getNote, getPrefetchedSha256, getProviderRouteRequirementIssue, handleEmbedRequests, hasFortemiSecureSecrets, importFullV1Snapshot, importShard, importShardToRecords, inferInferenceTaskCapability, inferLocalEmbeddingDimensions, isPluginScriptAllowed, isShardPrefetched, isShardSigningSupported, linkFromShard, linkToShard, linkingHandler, listNotes, manageArchive, manageAttachments, manageCapabilities, manageCollections, manageLinks, manageNote, manageTags, matchRoute, mergeInferenceRuntimeConfigs, mergeSearchEvidenceSets, migrateLegacyBlobStore, negotiateDatasetExecutionCapabilities, negotiateDatasetExecutionCapabilitiesFromWire, negotiateDatasetMaterializationProfile, noteFromShard, noteSkosTagToShard, noteToShard, openShard, packTarGz, parseCspReport, parseSearchEvidenceLocator, parseSearchEvidenceSet, prefetchShard, previewRecordStorePurge, profileSupportError, projectAttachments, projectNotes, projectRecords, provenanceEdgeToShard, providerSatisfiesRouteRequirements, purgeRecordStoreGraph, queryAiwgFortemiIndex, queryAiwgHybridIndex, queryAiwgSemanticIndex, registerLlmCapability, registerSemanticCapability, registerSemanticCapabilityWorker, registerServiceWorker, resolveSearchEvidence, restoreDbSnapshot, searchTool, selectBackend, selectEmbeddingTask, selectLlmModel, setEmbedFunction, setEmbeddingTaskSelectionOptions, setLlmFunction, sha256Hex, sidecarBlobDigests, signShard, skosConceptToShard, skosRelationToShard, skosSchemeToShard, suggestTags, tagsToShard, templateToShard, titleGenerationHandler, unpackTarGz, unregisterLlmCapability, unregisterSemanticCapability, upsertRecordStoreRequest, upsertRecordStoreSources, urlLinkToShard, validateAiwgFortemiChunkManifest, validateAiwgFortemiChunkPart, validateAiwgFortemiIndexExport, validateAiwgFortemiIndexExportSchema, validateAiwgFortemiProjectedRecordSchema, validateAiwgStaticEmbeddingSet, validateChecksums, validateCoreV1ShardArchive, validateDatasetBenchmarkEvidence, validateDatasetExecutionDescriptor, validateDatasetExecutionRequest, validateFortemiCompatibilityResponse, validateFullV1ShardArchive, validateProviderRoute, validateRecordV1ShardArchive, validateShardArchive, validateShardComponentRecord, validateShardManifest, verifyDbSnapshotMeta, verifyShardSignature, verifySri };
46936
48808
  //# sourceMappingURL=index.js.map
46937
48809
  //# sourceMappingURL=index.js.map