@semiont/make-meaning 0.5.13 → 0.5.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -44,6 +44,16 @@ interface WorkerInferenceConfig {
44
44
  }
45
45
  /** Narrow config type — only the fields make-meaning actually reads */
46
46
  interface MakeMeaningConfig {
47
+ /**
48
+ * Resource-gather policy. `settleTimeoutMs` bounds the semanticContext
49
+ * read-your-writes barrier (SMELTER-INDEX-SYNC D3/D5) — REQUIRED: the TOML
50
+ * loader owns the one default (15s at `[environments.<env>.make-meaning.gather]`);
51
+ * hand-built configs (scripts, tests) state their policy explicitly. Must
52
+ * nest inside downstream watchdogs (A4).
53
+ */
54
+ gather: {
55
+ settleTimeoutMs: number;
56
+ };
47
57
  services: {
48
58
  graph?: GraphServiceConfig;
49
59
  vectors?: VectorsServiceConfig;
@@ -276,10 +286,14 @@ declare class Gatherer$1 {
276
286
  private kb;
277
287
  private eventBus;
278
288
  private inferenceClient;
289
+ /** Settle bound for the resource-gather barrier — operator-owned config (D5), threaded from `MakeMeaningConfig.gather`. */
290
+ private settleTimeoutMs;
279
291
  private embeddingProvider?;
280
292
  private subscriptions;
281
293
  private readonly logger;
282
- constructor(kb: KnowledgeBase, eventBus: EventBus, inferenceClient: InferenceClient, logger: Logger, embeddingProvider?: EmbeddingProvider | undefined);
294
+ constructor(kb: KnowledgeBase, eventBus: EventBus, inferenceClient: InferenceClient,
295
+ /** Settle bound for the resource-gather barrier — operator-owned config (D5), threaded from `MakeMeaningConfig.gather`. */
296
+ settleTimeoutMs: number, logger: Logger, embeddingProvider?: EmbeddingProvider | undefined);
283
297
  initialize(): Promise<void>;
284
298
  private handleAnnotationGather;
285
299
  private handleResourceGather;
@@ -1378,20 +1392,6 @@ declare class AnnotationContext {
1378
1392
 
1379
1393
  type KnowledgeGraph = components['schemas']['KnowledgeGraph'];
1380
1394
  declare class GraphContext {
1381
- /**
1382
- * Backoff schedule for the projection-lag grace in `buildKnowledgeGraph`
1383
- * (GRAPH-PROJECTION-SYNC P1). Total wait is bounded at 375 ms — the Weaver
1384
- * applies in tens of milliseconds when merely lagging; anything slower is
1385
- * treated as a real miss.
1386
- */
1387
- private static readonly PROJECTION_LAG_BACKOFF_MS;
1388
- /**
1389
- * Bounded wait for the applied-offset barrier (GRAPH-PROJECTION-SYNC P2).
1390
- * The Weaver applies in tens of milliseconds when merely lagging; a
1391
- * barrier that hasn't woken in 500 ms means signals have stalled and the
1392
- * poll floor above owns the remainder.
1393
- */
1394
- private static readonly PROJECTION_BARRIER_TIMEOUT_MS;
1395
1395
  /**
1396
1396
  * Get all resources referencing this resource (backlinks)
1397
1397
  * Requires graph traversal - must use graph database
@@ -1426,7 +1426,9 @@ declare class GraphContext {
1426
1426
  * - annotations on the resource → `annotation` nodes + `annotation-of` edges,
1427
1427
  * so siblingEntityTypes = union of those nodes' entityTypes
1428
1428
  */
1429
- static buildKnowledgeGraph(resourceId: ResourceId, kb: KnowledgeBase): Promise<KnowledgeGraph>;
1429
+ static buildKnowledgeGraph(resourceId: ResourceId, kb: KnowledgeBase,
1430
+ /** Breadcrumb sink for the projection-lag degrade path; the degrade counter fires regardless. */
1431
+ logger?: Logger): Promise<KnowledgeGraph>;
1430
1432
  }
1431
1433
 
1432
1434
  /**
@@ -1452,7 +1454,16 @@ declare class LLMContext {
1452
1454
  * Get comprehensive LLM context for a resource
1453
1455
  * Includes: main resource, related resources, annotations, graph, content, summary, references
1454
1456
  */
1455
- static getResourceContext(resourceId: ResourceId, options: LLMContextOptions, kb: KnowledgeBase, inferenceClient: InferenceClient, logger: Logger): Promise<GatheredContext>;
1457
+ static getResourceContext(resourceId: ResourceId, options: LLMContextOptions, kb: KnowledgeBase, inferenceClient: InferenceClient,
1458
+ /**
1459
+ * Bound on the semanticContext read-your-writes barrier
1460
+ * (SMELTER-INDEX-SYNC D3/D5). Operator-owned deployment policy: born in
1461
+ * `[environments.<env>.make-meaning.gather] settleTimeoutMs` (the TOML
1462
+ * loader holds the ONE default, 15s), threaded here as a plain argument
1463
+ * via `MakeMeaningConfig.gather` → Gatherer. Must nest inside downstream
1464
+ * watchdogs (A4) — e.g. my-chat's 90s generation stall watchdog.
1465
+ */
1466
+ settleTimeoutMs: number, logger: Logger): Promise<GatheredContext>;
1456
1467
  }
1457
1468
 
1458
1469
  /**
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { FsJobQueue } from '@semiont/jobs';
1
+ import { STALL_THRESHOLD_MS, FsJobQueue } from '@semiont/jobs';
2
2
  import { FilesystemViewStorage, resolveStorageUri, EventQuery, createEventStore } from '@semiont/event-sourcing';
3
- import { getPrimaryRepresentation, decodeRepresentation, getResourceEntityTypes, getResourceId, getTargetSource, resourceId, getBodySource, getTargetSelector, deriveViews, getTextPositionSelector, annotationId, errField, userId, generateUuid, getExactText, busRequest, cloneToken, baseMediaType, isSupportedMediaType, capabilitiesOf, didToAgent, assembleAnnotation, jobId, entityType, baseUrl, busLog, BRIDGED_CHANNELS, burstBuffer, textExtractionOf, getPrimaryMediaType, extensionForMediaType, applyBodyOperations, softwareToAgent } from '@semiont/core';
4
- import { withActorSpan, recordBusEmit, withSpan, SpanKind, registerJobQueueProvider, registerVectorIndexSizeProvider } from '@semiont/observability';
3
+ import { getResourceEntityTypes, getResourceId, getTargetSource, resourceId, getPrimaryRepresentation, decodeRepresentation, getBodySource, getTargetSelector, deriveViews, getTextPositionSelector, annotationId, errField, userId, generateUuid, getExactText, busRequest, cloneToken, baseMediaType, isSupportedMediaType, capabilitiesOf, didToAgent, assembleAnnotation, jobId, entityType, baseUrl, busLog, BRIDGED_CHANNELS, burstBuffer, textExtractionOf, getPrimaryMediaType, extensionForMediaType, applyBodyOperations, softwareToAgent } from '@semiont/core';
4
+ import { recordGatherDegrade, withActorSpan, recordBusEmit, withSpan, SpanKind, registerJobQueueProvider, registerVectorIndexSizeProvider } from '@semiont/observability';
5
5
  import { createInferenceClient } from '@semiont/inference';
6
6
  import { getGraphDatabase } from '@semiont/graph';
7
7
  import { WorkingTreeStore, deriveStorageUri, calculateChecksum } from '@semiont/content';
@@ -9908,6 +9908,131 @@ async function createKnowledgeBase(eventStore, project, graphDb, eventBus, logge
9908
9908
  }
9909
9909
  return kb;
9910
9910
  }
9911
+ var PROJECTION_LAG_BACKOFF_MS = [25, 50, 100, 200];
9912
+ var PROJECTION_BARRIER_TIMEOUT_MS = 500;
9913
+ var GRAPH_BARRIER_BUDGET_MS = PROJECTION_BARRIER_TIMEOUT_MS + PROJECTION_LAG_BACKOFF_MS.reduce((a, b) => a + b, 0);
9914
+ var GraphContext = class {
9915
+ /**
9916
+ * Get all resources referencing this resource (backlinks)
9917
+ * Requires graph traversal - must use graph database
9918
+ */
9919
+ static async getBacklinks(resourceId10, kb) {
9920
+ return kb.graph.getResourceReferencedBy(resourceId10);
9921
+ }
9922
+ /**
9923
+ * Find shortest path between two resources
9924
+ * Requires graph traversal - must use graph database
9925
+ */
9926
+ static async findPath(fromResourceId, toResourceId, kb, maxDepth) {
9927
+ return kb.graph.findPath(fromResourceId, toResourceId, maxDepth);
9928
+ }
9929
+ /**
9930
+ * Get resource connections (graph edges)
9931
+ * Requires graph traversal - must use graph database
9932
+ */
9933
+ static async getResourceConnections(resourceId10, kb) {
9934
+ return kb.graph.getResourceConnections(resourceId10);
9935
+ }
9936
+ /**
9937
+ * Search resources by name (cross-resource query)
9938
+ * Requires full-text search - must use graph database
9939
+ */
9940
+ static async searchResources(query, kb, limit) {
9941
+ return kb.graph.searchResources(query, limit);
9942
+ }
9943
+ /**
9944
+ * Build the unified knowledge graph for a resource's neighborhood:
9945
+ * resources AND annotations as typed nodes, typed/directional edges.
9946
+ *
9947
+ * This is the single graph builder (CONTEXT-UNIFICATION D3) — both the
9948
+ * matcher (ranking) and the resource/viz path consume it. The flattened
9949
+ * signals the matcher reads today (`connections`, `citedBy`/count,
9950
+ * `siblingEntityTypes`, `bidirectional`) are all derivable from this:
9951
+ * - peer connections → resource nodes + main→peer edges carrying `bidirectional`
9952
+ * - inbound citations → citing-resource nodes + `citation` edges (citing→main),
9953
+ * so citedByCount = inbound citation-edge count
9954
+ * - annotations on the resource → `annotation` nodes + `annotation-of` edges,
9955
+ * so siblingEntityTypes = union of those nodes' entityTypes
9956
+ */
9957
+ static async buildKnowledgeGraph(resourceId10, kb, logger) {
9958
+ let mainDoc = await kb.graph.getResource(resourceId10);
9959
+ if (!mainDoc) {
9960
+ const view = await kb.views.get(resourceId10);
9961
+ if (view) {
9962
+ if (view.lastSequence !== void 0) {
9963
+ try {
9964
+ await kb.weaveProgress.whenApplied(
9965
+ String(resourceId10),
9966
+ view.lastSequence,
9967
+ PROJECTION_BARRIER_TIMEOUT_MS
9968
+ );
9969
+ mainDoc = await kb.graph.getResource(resourceId10);
9970
+ } catch (error) {
9971
+ if (!(error instanceof WeaveProgressTimeout)) throw error;
9972
+ }
9973
+ }
9974
+ if (!mainDoc) {
9975
+ for (const delayMs of PROJECTION_LAG_BACKOFF_MS) {
9976
+ await new Promise((resolve2) => setTimeout(resolve2, delayMs));
9977
+ mainDoc = await kb.graph.getResource(resourceId10);
9978
+ if (mainDoc) break;
9979
+ }
9980
+ }
9981
+ if (!mainDoc) {
9982
+ recordGatherDegrade("graph");
9983
+ logger?.warn("[gather DEGRADED] graph projection did not catch up \u2014 resource present in views, absent in graph", {
9984
+ resourceId: String(resourceId10),
9985
+ lastSequence: view.lastSequence,
9986
+ barrierTimeoutMs: PROJECTION_BARRIER_TIMEOUT_MS
9987
+ });
9988
+ throw new Error(
9989
+ `Graph projection did not catch up for ${String(resourceId10)} \u2014 present in views, absent in graph (Weaver lag, not a missing resource)`
9990
+ );
9991
+ }
9992
+ }
9993
+ }
9994
+ if (!mainDoc) {
9995
+ throw new Error("Resource not found");
9996
+ }
9997
+ const mainId = String(resourceId10);
9998
+ const [connections, referencedBy, annotations] = await Promise.all([
9999
+ kb.graph.getResourceConnections(resourceId10),
10000
+ kb.graph.getResourceReferencedBy(resourceId10),
10001
+ kb.graph.getResourceAnnotations(resourceId10)
10002
+ ]);
10003
+ const nodes = [];
10004
+ const edges = [];
10005
+ const seen = /* @__PURE__ */ new Set();
10006
+ const addResourceNode = (id, label, entityTypes) => {
10007
+ if (!id || seen.has(id)) return;
10008
+ nodes.push({ id, type: "resource", label, entityTypes });
10009
+ seen.add(id);
10010
+ };
10011
+ addResourceNode(mainId, mainDoc.name, getResourceEntityTypes(mainDoc));
10012
+ for (const conn of connections) {
10013
+ const peerId = getResourceId(conn.targetResource);
10014
+ if (!peerId) continue;
10015
+ addResourceNode(peerId, conn.targetResource.name, getResourceEntityTypes(conn.targetResource));
10016
+ edges.push({ source: mainId, target: peerId, type: conn.relationshipType || "link", bidirectional: conn.bidirectional });
10017
+ }
10018
+ const citedSeen = /* @__PURE__ */ new Set();
10019
+ for (const ann of referencedBy) {
10020
+ const source = getTargetSource(ann.target);
10021
+ if (!source || source === String(resourceId10) || citedSeen.has(source)) continue;
10022
+ citedSeen.add(source);
10023
+ const view = await kb.views.get(resourceId(source));
10024
+ addResourceNode(source, view?.resource?.name ?? source, view?.resource ? getResourceEntityTypes(view.resource) : []);
10025
+ edges.push({ source, target: mainId, type: "citation" });
10026
+ }
10027
+ for (const ann of annotations) {
10028
+ if (!ann.id || seen.has(ann.id)) continue;
10029
+ nodes.push({ id: ann.id, type: "annotation", label: ann.motivation ?? "annotation", entityTypes: getEntityTypes(ann) });
10030
+ seen.add(ann.id);
10031
+ edges.push({ source: ann.id, target: mainId, type: "annotation-of" });
10032
+ }
10033
+ return { nodes, edges };
10034
+ }
10035
+ };
9911
10036
 
9912
10037
  // src/gatherer.ts
9913
10038
  var import_rxjs = __toESM(require_cjs());
@@ -10014,130 +10139,6 @@ var ResourceContext = class _ResourceContext {
10014
10139
  return void 0;
10015
10140
  }
10016
10141
  };
10017
- var GraphContext = class _GraphContext {
10018
- /**
10019
- * Backoff schedule for the projection-lag grace in `buildKnowledgeGraph`
10020
- * (GRAPH-PROJECTION-SYNC P1). Total wait is bounded at 375 ms — the Weaver
10021
- * applies in tens of milliseconds when merely lagging; anything slower is
10022
- * treated as a real miss.
10023
- */
10024
- static PROJECTION_LAG_BACKOFF_MS = [25, 50, 100, 200];
10025
- /**
10026
- * Bounded wait for the applied-offset barrier (GRAPH-PROJECTION-SYNC P2).
10027
- * The Weaver applies in tens of milliseconds when merely lagging; a
10028
- * barrier that hasn't woken in 500 ms means signals have stalled and the
10029
- * poll floor above owns the remainder.
10030
- */
10031
- static PROJECTION_BARRIER_TIMEOUT_MS = 500;
10032
- /**
10033
- * Get all resources referencing this resource (backlinks)
10034
- * Requires graph traversal - must use graph database
10035
- */
10036
- static async getBacklinks(resourceId10, kb) {
10037
- return kb.graph.getResourceReferencedBy(resourceId10);
10038
- }
10039
- /**
10040
- * Find shortest path between two resources
10041
- * Requires graph traversal - must use graph database
10042
- */
10043
- static async findPath(fromResourceId, toResourceId, kb, maxDepth) {
10044
- return kb.graph.findPath(fromResourceId, toResourceId, maxDepth);
10045
- }
10046
- /**
10047
- * Get resource connections (graph edges)
10048
- * Requires graph traversal - must use graph database
10049
- */
10050
- static async getResourceConnections(resourceId10, kb) {
10051
- return kb.graph.getResourceConnections(resourceId10);
10052
- }
10053
- /**
10054
- * Search resources by name (cross-resource query)
10055
- * Requires full-text search - must use graph database
10056
- */
10057
- static async searchResources(query, kb, limit) {
10058
- return kb.graph.searchResources(query, limit);
10059
- }
10060
- /**
10061
- * Build the unified knowledge graph for a resource's neighborhood:
10062
- * resources AND annotations as typed nodes, typed/directional edges.
10063
- *
10064
- * This is the single graph builder (CONTEXT-UNIFICATION D3) — both the
10065
- * matcher (ranking) and the resource/viz path consume it. The flattened
10066
- * signals the matcher reads today (`connections`, `citedBy`/count,
10067
- * `siblingEntityTypes`, `bidirectional`) are all derivable from this:
10068
- * - peer connections → resource nodes + main→peer edges carrying `bidirectional`
10069
- * - inbound citations → citing-resource nodes + `citation` edges (citing→main),
10070
- * so citedByCount = inbound citation-edge count
10071
- * - annotations on the resource → `annotation` nodes + `annotation-of` edges,
10072
- * so siblingEntityTypes = union of those nodes' entityTypes
10073
- */
10074
- static async buildKnowledgeGraph(resourceId10, kb) {
10075
- let mainDoc = await kb.graph.getResource(resourceId10);
10076
- if (!mainDoc) {
10077
- const view = await kb.views.get(resourceId10);
10078
- if (view) {
10079
- if (view.lastSequence !== void 0) {
10080
- try {
10081
- await kb.weaveProgress.whenApplied(
10082
- String(resourceId10),
10083
- view.lastSequence,
10084
- _GraphContext.PROJECTION_BARRIER_TIMEOUT_MS
10085
- );
10086
- mainDoc = await kb.graph.getResource(resourceId10);
10087
- } catch {
10088
- }
10089
- }
10090
- if (!mainDoc) {
10091
- for (const delayMs of _GraphContext.PROJECTION_LAG_BACKOFF_MS) {
10092
- await new Promise((resolve2) => setTimeout(resolve2, delayMs));
10093
- mainDoc = await kb.graph.getResource(resourceId10);
10094
- if (mainDoc) break;
10095
- }
10096
- }
10097
- }
10098
- }
10099
- if (!mainDoc) {
10100
- throw new Error("Resource not found");
10101
- }
10102
- const mainId = String(resourceId10);
10103
- const [connections, referencedBy, annotations] = await Promise.all([
10104
- kb.graph.getResourceConnections(resourceId10),
10105
- kb.graph.getResourceReferencedBy(resourceId10),
10106
- kb.graph.getResourceAnnotations(resourceId10)
10107
- ]);
10108
- const nodes = [];
10109
- const edges = [];
10110
- const seen = /* @__PURE__ */ new Set();
10111
- const addResourceNode = (id, label, entityTypes) => {
10112
- if (!id || seen.has(id)) return;
10113
- nodes.push({ id, type: "resource", label, entityTypes });
10114
- seen.add(id);
10115
- };
10116
- addResourceNode(mainId, mainDoc.name, getResourceEntityTypes(mainDoc));
10117
- for (const conn of connections) {
10118
- const peerId = getResourceId(conn.targetResource);
10119
- if (!peerId) continue;
10120
- addResourceNode(peerId, conn.targetResource.name, getResourceEntityTypes(conn.targetResource));
10121
- edges.push({ source: mainId, target: peerId, type: conn.relationshipType || "link", bidirectional: conn.bidirectional });
10122
- }
10123
- const citedSeen = /* @__PURE__ */ new Set();
10124
- for (const ann of referencedBy) {
10125
- const source = getTargetSource(ann.target);
10126
- if (!source || source === String(resourceId10) || citedSeen.has(source)) continue;
10127
- citedSeen.add(source);
10128
- const view = await kb.views.get(resourceId(source));
10129
- addResourceNode(source, view?.resource?.name ?? source, view?.resource ? getResourceEntityTypes(view.resource) : []);
10130
- edges.push({ source, target: mainId, type: "citation" });
10131
- }
10132
- for (const ann of annotations) {
10133
- if (!ann.id || seen.has(ann.id)) continue;
10134
- nodes.push({ id: ann.id, type: "annotation", label: ann.motivation ?? "annotation", entityTypes: getEntityTypes(ann) });
10135
- seen.add(ann.id);
10136
- edges.push({ source: ann.id, target: mainId, type: "annotation-of" });
10137
- }
10138
- return { nodes, edges };
10139
- }
10140
- };
10141
10142
 
10142
10143
  // src/annotation-context.ts
10143
10144
  var AnnotationContext = class {
@@ -10252,7 +10253,7 @@ var AnnotationContext = class {
10252
10253
  }
10253
10254
  }
10254
10255
  logger?.debug("Building knowledge graph", { resourceId: resourceId10 });
10255
- const graph = await GraphContext.buildKnowledgeGraph(resourceId10, kb);
10256
+ const graph = await GraphContext.buildKnowledgeGraph(resourceId10, kb, logger);
10256
10257
  const views = deriveViews(graph, String(resourceId10), annotationId5);
10257
10258
  const entityTypeStats = await kb.graph.getEntityTypeStats();
10258
10259
  const entityTypeFrequencies = {};
@@ -10561,19 +10562,18 @@ Entity types: ${entityTypes.join(", ")}`;
10561
10562
  return inferenceClient.generateText(summaryPrompt, 500, 0.5);
10562
10563
  }
10563
10564
  };
10564
- var SMELT_SETTLE_TIMEOUT_MS = 15e3;
10565
10565
  var LLMContext = class {
10566
10566
  /**
10567
10567
  * Get comprehensive LLM context for a resource
10568
10568
  * Includes: main resource, related resources, annotations, graph, content, summary, references
10569
10569
  */
10570
- static async getResourceContext(resourceId10, options, kb, inferenceClient, logger) {
10570
+ static async getResourceContext(resourceId10, options, kb, inferenceClient, settleTimeoutMs, logger) {
10571
10571
  const mainDoc = await ResourceContext.getResourceMetadata(resourceId10, kb);
10572
10572
  if (!mainDoc) {
10573
10573
  throw new Error("Resource not found");
10574
10574
  }
10575
10575
  const mainContent = options.includeContent ? await ResourceContext.getResourceContent(mainDoc, kb) : void 0;
10576
- const graph = await GraphContext.buildKnowledgeGraph(resourceId10, kb);
10576
+ const graph = await GraphContext.buildKnowledgeGraph(resourceId10, kb, logger);
10577
10577
  const resourceIdStr = resourceId10.toString();
10578
10578
  const relatedDocs = [];
10579
10579
  const relatedNodes = graph.nodes.filter((node) => node.type === "resource" && node.id !== resourceIdStr).slice(0, Math.max(0, options.maxResources - 1));
@@ -10620,16 +10620,17 @@ var LLMContext = class {
10620
10620
  const contentChecksum = getPrimaryRepresentation(mainDoc)?.checksum;
10621
10621
  if (contentChecksum) {
10622
10622
  try {
10623
- const outcome = await kb.smeltProgress.whenSettled(resourceIdStr, contentChecksum, SMELT_SETTLE_TIMEOUT_MS);
10623
+ const outcome = await kb.smeltProgress.whenSettled(resourceIdStr, contentChecksum, settleTimeoutMs);
10624
10624
  if (outcome === "indexed") {
10625
10625
  matches = await search();
10626
10626
  }
10627
10627
  } catch (error) {
10628
10628
  if (!(error instanceof SmeltProgressTimeout)) throw error;
10629
+ recordGatherDegrade("vectors");
10629
10630
  logger.warn("[gather DEGRADED] semanticContext absent \u2014 the vector projection did not settle within the barrier", {
10630
10631
  resourceId: resourceIdStr,
10631
10632
  contentChecksum,
10632
- timeoutMs: SMELT_SETTLE_TIMEOUT_MS
10633
+ timeoutMs: settleTimeoutMs
10633
10634
  });
10634
10635
  }
10635
10636
  }
@@ -10667,16 +10668,18 @@ var LLMContext = class {
10667
10668
 
10668
10669
  // src/gatherer.ts
10669
10670
  var Gatherer = class {
10670
- constructor(kb, eventBus, inferenceClient, logger, embeddingProvider) {
10671
+ constructor(kb, eventBus, inferenceClient, settleTimeoutMs, logger, embeddingProvider) {
10671
10672
  this.kb = kb;
10672
10673
  this.eventBus = eventBus;
10673
10674
  this.inferenceClient = inferenceClient;
10675
+ this.settleTimeoutMs = settleTimeoutMs;
10674
10676
  this.embeddingProvider = embeddingProvider;
10675
10677
  this.logger = logger;
10676
10678
  }
10677
10679
  kb;
10678
10680
  eventBus;
10679
10681
  inferenceClient;
10682
+ settleTimeoutMs;
10680
10683
  embeddingProvider;
10681
10684
  subscriptions = [];
10682
10685
  logger;
@@ -10753,6 +10756,7 @@ var Gatherer = class {
10753
10756
  event.options,
10754
10757
  this.kb,
10755
10758
  this.inferenceClient,
10759
+ this.settleTimeoutMs,
10756
10760
  this.logger
10757
10761
  );
10758
10762
  this.eventBus.get("gather:resource-complete").next({
@@ -12837,6 +12841,7 @@ async function createKnowledgeSystemFromConfig(project, config, eventBus, logger
12837
12841
  kb,
12838
12842
  eventBus,
12839
12843
  createInferenceClient(resolveActorInference(config, "gatherer"), logger.child({ component: "inference-client-gatherer" })),
12844
+ config.gather.settleTimeoutMs,
12840
12845
  logger.child({ component: "gatherer" }),
12841
12846
  embeddingProvider
12842
12847
  );
@@ -12860,6 +12865,14 @@ async function startMakeMeaning(project, config, eventBus, logger, options) {
12860
12865
  if (!config.services?.graph) {
12861
12866
  throw new Error("services.graph is required for make-meaning service");
12862
12867
  }
12868
+ if (!Number.isFinite(config.gather.settleTimeoutMs) || config.gather.settleTimeoutMs <= 0) {
12869
+ throw new Error(`gather.settleTimeoutMs must be a positive number of milliseconds, got ${config.gather.settleTimeoutMs}`);
12870
+ }
12871
+ if (config.gather.settleTimeoutMs + GRAPH_BARRIER_BUDGET_MS >= STALL_THRESHOLD_MS) {
12872
+ throw new Error(
12873
+ `gather.settleTimeoutMs (${config.gather.settleTimeoutMs}ms) plus the graph barrier budget (${GRAPH_BARRIER_BUDGET_MS}ms) must nest inside the job-worker stall watchdog (${STALL_THRESHOLD_MS}ms) \u2014 lower settleTimeoutMs (A4)`
12874
+ );
12875
+ }
12863
12876
  const skipRebuild = options?.skipRebuild ?? process.env.SEMIONT_SKIP_REBUILD === "true";
12864
12877
  const { jobQueue, jobStatusSubscription } = await createJobQueue(project, eventBus, logger);
12865
12878
  const knowledgeSystem = await createKnowledgeSystemFromConfig(project, config, eventBus, logger, skipRebuild);