@semiont/make-meaning 0.5.28 → 0.5.29

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,15 +297,43 @@ 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;
@@ -277,6 +350,218 @@ declare class Stower {
277
350
  stop(): Promise<void>;
278
351
  }
279
352
 
353
+ /**
354
+ * Graph Context
355
+ *
356
+ * Provides graph database operations for resources and annotations.
357
+ * All methods require graph traversal - must use graph database.
358
+ */
359
+
360
+ /**
361
+ * What the unified graph builder reads (EXTRACT-LIBRARIAN P2) — Pick-derived,
362
+ * never restated. The weave fold is bus-fed (`weave:applied`), so this slice
363
+ * works identically in-process and in the standalone Librarian.
364
+ */
365
+ interface KnowledgeGraphReads {
366
+ graph: Pick<GraphDatabase, 'getResource' | 'getResourceConnections' | 'getResourceReferencedBy' | 'getResourceAnnotations'>;
367
+ views: Pick<ViewStorage, 'get'>;
368
+ weaveProgress: Pick<WeaveProgress, 'whenApplied'>;
369
+ }
370
+ type KnowledgeGraph = components['schemas']['KnowledgeGraph'];
371
+ declare class GraphContext {
372
+ /**
373
+ * Build the unified knowledge graph for a resource's neighborhood:
374
+ * resources AND annotations as typed nodes, typed/directional edges.
375
+ *
376
+ * This is the single graph builder (CONTEXT-UNIFICATION D3) — both the
377
+ * matcher (ranking) and the resource/viz path consume it. The flattened
378
+ * signals the matcher reads today (`connections`, `citedBy`/count,
379
+ * `siblingEntityTypes`, `bidirectional`) are all derivable from this:
380
+ * - peer connections → resource nodes + main→peer edges carrying `bidirectional`
381
+ * - inbound citations → citing-resource nodes + `citation` edges (citing→main),
382
+ * so citedByCount = inbound citation-edge count
383
+ * - annotations on the resource → `annotation` nodes + `annotation-of` edges,
384
+ * so siblingEntityTypes = union of those nodes' entityTypes
385
+ */
386
+ static buildKnowledgeGraph(resourceId: ResourceId, kb: KnowledgeGraphReads,
387
+ /** Breadcrumb sink for the projection-lag degrade path; the degrade counter fires regardless. */
388
+ logger?: Logger): Promise<KnowledgeGraph>;
389
+ }
390
+
391
+ /**
392
+ * Annotation Context
393
+ *
394
+ * Assembles annotation context from view storage and content store.
395
+ * Provides methods for:
396
+ * - Getting resource annotations
397
+ * - Building LLM context for annotations
398
+ * - Extracting annotation text context
399
+ * - Generating AI summaries
400
+ */
401
+
402
+ /** The view slice the annotation reads run on (EXTRACT-ARCHIVIST P1). */
403
+ type ViewGet = {
404
+ views: Pick<ViewStorage, 'get'>;
405
+ };
406
+ /**
407
+ * What the annotation-gather path reads (EXTRACT-LIBRARIAN P2; content
408
+ * re-keyed by D-CONTENT b) — the graph builder's slice plus this module's
409
+ * own reads. Pick-derived, never restated. In-process roots satisfy it with
410
+ * `workingTreeContentReads` over their `kb`; the Librarian passes
411
+ * `HttpContentTransport`.
412
+ */
413
+ interface AnnotationGatherReads {
414
+ views: Pick<ViewStorage, 'get'>;
415
+ content: ContentReads;
416
+ graph: KnowledgeGraphReads['graph'] & Pick<GraphDatabase, 'getEntityTypeStats'>;
417
+ vectors: Pick<VectorStore, 'searchAnnotations'>;
418
+ weaveProgress: KnowledgeGraphReads['weaveProgress'];
419
+ }
420
+
421
+ type AnnotationContextResponse = components['schemas']['AnnotationContextResponse'];
422
+ type ContextualSummaryResponse = components['schemas']['ContextualSummaryResponse'];
423
+ interface BuildContextOptions {
424
+ includeSourceContext?: boolean;
425
+ includeTargetContext?: boolean;
426
+ contextWindow?: number;
427
+ }
428
+ declare class AnnotationContext {
429
+ /**
430
+ * Build LLM context for an annotation
431
+ *
432
+ * @param annotationId - Bare annotation ID
433
+ * @param resourceId - Source resource ID
434
+ * @param kb - Knowledge base stores
435
+ * @param options - Context building options
436
+ * @param inferenceClient - Optional inference client for target context summary
437
+ * @returns Rich context for LLM processing
438
+ * @throws Error if annotation or resource not found
439
+ */
440
+ static buildLLMContext(annotationId: AnnotationId, resourceId: ResourceId, kb: AnnotationGatherReads, embeddingProvider: EmbeddingProvider, options?: BuildContextOptions, inferenceClient?: InferenceClient, logger?: Logger): Promise<GatheredContext>;
441
+ /**
442
+ * Get resource annotations from view storage (fast path)
443
+ * Throws if view missing
444
+ */
445
+ static getResourceAnnotations(resourceId: ResourceId, kb: ViewGet): Promise<ResourceAnnotations>;
446
+ /**
447
+ * Get all annotations
448
+ * @returns Array of all annotation objects
449
+ */
450
+ static getAllAnnotations(resourceId: ResourceId, kb: ViewGet): Promise<Annotation[]>;
451
+ /**
452
+ * Enrich reference annotations with resolved document names
453
+ * Adds _resolvedDocumentName property to annotations that link to documents
454
+ * @private
455
+ */
456
+ private static enrichResolvedReferences;
457
+ /**
458
+ * Get resource stats (version info)
459
+ * @returns Version and timestamp info for the annotations
460
+ */
461
+ static getResourceStats(resourceId: ResourceId, kb: ViewGet): Promise<{
462
+ resourceId: ResourceId;
463
+ version: number;
464
+ updatedAt: string;
465
+ }>;
466
+ /**
467
+ * Check if resource exists in view storage
468
+ */
469
+ static resourceExists(resourceId: ResourceId, kb: {
470
+ views: Pick<ViewStorage, 'exists'>;
471
+ }): Promise<boolean>;
472
+ /**
473
+ * Get a single annotation by ID
474
+ * O(1) lookup using resource ID to access view storage
475
+ */
476
+ static getAnnotation(annotationId: AnnotationId, resourceId: ResourceId, kb: ViewGet): Promise<Annotation | null>;
477
+ /**
478
+ * List annotations with optional filtering
479
+ * @param filters - Optional filters like resourceId and type
480
+ * @throws Error if resourceId not provided (cross-resource queries not supported in view storage)
481
+ */
482
+ static listAnnotations(filters: {
483
+ resourceId?: ResourceId;
484
+ type?: AnnotationCategory;
485
+ } | undefined, kb: ViewGet): Promise<Annotation[]>;
486
+ /**
487
+ * Get annotation context (selected text with surrounding context)
488
+ */
489
+ static getAnnotationContext(annotationId: AnnotationId, resourceId: ResourceId, contextBefore: number, contextAfter: number, kb: ViewGet & {
490
+ content: ContentReads;
491
+ }): Promise<AnnotationContextResponse>;
492
+ /**
493
+ * Generate AI summary of annotation in context
494
+ */
495
+ static generateAnnotationSummary(annotationId: AnnotationId, resourceId: ResourceId, kb: ViewGet & {
496
+ content: ContentReads;
497
+ }, inferenceClient: InferenceClient): Promise<ContextualSummaryResponse>;
498
+ /**
499
+ * Get resource content as string. ResourceId-keyed (D-CONTENT b): the
500
+ * primary representation's `storageUri` stays the has-content signal, the
501
+ * fetch goes by id.
502
+ */
503
+ private static getResourceContent;
504
+ /**
505
+ * Extract annotation context from resource content
506
+ */
507
+ private static extractAnnotationContext;
508
+ /**
509
+ * Generate LLM summary of annotation in context
510
+ * Creates inference client per-request (HTTP handler context)
511
+ */
512
+ private static generateSummary;
513
+ }
514
+
515
+ /**
516
+ * LLM Context
517
+ *
518
+ * Builds comprehensive context for LLM processing of resources
519
+ * Orchestrates: ResourceContext, GraphContext, AnnotationContext, and generation functions
520
+ */
521
+
522
+ /**
523
+ * What the resource-gather path reads (EXTRACT-LIBRARIAN P2; content re-keyed
524
+ * by D-CONTENT b) — the graph builder's slice plus this module's own reads.
525
+ * Pick-derived, never restated. In-process roots satisfy it with
526
+ * `workingTreeContentReads` over their `kb`; the Librarian passes
527
+ * `HttpContentTransport`.
528
+ */
529
+ interface ResourceGatherReads {
530
+ views: Pick<ViewStorage, 'get'>;
531
+ content: ContentReads;
532
+ graph: KnowledgeGraphReads['graph'];
533
+ vectors: Pick<VectorStore, 'searchByResource'>;
534
+ weaveProgress: KnowledgeGraphReads['weaveProgress'];
535
+ smeltProgress: Pick<SmeltProgress, 'whenSettled'>;
536
+ }
537
+ interface LLMContextOptions {
538
+ depth: number;
539
+ maxResources: number;
540
+ includeContent: boolean;
541
+ includeSummary: boolean;
542
+ /**
543
+ * Entity types to exclude from the resource-gather semantic recall
544
+ * (caller-supplied; e.g. ['Question']). Optional; default none.
545
+ */
546
+ excludeEntityTypes?: string[];
547
+ }
548
+ declare class LLMContext {
549
+ /**
550
+ * Get comprehensive LLM context for a resource
551
+ * Includes: main resource, related resources, annotations, graph, content, summary, references
552
+ */
553
+ static getResourceContext(resourceId: ResourceId, options: LLMContextOptions, kb: ResourceGatherReads, inferenceClient: InferenceClient,
554
+ /**
555
+ * Bound on the semanticContext read-your-writes barrier
556
+ * (SMELTER-INDEX-SYNC D3/D5). Operator-owned deployment policy: born in
557
+ * `[environments.<env>.make-meaning.gather] settleTimeoutMs` (the TOML
558
+ * loader holds the ONE default, 15s), threaded here as a plain argument
559
+ * via `MakeMeaningConfig.gather` → Gatherer. Must nest inside downstream
560
+ * watchdogs (A4) — e.g. my-chat's 90s generation stall watchdog.
561
+ */
562
+ settleTimeoutMs: number, logger: Logger): Promise<GatheredContext>;
563
+ }
564
+
280
565
  /**
281
566
  * Gatherer Actor
282
567
  *
@@ -303,8 +588,16 @@ declare class Stower {
303
588
  * by RPC-style services.
304
589
  */
305
590
 
306
- declare class Gatherer$1 {
307
- private kb;
591
+ /**
592
+ * The Gatherer's capability slice (EXTRACT-LIBRARIAN P2) — DERIVED as the
593
+ * intersection of the two gather paths' reads, never restated. A full
594
+ * `KnowledgeBase` satisfies it structurally; the standalone Librarian (P3)
595
+ * builds it from the shared stateDir (views), the network clients
596
+ * (graph/vectors), bus-fed progress folds, and D-CONTENT's answer (content).
597
+ */
598
+ type GathererStores = AnnotationGatherReads & ResourceGatherReads;
599
+ declare class Gatherer {
600
+ private stores;
308
601
  private eventBus;
309
602
  private inferenceClient;
310
603
  /** Settle bound for the resource-gather barrier — operator-owned config (D5), threaded from `MakeMeaningConfig.gather`. */
@@ -312,7 +605,7 @@ declare class Gatherer$1 {
312
605
  private embeddingProvider;
313
606
  private subscriptions;
314
607
  private readonly logger;
315
- constructor(kb: KnowledgeBase, eventBus: EventBus, inferenceClient: InferenceClient,
608
+ constructor(stores: GathererStores, eventBus: EventBus, inferenceClient: InferenceClient,
316
609
  /** Settle bound for the resource-gather barrier — operator-owned config (D5), threaded from `MakeMeaningConfig.gather`. */
317
610
  settleTimeoutMs: number, logger: Logger, embeddingProvider: EmbeddingProvider);
318
611
  initialize(): Promise<void>;
@@ -335,14 +628,27 @@ declare class Gatherer$1 {
335
628
  * is available from auth context.
336
629
  */
337
630
 
631
+ /**
632
+ * The Matcher's capability slice (EXTRACT-LIBRARIAN P1) — Pick-derived,
633
+ * never restated. `graph.getResource` + `views.get` are
634
+ * `resourceWithViewGrace`'s two halves: the view fallback is a
635
+ * filesystem-backed projection read, served to the standalone service by
636
+ * the shared stateDir mount (D6), and to in-process callers by the same
637
+ * `kb` object, which satisfies this slice structurally.
638
+ */
639
+ interface MatcherStores {
640
+ graph: Pick<GraphDatabase, 'listResources' | 'getResource'>;
641
+ views: Pick<ViewStorage, 'get'>;
642
+ vectors: Pick<VectorStore, 'searchResources'>;
643
+ }
338
644
  declare class Matcher {
339
- private kb;
645
+ private stores;
340
646
  private eventBus;
341
647
  private inferenceClient;
342
648
  private embeddingProvider;
343
649
  private subscriptions;
344
650
  private readonly logger;
345
- constructor(kb: KnowledgeBase, eventBus: EventBus, logger: Logger, inferenceClient: InferenceClient, embeddingProvider: EmbeddingProvider);
651
+ constructor(stores: MatcherStores, eventBus: EventBus, logger: Logger, inferenceClient: InferenceClient, embeddingProvider: EmbeddingProvider);
346
652
  initialize(): Promise<void>;
347
653
  private handleSearch;
348
654
  /**
@@ -416,6 +722,8 @@ interface LimitsDiscovery {
416
722
  *
417
723
  * Handles:
418
724
  * - browse:resource-requested — single resource metadata (materialized from events)
725
+ * - browse:anchored-text-by-checksum-requested — the detection workers' read-through
726
+ * cache consult: a stored extraction outcome by content identity (ANCHORED-TEXT-TO-SMELTER P2)
419
727
  * - browse:resources-requested — list resources
420
728
  * - browse:annotations-requested — all annotations for a resource
421
729
  * - browse:annotation-requested — single annotation with resolved resource
@@ -429,8 +737,22 @@ interface LimitsDiscovery {
429
737
  * - browse:directory-requested — list a project directory, merging fs + ViewStorage
430
738
  */
431
739
 
740
+ /**
741
+ * Browser's measured surface of the record (EXTRACT-ARCHIVIST P1) — reads
742
+ * only, every member a derived slice of its owning type. What is absent is
743
+ * the point: no appendEvent, no content bytes beyond `retrieve`, no
744
+ * projectionsDir, no weaveProgress.
745
+ */
746
+ interface BrowserReads {
747
+ views: Pick<ViewStorage, 'get' | 'getAll' | 'exists'>;
748
+ eventStore: EventStoreReads;
749
+ graph: Pick<GraphDatabase, 'getResource' | 'getResourceReferencedBy' | 'listResources' | 'getEntityTypeStats'>;
750
+ vectors: Pick<VectorStore, 'searchResources' | 'searchAnnotations'>;
751
+ content: Pick<WorkingTreeStore, 'retrieve'>;
752
+ anchoredText: Pick<AnchoredTextStore, 'read'>;
753
+ smeltProgress: Pick<SmeltProgress, 'whenSettled'>;
754
+ }
432
755
  declare class Browser {
433
- private views;
434
756
  private kb;
435
757
  private eventBus;
436
758
  private project;
@@ -441,7 +763,7 @@ declare class Browser {
441
763
  private embeddingProvider;
442
764
  private subscriptions;
443
765
  private readonly logger;
444
- constructor(views: ViewStorage, kb: KnowledgeBase, eventBus: EventBus, project: SemiontProject, config: MakeMeaningConfig,
766
+ constructor(kb: BrowserReads, eventBus: EventBus, project: SemiontProject, config: MakeMeaningConfig,
445
767
  /** Discovered per-(provider, model) ceilings for the roster (INFERENCE-LIMITS-EXPOSURE P2). */
446
768
  limitsDiscovery: LimitsDiscovery,
447
769
  /** For the semantic search fallback — mandatory (MANDATORY-EMBEDDING D0). */
@@ -462,6 +784,17 @@ declare class Browser {
462
784
  * this design exists to avoid.
463
785
  */
464
786
  private handleAnchoredText;
787
+ /**
788
+ * Serve the checksum-addressed consult (ANCHORED-TEXT-TO-SMELTER P2, D2) —
789
+ * the detection workers' read-through cache. The caller computed the key
790
+ * from bytes it already holds, so unlike the resource-addressed read there
791
+ * is nothing to resolve and no settle barrier: with no resourceId there is
792
+ * no content generation to wait on, and a miss means "extract it yourself".
793
+ * A hit — success or decline — is served whole, so the caller runs neither
794
+ * parser nor engine. Read-only over the wire: the Smelter is the sole
795
+ * writer and never answers here.
796
+ */
797
+ private handleAnchoredTextByChecksum;
465
798
  private handleBrowseResource;
466
799
  private handleBrowseResources;
467
800
  private handleBrowseAnnotations;
@@ -491,13 +824,24 @@ declare class Browser {
491
824
  * "Clone tokens produce new resources — that's yield."
492
825
  */
493
826
 
827
+ /**
828
+ * What the clone workflow touches (EXTRACT-ARCHIVIST P1/P3): resource
829
+ * metadata via views, and `resolveUri` for existence checks — never bytes
830
+ * (GATEWAY.md D4a). The clone's own bytes are stored by the gateway's
831
+ * upload path before `yield:clone-create` arrives; this actor holds NO
832
+ * byte capability at all.
833
+ */
834
+ interface CloneTokenStores {
835
+ views: Pick<ViewStorage, 'get'>;
836
+ content: Pick<WorkingTreeStore, 'resolveUri'>;
837
+ }
494
838
  declare class CloneTokenManager {
495
- private kb;
839
+ private stores;
496
840
  private eventBus;
497
841
  private subscriptions;
498
842
  private readonly logger;
499
843
  private readonly tokens;
500
- constructor(kb: KnowledgeBase, eventBus: EventBus, logger: Logger);
844
+ constructor(stores: CloneTokenStores, eventBus: EventBus, logger: Logger);
501
845
  initialize(): Promise<void>;
502
846
  private handleGenerateToken;
503
847
  private handleGetResource;
@@ -521,7 +865,7 @@ declare class CloneTokenManager {
521
865
  * These are the five access actors. Two projection-pipeline actors complete
522
866
  * the seven, and BOTH run standalone (D4: the projections are part of their
523
867
  * stores' stacks, not of the embedding process): the Weaver (weaver-main →
524
- * graph) and the Smelter (smelter-main → vectors). The backend keeps only
868
+ * graph) and the Smelter (smelter-main → vectors). The gateway keeps only
525
869
  * the Weaver's `weave:applied` fold (kb.weaveProgress).
526
870
  *
527
871
  * EventBus, JobQueue, and workers are peers to KnowledgeSystem, not members.
@@ -530,12 +874,24 @@ declare class CloneTokenManager {
530
874
  interface KnowledgeSystem {
531
875
  kb: KnowledgeBase;
532
876
  stower: Stower;
533
- gatherer: Gatherer$1;
877
+ gatherer: Gatherer;
534
878
  matcher: Matcher;
535
879
  browser: Browser;
536
880
  cloneTokenManager: CloneTokenManager;
537
881
  stop: () => Promise<void>;
538
882
  }
883
+ /**
884
+ * The gateway's view of the system after EXTRACT-ARCHIVIST P3 and
885
+ * EXTRACT-LIBRARIAN P3: the Archivist service owns
886
+ * Stower/Browser/CloneTokenManager and the Librarian owns Matcher and
887
+ * Gatherer, out-of-process. The gateway hosts NO actors — `kb` here is a
888
+ * READ bundle over the shared stateDir for the handler subset and the
889
+ * gateway's routes; the one writer is the Archivist (D4b/D6).
890
+ */
891
+ interface GatewayKnowledgeSystem {
892
+ kb: KnowledgeBase;
893
+ stop: () => Promise<void>;
894
+ }
539
895
  declare function stopKnowledgeSystem(ks: KnowledgeSystem): Promise<void>;
540
896
 
541
897
  /**
@@ -549,7 +905,7 @@ interface MakeMeaningService {
549
905
  knowledgeSystem: KnowledgeSystem;
550
906
  jobQueue: JobQueue;
551
907
  /**
552
- * The one SemiontProject this backend is serving — the same instance the
908
+ * The one SemiontProject this gateway is serving — the same instance the
553
909
  * KnowledgeSystem, the job queue and the bus handlers were built from.
554
910
  *
555
911
  * Exposed so request handlers reach for it instead of improvising their own
@@ -561,17 +917,132 @@ interface MakeMeaningService {
561
917
  project: SemiontProject;
562
918
  stop: () => Promise<void>;
563
919
  }
920
+ /**
921
+ * The in-process composition root: every access actor and handler on one
922
+ * caller-owned bus, for `LocalTransport` consumers — the SDK test seam and
923
+ * embedding. Production composes the same actors as extracted services
924
+ * (archivist-main, librarian-main); this second root is supported, not legacy.
925
+ */
564
926
  declare function startMakeMeaning(project: SemiontProject, config: MakeMeaningConfig, eventBus: EventBus, logger: Logger, options?: {
565
927
  skipRebuild?: boolean;
566
928
  }): Promise<MakeMeaningService>;
929
+ interface GatewayMakeMeaningService {
930
+ jobQueue: JobQueue;
931
+ /** Name + the state-mount paths. NOT a `SemiontProject`: the gateway
932
+ * mounts no KB tree, and the type is what says so (SINGLE-KB-MOUNT P5). */
933
+ state: SemiontState;
934
+ stop: () => Promise<void>;
935
+ }
936
+ /**
937
+ * The gateway's composition root: everything startMakeMeaning builds EXCEPT
938
+ * the actors, which have all left. The Archivist (archivist-main) owns
939
+ * Stower/Browser/CloneTokenManager, enrichment, the entity-type bootstrap +
940
+ * warm, and the view rebuild; the Librarian (librarian-main) owns Matcher
941
+ * and Gatherer (EXTRACT-LIBRARIAN P1/P3).
942
+ *
943
+ * What remains is the JOB QUEUE, and nothing else. It used to call
944
+ * `connectStores` as well — a graph connection, a vector store, an embedding
945
+ * provider, an event store, a working tree and an anchored-text store — and
946
+ * SINGLE-KB-MOUNT P5 measured that **no consumer read any of it**: the whole
947
+ * `kb` bundle existed to be constructed. Deleting it is what lets the gateway
948
+ * take a `SemiontState` instead of a `SemiontProject`, and therefore what
949
+ * lets P6 drop the `/kb` mount: the type no longer HAS a KB root to want.
950
+ *
951
+ * The job queue lives on the shared state mount (D6), so what is left needs
952
+ * no tree at all.
953
+ */
954
+ declare function startMakeMeaningGateway(state: SemiontState, config: MakeMeaningConfig, eventBus: EventBus, logger: Logger): Promise<GatewayMakeMeaningService>;
567
955
 
568
956
  /**
569
- * LocalTransport `ITransport` for an in-process `KnowledgeSystem`.
957
+ * The Archivist's HTTP surface: the /health probe, the D1 sequence-ranged
958
+ * event read path (EXTRACT-ARCHIVIST P2a), and the content write and read
959
+ * paths (SINGLE-KB-MOUNT P2/P3).
960
+ *
961
+ * ⚠️ STANDING RULE, load-bearing: **this surface serves the KB tree, and
962
+ * nothing else.** `browse:*`, `match:*`, `gather:*` stay on the bus. The
963
+ * earlier, narrower rule — exactly one customer, the gateway's SSE resume —
964
+ * was re-examined by SINGLE-KB-MOUNT D1 (2026-08-29), which reversed
965
+ * GATEWAY.md D4a: the Archivist is the knowledge base's storage authority,
966
+ * and this HTTP surface is how bytes and record reads reach it (D2: bytes
967
+ * ride HTTP, never the bus). That is a change of design, not a widened seam;
968
+ * an endpoint that is not a KB-tree read or write still does not belong here.
969
+ *
970
+ * D1 (settled 2026-08-27): moving the event store out of the gateway breaks
971
+ * `/bus/subscribe`'s `Last-Event-ID` replay, which reads the log in-process
972
+ * (apps/gateway/src/routes/bus.ts). The answer is one narrow call —
973
+ * the events for ONE resource from ONE sequence — which the gateway calls
974
+ * directly:
975
+ *
976
+ * GET /events/:resourceId?fromSequence=N (inclusive, like the filter it
977
+ * mirrors: `queryEvents(rId, { fromSequence })`; the caller does the +1)
978
+ *
979
+ * SINGLE-KB-MOUNT P2/P3: the gateway stops touching the shared mount for
980
+ * bytes and proxies both directions here —
981
+ *
982
+ * PUT /content/:storageUri[?checksum=sha256hex] (storageUri URI-encoded
983
+ * as one path segment; an optional checksum is verified BEFORE anything is
984
+ * written, and a disagreement is a 409)
985
+ *
986
+ * GET /resources/:id/content (the bytes, streamed,
987
+ * with the media type the record stores; the 404 carries `reason` so the
988
+ * gateway can serve its two different not-found messages)
989
+ *
990
+ * **The addresses differ because the lifecycle does**, not by oversight: at
991
+ * write time neither the resource nor its view exists — bytes land before the
992
+ * event — so the write has only a tree address to be addressed by, while the
993
+ * read has a record. Both go through ONE resolution (`representation.ts`);
994
+ * neither restates where bytes live.
995
+ *
996
+ * The write is `noGit` and emits nothing: the event contract is untouched —
997
+ * the Stower still `register`s the bytes from disk and does the one `git add`
998
+ * on event apply (GATEWAY.md D4b, single-writer).
999
+ *
1000
+ * Auth: callers authenticate with the same SEMIONT_WORKER_SECRET the
1001
+ * agent-token flow uses — service-to-service, one shared deployment fact.
1002
+ * With no secret configured, every path but /health refuses loudly (503)
1003
+ * rather than serving unauthenticated: absence fails, it is never a
1004
+ * default-open.
1005
+ */
1006
+
1007
+ interface ArchivistServerDeps {
1008
+ /** The record's log — the read half only. */
1009
+ events: Pick<EventLog, 'queryEvents'>;
1010
+ /** The KB tree's byte paths. `register` and the git index stay the
1011
+ * Stower's on event apply; reads go through `resolveRepresentation`. */
1012
+ content: Pick<WorkingTreeStore, 'store' | 'retrieveStream'>;
1013
+ /** The record's views — the resource half of the one resolution. */
1014
+ views: Pick<ViewStorage, 'get'>;
1015
+ /** Shared service secret; empty disables everything but /health (503), never opens it. */
1016
+ workerSecret: string;
1017
+ /** Liveness payload for /health — actor states, counters. */
1018
+ health: () => Record<string, unknown>;
1019
+ /**
1020
+ * The KB working tree's current branch, `null` outside a git checkout.
1021
+ *
1022
+ * A live fact about the tree, so it is answered by the process that HOLDS
1023
+ * the tree (SINGLE-KB-MOUNT P5). The gateway used to read it off its own
1024
+ * `/kb` mount; the launcher cannot stage it because a branch switch does
1025
+ * not restart the stack, and a staged value would quietly go stale.
1026
+ */
1027
+ branch: () => string | null;
1028
+ logger: Logger;
1029
+ }
1030
+ declare function createArchivistServer(deps: ArchivistServerDeps): Server;
1031
+
1032
+ /**
1033
+ * LocalTransport — `ITransport` onto an in-process make-meaning `EventBus`.
1034
+ *
1035
+ * It takes NO knowledge system. This is a bus transport: it publishes emits
1036
+ * onto the bus and bridges the reply channels back. It never touched a
1037
+ * `KnowledgeSystem` — the field that used to be here was declared and never
1038
+ * read, which made the transport look coupled to the monolith's shape when it
1039
+ * is coupled only to the bus. Whatever process hosts the actors on that bus
1040
+ * satisfies it.
570
1041
  *
571
1042
  * Bus-ownership pattern (see `docs/protocol/TRANSPORT-CONTRACT.md`):
572
1043
  * - The caller owns a make-meaning `EventBus` and passes it to both
573
1044
  * `startMakeMeaning` and `LocalTransport` so the transport can publish
574
- * directly onto the bus the `KnowledgeSystem` actors are listening on.
1045
+ * directly onto the bus the actors are listening on.
575
1046
  * - `SemiontClient` constructs its own `clientBus` and calls
576
1047
  * `bridgeInto(clientBus)` during construction. `LocalTransport`
577
1048
  * subscribes to every `BRIDGED_CHANNELS` entry on the make-meaning bus
@@ -579,22 +1050,17 @@ declare function startMakeMeaning(project: SemiontProject, config: MakeMeaningCo
579
1050
  * - The bus reference flows client → transport, never the other way.
580
1051
  *
581
1052
  * LocalTransport implements `ITransport` only. Auth, admin, and exchange
582
- * (`IBackendOperations`) are HTTP-shaped concepts that don't apply
1053
+ * (`IGatewayOperations`) are HTTP-shaped concepts that don't apply
583
1054
  * in-process — local mode runs as a single host-process identity supplied
584
1055
  * at construction, with no token/credential lifecycle. A `SemiontClient`
585
1056
  * built over this transport has no `.auth` / `.admin` namespaces.
586
1057
  */
587
1058
 
588
1059
  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
1060
  /**
595
1061
  * 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.
1062
+ * `startMakeMeaning` so that emits land on the bus the actors are
1063
+ * subscribed to.
598
1064
  */
599
1065
  eventBus: EventBus;
600
1066
  /**
@@ -641,8 +1107,13 @@ declare class LocalTransport implements ITransport {
641
1107
  }
642
1108
 
643
1109
  /**
644
- * LocalContentTransport — `IContentTransport` for an in-process
645
- * `KnowledgeSystem`.
1110
+ * LocalContentTransport — `IContentTransport` over an in-process
1111
+ * `KnowledgeBase`.
1112
+ *
1113
+ * Takes the KB, not the whole `KnowledgeSystem`: every read below goes through
1114
+ * `kb.*` and no actor is ever touched. The wider parameter forced callers that
1115
+ * legitimately hold only a KB to cast (`representation.test.ts` used
1116
+ * `as never`), which is a cast hiding nothing but an over-wide signature.
646
1117
  *
647
1118
  * Reads go straight to `kb.views` (resource lookup) + `kb.content`
648
1119
  * (byte retrieval). No network, no auth — local mode runs as a single
@@ -657,8 +1128,8 @@ declare class LocalTransport implements ITransport {
657
1128
 
658
1129
  type GetResourceResponse = components['schemas']['GetResourceResponse'];
659
1130
  declare class LocalContentTransport implements IContentTransport {
660
- private readonly ks;
661
- constructor(ks: KnowledgeSystem);
1131
+ private readonly kb;
1132
+ constructor(kb: KnowledgeBase);
662
1133
  putBinary(_request: PutBinaryRequest, _options?: PutBinaryOptions): Promise<{
663
1134
  resourceId: ResourceId;
664
1135
  }>;
@@ -704,6 +1175,12 @@ declare class LocalContentTransport implements IContentTransport {
704
1175
  stream: ReadableStream<Uint8Array>;
705
1176
  contentType: string;
706
1177
  }>;
1178
+ /**
1179
+ * The same resolution the wire path serves, buffered — local and hosted
1180
+ * modes must answer identically, which they did not before
1181
+ * SINGLE-KB-MOUNT P3: this resolved through `representations[].storageUri`,
1182
+ * a field `ViewMaterializer` never writes, so every binary read here threw.
1183
+ */
707
1184
  private loadBinary;
708
1185
  /**
709
1186
  * Assemble the resource's JSON-LD graph in-process from the KB — the local
@@ -718,7 +1195,7 @@ declare class LocalContentTransport implements IContentTransport {
718
1195
 
719
1196
  /**
720
1197
  * Adapt a raw in-process `EventBus` to the `BusRequestPrimitive` that
721
- * `busRequest` consumes. Lets backend-internal callers (bootstrap, event
1198
+ * `busRequest` consumes. Lets gateway-internal callers (bootstrap, event
722
1199
  * replay, linked-data import) use the same confirmed request/reply path as the
723
1200
  * SDK — `busRequest(asBusRequestPrimitive(eventBus), …)` — instead of
724
1201
  * hand-rolled `race(domain-event, *-failed, timeout)` blocks. The reply is
@@ -742,13 +1219,42 @@ declare function asBusRequestPrimitive(eventBus: EventBus): BusRequestPrimitive;
742
1219
  *
743
1220
  * This is a deferred-ack pattern: the result event attests that Stower has
744
1221
  * persisted the annotation, not merely that the command was well-formed.
1222
+ *
1223
+ * ## The annotatability gate (MEDIA-CAPABILITY-DISPATCH D6)
1224
+ *
1225
+ * Every GUI and SDK caller travels `mark:create-request` and is checked here.
1226
+ * The check is deliberately NOT on `mark:create`, which Stower consumes: that
1227
+ * channel is the fact-writing path, and gating it would need a leniency flag
1228
+ * for restore — the compatibility switch D6 was written to avoid.
1229
+ *
1230
+ * D6's original second emitter, the TypeScript import/replay path, was deleted
1231
+ * by EXPORT-VIA-LAUNCHER P3 (2026-08-27), so nothing travels the ungated
1232
+ * channel today. The separation is kept anyway, because restore returns in the
1233
+ * launcher and its fact-writing seam is still an open decision (that plan's
1234
+ * P5) — a restore that re-subjected historical facts to this gate would be the
1235
+ * 2026-07-09 "events are facts, commands are requests" ruling undone.
745
1236
  */
746
- declare function registerAnnotationAssemblyHandler(eventBus: EventBus, parentLogger: Logger): void;
1237
+ declare function registerAnnotationAssemblyHandler(eventBus: EventBus, kb: {
1238
+ views: Pick<ViewStorage, 'get'>;
1239
+ }, parentLogger: Logger): void;
747
1240
 
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;
1241
+ /**
1242
+ * Annotation lookup handlers — split along the EXTRACT-LIBRARIAN P3 cutover:
1243
+ *
1244
+ * - `browse:annotation-context-requested` is a pure views+content read with
1245
+ * no Gatherer. It registers wherever those capabilities live — the gateway
1246
+ * and the standalone root.
1247
+ * - `gather:summary-requested` calls the Gatherer's inference path, so it
1248
+ * follows the Gatherer (the Archivist's D2-i pattern): the standalone root
1249
+ * and librarian-main register it beside their Gatherer; the gateway does
1250
+ * NOT.
1251
+ */
1252
+
1253
+ declare function registerAnnotationContextHandler(eventBus: EventBus, kb: {
1254
+ views: Pick<ViewStorage, 'get'>;
1255
+ content: ContentReads;
1256
+ }, parentLogger: Logger): void;
1257
+ declare function registerGatherSummaryHandler(eventBus: EventBus, gatherer: Pick<Gatherer, 'generateAnnotationSummary'>, parentLogger: Logger): void;
752
1258
 
753
1259
  /**
754
1260
  * Handles `bind:update-body` — the Bind flow's authoritative "apply body
@@ -768,7 +1274,7 @@ declare function registerAnnotationLookupHandlers(eventBus: EventBus, kb: Knowle
768
1274
  */
769
1275
  declare function registerBindUpdateBodyHandler(eventBus: EventBus, parentLogger: Logger): void;
770
1276
 
771
- declare function registerJobCommandHandlers(eventBus: EventBus, jobQueue: JobQueue, project: SemiontProject, parentLogger: Logger): void;
1277
+ declare function registerJobCommandHandlers(eventBus: EventBus, jobQueue: JobQueue, state: SemiontState, parentLogger: Logger): void;
772
1278
 
773
1279
  /**
774
1280
  * Bus command handlers — pure bus-event translators that bridge the
@@ -777,7 +1283,7 @@ declare function registerJobCommandHandlers(eventBus: EventBus, jobQueue: JobQue
777
1283
  * `gather:summary-requested`) to the underlying make-meaning pipeline
778
1284
  * (Stower, Browser, Gatherer, JobQueue).
779
1285
  *
780
- * These ran in `apps/backend` historically because the HTTP gateway was
1286
+ * These ran in `apps/gateway` historically because the HTTP gateway was
781
1287
  * the only consumer that needed them. They are not HTTP-specific — moving
782
1288
  * them here means `LocalTransport` consumers (and any future transport)
783
1289
  * get the same contract automatically.
@@ -787,7 +1293,7 @@ declare function registerJobCommandHandlers(eventBus: EventBus, jobQueue: JobQue
787
1293
  * Register all bus command handlers on the make-meaning EventBus. Called
788
1294
  * during `startMakeMeaning` after the JobQueue and KnowledgeSystem exist.
789
1295
  */
790
- declare function registerBusHandlers(eventBus: EventBus, knowledgeSystem: KnowledgeSystem, jobQueue: JobQueue, project: SemiontProject, logger: Logger): void;
1296
+ declare function registerBusHandlers(eventBus: EventBus, knowledgeSystem: Pick<KnowledgeSystem, 'kb' | 'gatherer'>, jobQueue: JobQueue, state: SemiontState, logger: Logger): void;
791
1297
 
792
1298
  /**
793
1299
  * Entity Types Bootstrap
@@ -824,7 +1330,7 @@ declare function bootstrapEntityTypes(eventBus: EventBus, eventStore: EventStore
824
1330
  /**
825
1331
  * Read entity types from view storage projection
826
1332
  */
827
- declare function readEntityTypesProjection(project: SemiontProject): Promise<string[]>;
1333
+ declare function readEntityTypesProjection(state: SemiontState): Promise<string[]>;
828
1334
 
829
1335
  /**
830
1336
  * SmelterActorStateUnit — domain-event fan-in for the Smelter worker.
@@ -862,8 +1368,8 @@ declare function createSmelterActorStateUnit(options: SmelterActorStateUnitOptio
862
1368
  *
863
1369
  * Consumes the smelter-relevant domain events surfaced by
864
1370
  * `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
1371
+ * `ContentReads` (in the fleet, the Archivist's byte route — the stored
1372
+ * bytes, untouched), chunks and embeds it via the configured
867
1373
  * EmbeddingProvider, and indexes vectors into the VectorStore (Qdrant).
868
1374
  * `smelter-main` is the container entry point that wires this up.
869
1375
  *
@@ -950,7 +1456,19 @@ declare class Smelter {
950
1456
  private rebuildAnchors$;
951
1457
  private vectorStore;
952
1458
  private embeddingProvider;
1459
+ /** Byte reads only — the Smelter never writes through this seam, so it
1460
+ * declares `ContentReads` and any implementation satisfies it: the
1461
+ * Archivist's client in the fleet, the working tree in-process. */
953
1462
  private content;
1463
+ /**
1464
+ * The anchored-text store, held DIRECTLY (ANCHORED-TEXT-TO-SMELTER P1).
1465
+ *
1466
+ * It used to be built here over the content transport, which put the
1467
+ * gateway between this process and an artifact it produces itself. The
1468
+ * Smelter now owns the store on its own mount and is the only writer;
1469
+ * every read of it moved to the Archivist's bus channels.
1470
+ */
1471
+ private anchoredStore;
954
1472
  private bus;
955
1473
  private chunkingConfig;
956
1474
  private timing;
@@ -976,8 +1494,20 @@ declare class Smelter {
976
1494
  private drainChain;
977
1495
  constructor(events$: Observable<SmelterEvent>,
978
1496
  /** `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;
1497
+ rebuildAnchors$: Observable<EventMap['smelt:rebuild-anchors']>, vectorStore: VectorStore, embeddingProvider: EmbeddingProvider,
1498
+ /** Byte reads only — the Smelter never writes through this seam, so it
1499
+ * declares `ContentReads` and any implementation satisfies it: the
1500
+ * Archivist's client in the fleet, the working tree in-process. */
1501
+ content: ContentReads,
1502
+ /**
1503
+ * The anchored-text store, held DIRECTLY (ANCHORED-TEXT-TO-SMELTER P1).
1504
+ *
1505
+ * It used to be built here over the content transport, which put the
1506
+ * gateway between this process and an artifact it produces itself. The
1507
+ * Smelter now owns the store on its own mount and is the only writer;
1508
+ * every read of it moved to the Archivist's bus channels.
1509
+ */
1510
+ anchoredStore: AnchoredTextStore, bus: BusRequestPrimitive, chunkingConfig: ChunkingConfig, timing: SmelterTiming, logger: Logger);
981
1511
  get eventsProcessed(): number;
982
1512
  get reconcileState(): ReconcileState;
983
1513
  initialize(): void;
@@ -1135,228 +1665,6 @@ declare class Smelter {
1135
1665
  private listAllResources;
1136
1666
  }
1137
1667
 
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
1668
  /**
1361
1669
  * Resource Operations
1362
1670
  *
@@ -1390,6 +1698,39 @@ declare class ResourceOperations {
1390
1698
  * Create a new resource via EventBus → Stower
1391
1699
  */
1392
1700
  static createResource(input: CreateResourceInput, userId: UserId, eventBus: EventBus): Promise<ResourceId>;
1701
+ /**
1702
+ * Persist a CLONE via EventBus → Stower.
1703
+ *
1704
+ * Separate from `createResource` because a clone is a separate fact: it
1705
+ * names its parent, and `yield:cloned` requires that name. Callers reach
1706
+ * this only after the CloneTokenManager has validated the token — it is the
1707
+ * inner half of the flow, not a public entry point.
1708
+ */
1709
+ static persistClone(input: {
1710
+ name: string;
1711
+ storageUri: string;
1712
+ contentChecksum: string;
1713
+ byteSize: number;
1714
+ format: ContentFormat;
1715
+ parentResourceId: string;
1716
+ entityTypes?: string[];
1717
+ language?: string;
1718
+ }, userId: UserId, eventBus: EventBus): Promise<ResourceId>;
1719
+ /**
1720
+ * Create a resource from a clone token via EventBus → CloneTokenManager.
1721
+ * The bytes are already stored (the gateway's upload path, `noGit` — the
1722
+ * Archivist's register does the one `git add`, D4b); the command carries
1723
+ * storage coordinates only (EXTRACT-ARCHIVIST P3, D4a).
1724
+ */
1725
+ static createFromCloneToken(input: {
1726
+ token: string;
1727
+ name: string;
1728
+ storageUri: string;
1729
+ contentChecksum: string;
1730
+ byteSize: number;
1731
+ format: ContentFormat;
1732
+ archiveOriginal?: boolean;
1733
+ }, userId: UserId, eventBus: EventBus): Promise<ResourceId>;
1393
1734
  }
1394
1735
 
1395
1736
  /**
@@ -1418,15 +1759,21 @@ declare class AnnotationOperations {
1418
1759
  /**
1419
1760
  * Create a new annotation via EventBus → Stower
1420
1761
  */
1421
- static createAnnotation(request: CreateAnnotationRequest, userId: UserId, creator: Agent, eventBus: EventBus): Promise<CreateAnnotationResult>;
1762
+ static createAnnotation(request: CreateAnnotationRequest, userId: UserId, creator: Agent, eventBus: EventBus, kb: {
1763
+ views: Pick<ViewStorage, 'get'>;
1764
+ }): Promise<CreateAnnotationResult>;
1422
1765
  /**
1423
1766
  * Update annotation body via EventBus → Stower
1424
1767
  */
1425
- static updateAnnotationBody(id: string, request: UpdateAnnotationBodyRequest, userId: UserId, eventBus: EventBus, kb: KnowledgeBase): Promise<UpdateAnnotationBodyResult>;
1768
+ static updateAnnotationBody(id: string, request: UpdateAnnotationBodyRequest, userId: UserId, eventBus: EventBus, kb: {
1769
+ views: Pick<ViewStorage, 'get'>;
1770
+ }): Promise<UpdateAnnotationBodyResult>;
1426
1771
  /**
1427
1772
  * Delete an annotation via EventBus → Stower
1428
1773
  */
1429
- static deleteAnnotation(id: string, resourceIdStr: string, userId: UserId, eventBus: EventBus, kb: KnowledgeBase, logger?: Logger): Promise<void>;
1774
+ static deleteAnnotation(id: string, resourceIdStr: string, userId: UserId, eventBus: EventBus, kb: {
1775
+ views: Pick<ViewStorage, 'get'>;
1776
+ }, logger?: Logger): Promise<void>;
1430
1777
  }
1431
1778
 
1432
1779
  /**
@@ -1439,6 +1786,14 @@ declare class AnnotationOperations {
1439
1786
  * single-index reads; anything that FUSES sources belongs to the Matcher.
1440
1787
  */
1441
1788
 
1789
+ /** What the listing paths read (EXTRACT-ARCHIVIST P1): lexical search in
1790
+ * the graph, unsearched listings from views, the semantic fallback in the
1791
+ * vector index — plus `resourceWithViewGrace`'s graph-first hydration. */
1792
+ interface ListResourcesReads {
1793
+ views: Pick<ViewStorage, 'get' | 'getAll'>;
1794
+ graph: Pick<GraphDatabase, 'listResources' | 'getResource'>;
1795
+ vectors: Pick<VectorStore, 'searchResources'>;
1796
+ }
1442
1797
  interface ListResourcesFilters {
1443
1798
  search?: string;
1444
1799
  archived?: boolean;
@@ -1481,7 +1836,9 @@ declare class ResourceContext {
1481
1836
  /**
1482
1837
  * Get resource metadata from view storage
1483
1838
  */
1484
- static getResourceMetadata(resourceId: ResourceId, kb: KnowledgeBase): Promise<ResourceDescriptor | null>;
1839
+ static getResourceMetadata(resourceId: ResourceId, kb: {
1840
+ views: Pick<ViewStorage, 'get'>;
1841
+ }): Promise<ResourceDescriptor | null>;
1485
1842
  /**
1486
1843
  * List resources, optionally filtered, as one page plus the size of the whole
1487
1844
  * match set. Every filter is applied before pagination on both paths — a
@@ -1496,7 +1853,7 @@ declare class ResourceContext {
1496
1853
  * barrier-stamped projection, so an unsearched listing is read-your-writes
1497
1854
  * where the graph is only eventually consistent.
1498
1855
  */
1499
- static listResources(filters: ListResourcesFilters | undefined, kb: KnowledgeBase, semantic: SemanticFallbackDeps): Promise<ListResourcesResult>;
1856
+ static listResources(filters: ListResourcesFilters | undefined, kb: ListResourcesReads, semantic: SemanticFallbackDeps): Promise<ListResourcesResult>;
1500
1857
  /**
1501
1858
  * Answer an empty lexical search from the vector index (SEMANTIC-FALLBACK):
1502
1859
  * embed the query once, fold chunk hits per resource, floor them, and label
@@ -1517,189 +1874,21 @@ declare class ResourceContext {
1517
1874
  * Add content previews to resources (for search results)
1518
1875
  * Retrieves and decodes the first 200 characters of each resource's primary representation
1519
1876
  */
1520
- static addContentPreviews(resources: ResourceDescriptor[], kb: KnowledgeBase): Promise<Array<ResourceDescriptor & {
1877
+ static addContentPreviews(resources: ResourceDescriptor[], kb: {
1878
+ content: Pick<WorkingTreeStore, 'retrieve'>;
1879
+ }): Promise<Array<ResourceDescriptor & {
1521
1880
  content: string;
1522
1881
  }>>;
1523
1882
  /**
1524
1883
  * 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>;
1884
+ * Retrieves and decodes the primary representation. ResourceId-keyed
1885
+ * (EXTRACT-LIBRARIAN P3, D-CONTENT b): the descriptor's `storageUri` is the
1886
+ * has-content signal; the fetch itself goes by id, so the standalone
1887
+ * Librarian serves it over the transport.
1888
+ */
1889
+ static getResourceContent(resource: ResourceDescriptor, kb: {
1890
+ content: ContentReads;
1891
+ }): Promise<string | undefined>;
1703
1892
  }
1704
1893
 
1705
1894
  /**
@@ -1722,5 +1911,5 @@ declare function generateResourceSummary(resourceName: string, content: string,
1722
1911
  */
1723
1912
  declare function generateReferenceSuggestions(referenceTitle: string, client: InferenceClient, entityType?: string, currentContent?: string): Promise<string[] | null>;
1724
1913
 
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 };
1914
+ 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 };
1915
+ 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 };