@semiont/make-meaning 0.5.28 → 0.5.30

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
@@ -1,14 +1,14 @@
1
1
  import { JobQueue } from '@semiont/jobs';
2
- import { SemiontProject } from '@semiont/core/node';
3
- import { GraphServiceConfig, VectorsServiceConfig, EmbeddingServiceConfig, StateUnit, EventBus, Logger, ResourceId, ResourceDescriptor, AnnotationId, components, ITransport, BaseUrl, ConnectionState, SemiontError, UserDID, EventMap, IContentTransport, PutBinaryRequest, PutBinaryOptions, ExtractionOutcome, AccessToken, BusRequestPrimitive, ChunkingConfig, StoredEvent, Annotation, UserId, GatheredContext, ResourceAnnotations, AnnotationCategory, GraphPath, GraphConnection } from '@semiont/core';
4
- import { EventStore, ViewStorage } from '@semiont/event-sourcing';
5
- import { WorkingTreeStore, AnchoredTextStore } from '@semiont/content';
2
+ import { SemiontProject, SemiontState } from '@semiont/core/node';
3
+ import { GraphServiceConfig, VectorsServiceConfig, EmbeddingServiceConfig, ArchivistServiceConfig, EnvironmentConfig, StateUnit, EventBus, Logger, ResourceId, ResourceDescriptor, components, AnnotationId, GatheredContext, ResourceAnnotations, Annotation, AnnotationCategory, ITransport, BaseUrl, ConnectionState, SemiontError, UserDID, EventMap, IContentTransport, PutBinaryRequest, PutBinaryOptions, ExtractionOutcome, AccessToken, BusRequestPrimitive, ChunkingConfig, UserId } from '@semiont/core';
4
+ import { EventReadStorage, ViewMaterializer, EventStore, ViewStorage, EventLog } from '@semiont/event-sourcing';
5
+ import { WorkingTreeStore, AnchoredTextStore, ContentReads } from '@semiont/content';
6
6
  import { GraphDatabase } from '@semiont/graph';
7
7
  import { VectorStore, EmbeddingProvider } from '@semiont/vectors';
8
8
  import { InferenceClient } from '@semiont/inference';
9
+ import { Server } from 'http';
9
10
  import { BehaviorSubject, Observable } from 'rxjs';
10
11
  import { WorkerBus } from '@semiont/sdk';
11
- import { Writable, Readable } from 'node:stream';
12
12
 
13
13
  /**
14
14
  * Inference configuration for a single actor or worker.
@@ -74,10 +74,14 @@ interface MakeMeaningConfig {
74
74
  /** REQUIRED (same ruling): the embedding provider is the KB's semantic
75
75
  * identity — always named, never detected or defaulted. */
76
76
  embedding: EmbeddingServiceConfig;
77
+ /** Where the record is. Optional in the type because the actors that
78
+ * hold a KB mount never dial it; the Librarian does, and refuses at
79
+ * boot when it is absent (SINGLE-KB-MOUNT P4). */
80
+ archivist?: ArchivistServiceConfig;
77
81
  };
78
82
  /**
79
83
  * The KB's canonical identity domain — the SAME value `/api/tokens/agent`
80
- * mints agent DIDs from (backend `site.domain`). The agent roster consumes
84
+ * mints agent DIDs from (gateway `site.domain`). The agent roster consumes
81
85
  * it verbatim, so directory DIDs and work-stamped `generator` DIDs are
82
86
  * equal by construction; it is never derived from service topology
83
87
  * (.plans/bugs/agent-did-host-skew.md).
@@ -90,9 +94,25 @@ interface MakeMeaningConfig {
90
94
  /** Per-worker-type inference config */
91
95
  workers?: WorkerInferenceConfig;
92
96
  }
97
+ /**
98
+ * Extract the MakeMeaningConfig slice from a full EnvironmentConfig.
99
+ * actors and workers come from _metadata (populated by the TOML loader).
100
+ *
101
+ * Lives here (not in a consumer) because every composition root that runs
102
+ * make-meaning actors — the gateway's startMakeMeaning and the Archivist's
103
+ * archivist-main — needs the identical mapping; two copies would drift.
104
+ */
105
+ /**
106
+ * The KB name a mountless service composes its state paths from —
107
+ * `[kb] name`, staged by the launcher (SINGLE-KB-MOUNT D4). Refusing is the
108
+ * point: a defaulted name composes a state path nobody writes to, and the
109
+ * service reads an empty view store forever, silently.
110
+ */
111
+ declare function requireKBName(config: EnvironmentConfig): string;
112
+ declare function makeMeaningConfigFrom(config: EnvironmentConfig): MakeMeaningConfig;
93
113
 
94
114
  /**
95
- * WeaveProgress — backend-local fold of `weave:applied` signals
115
+ * WeaveProgress — gateway-local fold of `weave:applied` signals
96
116
  * (GRAPH-PROJECTION-SYNC P2, D2 = push).
97
117
  *
98
118
  * The Weaver emits `weave:applied` after applying an event (or a batch's
@@ -108,7 +128,7 @@ interface MakeMeaningConfig {
108
128
  * WEAVER-ISOLATION the same channel arrives through the bus gateway and
109
129
  * this unit does not change.
110
130
  *
111
- * The map is ephemeral by design — on backend restart it rebuilds lazily
131
+ * The map is ephemeral by design — on gateway restart it rebuilds lazily
112
132
  * from live signals. That loses nothing: a waiter only ever waits for an
113
133
  * apply that has not happened yet, and those signals are still to come.
114
134
  */
@@ -126,7 +146,7 @@ interface WeaveProgress extends StateUnit {
126
146
  }
127
147
 
128
148
  /**
129
- * SmeltProgress — backend-local fold of `smelt:settled` signals
149
+ * SmeltProgress — gateway-local fold of `smelt:settled` signals
130
150
  * (SMELTER-INDEX-SYNC P1, D1 = push barrier).
131
151
  *
132
152
  * The Smelter emits `smelt:settled` after deciding a resource's content:
@@ -144,7 +164,7 @@ interface WeaveProgress extends StateUnit {
144
164
  * worker; an in-process Smelter would ride the core EventBus and this unit
145
165
  * would not change (the WeaveProgress precedent).
146
166
  *
147
- * The fold is ephemeral by design — on backend restart it rebuilds lazily
167
+ * The fold is ephemeral by design — on gateway restart it rebuilds lazily
148
168
  * from live signals. Barrier callers probe the vector store first
149
169
  * (SMELTER-INDEX-SYNC A3), so a cold fold only costs waits for resources
150
170
  * whose settlement genuinely hasn't been observed yet.
@@ -200,6 +220,30 @@ interface KnowledgeBase {
200
220
  vectors: VectorStore;
201
221
  projectionsDir: string;
202
222
  }
223
+ /**
224
+ * Capability slices of the record (EXTRACT-ARCHIVIST P1).
225
+ *
226
+ * An Archivist actor takes the slice it actually uses, never the whole
227
+ * KnowledgeBase. Every slice is DERIVED from the owning type with Pick;
228
+ * a hand-restated shape here would be a mirror of a fact someone else owns.
229
+ */
230
+ /** The lifecycle half of the working tree (GATEWAY.md D4a): the Archivist
231
+ * accessions, moves, removes and resolves — it never serves bytes. */
232
+ type ContentLifecycle = Pick<WorkingTreeStore, 'register' | 'move' | 'remove' | 'resolveUri'>;
233
+ /** The record's single write seam. `Stower` is the only appendEvent caller
234
+ * anywhere in make-meaning or the gateway (post-#1252): single-owner by
235
+ * construction. A second caller is a design smell, not a wiring chore. */
236
+ type EventAppends = Pick<EventStore, 'appendEvent'>;
237
+ /** Read-only reach into the event store: the log for queries, the
238
+ * materializer for on-demand view assembly (`assembleResourceGraph`). */
239
+ interface EventStoreReads {
240
+ log: {
241
+ storage: EventReadStorage;
242
+ };
243
+ views: {
244
+ materializer: Pick<ViewMaterializer, 'materialize'>;
245
+ };
246
+ }
203
247
  interface CreateKnowledgeBaseOptions {
204
248
  /** Required (MANDATORY-EMBEDDING D0): a KB without vector search is not a
205
249
  * configuration we support; `MemoryVectorStore` is the explicit named
@@ -227,6 +271,7 @@ declare function createKnowledgeBase(eventStore: EventStore, project: SemiontPro
227
271
  *
228
272
  * Subscriptions:
229
273
  * - yield:create → resource.created (+ content store) → yield:created / yield:create-failed
274
+ * - yield:clone-persist → resource.cloned (+ content store) → yield:cloned / yield:clone-persist-failed
230
275
  * - yield:update → resource.updated (+ content store) → yield:updated / yield:update-failed
231
276
  * - yield:mv → resource.moved (+ working tree move) → yield:moved / yield:move-failed
232
277
  * - mark:create → annotation.added → mark:created / mark:create-failed
@@ -252,18 +297,65 @@ interface CreateResourceResult {
252
297
  resourceId: ResourceId;
253
298
  resource: ResourceDescriptor;
254
299
  }
300
+ /**
301
+ * The stores Stower writes through (EXTRACT-ARCHIVIST P1): the record's
302
+ * single write seam plus the content lifecycle — never bytes (GATEWAY.md
303
+ * D4a). Resource resolution for moves goes through `project.projectionsDir`.
304
+ */
305
+ interface StowerStores {
306
+ content: ContentLifecycle;
307
+ eventStore: EventAppends;
308
+ }
255
309
  declare class Stower {
256
- private kb;
310
+ private stores;
257
311
  private eventBus;
258
312
  private project;
259
313
  private subscription;
260
314
  private readonly logger;
261
- constructor(kb: KnowledgeBase, eventBus: EventBus, project: SemiontProject, logger: Logger);
315
+ constructor(stores: StowerStores, eventBus: EventBus, project: SemiontProject, logger: Logger);
262
316
  initialize(): Promise<void>;
263
317
  private handleYieldCreate;
318
+ /**
319
+ * Persist a clone (the CloneTokenManager's second half).
320
+ *
321
+ * A clone is its own domain fact, not a creation with an extra field: it
322
+ * NAMES the resource it came from, and `ResourceClonedPayload` requires
323
+ * that name. So it gets its own command and appends its own event, rather
324
+ * than an optional parent turning `yield:created` into something else at
325
+ * runtime.
326
+ *
327
+ * The token was already validated and the source's entity types already
328
+ * read by the CloneTokenManager — the one party that can do either. What
329
+ * happens here is what only the Stower may do: register the bytes and
330
+ * append the event (single-writer, GATEWAY.md D4b).
331
+ *
332
+ * Generated resources do NOT come through here. Their provenance is
333
+ * `generatedFrom` on `yield:created`, which is a different relation: a
334
+ * generated resource is derived from a source, a clone IS a copy of one.
335
+ */
336
+ private handleYieldClonePersist;
264
337
  private handleYieldUpdate;
265
338
  private handleYieldMv;
266
339
  private handleMarkCreate;
340
+ /**
341
+ * Persist a detection unit's annotations as ONE acknowledged batch, then
342
+ * answer (JOB-RESTART-SAFETY P6).
343
+ *
344
+ * The difference from `mark:create` is the reply, and it is the whole point.
345
+ * `mark:create` is fire-and-forget: the worker's emit resolves when the bus
346
+ * accepts it, which says nothing about the event log, so a down Stower loses
347
+ * a unit silently and a flapping one hangs the worker forever. This answers
348
+ * only after every append has returned, so the worker can gate unit
349
+ * completion — and its checkpoint — on durability.
350
+ *
351
+ * Appends are sequential, not concurrent: the event log is the system of
352
+ * record and a batch that half-lands under concurrency is harder to reason
353
+ * about than one that stops at the first failure. A partial batch is
354
+ * reported as a failure and the worker retries the WHOLE unit, which is safe
355
+ * because ids are deterministic (P3) and the annotation fold is idempotent
356
+ * by id — re-appending what already landed changes nothing.
357
+ */
358
+ private handleMarkCommit;
267
359
  private handleMarkDelete;
268
360
  private handleMarkUpdateBody;
269
361
  private handleMarkArchive;
@@ -277,6 +369,218 @@ declare class Stower {
277
369
  stop(): Promise<void>;
278
370
  }
279
371
 
372
+ /**
373
+ * Graph Context
374
+ *
375
+ * Provides graph database operations for resources and annotations.
376
+ * All methods require graph traversal - must use graph database.
377
+ */
378
+
379
+ /**
380
+ * What the unified graph builder reads (EXTRACT-LIBRARIAN P2) — Pick-derived,
381
+ * never restated. The weave fold is bus-fed (`weave:applied`), so this slice
382
+ * works identically in-process and in the standalone Librarian.
383
+ */
384
+ interface KnowledgeGraphReads {
385
+ graph: Pick<GraphDatabase, 'getResource' | 'getResourceConnections' | 'getResourceReferencedBy' | 'getResourceAnnotations'>;
386
+ views: Pick<ViewStorage, 'get'>;
387
+ weaveProgress: Pick<WeaveProgress, 'whenApplied'>;
388
+ }
389
+ type KnowledgeGraph = components['schemas']['KnowledgeGraph'];
390
+ declare class GraphContext {
391
+ /**
392
+ * Build the unified knowledge graph for a resource's neighborhood:
393
+ * resources AND annotations as typed nodes, typed/directional edges.
394
+ *
395
+ * This is the single graph builder (CONTEXT-UNIFICATION D3) — both the
396
+ * matcher (ranking) and the resource/viz path consume it. The flattened
397
+ * signals the matcher reads today (`connections`, `citedBy`/count,
398
+ * `siblingEntityTypes`, `bidirectional`) are all derivable from this:
399
+ * - peer connections → resource nodes + main→peer edges carrying `bidirectional`
400
+ * - inbound citations → citing-resource nodes + `citation` edges (citing→main),
401
+ * so citedByCount = inbound citation-edge count
402
+ * - annotations on the resource → `annotation` nodes + `annotation-of` edges,
403
+ * so siblingEntityTypes = union of those nodes' entityTypes
404
+ */
405
+ static buildKnowledgeGraph(resourceId: ResourceId, kb: KnowledgeGraphReads,
406
+ /** Breadcrumb sink for the projection-lag degrade path; the degrade counter fires regardless. */
407
+ logger?: Logger): Promise<KnowledgeGraph>;
408
+ }
409
+
410
+ /**
411
+ * Annotation Context
412
+ *
413
+ * Assembles annotation context from view storage and content store.
414
+ * Provides methods for:
415
+ * - Getting resource annotations
416
+ * - Building LLM context for annotations
417
+ * - Extracting annotation text context
418
+ * - Generating AI summaries
419
+ */
420
+
421
+ /** The view slice the annotation reads run on (EXTRACT-ARCHIVIST P1). */
422
+ type ViewGet = {
423
+ views: Pick<ViewStorage, 'get'>;
424
+ };
425
+ /**
426
+ * What the annotation-gather path reads (EXTRACT-LIBRARIAN P2; content
427
+ * re-keyed by D-CONTENT b) — the graph builder's slice plus this module's
428
+ * own reads. Pick-derived, never restated. In-process roots satisfy it with
429
+ * `workingTreeContentReads` over their `kb`; the Librarian passes
430
+ * `HttpContentTransport`.
431
+ */
432
+ interface AnnotationGatherReads {
433
+ views: Pick<ViewStorage, 'get'>;
434
+ content: ContentReads;
435
+ graph: KnowledgeGraphReads['graph'] & Pick<GraphDatabase, 'getEntityTypeStats'>;
436
+ vectors: Pick<VectorStore, 'searchAnnotations'>;
437
+ weaveProgress: KnowledgeGraphReads['weaveProgress'];
438
+ }
439
+
440
+ type AnnotationContextResponse = components['schemas']['AnnotationContextResponse'];
441
+ type ContextualSummaryResponse = components['schemas']['ContextualSummaryResponse'];
442
+ interface BuildContextOptions {
443
+ includeSourceContext?: boolean;
444
+ includeTargetContext?: boolean;
445
+ contextWindow?: number;
446
+ }
447
+ declare class AnnotationContext {
448
+ /**
449
+ * Build LLM context for an annotation
450
+ *
451
+ * @param annotationId - Bare annotation ID
452
+ * @param resourceId - Source resource ID
453
+ * @param kb - Knowledge base stores
454
+ * @param options - Context building options
455
+ * @param inferenceClient - Optional inference client for target context summary
456
+ * @returns Rich context for LLM processing
457
+ * @throws Error if annotation or resource not found
458
+ */
459
+ static buildLLMContext(annotationId: AnnotationId, resourceId: ResourceId, kb: AnnotationGatherReads, embeddingProvider: EmbeddingProvider, options?: BuildContextOptions, inferenceClient?: InferenceClient, logger?: Logger): Promise<GatheredContext>;
460
+ /**
461
+ * Get resource annotations from view storage (fast path)
462
+ * Throws if view missing
463
+ */
464
+ static getResourceAnnotations(resourceId: ResourceId, kb: ViewGet): Promise<ResourceAnnotations>;
465
+ /**
466
+ * Get all annotations
467
+ * @returns Array of all annotation objects
468
+ */
469
+ static getAllAnnotations(resourceId: ResourceId, kb: ViewGet): Promise<Annotation[]>;
470
+ /**
471
+ * Enrich reference annotations with resolved document names
472
+ * Adds _resolvedDocumentName property to annotations that link to documents
473
+ * @private
474
+ */
475
+ private static enrichResolvedReferences;
476
+ /**
477
+ * Get resource stats (version info)
478
+ * @returns Version and timestamp info for the annotations
479
+ */
480
+ static getResourceStats(resourceId: ResourceId, kb: ViewGet): Promise<{
481
+ resourceId: ResourceId;
482
+ version: number;
483
+ updatedAt: string;
484
+ }>;
485
+ /**
486
+ * Check if resource exists in view storage
487
+ */
488
+ static resourceExists(resourceId: ResourceId, kb: {
489
+ views: Pick<ViewStorage, 'exists'>;
490
+ }): Promise<boolean>;
491
+ /**
492
+ * Get a single annotation by ID
493
+ * O(1) lookup using resource ID to access view storage
494
+ */
495
+ static getAnnotation(annotationId: AnnotationId, resourceId: ResourceId, kb: ViewGet): Promise<Annotation | null>;
496
+ /**
497
+ * List annotations with optional filtering
498
+ * @param filters - Optional filters like resourceId and type
499
+ * @throws Error if resourceId not provided (cross-resource queries not supported in view storage)
500
+ */
501
+ static listAnnotations(filters: {
502
+ resourceId?: ResourceId;
503
+ type?: AnnotationCategory;
504
+ } | undefined, kb: ViewGet): Promise<Annotation[]>;
505
+ /**
506
+ * Get annotation context (selected text with surrounding context)
507
+ */
508
+ static getAnnotationContext(annotationId: AnnotationId, resourceId: ResourceId, contextBefore: number, contextAfter: number, kb: ViewGet & {
509
+ content: ContentReads;
510
+ }): Promise<AnnotationContextResponse>;
511
+ /**
512
+ * Generate AI summary of annotation in context
513
+ */
514
+ static generateAnnotationSummary(annotationId: AnnotationId, resourceId: ResourceId, kb: ViewGet & {
515
+ content: ContentReads;
516
+ }, inferenceClient: InferenceClient): Promise<ContextualSummaryResponse>;
517
+ /**
518
+ * Get resource content as string. ResourceId-keyed (D-CONTENT b): the
519
+ * primary representation's `storageUri` stays the has-content signal, the
520
+ * fetch goes by id.
521
+ */
522
+ private static getResourceContent;
523
+ /**
524
+ * Extract annotation context from resource content
525
+ */
526
+ private static extractAnnotationContext;
527
+ /**
528
+ * Generate LLM summary of annotation in context
529
+ * Creates inference client per-request (HTTP handler context)
530
+ */
531
+ private static generateSummary;
532
+ }
533
+
534
+ /**
535
+ * LLM Context
536
+ *
537
+ * Builds comprehensive context for LLM processing of resources
538
+ * Orchestrates: ResourceContext, GraphContext, AnnotationContext, and generation functions
539
+ */
540
+
541
+ /**
542
+ * What the resource-gather path reads (EXTRACT-LIBRARIAN P2; content re-keyed
543
+ * by D-CONTENT b) — the graph builder's slice plus this module's own reads.
544
+ * Pick-derived, never restated. In-process roots satisfy it with
545
+ * `workingTreeContentReads` over their `kb`; the Librarian passes
546
+ * `HttpContentTransport`.
547
+ */
548
+ interface ResourceGatherReads {
549
+ views: Pick<ViewStorage, 'get'>;
550
+ content: ContentReads;
551
+ graph: KnowledgeGraphReads['graph'];
552
+ vectors: Pick<VectorStore, 'searchByResource'>;
553
+ weaveProgress: KnowledgeGraphReads['weaveProgress'];
554
+ smeltProgress: Pick<SmeltProgress, 'whenSettled'>;
555
+ }
556
+ interface LLMContextOptions {
557
+ depth: number;
558
+ maxResources: number;
559
+ includeContent: boolean;
560
+ includeSummary: boolean;
561
+ /**
562
+ * Entity types to exclude from the resource-gather semantic recall
563
+ * (caller-supplied; e.g. ['Question']). Optional; default none.
564
+ */
565
+ excludeEntityTypes?: string[];
566
+ }
567
+ declare class LLMContext {
568
+ /**
569
+ * Get comprehensive LLM context for a resource
570
+ * Includes: main resource, related resources, annotations, graph, content, summary, references
571
+ */
572
+ static getResourceContext(resourceId: ResourceId, options: LLMContextOptions, kb: ResourceGatherReads, inferenceClient: InferenceClient,
573
+ /**
574
+ * Bound on the semanticContext read-your-writes barrier
575
+ * (SMELTER-INDEX-SYNC D3/D5). Operator-owned deployment policy: born in
576
+ * `[environments.<env>.make-meaning.gather] settleTimeoutMs` (the TOML
577
+ * loader holds the ONE default, 15s), threaded here as a plain argument
578
+ * via `MakeMeaningConfig.gather` → Gatherer. Must nest inside downstream
579
+ * watchdogs (A4) — e.g. my-chat's 90s generation stall watchdog.
580
+ */
581
+ settleTimeoutMs: number, logger: Logger): Promise<GatheredContext>;
582
+ }
583
+
280
584
  /**
281
585
  * Gatherer Actor
282
586
  *
@@ -303,8 +607,16 @@ declare class Stower {
303
607
  * by RPC-style services.
304
608
  */
305
609
 
306
- declare class Gatherer$1 {
307
- private kb;
610
+ /**
611
+ * The Gatherer's capability slice (EXTRACT-LIBRARIAN P2) — DERIVED as the
612
+ * intersection of the two gather paths' reads, never restated. A full
613
+ * `KnowledgeBase` satisfies it structurally; the standalone Librarian (P3)
614
+ * builds it from the shared stateDir (views), the network clients
615
+ * (graph/vectors), bus-fed progress folds, and D-CONTENT's answer (content).
616
+ */
617
+ type GathererStores = AnnotationGatherReads & ResourceGatherReads;
618
+ declare class Gatherer {
619
+ private stores;
308
620
  private eventBus;
309
621
  private inferenceClient;
310
622
  /** Settle bound for the resource-gather barrier — operator-owned config (D5), threaded from `MakeMeaningConfig.gather`. */
@@ -312,7 +624,7 @@ declare class Gatherer$1 {
312
624
  private embeddingProvider;
313
625
  private subscriptions;
314
626
  private readonly logger;
315
- constructor(kb: KnowledgeBase, eventBus: EventBus, inferenceClient: InferenceClient,
627
+ constructor(stores: GathererStores, eventBus: EventBus, inferenceClient: InferenceClient,
316
628
  /** Settle bound for the resource-gather barrier — operator-owned config (D5), threaded from `MakeMeaningConfig.gather`. */
317
629
  settleTimeoutMs: number, logger: Logger, embeddingProvider: EmbeddingProvider);
318
630
  initialize(): Promise<void>;
@@ -335,14 +647,27 @@ declare class Gatherer$1 {
335
647
  * is available from auth context.
336
648
  */
337
649
 
650
+ /**
651
+ * The Matcher's capability slice (EXTRACT-LIBRARIAN P1) — Pick-derived,
652
+ * never restated. `graph.getResource` + `views.get` are
653
+ * `resourceWithViewGrace`'s two halves: the view fallback is a
654
+ * filesystem-backed projection read, served to the standalone service by
655
+ * the shared stateDir mount (D6), and to in-process callers by the same
656
+ * `kb` object, which satisfies this slice structurally.
657
+ */
658
+ interface MatcherStores {
659
+ graph: Pick<GraphDatabase, 'listResources' | 'getResource'>;
660
+ views: Pick<ViewStorage, 'get'>;
661
+ vectors: Pick<VectorStore, 'searchResources'>;
662
+ }
338
663
  declare class Matcher {
339
- private kb;
664
+ private stores;
340
665
  private eventBus;
341
666
  private inferenceClient;
342
667
  private embeddingProvider;
343
668
  private subscriptions;
344
669
  private readonly logger;
345
- constructor(kb: KnowledgeBase, eventBus: EventBus, logger: Logger, inferenceClient: InferenceClient, embeddingProvider: EmbeddingProvider);
670
+ constructor(stores: MatcherStores, eventBus: EventBus, logger: Logger, inferenceClient: InferenceClient, embeddingProvider: EmbeddingProvider);
346
671
  initialize(): Promise<void>;
347
672
  private handleSearch;
348
673
  /**
@@ -416,6 +741,8 @@ interface LimitsDiscovery {
416
741
  *
417
742
  * Handles:
418
743
  * - browse:resource-requested — single resource metadata (materialized from events)
744
+ * - browse:anchored-text-by-checksum-requested — the detection workers' read-through
745
+ * cache consult: a stored extraction outcome by content identity (ANCHORED-TEXT-TO-SMELTER P2)
419
746
  * - browse:resources-requested — list resources
420
747
  * - browse:annotations-requested — all annotations for a resource
421
748
  * - browse:annotation-requested — single annotation with resolved resource
@@ -429,8 +756,22 @@ interface LimitsDiscovery {
429
756
  * - browse:directory-requested — list a project directory, merging fs + ViewStorage
430
757
  */
431
758
 
759
+ /**
760
+ * Browser's measured surface of the record (EXTRACT-ARCHIVIST P1) — reads
761
+ * only, every member a derived slice of its owning type. What is absent is
762
+ * the point: no appendEvent, no content bytes beyond `retrieve`, no
763
+ * projectionsDir, no weaveProgress.
764
+ */
765
+ interface BrowserReads {
766
+ views: Pick<ViewStorage, 'get' | 'getAll' | 'exists'>;
767
+ eventStore: EventStoreReads;
768
+ graph: Pick<GraphDatabase, 'getResource' | 'getResourceReferencedBy' | 'listResources' | 'getEntityTypeStats'>;
769
+ vectors: Pick<VectorStore, 'searchResources' | 'searchAnnotations'>;
770
+ content: Pick<WorkingTreeStore, 'retrieve'>;
771
+ anchoredText: Pick<AnchoredTextStore, 'read'>;
772
+ smeltProgress: Pick<SmeltProgress, 'whenSettled'>;
773
+ }
432
774
  declare class Browser {
433
- private views;
434
775
  private kb;
435
776
  private eventBus;
436
777
  private project;
@@ -441,7 +782,7 @@ declare class Browser {
441
782
  private embeddingProvider;
442
783
  private subscriptions;
443
784
  private readonly logger;
444
- constructor(views: ViewStorage, kb: KnowledgeBase, eventBus: EventBus, project: SemiontProject, config: MakeMeaningConfig,
785
+ constructor(kb: BrowserReads, eventBus: EventBus, project: SemiontProject, config: MakeMeaningConfig,
445
786
  /** Discovered per-(provider, model) ceilings for the roster (INFERENCE-LIMITS-EXPOSURE P2). */
446
787
  limitsDiscovery: LimitsDiscovery,
447
788
  /** For the semantic search fallback — mandatory (MANDATORY-EMBEDDING D0). */
@@ -462,6 +803,17 @@ declare class Browser {
462
803
  * this design exists to avoid.
463
804
  */
464
805
  private handleAnchoredText;
806
+ /**
807
+ * Serve the checksum-addressed consult (ANCHORED-TEXT-TO-SMELTER P2, D2) —
808
+ * the detection workers' read-through cache. The caller computed the key
809
+ * from bytes it already holds, so unlike the resource-addressed read there
810
+ * is nothing to resolve and no settle barrier: with no resourceId there is
811
+ * no content generation to wait on, and a miss means "extract it yourself".
812
+ * A hit — success or decline — is served whole, so the caller runs neither
813
+ * parser nor engine. Read-only over the wire: the Smelter is the sole
814
+ * writer and never answers here.
815
+ */
816
+ private handleAnchoredTextByChecksum;
465
817
  private handleBrowseResource;
466
818
  private handleBrowseResources;
467
819
  private handleBrowseAnnotations;
@@ -491,13 +843,24 @@ declare class Browser {
491
843
  * "Clone tokens produce new resources — that's yield."
492
844
  */
493
845
 
846
+ /**
847
+ * What the clone workflow touches (EXTRACT-ARCHIVIST P1/P3): resource
848
+ * metadata via views, and `resolveUri` for existence checks — never bytes
849
+ * (GATEWAY.md D4a). The clone's own bytes are stored by the gateway's
850
+ * upload path before `yield:clone-create` arrives; this actor holds NO
851
+ * byte capability at all.
852
+ */
853
+ interface CloneTokenStores {
854
+ views: Pick<ViewStorage, 'get'>;
855
+ content: Pick<WorkingTreeStore, 'resolveUri'>;
856
+ }
494
857
  declare class CloneTokenManager {
495
- private kb;
858
+ private stores;
496
859
  private eventBus;
497
860
  private subscriptions;
498
861
  private readonly logger;
499
862
  private readonly tokens;
500
- constructor(kb: KnowledgeBase, eventBus: EventBus, logger: Logger);
863
+ constructor(stores: CloneTokenStores, eventBus: EventBus, logger: Logger);
501
864
  initialize(): Promise<void>;
502
865
  private handleGenerateToken;
503
866
  private handleGetResource;
@@ -521,7 +884,7 @@ declare class CloneTokenManager {
521
884
  * These are the five access actors. Two projection-pipeline actors complete
522
885
  * the seven, and BOTH run standalone (D4: the projections are part of their
523
886
  * stores' stacks, not of the embedding process): the Weaver (weaver-main →
524
- * graph) and the Smelter (smelter-main → vectors). The backend keeps only
887
+ * graph) and the Smelter (smelter-main → vectors). The gateway keeps only
525
888
  * the Weaver's `weave:applied` fold (kb.weaveProgress).
526
889
  *
527
890
  * EventBus, JobQueue, and workers are peers to KnowledgeSystem, not members.
@@ -530,12 +893,24 @@ declare class CloneTokenManager {
530
893
  interface KnowledgeSystem {
531
894
  kb: KnowledgeBase;
532
895
  stower: Stower;
533
- gatherer: Gatherer$1;
896
+ gatherer: Gatherer;
534
897
  matcher: Matcher;
535
898
  browser: Browser;
536
899
  cloneTokenManager: CloneTokenManager;
537
900
  stop: () => Promise<void>;
538
901
  }
902
+ /**
903
+ * The gateway's view of the system after EXTRACT-ARCHIVIST P3 and
904
+ * EXTRACT-LIBRARIAN P3: the Archivist service owns
905
+ * Stower/Browser/CloneTokenManager and the Librarian owns Matcher and
906
+ * Gatherer, out-of-process. The gateway hosts NO actors — `kb` here is a
907
+ * READ bundle over the shared stateDir for the handler subset and the
908
+ * gateway's routes; the one writer is the Archivist (D4b/D6).
909
+ */
910
+ interface GatewayKnowledgeSystem {
911
+ kb: KnowledgeBase;
912
+ stop: () => Promise<void>;
913
+ }
539
914
  declare function stopKnowledgeSystem(ks: KnowledgeSystem): Promise<void>;
540
915
 
541
916
  /**
@@ -549,7 +924,7 @@ interface MakeMeaningService {
549
924
  knowledgeSystem: KnowledgeSystem;
550
925
  jobQueue: JobQueue;
551
926
  /**
552
- * The one SemiontProject this backend is serving — the same instance the
927
+ * The one SemiontProject this gateway is serving — the same instance the
553
928
  * KnowledgeSystem, the job queue and the bus handlers were built from.
554
929
  *
555
930
  * Exposed so request handlers reach for it instead of improvising their own
@@ -561,17 +936,132 @@ interface MakeMeaningService {
561
936
  project: SemiontProject;
562
937
  stop: () => Promise<void>;
563
938
  }
939
+ /**
940
+ * The in-process composition root: every access actor and handler on one
941
+ * caller-owned bus, for `LocalTransport` consumers — the SDK test seam and
942
+ * embedding. Production composes the same actors as extracted services
943
+ * (archivist-main, librarian-main); this second root is supported, not legacy.
944
+ */
564
945
  declare function startMakeMeaning(project: SemiontProject, config: MakeMeaningConfig, eventBus: EventBus, logger: Logger, options?: {
565
946
  skipRebuild?: boolean;
566
947
  }): Promise<MakeMeaningService>;
948
+ interface GatewayMakeMeaningService {
949
+ jobQueue: JobQueue;
950
+ /** Name + the state-mount paths. NOT a `SemiontProject`: the gateway
951
+ * mounts no KB tree, and the type is what says so (SINGLE-KB-MOUNT P5). */
952
+ state: SemiontState;
953
+ stop: () => Promise<void>;
954
+ }
955
+ /**
956
+ * The gateway's composition root: everything startMakeMeaning builds EXCEPT
957
+ * the actors, which have all left. The Archivist (archivist-main) owns
958
+ * Stower/Browser/CloneTokenManager, enrichment, the entity-type bootstrap +
959
+ * warm, and the view rebuild; the Librarian (librarian-main) owns Matcher
960
+ * and Gatherer (EXTRACT-LIBRARIAN P1/P3).
961
+ *
962
+ * What remains is the JOB QUEUE, and nothing else. It used to call
963
+ * `connectStores` as well — a graph connection, a vector store, an embedding
964
+ * provider, an event store, a working tree and an anchored-text store — and
965
+ * SINGLE-KB-MOUNT P5 measured that **no consumer read any of it**: the whole
966
+ * `kb` bundle existed to be constructed. Deleting it is what lets the gateway
967
+ * take a `SemiontState` instead of a `SemiontProject`, and therefore what
968
+ * lets P6 drop the `/kb` mount: the type no longer HAS a KB root to want.
969
+ *
970
+ * The job queue lives on the shared state mount (D6), so what is left needs
971
+ * no tree at all.
972
+ */
973
+ declare function startMakeMeaningGateway(state: SemiontState, config: MakeMeaningConfig, eventBus: EventBus, logger: Logger): Promise<GatewayMakeMeaningService>;
567
974
 
568
975
  /**
569
- * LocalTransport `ITransport` for an in-process `KnowledgeSystem`.
976
+ * The Archivist's HTTP surface: the /health probe, the D1 sequence-ranged
977
+ * event read path (EXTRACT-ARCHIVIST P2a), and the content write and read
978
+ * paths (SINGLE-KB-MOUNT P2/P3).
979
+ *
980
+ * ⚠️ STANDING RULE, load-bearing: **this surface serves the KB tree, and
981
+ * nothing else.** `browse:*`, `match:*`, `gather:*` stay on the bus. The
982
+ * earlier, narrower rule — exactly one customer, the gateway's SSE resume —
983
+ * was re-examined by SINGLE-KB-MOUNT D1 (2026-08-29), which reversed
984
+ * GATEWAY.md D4a: the Archivist is the knowledge base's storage authority,
985
+ * and this HTTP surface is how bytes and record reads reach it (D2: bytes
986
+ * ride HTTP, never the bus). That is a change of design, not a widened seam;
987
+ * an endpoint that is not a KB-tree read or write still does not belong here.
988
+ *
989
+ * D1 (settled 2026-08-27): moving the event store out of the gateway breaks
990
+ * `/bus/subscribe`'s `Last-Event-ID` replay, which reads the log in-process
991
+ * (apps/gateway/src/routes/bus.ts). The answer is one narrow call —
992
+ * the events for ONE resource from ONE sequence — which the gateway calls
993
+ * directly:
994
+ *
995
+ * GET /events/:resourceId?fromSequence=N (inclusive, like the filter it
996
+ * mirrors: `queryEvents(rId, { fromSequence })`; the caller does the +1)
997
+ *
998
+ * SINGLE-KB-MOUNT P2/P3: the gateway stops touching the shared mount for
999
+ * bytes and proxies both directions here —
1000
+ *
1001
+ * PUT /content/:storageUri[?checksum=sha256hex] (storageUri URI-encoded
1002
+ * as one path segment; an optional checksum is verified BEFORE anything is
1003
+ * written, and a disagreement is a 409)
1004
+ *
1005
+ * GET /resources/:id/content (the bytes, streamed,
1006
+ * with the media type the record stores; the 404 carries `reason` so the
1007
+ * gateway can serve its two different not-found messages)
1008
+ *
1009
+ * **The addresses differ because the lifecycle does**, not by oversight: at
1010
+ * write time neither the resource nor its view exists — bytes land before the
1011
+ * event — so the write has only a tree address to be addressed by, while the
1012
+ * read has a record. Both go through ONE resolution (`representation.ts`);
1013
+ * neither restates where bytes live.
1014
+ *
1015
+ * The write is `noGit` and emits nothing: the event contract is untouched —
1016
+ * the Stower still `register`s the bytes from disk and does the one `git add`
1017
+ * on event apply (GATEWAY.md D4b, single-writer).
1018
+ *
1019
+ * Auth: callers authenticate with the same SEMIONT_WORKER_SECRET the
1020
+ * agent-token flow uses — service-to-service, one shared deployment fact.
1021
+ * With no secret configured, every path but /health refuses loudly (503)
1022
+ * rather than serving unauthenticated: absence fails, it is never a
1023
+ * default-open.
1024
+ */
1025
+
1026
+ interface ArchivistServerDeps {
1027
+ /** The record's log — the read half only. */
1028
+ events: Pick<EventLog, 'queryEvents'>;
1029
+ /** The KB tree's byte paths. `register` and the git index stay the
1030
+ * Stower's on event apply; reads go through `resolveRepresentation`. */
1031
+ content: Pick<WorkingTreeStore, 'store' | 'retrieveStream'>;
1032
+ /** The record's views — the resource half of the one resolution. */
1033
+ views: Pick<ViewStorage, 'get'>;
1034
+ /** Shared service secret; empty disables everything but /health (503), never opens it. */
1035
+ workerSecret: string;
1036
+ /** Liveness payload for /health — actor states, counters. */
1037
+ health: () => Record<string, unknown>;
1038
+ /**
1039
+ * The KB working tree's current branch, `null` outside a git checkout.
1040
+ *
1041
+ * A live fact about the tree, so it is answered by the process that HOLDS
1042
+ * the tree (SINGLE-KB-MOUNT P5). The gateway used to read it off its own
1043
+ * `/kb` mount; the launcher cannot stage it because a branch switch does
1044
+ * not restart the stack, and a staged value would quietly go stale.
1045
+ */
1046
+ branch: () => string | null;
1047
+ logger: Logger;
1048
+ }
1049
+ declare function createArchivistServer(deps: ArchivistServerDeps): Server;
1050
+
1051
+ /**
1052
+ * LocalTransport — `ITransport` onto an in-process make-meaning `EventBus`.
1053
+ *
1054
+ * It takes NO knowledge system. This is a bus transport: it publishes emits
1055
+ * onto the bus and bridges the reply channels back. It never touched a
1056
+ * `KnowledgeSystem` — the field that used to be here was declared and never
1057
+ * read, which made the transport look coupled to the monolith's shape when it
1058
+ * is coupled only to the bus. Whatever process hosts the actors on that bus
1059
+ * satisfies it.
570
1060
  *
571
1061
  * Bus-ownership pattern (see `docs/protocol/TRANSPORT-CONTRACT.md`):
572
1062
  * - The caller owns a make-meaning `EventBus` and passes it to both
573
1063
  * `startMakeMeaning` and `LocalTransport` so the transport can publish
574
- * directly onto the bus the `KnowledgeSystem` actors are listening on.
1064
+ * directly onto the bus the actors are listening on.
575
1065
  * - `SemiontClient` constructs its own `clientBus` and calls
576
1066
  * `bridgeInto(clientBus)` during construction. `LocalTransport`
577
1067
  * subscribes to every `BRIDGED_CHANNELS` entry on the make-meaning bus
@@ -579,22 +1069,17 @@ declare function startMakeMeaning(project: SemiontProject, config: MakeMeaningCo
579
1069
  * - The bus reference flows client → transport, never the other way.
580
1070
  *
581
1071
  * LocalTransport implements `ITransport` only. Auth, admin, and exchange
582
- * (`IBackendOperations`) are HTTP-shaped concepts that don't apply
1072
+ * (`IGatewayOperations`) are HTTP-shaped concepts that don't apply
583
1073
  * in-process — local mode runs as a single host-process identity supplied
584
1074
  * at construction, with no token/credential lifecycle. A `SemiontClient`
585
1075
  * built over this transport has no `.auth` / `.admin` namespaces.
586
1076
  */
587
1077
 
588
1078
  interface LocalTransportConfig {
589
- /**
590
- * The in-process knowledge system. Lifetime is owned by the caller —
591
- * `dispose()` on this transport does not stop the KnowledgeSystem.
592
- */
593
- knowledgeSystem: KnowledgeSystem;
594
1079
  /**
595
1080
  * The make-meaning `EventBus`. Must be the same instance passed to
596
- * `startMakeMeaning` so that emits land on the bus KnowledgeSystem
597
- * actors are subscribed to.
1081
+ * `startMakeMeaning` so that emits land on the bus the actors are
1082
+ * subscribed to.
598
1083
  */
599
1084
  eventBus: EventBus;
600
1085
  /**
@@ -641,8 +1126,13 @@ declare class LocalTransport implements ITransport {
641
1126
  }
642
1127
 
643
1128
  /**
644
- * LocalContentTransport — `IContentTransport` for an in-process
645
- * `KnowledgeSystem`.
1129
+ * LocalContentTransport — `IContentTransport` over an in-process
1130
+ * `KnowledgeBase`.
1131
+ *
1132
+ * Takes the KB, not the whole `KnowledgeSystem`: every read below goes through
1133
+ * `kb.*` and no actor is ever touched. The wider parameter forced callers that
1134
+ * legitimately hold only a KB to cast (`representation.test.ts` used
1135
+ * `as never`), which is a cast hiding nothing but an over-wide signature.
646
1136
  *
647
1137
  * Reads go straight to `kb.views` (resource lookup) + `kb.content`
648
1138
  * (byte retrieval). No network, no auth — local mode runs as a single
@@ -657,8 +1147,8 @@ declare class LocalTransport implements ITransport {
657
1147
 
658
1148
  type GetResourceResponse = components['schemas']['GetResourceResponse'];
659
1149
  declare class LocalContentTransport implements IContentTransport {
660
- private readonly ks;
661
- constructor(ks: KnowledgeSystem);
1150
+ private readonly kb;
1151
+ constructor(kb: KnowledgeBase);
662
1152
  putBinary(_request: PutBinaryRequest, _options?: PutBinaryOptions): Promise<{
663
1153
  resourceId: ResourceId;
664
1154
  }>;
@@ -704,6 +1194,12 @@ declare class LocalContentTransport implements IContentTransport {
704
1194
  stream: ReadableStream<Uint8Array>;
705
1195
  contentType: string;
706
1196
  }>;
1197
+ /**
1198
+ * The same resolution the wire path serves, buffered — local and hosted
1199
+ * modes must answer identically, which they did not before
1200
+ * SINGLE-KB-MOUNT P3: this resolved through `representations[].storageUri`,
1201
+ * a field `ViewMaterializer` never writes, so every binary read here threw.
1202
+ */
707
1203
  private loadBinary;
708
1204
  /**
709
1205
  * Assemble the resource's JSON-LD graph in-process from the KB — the local
@@ -718,7 +1214,7 @@ declare class LocalContentTransport implements IContentTransport {
718
1214
 
719
1215
  /**
720
1216
  * Adapt a raw in-process `EventBus` to the `BusRequestPrimitive` that
721
- * `busRequest` consumes. Lets backend-internal callers (bootstrap, event
1217
+ * `busRequest` consumes. Lets gateway-internal callers (bootstrap, event
722
1218
  * replay, linked-data import) use the same confirmed request/reply path as the
723
1219
  * SDK — `busRequest(asBusRequestPrimitive(eventBus), …)` — instead of
724
1220
  * hand-rolled `race(domain-event, *-failed, timeout)` blocks. The reply is
@@ -742,13 +1238,42 @@ declare function asBusRequestPrimitive(eventBus: EventBus): BusRequestPrimitive;
742
1238
  *
743
1239
  * This is a deferred-ack pattern: the result event attests that Stower has
744
1240
  * persisted the annotation, not merely that the command was well-formed.
1241
+ *
1242
+ * ## The annotatability gate (MEDIA-CAPABILITY-DISPATCH D6)
1243
+ *
1244
+ * Every GUI and SDK caller travels `mark:create-request` and is checked here.
1245
+ * The check is deliberately NOT on `mark:create`, which Stower consumes: that
1246
+ * channel is the fact-writing path, and gating it would need a leniency flag
1247
+ * for restore — the compatibility switch D6 was written to avoid.
1248
+ *
1249
+ * D6's original second emitter, the TypeScript import/replay path, was deleted
1250
+ * by EXPORT-VIA-LAUNCHER P3 (2026-08-27), so nothing travels the ungated
1251
+ * channel today. The separation is kept anyway, because restore returns in the
1252
+ * launcher and its fact-writing seam is still an open decision (that plan's
1253
+ * P5) — a restore that re-subjected historical facts to this gate would be the
1254
+ * 2026-07-09 "events are facts, commands are requests" ruling undone.
745
1255
  */
746
- declare function registerAnnotationAssemblyHandler(eventBus: EventBus, parentLogger: Logger): void;
1256
+ declare function registerAnnotationAssemblyHandler(eventBus: EventBus, kb: {
1257
+ views: Pick<ViewStorage, 'get'>;
1258
+ }, parentLogger: Logger): void;
747
1259
 
748
- interface Gatherer {
749
- generateAnnotationSummary(annId: AnnotationId, resId: ResourceId): Promise<Record<string, unknown>>;
750
- }
751
- declare function registerAnnotationLookupHandlers(eventBus: EventBus, kb: KnowledgeBase, gatherer: Gatherer, parentLogger: Logger): void;
1260
+ /**
1261
+ * Annotation lookup handlers — split along the EXTRACT-LIBRARIAN P3 cutover:
1262
+ *
1263
+ * - `browse:annotation-context-requested` is a pure views+content read with
1264
+ * no Gatherer. It registers wherever those capabilities live — the gateway
1265
+ * and the standalone root.
1266
+ * - `gather:summary-requested` calls the Gatherer's inference path, so it
1267
+ * follows the Gatherer (the Archivist's D2-i pattern): the standalone root
1268
+ * and librarian-main register it beside their Gatherer; the gateway does
1269
+ * NOT.
1270
+ */
1271
+
1272
+ declare function registerAnnotationContextHandler(eventBus: EventBus, kb: {
1273
+ views: Pick<ViewStorage, 'get'>;
1274
+ content: ContentReads;
1275
+ }, parentLogger: Logger): void;
1276
+ declare function registerGatherSummaryHandler(eventBus: EventBus, gatherer: Pick<Gatherer, 'generateAnnotationSummary'>, parentLogger: Logger): void;
752
1277
 
753
1278
  /**
754
1279
  * Handles `bind:update-body` — the Bind flow's authoritative "apply body
@@ -768,7 +1293,7 @@ declare function registerAnnotationLookupHandlers(eventBus: EventBus, kb: Knowle
768
1293
  */
769
1294
  declare function registerBindUpdateBodyHandler(eventBus: EventBus, parentLogger: Logger): void;
770
1295
 
771
- declare function registerJobCommandHandlers(eventBus: EventBus, jobQueue: JobQueue, project: SemiontProject, parentLogger: Logger): void;
1296
+ declare function registerJobCommandHandlers(eventBus: EventBus, jobQueue: JobQueue, state: SemiontState, parentLogger: Logger): void;
772
1297
 
773
1298
  /**
774
1299
  * Bus command handlers — pure bus-event translators that bridge the
@@ -777,7 +1302,7 @@ declare function registerJobCommandHandlers(eventBus: EventBus, jobQueue: JobQue
777
1302
  * `gather:summary-requested`) to the underlying make-meaning pipeline
778
1303
  * (Stower, Browser, Gatherer, JobQueue).
779
1304
  *
780
- * These ran in `apps/backend` historically because the HTTP gateway was
1305
+ * These ran in `apps/gateway` historically because the HTTP gateway was
781
1306
  * the only consumer that needed them. They are not HTTP-specific — moving
782
1307
  * them here means `LocalTransport` consumers (and any future transport)
783
1308
  * get the same contract automatically.
@@ -787,7 +1312,7 @@ declare function registerJobCommandHandlers(eventBus: EventBus, jobQueue: JobQue
787
1312
  * Register all bus command handlers on the make-meaning EventBus. Called
788
1313
  * during `startMakeMeaning` after the JobQueue and KnowledgeSystem exist.
789
1314
  */
790
- declare function registerBusHandlers(eventBus: EventBus, knowledgeSystem: KnowledgeSystem, jobQueue: JobQueue, project: SemiontProject, logger: Logger): void;
1315
+ declare function registerBusHandlers(eventBus: EventBus, knowledgeSystem: Pick<KnowledgeSystem, 'kb' | 'gatherer'>, jobQueue: JobQueue, state: SemiontState, logger: Logger): void;
791
1316
 
792
1317
  /**
793
1318
  * Entity Types Bootstrap
@@ -824,7 +1349,7 @@ declare function bootstrapEntityTypes(eventBus: EventBus, eventStore: EventStore
824
1349
  /**
825
1350
  * Read entity types from view storage projection
826
1351
  */
827
- declare function readEntityTypesProjection(project: SemiontProject): Promise<string[]>;
1352
+ declare function readEntityTypesProjection(state: SemiontState): Promise<string[]>;
828
1353
 
829
1354
  /**
830
1355
  * SmelterActorStateUnit — domain-event fan-in for the Smelter worker.
@@ -862,8 +1387,8 @@ declare function createSmelterActorStateUnit(options: SmelterActorStateUnitOptio
862
1387
  *
863
1388
  * Consumes the smelter-relevant domain events surfaced by
864
1389
  * `SmelterActorStateUnit.events$`, reads resource content via the injected
865
- * `IContentTransport` (HTTP verbatim mode in worker deployments — the
866
- * stored bytes, untouched), chunks and embeds it via the configured
1390
+ * `ContentReads` (in the fleet, the Archivist's byte route — the stored
1391
+ * bytes, untouched), chunks and embeds it via the configured
867
1392
  * EmbeddingProvider, and indexes vectors into the VectorStore (Qdrant).
868
1393
  * `smelter-main` is the container entry point that wires this up.
869
1394
  *
@@ -950,7 +1475,19 @@ declare class Smelter {
950
1475
  private rebuildAnchors$;
951
1476
  private vectorStore;
952
1477
  private embeddingProvider;
1478
+ /** Byte reads only — the Smelter never writes through this seam, so it
1479
+ * declares `ContentReads` and any implementation satisfies it: the
1480
+ * Archivist's client in the fleet, the working tree in-process. */
953
1481
  private content;
1482
+ /**
1483
+ * The anchored-text store, held DIRECTLY (ANCHORED-TEXT-TO-SMELTER P1).
1484
+ *
1485
+ * It used to be built here over the content transport, which put the
1486
+ * gateway between this process and an artifact it produces itself. The
1487
+ * Smelter now owns the store on its own mount and is the only writer;
1488
+ * every read of it moved to the Archivist's bus channels.
1489
+ */
1490
+ private anchoredStore;
954
1491
  private bus;
955
1492
  private chunkingConfig;
956
1493
  private timing;
@@ -976,8 +1513,20 @@ declare class Smelter {
976
1513
  private drainChain;
977
1514
  constructor(events$: Observable<SmelterEvent>,
978
1515
  /** `smelt:rebuild-anchors` commands — a separate stream, never the event mailbox (see SmelterActorStateUnit). */
979
- rebuildAnchors$: Observable<EventMap['smelt:rebuild-anchors']>, vectorStore: VectorStore, embeddingProvider: EmbeddingProvider, content: IContentTransport, bus: BusRequestPrimitive, chunkingConfig: ChunkingConfig, timing: SmelterTiming, logger: Logger);
980
- private readonly anchoredStore;
1516
+ rebuildAnchors$: Observable<EventMap['smelt:rebuild-anchors']>, vectorStore: VectorStore, embeddingProvider: EmbeddingProvider,
1517
+ /** Byte reads only — the Smelter never writes through this seam, so it
1518
+ * declares `ContentReads` and any implementation satisfies it: the
1519
+ * Archivist's client in the fleet, the working tree in-process. */
1520
+ content: ContentReads,
1521
+ /**
1522
+ * The anchored-text store, held DIRECTLY (ANCHORED-TEXT-TO-SMELTER P1).
1523
+ *
1524
+ * It used to be built here over the content transport, which put the
1525
+ * gateway between this process and an artifact it produces itself. The
1526
+ * Smelter now owns the store on its own mount and is the only writer;
1527
+ * every read of it moved to the Archivist's bus channels.
1528
+ */
1529
+ anchoredStore: AnchoredTextStore, bus: BusRequestPrimitive, chunkingConfig: ChunkingConfig, timing: SmelterTiming, logger: Logger);
981
1530
  get eventsProcessed(): number;
982
1531
  get reconcileState(): ReconcileState;
983
1532
  initialize(): void;
@@ -1135,228 +1684,6 @@ declare class Smelter {
1135
1684
  private listAllResources;
1136
1685
  }
1137
1686
 
1138
- /**
1139
- * Exchange Format Manifest Types
1140
- *
1141
- * Defines the metadata structures for backup archives.
1142
- * The manifest is the first entry in an archive and describes its contents.
1143
- */
1144
- declare const BACKUP_FORMAT: "semiont-backup";
1145
- declare const FORMAT_VERSION = 1;
1146
- interface BackupManifestHeader {
1147
- format: typeof BACKUP_FORMAT;
1148
- version: number;
1149
- exportedAt: string;
1150
- sourceUrl: string;
1151
- stats: {
1152
- streams: number;
1153
- events: number;
1154
- blobs: number;
1155
- contentBytes: number;
1156
- };
1157
- }
1158
- interface BackupStreamSummary {
1159
- stream: string;
1160
- eventCount: number;
1161
- }
1162
- declare const LINKED_DATA_FORMAT: "semiont-linked-data";
1163
- interface LinkedDataManifest {
1164
- '@context': Record<string, string>;
1165
- '@type': string;
1166
- 'semiont:format': typeof LINKED_DATA_FORMAT;
1167
- 'semiont:version': number;
1168
- 'dct:created': string;
1169
- 'prov:wasGeneratedBy': {
1170
- '@type': string;
1171
- 'prov:used': string;
1172
- };
1173
- 'semiont:entityTypes': string[];
1174
- 'void:entities': number;
1175
- }
1176
- declare function isBackupManifest(obj: unknown): obj is BackupManifestHeader;
1177
- declare function validateManifestVersion(version: number): void;
1178
-
1179
- /**
1180
- * Backup Exporter
1181
- *
1182
- * Produces a lossless tar.gz archive of the system of record:
1183
- * - Event log (all streams, JSONL format)
1184
- * - Working-tree content (archived as checksum-named blobs)
1185
- *
1186
- * Reads events via EventStore and content via WorkingTreeStore.
1187
- * The archive can restore a complete knowledge base.
1188
- */
1189
-
1190
- /** Subset of EventStore used by the backup exporter. */
1191
- interface BackupEventStoreReader {
1192
- log: {
1193
- storage: {
1194
- getAllResourceIds(): Promise<ResourceId[]>;
1195
- };
1196
- getEvents(resourceId: ResourceId): Promise<StoredEvent[]>;
1197
- };
1198
- }
1199
- /** Subset of WorkingTreeStore used by the backup exporter. */
1200
- interface BackupContentReader {
1201
- retrieve(storageUri: string): Promise<Buffer>;
1202
- }
1203
- interface BackupExporterOptions {
1204
- eventStore: BackupEventStoreReader;
1205
- content: BackupContentReader;
1206
- sourceUrl: string;
1207
- logger?: Logger;
1208
- }
1209
- /**
1210
- * Export a full backup of the knowledge base to a tar.gz stream.
1211
- *
1212
- * Archive structure:
1213
- * .semiont/manifest.jsonl - Format metadata + per-stream checksums
1214
- * .semiont/events/__system__.jsonl - System events
1215
- * .semiont/events/{resourceId}.jsonl - Per-resource events
1216
- * {checksum}.{ext} - Content blobs (root level)
1217
- */
1218
- declare function exportBackup(options: BackupExporterOptions, output: Writable): Promise<BackupManifestHeader>;
1219
-
1220
- /**
1221
- * Event Replay
1222
- *
1223
- * Replays parsed JSONL event streams through the EventBus.
1224
- * Each domain event is translated to the corresponding command event
1225
- * (e.g. yield:created → yield:create), emitted, and the result
1226
- * event is awaited before proceeding (backpressure).
1227
- *
1228
- * Content blobs are resolved lazily via a lookup function so that
1229
- * the caller controls memory strategy (streaming, on-disk, etc.).
1230
- */
1231
-
1232
- /**
1233
- * Resolves a content blob by its checksum.
1234
- * Returned by the caller so replay doesn't dictate memory strategy.
1235
- */
1236
- type ContentBlobResolver = (checksum: string) => Buffer | undefined;
1237
- interface ReplayStats {
1238
- eventsReplayed: number;
1239
- resourcesCreated: number;
1240
- annotationsCreated: number;
1241
- entityTypesAdded: number;
1242
- }
1243
-
1244
- /**
1245
- * Backup Importer
1246
- *
1247
- * Restores a knowledge base from a backup tar.gz archive.
1248
- * Replays events through the EventBus → Stower pipeline so all
1249
- * derived state (materialized views, graph) rebuilds naturally.
1250
- *
1251
- * Accepts a Readable stream so callers can pipe directly from disk
1252
- * or network without buffering the entire archive first.
1253
- * Content blobs are resolved lazily via a closure over the parsed
1254
- * tar entries, avoiding a separate copy of all blob data in memory.
1255
- */
1256
-
1257
- interface BackupImporterOptions {
1258
- eventBus: EventBus;
1259
- /** Replay appends historical events directly (facts, not commands). */
1260
- eventStore: EventStore;
1261
- contentStore: WorkingTreeStore;
1262
- logger?: Logger;
1263
- }
1264
- interface BackupImportResult {
1265
- manifest: BackupManifestHeader;
1266
- stats: ReplayStats;
1267
- }
1268
- /**
1269
- * Import a backup archive by replaying events through the EventBus.
1270
- *
1271
- * Flow:
1272
- * 1. Stream and decompress tar.gz entries
1273
- * 2. Parse .semiont/manifest.jsonl → validate format
1274
- * 3. Build blob resolver over root-level content entries
1275
- * 4. Replay .semiont/events/__system__.jsonl (entity types)
1276
- * 5. Replay each .semiont/events/{resourceId}.jsonl (resources, annotations)
1277
- *
1278
- * Events flow: importer → EventBus → Stower → EventStore + Views
1279
- */
1280
- declare function importBackup(archive: Readable, options: BackupImporterOptions): Promise<BackupImportResult>;
1281
-
1282
- /**
1283
- * Linked Data Exporter
1284
- *
1285
- * Produces a JSON-LD tar.gz archive from the current state of the knowledge base.
1286
- * Reads materialized views (not the event log) for a fast, current-state export.
1287
- *
1288
- * Archive structure:
1289
- * .semiont/manifest.jsonld - JSON-LD manifest with format metadata
1290
- * .semiont/resources/{resourceId}.jsonld - One JSON-LD document per resource
1291
- * {checksum}.{ext} - Content blobs (root level)
1292
- */
1293
-
1294
- /** Subset of ViewStorage used by the linked-data exporter. */
1295
- interface LinkedDataViewReader {
1296
- getAll(): Promise<Array<{
1297
- resource: ResourceDescriptor;
1298
- annotations: {
1299
- annotations: Annotation[];
1300
- };
1301
- }>>;
1302
- }
1303
- /** Subset of WorkingTreeStore used by the linked-data exporter. */
1304
- interface LinkedDataContentReader {
1305
- retrieve(storageUri: string): Promise<Buffer>;
1306
- }
1307
- interface LinkedDataExporterOptions {
1308
- views: LinkedDataViewReader;
1309
- content: LinkedDataContentReader;
1310
- sourceUrl: string;
1311
- entityTypes: string[];
1312
- includeArchived?: boolean;
1313
- logger?: Logger;
1314
- }
1315
- /**
1316
- * Export the knowledge base as a JSON-LD tar.gz archive.
1317
- */
1318
- declare function exportLinkedData(options: LinkedDataExporterOptions, output: Writable): Promise<LinkedDataManifest>;
1319
-
1320
- /**
1321
- * Linked Data Importer
1322
- *
1323
- * Creates resources from a JSON-LD tar.gz archive exported by the linked-data exporter.
1324
- * Unlike the backup importer, this is lossy — new resources are created (new IDs),
1325
- * no event history is preserved. Entity types are restored from the manifest.
1326
- *
1327
- * Parses .semiont/manifest.jsonld for format validation and entity types,
1328
- * then processes each .semiont/resources/{resourceId}.jsonld to create
1329
- * resources and annotations via the EventBus → Stower pipeline.
1330
- */
1331
-
1332
- interface LinkedDataImporterOptions {
1333
- eventBus: EventBus;
1334
- contentStore: WorkingTreeStore;
1335
- userId: UserId;
1336
- logger?: Logger;
1337
- }
1338
- interface LinkedDataImportResult {
1339
- manifest: LinkedDataManifest;
1340
- resourcesCreated: number;
1341
- annotationsCreated: number;
1342
- entityTypesAdded: number;
1343
- }
1344
- /**
1345
- * Import a JSON-LD archive by creating resources through the EventBus.
1346
- *
1347
- * Flow:
1348
- * 1. Stream and decompress tar.gz entries
1349
- * 2. Parse .semiont/manifest.jsonld → validate format
1350
- * 3. Build blob resolver over root-level content entries
1351
- * 4. Add entity types from manifest via frame:add-entity-type
1352
- * 5. For each .semiont/resources/{id}.jsonld:
1353
- * a. Parse JSON-LD document
1354
- * b. Resolve content blob by checksum from representations
1355
- * c. Emit yield:create → await yield:created
1356
- * d. For each annotation: emit mark:create → await mark:created
1357
- */
1358
- declare function importLinkedData(archive: Readable, options: LinkedDataImporterOptions): Promise<LinkedDataImportResult>;
1359
-
1360
1687
  /**
1361
1688
  * Resource Operations
1362
1689
  *
@@ -1390,6 +1717,39 @@ declare class ResourceOperations {
1390
1717
  * Create a new resource via EventBus → Stower
1391
1718
  */
1392
1719
  static createResource(input: CreateResourceInput, userId: UserId, eventBus: EventBus): Promise<ResourceId>;
1720
+ /**
1721
+ * Persist a CLONE via EventBus → Stower.
1722
+ *
1723
+ * Separate from `createResource` because a clone is a separate fact: it
1724
+ * names its parent, and `yield:cloned` requires that name. Callers reach
1725
+ * this only after the CloneTokenManager has validated the token — it is the
1726
+ * inner half of the flow, not a public entry point.
1727
+ */
1728
+ static persistClone(input: {
1729
+ name: string;
1730
+ storageUri: string;
1731
+ contentChecksum: string;
1732
+ byteSize: number;
1733
+ format: ContentFormat;
1734
+ parentResourceId: string;
1735
+ entityTypes?: string[];
1736
+ language?: string;
1737
+ }, userId: UserId, eventBus: EventBus): Promise<ResourceId>;
1738
+ /**
1739
+ * Create a resource from a clone token via EventBus → CloneTokenManager.
1740
+ * The bytes are already stored (the gateway's upload path, `noGit` — the
1741
+ * Archivist's register does the one `git add`, D4b); the command carries
1742
+ * storage coordinates only (EXTRACT-ARCHIVIST P3, D4a).
1743
+ */
1744
+ static createFromCloneToken(input: {
1745
+ token: string;
1746
+ name: string;
1747
+ storageUri: string;
1748
+ contentChecksum: string;
1749
+ byteSize: number;
1750
+ format: ContentFormat;
1751
+ archiveOriginal?: boolean;
1752
+ }, userId: UserId, eventBus: EventBus): Promise<ResourceId>;
1393
1753
  }
1394
1754
 
1395
1755
  /**
@@ -1418,15 +1778,21 @@ declare class AnnotationOperations {
1418
1778
  /**
1419
1779
  * Create a new annotation via EventBus → Stower
1420
1780
  */
1421
- static createAnnotation(request: CreateAnnotationRequest, userId: UserId, creator: Agent, eventBus: EventBus): Promise<CreateAnnotationResult>;
1781
+ static createAnnotation(request: CreateAnnotationRequest, userId: UserId, creator: Agent, eventBus: EventBus, kb: {
1782
+ views: Pick<ViewStorage, 'get'>;
1783
+ }): Promise<CreateAnnotationResult>;
1422
1784
  /**
1423
1785
  * Update annotation body via EventBus → Stower
1424
1786
  */
1425
- static updateAnnotationBody(id: string, request: UpdateAnnotationBodyRequest, userId: UserId, eventBus: EventBus, kb: KnowledgeBase): Promise<UpdateAnnotationBodyResult>;
1787
+ static updateAnnotationBody(id: string, request: UpdateAnnotationBodyRequest, userId: UserId, eventBus: EventBus, kb: {
1788
+ views: Pick<ViewStorage, 'get'>;
1789
+ }): Promise<UpdateAnnotationBodyResult>;
1426
1790
  /**
1427
1791
  * Delete an annotation via EventBus → Stower
1428
1792
  */
1429
- static deleteAnnotation(id: string, resourceIdStr: string, userId: UserId, eventBus: EventBus, kb: KnowledgeBase, logger?: Logger): Promise<void>;
1793
+ static deleteAnnotation(id: string, resourceIdStr: string, userId: UserId, eventBus: EventBus, kb: {
1794
+ views: Pick<ViewStorage, 'get'>;
1795
+ }, logger?: Logger): Promise<void>;
1430
1796
  }
1431
1797
 
1432
1798
  /**
@@ -1439,6 +1805,14 @@ declare class AnnotationOperations {
1439
1805
  * single-index reads; anything that FUSES sources belongs to the Matcher.
1440
1806
  */
1441
1807
 
1808
+ /** What the listing paths read (EXTRACT-ARCHIVIST P1): lexical search in
1809
+ * the graph, unsearched listings from views, the semantic fallback in the
1810
+ * vector index — plus `resourceWithViewGrace`'s graph-first hydration. */
1811
+ interface ListResourcesReads {
1812
+ views: Pick<ViewStorage, 'get' | 'getAll'>;
1813
+ graph: Pick<GraphDatabase, 'listResources' | 'getResource'>;
1814
+ vectors: Pick<VectorStore, 'searchResources'>;
1815
+ }
1442
1816
  interface ListResourcesFilters {
1443
1817
  search?: string;
1444
1818
  archived?: boolean;
@@ -1481,7 +1855,9 @@ declare class ResourceContext {
1481
1855
  /**
1482
1856
  * Get resource metadata from view storage
1483
1857
  */
1484
- static getResourceMetadata(resourceId: ResourceId, kb: KnowledgeBase): Promise<ResourceDescriptor | null>;
1858
+ static getResourceMetadata(resourceId: ResourceId, kb: {
1859
+ views: Pick<ViewStorage, 'get'>;
1860
+ }): Promise<ResourceDescriptor | null>;
1485
1861
  /**
1486
1862
  * List resources, optionally filtered, as one page plus the size of the whole
1487
1863
  * match set. Every filter is applied before pagination on both paths — a
@@ -1496,7 +1872,7 @@ declare class ResourceContext {
1496
1872
  * barrier-stamped projection, so an unsearched listing is read-your-writes
1497
1873
  * where the graph is only eventually consistent.
1498
1874
  */
1499
- static listResources(filters: ListResourcesFilters | undefined, kb: KnowledgeBase, semantic: SemanticFallbackDeps): Promise<ListResourcesResult>;
1875
+ static listResources(filters: ListResourcesFilters | undefined, kb: ListResourcesReads, semantic: SemanticFallbackDeps): Promise<ListResourcesResult>;
1500
1876
  /**
1501
1877
  * Answer an empty lexical search from the vector index (SEMANTIC-FALLBACK):
1502
1878
  * embed the query once, fold chunk hits per resource, floor them, and label
@@ -1517,189 +1893,21 @@ declare class ResourceContext {
1517
1893
  * Add content previews to resources (for search results)
1518
1894
  * Retrieves and decodes the first 200 characters of each resource's primary representation
1519
1895
  */
1520
- static addContentPreviews(resources: ResourceDescriptor[], kb: KnowledgeBase): Promise<Array<ResourceDescriptor & {
1896
+ static addContentPreviews(resources: ResourceDescriptor[], kb: {
1897
+ content: Pick<WorkingTreeStore, 'retrieve'>;
1898
+ }): Promise<Array<ResourceDescriptor & {
1521
1899
  content: string;
1522
1900
  }>>;
1523
1901
  /**
1524
1902
  * Get full content for a resource
1525
- * Retrieves and decodes the primary representation
1526
- */
1527
- static getResourceContent(resource: ResourceDescriptor, kb: KnowledgeBase): Promise<string | undefined>;
1528
- }
1529
-
1530
- /**
1531
- * Annotation Context
1532
- *
1533
- * Assembles annotation context from view storage and content store.
1534
- * Provides methods for:
1535
- * - Getting resource annotations
1536
- * - Building LLM context for annotations
1537
- * - Extracting annotation text context
1538
- * - Generating AI summaries
1539
- */
1540
-
1541
- type AnnotationContextResponse = components['schemas']['AnnotationContextResponse'];
1542
- type ContextualSummaryResponse = components['schemas']['ContextualSummaryResponse'];
1543
- interface BuildContextOptions {
1544
- includeSourceContext?: boolean;
1545
- includeTargetContext?: boolean;
1546
- contextWindow?: number;
1547
- }
1548
- declare class AnnotationContext {
1549
- /**
1550
- * Build LLM context for an annotation
1551
- *
1552
- * @param annotationId - Bare annotation ID
1553
- * @param resourceId - Source resource ID
1554
- * @param kb - Knowledge base stores
1555
- * @param options - Context building options
1556
- * @param inferenceClient - Optional inference client for target context summary
1557
- * @returns Rich context for LLM processing
1558
- * @throws Error if annotation or resource not found
1559
- */
1560
- static buildLLMContext(annotationId: AnnotationId, resourceId: ResourceId, kb: KnowledgeBase, embeddingProvider: EmbeddingProvider, options?: BuildContextOptions, inferenceClient?: InferenceClient, logger?: Logger): Promise<GatheredContext>;
1561
- /**
1562
- * Get resource annotations from view storage (fast path)
1563
- * Throws if view missing
1564
- */
1565
- static getResourceAnnotations(resourceId: ResourceId, kb: KnowledgeBase): Promise<ResourceAnnotations>;
1566
- /**
1567
- * Get all annotations
1568
- * @returns Array of all annotation objects
1569
- */
1570
- static getAllAnnotations(resourceId: ResourceId, kb: KnowledgeBase): Promise<Annotation[]>;
1571
- /**
1572
- * Enrich reference annotations with resolved document names
1573
- * Adds _resolvedDocumentName property to annotations that link to documents
1574
- * @private
1575
- */
1576
- private static enrichResolvedReferences;
1577
- /**
1578
- * Get resource stats (version info)
1579
- * @returns Version and timestamp info for the annotations
1580
- */
1581
- static getResourceStats(resourceId: ResourceId, kb: KnowledgeBase): Promise<{
1582
- resourceId: ResourceId;
1583
- version: number;
1584
- updatedAt: string;
1585
- }>;
1586
- /**
1587
- * Check if resource exists in view storage
1588
- */
1589
- static resourceExists(resourceId: ResourceId, kb: KnowledgeBase): Promise<boolean>;
1590
- /**
1591
- * Get a single annotation by ID
1592
- * O(1) lookup using resource ID to access view storage
1593
- */
1594
- static getAnnotation(annotationId: AnnotationId, resourceId: ResourceId, kb: KnowledgeBase): Promise<Annotation | null>;
1595
- /**
1596
- * List annotations with optional filtering
1597
- * @param filters - Optional filters like resourceId and type
1598
- * @throws Error if resourceId not provided (cross-resource queries not supported in view storage)
1599
- */
1600
- static listAnnotations(filters: {
1601
- resourceId?: ResourceId;
1602
- type?: AnnotationCategory;
1603
- } | undefined, kb: KnowledgeBase): Promise<Annotation[]>;
1604
- /**
1605
- * Get annotation context (selected text with surrounding context)
1606
- */
1607
- static getAnnotationContext(annotationId: AnnotationId, resourceId: ResourceId, contextBefore: number, contextAfter: number, kb: KnowledgeBase): Promise<AnnotationContextResponse>;
1608
- /**
1609
- * Generate AI summary of annotation in context
1610
- */
1611
- static generateAnnotationSummary(annotationId: AnnotationId, resourceId: ResourceId, kb: KnowledgeBase, inferenceClient: InferenceClient): Promise<ContextualSummaryResponse>;
1612
- /**
1613
- * Get resource content as string
1614
- */
1615
- private static getResourceContent;
1616
- /**
1617
- * Extract annotation context from resource content
1618
- */
1619
- private static extractAnnotationContext;
1620
- /**
1621
- * Generate LLM summary of annotation in context
1622
- * Creates inference client per-request (HTTP handler context)
1623
- */
1624
- private static generateSummary;
1625
- }
1626
-
1627
- /**
1628
- * Graph Context
1629
- *
1630
- * Provides graph database operations for resources and annotations.
1631
- * All methods require graph traversal - must use graph database.
1632
- */
1633
-
1634
- type KnowledgeGraph = components['schemas']['KnowledgeGraph'];
1635
- declare class GraphContext {
1636
- /**
1637
- * Get all resources referencing this resource (backlinks)
1638
- * Requires graph traversal - must use graph database
1639
- */
1640
- static getBacklinks(resourceId: ResourceId, kb: KnowledgeBase): Promise<Annotation[]>;
1641
- /**
1642
- * Find shortest path between two resources
1643
- * Requires graph traversal - must use graph database
1644
- */
1645
- static findPath(fromResourceId: ResourceId, toResourceId: ResourceId, kb: KnowledgeBase, maxDepth?: number): Promise<GraphPath[]>;
1646
- /**
1647
- * Get resource connections (graph edges)
1648
- * Requires graph traversal - must use graph database
1649
- */
1650
- static getResourceConnections(resourceId: ResourceId, kb: KnowledgeBase): Promise<GraphConnection[]>;
1651
- /**
1652
- * Build the unified knowledge graph for a resource's neighborhood:
1653
- * resources AND annotations as typed nodes, typed/directional edges.
1654
- *
1655
- * This is the single graph builder (CONTEXT-UNIFICATION D3) — both the
1656
- * matcher (ranking) and the resource/viz path consume it. The flattened
1657
- * signals the matcher reads today (`connections`, `citedBy`/count,
1658
- * `siblingEntityTypes`, `bidirectional`) are all derivable from this:
1659
- * - peer connections → resource nodes + main→peer edges carrying `bidirectional`
1660
- * - inbound citations → citing-resource nodes + `citation` edges (citing→main),
1661
- * so citedByCount = inbound citation-edge count
1662
- * - annotations on the resource → `annotation` nodes + `annotation-of` edges,
1663
- * so siblingEntityTypes = union of those nodes' entityTypes
1664
- */
1665
- static buildKnowledgeGraph(resourceId: ResourceId, kb: KnowledgeBase,
1666
- /** Breadcrumb sink for the projection-lag degrade path; the degrade counter fires regardless. */
1667
- logger?: Logger): Promise<KnowledgeGraph>;
1668
- }
1669
-
1670
- /**
1671
- * LLM Context
1672
- *
1673
- * Builds comprehensive context for LLM processing of resources
1674
- * Orchestrates: ResourceContext, GraphContext, AnnotationContext, and generation functions
1675
- */
1676
-
1677
- interface LLMContextOptions {
1678
- depth: number;
1679
- maxResources: number;
1680
- includeContent: boolean;
1681
- includeSummary: boolean;
1682
- /**
1683
- * Entity types to exclude from the resource-gather semantic recall
1684
- * (caller-supplied; e.g. ['Question']). Optional; default none.
1685
- */
1686
- excludeEntityTypes?: string[];
1687
- }
1688
- declare class LLMContext {
1689
- /**
1690
- * Get comprehensive LLM context for a resource
1691
- * Includes: main resource, related resources, annotations, graph, content, summary, references
1692
- */
1693
- static getResourceContext(resourceId: ResourceId, options: LLMContextOptions, kb: KnowledgeBase, inferenceClient: InferenceClient,
1694
- /**
1695
- * Bound on the semanticContext read-your-writes barrier
1696
- * (SMELTER-INDEX-SYNC D3/D5). Operator-owned deployment policy: born in
1697
- * `[environments.<env>.make-meaning.gather] settleTimeoutMs` (the TOML
1698
- * loader holds the ONE default, 15s), threaded here as a plain argument
1699
- * via `MakeMeaningConfig.gather` → Gatherer. Must nest inside downstream
1700
- * watchdogs (A4) — e.g. my-chat's 90s generation stall watchdog.
1701
- */
1702
- settleTimeoutMs: number, logger: Logger): Promise<GatheredContext>;
1903
+ * Retrieves and decodes the primary representation. ResourceId-keyed
1904
+ * (EXTRACT-LIBRARIAN P3, D-CONTENT b): the descriptor's `storageUri` is the
1905
+ * has-content signal; the fetch itself goes by id, so the standalone
1906
+ * Librarian serves it over the transport.
1907
+ */
1908
+ static getResourceContent(resource: ResourceDescriptor, kb: {
1909
+ content: ContentReads;
1910
+ }): Promise<string | undefined>;
1703
1911
  }
1704
1912
 
1705
1913
  /**
@@ -1722,5 +1930,5 @@ declare function generateResourceSummary(resourceName: string, content: string,
1722
1930
  */
1723
1931
  declare function generateReferenceSuggestions(referenceTitle: string, client: InferenceClient, entityType?: string, currentContent?: string): Promise<string[] | null>;
1724
1932
 
1725
- export { AnnotationContext, AnnotationOperations, BACKUP_FORMAT, Browser, CloneTokenManager, FORMAT_VERSION, Gatherer$1 as Gatherer, GraphContext, LLMContext, LocalContentTransport, LocalTransport, Matcher, ResourceContext, ResourceOperations, Smelter, Stower, asBusRequestPrimitive, bootstrapEntityTypes, createKnowledgeBase, createSmelterActorStateUnit, exportBackup, exportLinkedData, generateReferenceSuggestions, generateResourceSummary, importBackup, importLinkedData, isBackupManifest, readEntityTypesProjection, registerAnnotationAssemblyHandler, registerAnnotationLookupHandlers, registerBindUpdateBodyHandler, registerBusHandlers, registerJobCommandHandlers, startMakeMeaning, stopKnowledgeSystem, validateManifestVersion };
1726
- export type { BackupContentReader, BackupEventStoreReader, BackupExporterOptions, BackupImportResult, BackupImporterOptions, BackupManifestHeader, BackupStreamSummary, BuildContextOptions, ContentBlobResolver, CreateAnnotationResult, CreateResourceInput, CreateResourceResult, KnowledgeBase, KnowledgeSystem, LLMContextOptions, LinkedDataContentReader, LinkedDataExporterOptions, LinkedDataImportResult, LinkedDataImporterOptions, LinkedDataViewReader, ListResourcesFilters, ListResourcesResult, LocalTransportConfig, MakeMeaningConfig, MakeMeaningService, ReconcileState, ReconcileSummary, ReplayStats, SmelterActorStateUnit, SmelterActorStateUnitOptions, SmelterEvent, SmelterInput, SmelterTiming, SmelterWorkItem, UpdateAnnotationBodyResult };
1933
+ export { AnnotationContext, AnnotationOperations, Browser, CloneTokenManager, Gatherer, GraphContext, LLMContext, LocalContentTransport, LocalTransport, Matcher, ResourceContext, ResourceOperations, Smelter, Stower, asBusRequestPrimitive, bootstrapEntityTypes, createArchivistServer, createKnowledgeBase, createSmelterActorStateUnit, generateReferenceSuggestions, generateResourceSummary, makeMeaningConfigFrom, readEntityTypesProjection, registerAnnotationAssemblyHandler, registerAnnotationContextHandler, registerBindUpdateBodyHandler, registerBusHandlers, registerGatherSummaryHandler, registerJobCommandHandlers, requireKBName, startMakeMeaning, startMakeMeaningGateway, stopKnowledgeSystem };
1934
+ export type { ArchivistServerDeps, BuildContextOptions, CreateAnnotationResult, CreateResourceInput, CreateResourceResult, GatewayKnowledgeSystem, GatewayMakeMeaningService, KnowledgeBase, KnowledgeSystem, LLMContextOptions, ListResourcesFilters, ListResourcesResult, LocalTransportConfig, MakeMeaningConfig, MakeMeaningService, ReconcileState, ReconcileSummary, SmelterActorStateUnit, SmelterActorStateUnitOptions, SmelterEvent, SmelterInput, SmelterTiming, SmelterWorkItem, UpdateAnnotationBodyResult };